diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index c0023560ff..3bb3df8dbd 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -237,7 +237,7 @@ class PurchaseInvoice(BuyingController): item.expense_account = warehouse_account[item.warehouse]["account"] else: item.expense_account = stock_not_billed_account - elif item.is_fixed_asset and not is_cwip_accounting_enabled(self.company, asset_category): + elif item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category): item.expense_account = get_asset_category_account('fixed_asset_account', item=item.item_code, company = self.company) elif item.is_fixed_asset and item.pr_detail: @@ -408,7 +408,7 @@ class PurchaseInvoice(BuyingController): for item in self.get("items"): if item.item_code and item.is_fixed_asset: asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") - if is_cwip_accounting_enabled(self.company, asset_category): + if is_cwip_accounting_enabled(asset_category): return 1 return 0 @@ -504,8 +504,7 @@ class PurchaseInvoice(BuyingController): "credit": flt(item.rm_supp_cost) }, warehouse_account[self.supplier_warehouse]["account_currency"], item=item)) - elif not item.is_fixed_asset or (item.is_fixed_asset and not is_cwip_accounting_enabled(self.company, - asset_category)): + elif not item.is_fixed_asset or (item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category)): expense_account = (item.expense_account if (not item.enable_deferred_expense or self.is_return) else item.deferred_expense_account) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 38f283c8d4..e9703dd790 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -175,11 +175,7 @@ def validate_account_for_perpetual_inventory(gl_map): StockValueAndAccountBalanceOutOfSync, title=_('Account Balance Out Of Sync')) def validate_cwip_accounts(gl_map): - cwip_enabled = cint(frappe.get_cached_value("Company", - gl_map[0].company, "enable_cwip_accounting")) - - if not cwip_enabled: - cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")]) + cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")]) if cwip_enabled and gl_map[0].voucher_type == "Journal Entry": cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 8b6bc40cf0..546f374094 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -31,8 +31,7 @@ class Asset(AccountsController): self.validate_in_use_date() self.set_status() self.make_asset_movement() - if not self.booked_fixed_asset and is_cwip_accounting_enabled(self.company, - self.asset_category): + if not self.booked_fixed_asset and is_cwip_accounting_enabled(self.asset_category): self.make_gl_entries() def before_cancel(self): @@ -99,7 +98,7 @@ class Asset(AccountsController): if not flt(self.gross_purchase_amount): frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) - if is_cwip_accounting_enabled(self.company, self.asset_category): + if is_cwip_accounting_enabled(self.asset_category): if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice): frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}"). format(self.item_code)) @@ -295,7 +294,9 @@ class Asset(AccountsController): .format(row.idx)) if not row.depreciation_start_date: - frappe.throw(_("Row {0}: Depreciation Start Date is required").format(row.idx)) + if not self.available_for_use_date: + frappe.throw(_("Row {0}: Depreciation Start Date is required").format(row.idx)) + row.depreciation_start_date = self.available_for_use_date if not self.is_existing_asset: self.opening_accumulated_depreciation = 0 @@ -514,7 +515,7 @@ def update_maintenance_status(): asset.set_status('Out of Order') def make_post_gl_entry(): - if not is_cwip_accounting_enabled(self.company, self.asset_category): + if not is_cwip_accounting_enabled(self.asset_category): return assets = frappe.db.sql_list(""" select name from `tabAsset` @@ -683,12 +684,7 @@ def make_asset_movement(assets, purpose=None): if asset_movement.get('assets'): return asset_movement.as_dict() -def is_cwip_accounting_enabled(company, asset_category=None): - enable_cwip_in_company = cint(frappe.db.get_value("Company", company, "enable_cwip_accounting")) - - if enable_cwip_in_company or not asset_category: - return enable_cwip_in_company - +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): diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 53fd6d394d..a56440de3d 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -69,508 +69,508 @@ class TestAsset(unittest.TestCase): self.assertFalse(frappe.db.get_value("GL Entry", {"voucher_type": "Purchase Invoice", "voucher_no": pi.name})) - # def test_is_fixed_asset_set(self): - # asset = create_asset(is_existing_asset = 1) - # doc = frappe.new_doc('Purchase Invoice') - # doc.supplier = '_Test Supplier' - # doc.append('items', { - # 'item_code': 'Macbook Pro', - # 'qty': 1, - # 'asset': asset.name - # }) - - # doc.set_missing_values() - # self.assertEquals(doc.items[0].is_fixed_asset, 1) - - - # def test_schedule_for_straight_line_method(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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-01-01' - # asset.purchase_date = '2030-01-01' - - # asset.append("finance_books", { - # "expected_value_after_useful_life": 10000, - # "depreciation_method": "Straight Line", - # "total_number_of_depreciations": 3, - # "frequency_of_depreciation": 12, - # "depreciation_start_date": "2030-12-31" - # }) - # asset.save() - - # self.assertEqual(asset.status, "Draft") - # expected_schedules = [ - # ["2030-12-31", 30000.00, 30000.00], - # ["2031-12-31", 30000.00, 60000.00], - # ["2032-12-31", 30000.00, 90000.00] - # ] - - # 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_straight_line_method_for_existing_asset(self): - # create_asset(is_existing_asset=1) - # asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) - # asset.calculate_depreciation = 1 - # asset.number_of_depreciations_booked = 1 - # asset.opening_accumulated_depreciation = 40000 - # asset.available_for_use_date = "2030-06-06" - # asset.append("finance_books", { - # "expected_value_after_useful_life": 10000, - # "depreciation_method": "Straight Line", - # "total_number_of_depreciations": 3, - # "frequency_of_depreciation": 12, - # "depreciation_start_date": "2030-12-31" - # }) - # asset.insert() - # self.assertEqual(asset.status, "Draft") - # asset.save() - # expected_schedules = [ - # ["2030-12-31", 14246.58, 54246.58], - # ["2031-12-31", 25000.00, 79246.58], - # ["2032-06-06", 10753.42, 90000.00] - # ] - # 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): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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-01-01' - # asset.purchase_date = '2030-01-01' - # asset.append("finance_books", { - # "expected_value_after_useful_life": 10000, - # "depreciation_method": "Double Declining Balance", - # "total_number_of_depreciations": 3, - # "frequency_of_depreciation": 12, - # "depreciation_start_date": '2030-12-31' - # }) - # asset.insert() - # self.assertEqual(asset.status, "Draft") - # asset.save() - - # expected_schedules = [ - # ['2030-12-31', 66667.00, 66667.00], - # ['2031-12-31', 22222.11, 88889.11], - # ['2032-12-31', 1110.89, 90000.0] - # ] - - # 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_double_declining_method_for_existing_asset(self): - # create_asset(is_existing_asset = 1) - # asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) - # asset.calculate_depreciation = 1 - # asset.is_existing_asset = 1 - # asset.number_of_depreciations_booked = 1 - # asset.opening_accumulated_depreciation = 50000 - # asset.available_for_use_date = '2030-01-01' - # asset.purchase_date = '2029-11-30' - # asset.append("finance_books", { - # "expected_value_after_useful_life": 10000, - # "depreciation_method": "Double Declining Balance", - # "total_number_of_depreciations": 3, - # "frequency_of_depreciation": 12, - # "depreciation_start_date": "2030-12-31" - # }) - # asset.insert() - # self.assertEqual(asset.status, "Draft") - - # expected_schedules = [ - # ["2030-12-31", 33333.50, 83333.50], - # ["2031-12-31", 6666.50, 90000.0] - # ] - - # 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_prorated_straight_line_method(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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.purchase_date = '2030-01-30' - # asset.is_existing_asset = 0 - # asset.available_for_use_date = "2030-01-30" - # asset.append("finance_books", { - # "expected_value_after_useful_life": 10000, - # "depreciation_method": "Straight Line", - # "total_number_of_depreciations": 3, - # "frequency_of_depreciation": 12, - # "depreciation_start_date": "2030-12-31" - # }) - - # asset.insert() - # asset.save() - - # expected_schedules = [ - # ["2030-12-31", 27534.25, 27534.25], - # ["2031-12-31", 30000.0, 57534.25], - # ["2032-12-31", 30000.0, 87534.25], - # ["2033-01-30", 2465.75, 90000.0] - # ] - - # 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) - - # def test_depreciation(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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.purchase_date = '2020-01-30' - # 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") - - # frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") - # post_depreciation_entries(date="2021-01-01") - # asset.load_from_db() - - # # 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) - # ) - - # gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - # where against_voucher_type='Asset' and against_voucher = %s - # order by account""", asset.name) - - # self.assertEqual(gle, expected_gle) - # self.assertEqual(asset.get("value_after_depreciation"), 0) - - # def test_depreciation_entry_for_wdv_without_pro_rata(self): - # 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-01-01' - # 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", 4000.00, 4000.00], - # ["2031-12-31", 2000.00, 6000.00], - # ["2032-12-31", 1000.00, 7000.0], - # ] - - # 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) - - # def test_pro_rata_depreciation_entry_for_wdv(self): - # 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-06' - # 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", 2279.45, 2279.45], - # ["2031-12-31", 2860.28, 5139.73], - # ["2032-12-31", 1430.14, 6569.87], - # ["2033-06-06", 430.13, 7000.0], - # ] - - # 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) - - # def test_depreciation_entry_cancellation(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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 = '2020-06-06' - # asset.purchase_date = '2020-06-06' - # 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") - - # asset.load_from_db() - - # # cancel depreciation entry - # depr_entry = asset.get("schedules")[0].journal_entry - # self.assertTrue(depr_entry) - # frappe.get_doc("Journal Entry", depr_entry).cancel() - - # asset.load_from_db() - # depr_entry = asset.get("schedules")[0].journal_entry - # self.assertFalse(depr_entry) - - # def test_scrap_asset(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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 = nowdate() - # asset.purchase_date = nowdate() - # 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": nowdate() - # }) - # asset.insert() - # asset.submit() - - # post_depreciation_entries(date=add_months(nowdate(), 10)) - - # 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) - # ) - - # 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(asset.name) - - # asset.load_from_db() - # self.assertFalse(asset.journal_entry_for_scrap) - # self.assertEqual(asset.status, "Partially Depreciated") - - # def test_asset_sale(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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 = '2020-06-06' - # asset.purchase_date = '2020-06-06' - # 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=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", asset.name, "status"), "Sold") - - # expected_gle = ( - # ("_Test Accumulated Depreciations - _TC", 20392.16, 0.0), - # ("_Test Fixed Asset - _TC", 0.0, 100000.0), - # ("_Test Gain/Loss on Asset Disposal - _TC", 54607.84, 0.0), - # ("Debtors - _TC", 25000.0, 0.0) - # ) - - # gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - # where voucher_type='Sales Invoice' and voucher_no = %s - # order by account""", si.name) - - # self.assertEqual(gle, expected_gle) - - # si.cancel() - # self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated") - - # def test_asset_expected_value_after_useful_life(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.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 = '2020-06-06' - # asset.purchase_date = '2020-06-06' - # 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-06-06" - # }) - # 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.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) - - # def test_cwip_accounting(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=5000, do_not_submit=True, location="Test Location") - - # pr.set('taxes', [{ - # 'category': 'Total', - # 'add_deduct_tax': 'Add', - # 'charge_type': 'On Net Total', - # 'account_head': '_Test Account Service Tax - _TC', - # 'description': '_Test Account Service Tax', - # 'cost_center': 'Main - _TC', - # 'rate': 5.0 - # }, { - # 'category': 'Valuation and Total', - # 'add_deduct_tax': 'Add', - # 'charge_type': 'On Net Total', - # 'account_head': '_Test Account Shipping Charges - _TC', - # 'description': '_Test Account Shipping Charges', - # 'cost_center': 'Main - _TC', - # 'rate': 5.0 - # }]) - - # pr.submit() - - # expected_gle = ( - # ("Asset Received But Not Billed - _TC", 0.0, 5250.0), - # ("CWIP Account - _TC", 5250.0, 0.0) - # ) - - # pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - # where voucher_type='Purchase Receipt' and voucher_no = %s - # order by account""", pr.name) - - # self.assertEqual(pr_gle, expected_gle) - - # pi = make_invoice(pr.name) - # pi.submit() - - # expected_gle = ( - # ("_Test Account Service Tax - _TC", 250.0, 0.0), - # ("_Test Account Shipping Charges - _TC", 250.0, 0.0), - # ("Asset Received But Not Billed - _TC", 5250.0, 0.0), - # ("Creditors - _TC", 0.0, 5500.0), - # ("Expenses Included In Asset Valuation - _TC", 0.0, 250.0), - # ) - - # pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - # where voucher_type='Purchase Invoice' and voucher_no = %s - # order by account""", pi.name) - - # self.assertEqual(pi_gle, expected_gle) - - # asset = frappe.db.get_value('Asset', - # {'purchase_receipt': pr.name, 'docstatus': 0}, 'name') - - # asset_doc = frappe.get_doc('Asset', asset) - - # month_end_date = get_last_day(nowdate()) - # asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15) - # self.assertEqual(asset_doc.gross_purchase_amount, 5250.0) - - # asset_doc.append("finance_books", { - # "expected_value_after_useful_life": 200, - # "depreciation_method": "Straight Line", - # "total_number_of_depreciations": 3, - # "frequency_of_depreciation": 10, - # "depreciation_start_date": month_end_date - # }) - # asset_doc.submit() - - # expected_gle = ( - # ("_Test Fixed Asset - _TC", 5250.0, 0.0), - # ("CWIP Account - _TC", 0.0, 5250.0) - # ) - - # gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - # where voucher_type='Asset' and voucher_no = %s - # order by account""", asset_doc.name) - - - # self.assertEqual(gle, expected_gle) - - # def test_expense_head(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=2, rate=200000.0, location="Test Location") - - # doc = make_invoice(pr.name) - - # self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account) + def test_is_fixed_asset_set(self): + asset = create_asset(is_existing_asset = 1) + doc = frappe.new_doc('Purchase Invoice') + doc.supplier = '_Test Supplier' + doc.append('items', { + 'item_code': 'Macbook Pro', + 'qty': 1, + 'asset': asset.name + }) + + doc.set_missing_values() + self.assertEquals(doc.items[0].is_fixed_asset, 1) + + + def test_schedule_for_straight_line_method(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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-01-01' + asset.purchase_date = '2030-01-01' + + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.save() + + self.assertEqual(asset.status, "Draft") + expected_schedules = [ + ["2030-12-31", 30000.00, 30000.00], + ["2031-12-31", 30000.00, 60000.00], + ["2032-12-31", 30000.00, 90000.00] + ] + + 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_straight_line_method_for_existing_asset(self): + create_asset(is_existing_asset=1) + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 + asset.number_of_depreciations_booked = 1 + asset.opening_accumulated_depreciation = 40000 + asset.available_for_use_date = "2030-06-06" + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.insert() + self.assertEqual(asset.status, "Draft") + asset.save() + expected_schedules = [ + ["2030-12-31", 14246.58, 54246.58], + ["2031-12-31", 25000.00, 79246.58], + ["2032-06-06", 10753.42, 90000.00] + ] + 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): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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-01-01' + asset.purchase_date = '2030-01-01' + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Double Declining Balance", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": '2030-12-31' + }) + asset.insert() + self.assertEqual(asset.status, "Draft") + asset.save() + + expected_schedules = [ + ['2030-12-31', 66667.00, 66667.00], + ['2031-12-31', 22222.11, 88889.11], + ['2032-12-31', 1110.89, 90000.0] + ] + + 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_double_declining_method_for_existing_asset(self): + create_asset(is_existing_asset = 1) + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 + asset.is_existing_asset = 1 + asset.number_of_depreciations_booked = 1 + asset.opening_accumulated_depreciation = 50000 + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2029-11-30' + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Double Declining Balance", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.insert() + self.assertEqual(asset.status, "Draft") + + expected_schedules = [ + ["2030-12-31", 33333.50, 83333.50], + ["2031-12-31", 6666.50, 90000.0] + ] + + 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_prorated_straight_line_method(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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.purchase_date = '2030-01-30' + asset.is_existing_asset = 0 + asset.available_for_use_date = "2030-01-30" + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + + asset.insert() + asset.save() + + expected_schedules = [ + ["2030-12-31", 27534.25, 27534.25], + ["2031-12-31", 30000.0, 57534.25], + ["2032-12-31", 30000.0, 87534.25], + ["2033-01-30", 2465.75, 90000.0] + ] + + 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) + + def test_depreciation(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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.purchase_date = '2020-01-30' + 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") + + frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") + post_depreciation_entries(date="2021-01-01") + asset.load_from_db() + + # 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) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where against_voucher_type='Asset' and against_voucher = %s + order by account""", asset.name) + + self.assertEqual(gle, expected_gle) + self.assertEqual(asset.get("value_after_depreciation"), 0) + + def test_depreciation_entry_for_wdv_without_pro_rata(self): + 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-01-01' + 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", 4000.00, 4000.00], + ["2031-12-31", 2000.00, 6000.00], + ["2032-12-31", 1000.00, 7000.0], + ] + + 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) + + def test_pro_rata_depreciation_entry_for_wdv(self): + 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-06' + 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", 2279.45, 2279.45], + ["2031-12-31", 2860.28, 5139.73], + ["2032-12-31", 1430.14, 6569.87], + ["2033-06-06", 430.13, 7000.0], + ] + + 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) + + def test_depreciation_entry_cancellation(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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 = '2020-06-06' + asset.purchase_date = '2020-06-06' + 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") + + asset.load_from_db() + + # cancel depreciation entry + depr_entry = asset.get("schedules")[0].journal_entry + self.assertTrue(depr_entry) + frappe.get_doc("Journal Entry", depr_entry).cancel() + + asset.load_from_db() + depr_entry = asset.get("schedules")[0].journal_entry + self.assertFalse(depr_entry) + + def test_scrap_asset(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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 = nowdate() + asset.purchase_date = nowdate() + 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": nowdate() + }) + asset.insert() + asset.submit() + + post_depreciation_entries(date=add_months(nowdate(), 10)) + + 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) + ) + + 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(asset.name) + + asset.load_from_db() + self.assertFalse(asset.journal_entry_for_scrap) + self.assertEqual(asset.status, "Partially Depreciated") + + def test_asset_sale(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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 = '2020-06-06' + asset.purchase_date = '2020-06-06' + 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=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", asset.name, "status"), "Sold") + + expected_gle = ( + ("_Test Accumulated Depreciations - _TC", 20392.16, 0.0), + ("_Test Fixed Asset - _TC", 0.0, 100000.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 54607.84, 0.0), + ("Debtors - _TC", 25000.0, 0.0) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no = %s + order by account""", si.name) + + self.assertEqual(gle, expected_gle) + + si.cancel() + self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated") + + def test_asset_expected_value_after_useful_life(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.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 = '2020-06-06' + asset.purchase_date = '2020-06-06' + 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-06-06" + }) + 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.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) + + def test_cwip_accounting(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=5000, do_not_submit=True, location="Test Location") + + pr.set('taxes', [{ + 'category': 'Total', + 'add_deduct_tax': 'Add', + 'charge_type': 'On Net Total', + 'account_head': '_Test Account Service Tax - _TC', + 'description': '_Test Account Service Tax', + 'cost_center': 'Main - _TC', + 'rate': 5.0 + }, { + 'category': 'Valuation and Total', + 'add_deduct_tax': 'Add', + 'charge_type': 'On Net Total', + 'account_head': '_Test Account Shipping Charges - _TC', + 'description': '_Test Account Shipping Charges', + 'cost_center': 'Main - _TC', + 'rate': 5.0 + }]) + + pr.submit() + + expected_gle = ( + ("Asset Received But Not Billed - _TC", 0.0, 5250.0), + ("CWIP Account - _TC", 5250.0, 0.0) + ) + + pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where voucher_type='Purchase Receipt' and voucher_no = %s + order by account""", pr.name) + + self.assertEqual(pr_gle, expected_gle) + + pi = make_invoice(pr.name) + pi.submit() + + expected_gle = ( + ("_Test Account Service Tax - _TC", 250.0, 0.0), + ("_Test Account Shipping Charges - _TC", 250.0, 0.0), + ("Asset Received But Not Billed - _TC", 5250.0, 0.0), + ("Creditors - _TC", 0.0, 5500.0), + ("Expenses Included In Asset Valuation - _TC", 0.0, 250.0), + ) + + pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where voucher_type='Purchase Invoice' and voucher_no = %s + order by account""", pi.name) + + self.assertEqual(pi_gle, expected_gle) + + asset = frappe.db.get_value('Asset', + {'purchase_receipt': pr.name, 'docstatus': 0}, 'name') + + asset_doc = frappe.get_doc('Asset', asset) + + month_end_date = get_last_day(nowdate()) + asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15) + self.assertEqual(asset_doc.gross_purchase_amount, 5250.0) + + asset_doc.append("finance_books", { + "expected_value_after_useful_life": 200, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10, + "depreciation_start_date": month_end_date + }) + asset_doc.submit() + + expected_gle = ( + ("_Test Fixed Asset - _TC", 5250.0, 0.0), + ("CWIP Account - _TC", 0.0, 5250.0) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where voucher_type='Asset' and voucher_no = %s + order by account""", asset_doc.name) + + + self.assertEqual(gle, expected_gle) + + def test_expense_head(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=2, rate=200000.0, location="Test Location") + + doc = make_invoice(pr.name) + + self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account) def create_asset_data(): if not frappe.db.exists("Asset Category", "Computers"): diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py index 14f3922c05..2a42894623 100644 --- a/erpnext/assets/doctype/asset_category/asset_category.py +++ b/erpnext/assets/doctype/asset_category/asset_category.py @@ -11,7 +11,6 @@ from frappe.model.document import Document class AssetCategory(Document): def validate(self): self.validate_finance_books() - self.validate_enable_cwip_accounting() def validate_finance_books(self): for d in self.finance_books: @@ -19,15 +18,6 @@ class AssetCategory(Document): if cint(d.get(frappe.scrub(field)))<1: frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError) - def validate_enable_cwip_accounting(self): - if self.enable_cwip_accounting : - for d in self.accounts: - cwip = frappe.db.get_value("Company",d.company_name,"enable_cwip_accounting") - if cwip: - frappe.throw(_ - ("CWIP is enabled globally in Company {1}. To enable it in Asset Category, first disable it in {1} ").format( - frappe.bold(d.idx), frappe.bold(d.company_name))) - @frappe.whitelist() def get_asset_category_account(fieldname, item=None, asset=None, account=None, asset_category = None, company = None): if item and frappe.db.get_value("Item", item, "is_fixed_asset"): diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.json b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.json index a25b4ce82e..3236e726de 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.json +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.json @@ -60,7 +60,8 @@ { "fieldname": "date", "fieldtype": "Date", - "label": "Date" + "label": "Date", + "reqd": 1 }, { "fieldname": "current_asset_value", @@ -110,7 +111,7 @@ } ], "is_submittable": 1, - "modified": "2019-05-26 09:46:23.613412", + "modified": "2019-11-22 14:09:25.800375", "modified_by": "Administrator", "module": "Assets", "name": "Asset Value Adjustment", diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 56425a0dcb..155597e856 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -5,12 +5,13 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import flt, getdate, cint, date_diff +from frappe.utils import flt, getdate, cint, date_diff, formatdate from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from frappe.model.document import Document class AssetValueAdjustment(Document): def validate(self): + self.validate_date() self.set_difference_amount() self.set_current_asset_value() @@ -23,6 +24,12 @@ class AssetValueAdjustment(Document): frappe.throw(_("Cancel the journal entry {0} first").format(self.journal_entry)) self.reschedule_depreciations(self.current_asset_value) + + def validate_date(self): + asset_purchase_date = frappe.db.get_value('Asset', self.asset, 'purchase_date') + if getdate(self.date) < getdate(asset_purchase_date): + frappe.throw(_("Asset Value Adjustment cannot be posted before Asset's purchase date {0}.") + .format(formatdate(asset_purchase_date)), title="Incorrect Date") def set_difference_amount(self): self.difference_amount = flt(self.current_asset_value - self.new_asset_value) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index d0befcbcf3..3392850e96 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -577,6 +577,7 @@ class BuyingController(StockController): def auto_make_assets(self, asset_items): items_data = get_asset_item_details(asset_items) + messages = [] for d in self.items: if d.is_fixed_asset: @@ -589,12 +590,16 @@ class BuyingController(StockController): for qty in range(cint(d.qty)): self.make_asset(d) is_plural = 's' if cint(d.qty) != 1 else '' - frappe.msgprint(_('{0} Asset{2} Created for {1}').format(cint(d.qty), d.item_code, is_plural)) + messages.append(_('{0} Asset{2} Created for {1}').format(cint(d.qty), d.item_code, is_plural)) else: - frappe.throw(_("Asset Naming Series is mandatory for the auto creation for item {0}").format(d.item_code)) + frappe.throw(_("Row {1}: Asset Naming Series is mandatory for the auto creation for item {0}") + .format(d.item_code, d.idx)) else: - frappe.msgprint(_("Assets not created. You will have to create asset manually.")) - + messages.append(_("Assets not created for {0}. You will have to create asset manually.") + .format(d.item_code)) + + for message in messages: + frappe.msgprint(message, title="Success") def make_asset(self, row): if not row.asset_location: diff --git a/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py b/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py index 5842e9edbf..4d4fc7c462 100644 --- a/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py +++ b/erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py @@ -7,15 +7,11 @@ def execute(): '''Get 'Disable CWIP Accounting value' from Asset Settings, set it in 'Enable Capital Work in Progress Accounting' field in Company, delete Asset Settings ''' - if frappe.db.exists("DocType","Asset Settings"): - frappe.reload_doctype("Company") - cwip_value = frappe.db.get_single_value("Asset Settings","disable_cwip_accounting") + if frappe.db.exists("DocType", "Asset Settings"): + frappe.reload_doctype("Asset Category") + cwip_value = frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting") + + frappe.db.sql("""UPDATE `tabAsset Category` SET enable_cwip_accounting = %s""", cint(cwip_value)) - companies = [x['name'] for x in frappe.get_all("Company", "name")] - for company in companies: - enable_cwip_accounting = cint(not cint(cwip_value)) - frappe.db.set_value("Company", company, "enable_cwip_accounting", enable_cwip_accounting) - - frappe.db.sql( - """ DELETE FROM `tabSingles` where doctype = 'Asset Settings' """) - frappe.delete_doc_if_exists("DocType","Asset Settings") \ No newline at end of file + frappe.db.sql("""DELETE FROM `tabSingles` where doctype = 'Asset Settings'""") + frappe.delete_doc_if_exists("DocType", "Asset Settings") \ No newline at end of file diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 2d181b53ca..dd602eca10 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -72,7 +72,6 @@ "stock_received_but_not_billed", "expenses_included_in_valuation", "fixed_asset_depreciation_settings", - "enable_cwip_accounting", "accumulated_depreciation_account", "depreciation_expense_account", "series_for_depreciation_entry", @@ -721,18 +720,12 @@ "fieldtype": "Link", "label": "Default Buying Terms", "options": "Terms and Conditions" - }, - { - "default": "0", - "fieldname": "enable_cwip_accounting", - "fieldtype": "Check", - "label": "Enable Capital Work in Progress Accounting" } ], "icon": "fa fa-building", "idx": 1, "image_field": "company_logo", - "modified": "2019-10-09 14:42:04.440974", + "modified": "2019-11-22 13:04:47.470768", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 2f4abbcea6..410d9f1b45 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -49,7 +49,7 @@ frappe.ui.form.on("Item", { if (!frm.doc.is_fixed_asset) { erpnext.item.make_dashboard(frm); } - + if (frm.doc.is_fixed_asset) { frm.trigger('is_fixed_asset'); frm.trigger('auto_create_assets'); @@ -140,6 +140,7 @@ frappe.ui.form.on("Item", { // set serial no to false & toggles its visibility frm.set_value('has_serial_no', 0); frm.toggle_enable(['has_serial_no', 'serial_no_series'], !frm.doc.is_fixed_asset); + frm.toggle_reqd(['asset_category'], frm.doc.is_fixed_asset); frm.toggle_display(['has_serial_no', 'serial_no_series'], !frm.doc.is_fixed_asset); frm.call({ @@ -150,6 +151,8 @@ frappe.ui.form.on("Item", { frm.trigger("set_asset_naming_series"); } }); + + frm.trigger('auto_create_assets'); }, set_asset_naming_series: function(frm) { @@ -159,8 +162,8 @@ frappe.ui.form.on("Item", { }, auto_create_assets: function(frm) { - frm.toggle_reqd(['asset_category', 'asset_naming_series'], frm.doc.auto_create_assets); - frm.toggle_display(['asset_category', 'asset_naming_series'], frm.doc.auto_create_assets); + frm.toggle_reqd(['asset_naming_series'], frm.doc.auto_create_assets); + frm.toggle_display(['asset_naming_series'], frm.doc.auto_create_assets); }, page_name: frappe.utils.warn_page_name_change, diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index 173b394f79..7df40fb02c 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -138,8 +138,8 @@ class LandedCostVoucher(Document): if item.is_fixed_asset: receipt_document_type = 'purchase_invoice' if item.receipt_document_type == 'Purchase Invoice' \ else 'purchase_receipt' - docs = frappe.db.get_all('Asset', filters={ receipt_document_type: item.receipt_document }, - fields=['name', 'docstatus']) + docs = frappe.db.get_all('Asset', filters={ receipt_document_type: item.receipt_document, + 'item_code': item.item_code }, fields=['name', 'docstatus']) if not docs or len(docs) != item.qty: frappe.throw(_('There are not enough asset created or linked to {0}. \ Please create or link {1} Assets with respective document.').format(item.receipt_document, item.qty)) @@ -148,8 +148,7 @@ class LandedCostVoucher(Document): if d.docstatus == 1: frappe.throw(_('{2} {0} has submitted Assets.\ Remove Item {1} from table to continue.').format( - item.receipt_document, item.item_code, item.receipt_document_type) - ) + item.receipt_document, item.item_code, item.receipt_document_type)) def update_rate_in_serial_no_for_non_asset_items(self, receipt_document): for item in receipt_document.get("items"): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 0cb21d73f9..d0fae6a227 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -82,11 +82,21 @@ class PurchaseReceipt(BuyingController): self.validate_with_previous_doc() self.validate_uom_is_integer("uom", ["qty", "received_qty"]) self.validate_uom_is_integer("stock_uom", "stock_qty") + self.validate_cwip_accounts() self.check_on_hold_or_closed_status() if getdate(self.posting_date) > getdate(nowdate()): throw(_("Posting Date cannot be future date")) + + def validate_cwip_accounts(self): + for item in self.get('items'): + if item.is_fixed_asset and is_cwip_accounting_enabled(item.asset_category): + # check cwip accounts before making auto assets + # Improves UX by not giving messages of "Assets Created" before throwing error of not finding arbnb account + arbnb_account = self.get_company_default("asset_received_but_not_billed") + cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company) + break def validate_with_previous_doc(self): super(PurchaseReceipt, self).validate_with_previous_doc({ @@ -343,7 +353,7 @@ class PurchaseReceipt(BuyingController): def get_asset_gl_entry(self, gl_entries): for item in self.get("items"): if item.is_fixed_asset: - if is_cwip_accounting_enabled(self.company, item.asset_category): + if is_cwip_accounting_enabled(item.asset_category): self.add_asset_gl_entries(item, gl_entries) if flt(item.landed_cost_voucher_amount): self.add_lcv_gl_entries(item, gl_entries) @@ -386,7 +396,7 @@ class PurchaseReceipt(BuyingController): def add_lcv_gl_entries(self, item, gl_entries): expenses_included_in_asset_valuation = self.get_company_default("expenses_included_in_asset_valuation") - if not is_cwip_accounting_enabled(self.company, item.asset_category): + if not is_cwip_accounting_enabled(item.asset_category): asset_account = get_asset_category_account(asset_category=item.asset_category, \ fieldname='fixed_asset_account', company=self.company) else: