diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index b6d3d6ba86..6cdb550c9d 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -305,10 +305,11 @@ class Asset(AccountsController): if self.journal_entry_for_scrap: status = "Scrapped" - elif flt(value_after_depreciation) <= expected_value_after_useful_life: - status = "Fully Depreciated" - elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount): - status = 'Partially Depreciated' + elif self.finance_books: + if flt(value_after_depreciation) <= expected_value_after_useful_life: + status = "Fully Depreciated" + elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount): + status = 'Partially Depreciated' elif self.docstatus == 2: status = "Cancelled" return status diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index aacaef5414..8111daec5e 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -11,7 +11,6 @@ def post_depreciation_entries(date=None): # Return if automatic booking of asset depreciation is disabled if not frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically"): return - if not date: date = today() for asset in get_depreciable_assets(date): @@ -28,7 +27,7 @@ def get_depreciable_assets(date): @frappe.whitelist() def make_depreciation_entry(asset_name, date=None): frappe.has_permission('Journal Entry', throw=True) - + if not date: date = today() @@ -38,7 +37,6 @@ def make_depreciation_entry(asset_name, date=None): depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]) - for d in asset.get("schedules"): if not d.journal_entry and getdate(d.schedule_date) <= getdate(date): @@ -81,7 +79,7 @@ def make_depreciation_entry(asset_name, date=None): def get_depreciation_accounts(asset): fixed_asset_account = accumulated_depreciation_account = depreciation_expense_account = None - + accounts = frappe.db.get_value("Asset Category Account", filters={'parent': asset.asset_category, 'company_name': asset.company}, fieldname = ['fixed_asset_account', 'accumulated_depreciation_account', diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index b9460b60e1..9846ec9717 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -17,7 +17,7 @@ class TestAsset(unittest.TestCase): frappe.db.sql("delete from `tabTax Rule`") def test_purchase_asset(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) asset.submit() pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount, @@ -53,14 +53,21 @@ class TestAsset(unittest.TestCase): def test_schedule_for_straight_line_method(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") - + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "next_depreciation_date": "2020-12-31", + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": add_days(nowdate(), 5) + }) + asset.insert() self.assertEqual(asset.status, "Draft") - expected_schedules = [ - ["2020-12-31", 30000, 30000], - ["2021-03-31", 30000, 60000], - ["2021-06-30", 30000, 90000] + ["2018-06-11", 490.20, 490.20], + ["2019-04-11", 49673.20, 50163.40], + ["2020-02-11", 39836.60, 90000.00] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -69,34 +76,48 @@ class TestAsset(unittest.TestCase): self.assertEqual(schedules, expected_schedules) def test_schedule_for_straight_line_method_for_existing_asset(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) asset.is_existing_asset = 1 asset.number_of_depreciations_booked = 1 asset.opening_accumulated_depreciation = 40000 - asset.save() - + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "next_depreciation_date": "2020-12-31", + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": add_days(nowdate(), 5) + }) + asset.insert() self.assertEqual(asset.status, "Draft") - + asset.save() expected_schedules = [ - ["2020-12-31", 25000, 65000], - ["2021-03-31", 25000, 90000] + ["2018-06-11", 588.24, 40588.24], + ["2019-04-11", 49411.76, 90000.00] ] - - schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] for d in asset.get("schedules")] self.assertEqual(schedules, expected_schedules) - def test_schedule_for_double_declining_method(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") - asset.depreciation_method = "Double Declining Balance" + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "next_depreciation_date": "2020-12-31", + "depreciation_method": "Double Declining Balance", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": add_days(nowdate(), 5) + }) + asset.insert() + self.assertEqual(asset.status, "Draft") asset.save() expected_schedules = [ - ["2020-12-31", 66667, 66667], - ["2021-03-31", 22222, 88889], - ["2021-06-30", 1111, 90000] + ["2018-06-11", 66667.0, 66667.0], + ["2019-04-11", 22222.0, 88889.0], + ["2020-02-11", 1111.0, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -105,40 +126,27 @@ class TestAsset(unittest.TestCase): self.assertEqual(schedules, expected_schedules) def test_schedule_for_double_declining_method_for_existing_asset(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") - asset.depreciation_method = "Double Declining Balance" + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) asset.is_existing_asset = 1 asset.number_of_depreciations_booked = 1 asset.opening_accumulated_depreciation = 50000 - asset.save() - - expected_schedules = [ - ["2020-12-31", 33333, 83333], - ["2021-03-31", 6667, 90000] - ] - - schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_schedule_for_manual_method(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") - asset.depreciation_method = "Manual" - asset.schedules = [] - for schedule_date, amount in [["2020-12-31", 40000], ["2021-06-30", 30000], ["2021-10-31", 20000]]: - asset.append("schedules", { - "schedule_date": schedule_date, - "depreciation_amount": amount - }) - asset.save() - + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "next_depreciation_date": "2020-12-31", + "depreciation_method": "Double Declining Balance", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": add_days(nowdate(), 5) + }) + asset.insert() self.assertEqual(asset.status, "Draft") + asset.save() + + asset.save() expected_schedules = [ - ["2020-12-31", 40000, 40000], - ["2021-06-30", 30000, 70000], - ["2021-10-31", 20000, 90000] + ["2018-06-11", 33333.0, 83333.0], + ["2019-04-11", 6667.0, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -148,21 +156,28 @@ class TestAsset(unittest.TestCase): def test_schedule_for_prorated_straight_line_method(self): set_prorated_depreciation_schedule() - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) asset.is_existing_asset = 0 asset.available_for_use_date = "2020-01-30" - asset.next_depreciation_date = "2020-12-31" - asset.depreciation_method = "Straight Line" + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": "2020-12-31" + }) + + asset.insert() asset.save() expected_schedules = [ - ["2020-12-31", 28000, 28000], - ["2021-12-31", 30000, 58000], - ["2022-12-31", 30000, 88000], - ["2023-01-30", 2000, 90000] + ["2020-12-31", 28000.0, 28000.0], + ["2021-12-31", 30000.0, 58000.0], + ["2022-12-31", 30000.0, 88000.0], + ["2023-01-30", 2000.0, 90000.0] ] - schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + 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) @@ -170,24 +185,30 @@ class TestAsset(unittest.TestCase): remove_prorated_depreciation_schedule() def test_depreciation(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.available_for_use_date = "2020-01-30" + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": "2020-12-31" + }) + asset.insert() asset.submit() asset.load_from_db() - self.assertEqual(asset.status, "Submitted") + self.assertEqual(asset.status, "Partially Depreciated") frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") - post_depreciation_entries(date="2021-01-01") asset.load_from_db() - self.assertEqual(asset.status, "Partially Depreciated") - # check depreciation entry series self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR") expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), - ("_Test Depreciations - _TC", 30000.0, 0.0) + ("_Test Accumulated Depreciations - _TC", 0.0, 35699.15), + ("_Test Depreciations - _TC", 35699.15, 0.0) ) gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` @@ -195,10 +216,18 @@ class TestAsset(unittest.TestCase): order by account""", asset.name) self.assertEqual(gle, expected_gle) - self.assertEqual(asset.get("value_after_depreciation"), 70000) + self.assertEqual(asset.get("value_after_depreciation"), 0) def test_depreciation_entry_cancellation(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": "2020-12-31" + }) + asset.insert() asset.submit() post_depreciation_entries(date="2021-01-01") @@ -215,51 +244,66 @@ class TestAsset(unittest.TestCase): def test_scrap_asset(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": "2020-12-31" + }) + asset.insert() asset.submit() post_depreciation_entries(date="2021-01-01") - scrap_asset("Macbook Pro 1") + scrap_asset(asset.name) asset.load_from_db() self.assertEqual(asset.status, "Scrapped") self.assertTrue(asset.journal_entry_for_scrap) expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0), - ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 70000.0, 0.0) + ("_Test Accumulated Depreciations - _TC", 100000.0, 0.0), + ("_Test Fixed Asset - _TC", 0.0, 100000.0) ) gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no = %s order by account""", asset.journal_entry_for_scrap) - self.assertEqual(gle, expected_gle) - restore_asset("Macbook Pro 1") + restore_asset(asset.name) asset.load_from_db() self.assertFalse(asset.journal_entry_for_scrap) self.assertEqual(asset.status, "Partially Depreciated") def test_asset_sale(self): - frappe.get_doc("Asset", "Macbook Pro 1").submit() + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": "2020-12-31" + }) + asset.insert() + asset.submit() post_depreciation_entries(date="2021-01-01") - si = make_sales_invoice(asset="Macbook Pro 1", 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.due_date = nowdate() si.get("items")[0].rate = 25000 si.insert() si.submit() - self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Sold") + self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0), + ("_Test Accumulated Depreciations - _TC", 100000.0, 0.0), ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 45000.0, 0.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 0, 25000.0), ("Debtors - _TC", 25000.0, 0.0) ) @@ -272,34 +316,36 @@ class TestAsset(unittest.TestCase): si.cancel() frappe.delete_doc("Sales Invoice", si.name) - self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Partially Depreciated") + self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated") def test_asset_expected_value_after_useful_life(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) asset.depreciation_method = "Straight Line" - asset.is_existing_asset = 1 - asset.total_number_of_depreciations = 400 - asset.gross_purchase_amount = 16866177.00 - asset.expected_value_after_useful_life = 500000 - asset.save() - + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": "2020-12-31" + }) + asset.insert() accumulated_depreciation_after_full_schedule = \ max([d.accumulated_depreciation_amount for d in asset.get("schedules")]) asset_value_after_full_schedule = (flt(asset.gross_purchase_amount) - flt(accumulated_depreciation_after_full_schedule)) - self.assertTrue(asset.expected_value_after_useful_life >= asset_value_after_full_schedule) + self.assertTrue(asset.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) def tearDown(self): - asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) if asset.docstatus == 1 and asset.status not in ("Scrapped", "Sold", "Draft", "Cancelled"): asset.cancel() - self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Cancelled") + self.assertEqual(frappe.db.get_value("Asset", {"asset_name": "Macbook Pro 1"}, "status"), "Cancelled") - frappe.delete_doc("Asset", "Macbook Pro 1") + frappe.delete_doc("Asset", {"asset_name": "Macbook Pro 1"}) def create_asset(): if not frappe.db.exists("Asset Category", "Computers"): @@ -322,7 +368,6 @@ def create_asset(): "company": "_Test Company", "purchase_date": "2015-01-01", "calculate_depreciation": 1, - "next_depreciation_date": "2020-12-31", "gross_purchase_amount": 100000, "expected_value_after_useful_life": 10000, "warehouse": "_Test Warehouse - _TC", @@ -330,6 +375,7 @@ def create_asset(): "location": "Test Location", "asset_owner": "Company" }) + try: asset.save() except frappe.DuplicateEntryError: diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 78f1eb84e2..7966d14624 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -95,7 +95,6 @@ class TestPurchaseReceipt(unittest.TestCase): make_stock_entry(item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100) make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100) - frappe.db.set_value("Item", "_Test FG Item", "end_of_life", add_days(nowdate(), 2)) pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes") self.assertEqual(len(pr.get("supplied_items")), 2)