diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 079f599706..c5260a1239 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -711,7 +711,8 @@ class PurchaseInvoice(BuyingController):
item.item_tax_amount / self.conversion_rate)
}, item=item))
else:
- cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company)
+ cwip_account = get_asset_account("capital_work_in_progress_account",
+ asset_category=item.asset_category,company=self.company)
cwip_account_currency = get_account_currency(cwip_account)
gl_entries.append(self.get_gl_dict({
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 9a666bf9f8..2e5a7142a3 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1002,7 +1002,8 @@ def make_purchase_invoice(**args):
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"project": args.project,
"rejected_warehouse": args.rejected_warehouse or "",
- "rejected_serial_no": args.rejected_serial_no or ""
+ "rejected_serial_no": args.rejected_serial_no or "",
+ "asset_location": args.location or ""
})
if args.get_taxes_and_charges:
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index efdbdb1fbf..fca9559504 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -466,50 +466,63 @@ class Asset(AccountsController):
def validate_make_gl_entry(self):
purchase_document = self.get_purchase_document()
- asset_bought_with_invoice = purchase_document == self.purchase_invoice
- fixed_asset_account, cwip_account = self.get_asset_accounts()
- cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
- # check if expense already has been booked in case of cwip was enabled after purchasing asset
- expense_booked = False
- cwip_booked = False
-
- if asset_bought_with_invoice:
- expense_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
- (purchase_document, fixed_asset_account), as_dict=1)
- else:
- cwip_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
- (purchase_document, cwip_account), as_dict=1)
-
- if cwip_enabled and (expense_booked or not cwip_booked):
- # if expense has already booked from invoice or cwip is booked from receipt
+ if not purchase_document:
return False
- elif not cwip_enabled and (not expense_booked or cwip_booked):
- # if cwip is disabled but expense hasn't been booked yet
- return True
- elif cwip_enabled:
- # default condition
- return True
+
+ asset_bought_with_invoice = (purchase_document == self.purchase_invoice)
+ fixed_asset_account = self.get_fixed_asset_account()
+
+ cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
+ cwip_account = self.get_cwip_account(cwip_enabled=cwip_enabled)
+
+ query = """SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s"""
+ if asset_bought_with_invoice:
+ # with invoice purchase either expense or cwip has been booked
+ expense_booked = frappe.db.sql(query, (purchase_document, fixed_asset_account), as_dict=1)
+ if expense_booked:
+ # if expense is already booked from invoice then do not make gl entries regardless of cwip enabled/disabled
+ return False
+
+ cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
+ if cwip_booked:
+ # if cwip is booked from invoice then make gl entries regardless of cwip enabled/disabled
+ return True
+ else:
+ # with receipt purchase either cwip has been booked or no entries have been made
+ if not cwip_account:
+ # if cwip account isn't available do not make gl entries
+ return False
+
+ cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
+ # if cwip is not booked from receipt then do not make gl entries
+ # if cwip is booked from receipt then make gl entries
+ return cwip_booked
def get_purchase_document(self):
asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')
purchase_document = self.purchase_invoice if asset_bought_with_invoice else self.purchase_receipt
return purchase_document
+
+ def get_fixed_asset_account(self):
+ return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
+
+ def get_cwip_account(self, cwip_enabled=False):
+ cwip_account = None
+ try:
+ cwip_account = get_asset_account("capital_work_in_progress_account", self.name, self.asset_category, self.company)
+ except:
+ # if no cwip account found in category or company and "cwip is enabled" then raise else silently pass
+ if cwip_enabled:
+ raise
- def get_asset_accounts(self):
- fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name,
- asset_category = self.asset_category, company = self.company)
-
- cwip_account = get_asset_account("capital_work_in_progress_account",
- self.name, self.asset_category, self.company)
-
- return fixed_asset_account, cwip_account
+ return cwip_account
def make_gl_entries(self):
gl_entries = []
purchase_document = self.get_purchase_document()
- fixed_asset_account, cwip_account = self.get_asset_accounts()
+ fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 52039c183b..a0d76031fc 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -9,6 +9,7 @@ from frappe.utils import cstr, nowdate, getdate, flt, get_last_day, add_days, ad
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
from erpnext.assets.doctype.asset.asset import make_sales_invoice
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice
class TestAsset(unittest.TestCase):
@@ -558,81 +559,6 @@ class TestAsset(unittest.TestCase):
self.assertEqual(gle, expected_gle)
- def test_gle_with_cwip_toggling(self):
- # TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset
- frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
-
- 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
- })
-
- # disable cwip and try submitting
- frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
- asset_doc.submit()
- # asset should have gl entries even if cwip is disabled
- 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)
-
- frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
-
def test_expense_head(self):
pr = make_purchase_receipt(item_code="Macbook Pro",
qty=2, rate=200000.0, location="Test Location")
@@ -640,6 +566,74 @@ class TestAsset(unittest.TestCase):
doc = make_invoice(pr.name)
self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
+
+ def test_asset_cwip_toggling_cases(self):
+ cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
+ name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
+ cwip_acc = "CWIP Account - _TC"
+
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+ frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "")
+ frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", "")
+
+ # case 0 -- PI with cwip disable, Asset with cwip disabled, No cwip account set
+ pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+ asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertFalse(gle)
+
+ # case 1 -- PR with cwip disabled, Asset with cwip enabled
+ pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+ frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
+ asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertFalse(gle)
+
+ # case 2 -- PR with cwip enabled, Asset with cwip disabled
+ pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+ asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertTrue(gle)
+
+ # case 3 -- PI with cwip disabled, Asset with cwip enabled
+ pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+ asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertFalse(gle)
+
+ # case 4 -- PI with cwip enabled, Asset with cwip disabled
+ pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+ asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertTrue(gle)
+
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", cwip)
+ frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
+ frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc)
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 9a33fc14ac..46620d56e9 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import cint
+from frappe.utils import cint, get_link_to_form
from frappe.model.document import Document
class AssetCategory(Document):
@@ -13,6 +13,7 @@ class AssetCategory(Document):
self.validate_finance_books()
self.validate_account_types()
self.validate_account_currency()
+ self.valide_cwip_account()
def validate_finance_books(self):
for d in self.finance_books:
@@ -58,6 +59,21 @@ class AssetCategory(Document):
frappe.throw(_("Row #{}: {} of {} should be {}. Please modify the account or select a different account.")
.format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)),
title=_("Invalid Account"))
+
+ def valide_cwip_account(self):
+ if self.enable_cwip_accounting:
+ missing_cwip_accounts_for_company = []
+ for d in self.accounts:
+ if (not d.capital_work_in_progress_account and
+ not frappe.db.get_value("Company", d.company_name, "capital_work_in_progress_account")):
+ missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name))
+
+ if missing_cwip_accounts_for_company:
+ msg = _("""To enable Capital Work in Progress Accounting, """)
+ msg += _("""you must select Capital Work in Progress Account in accounts table""")
+ msg += "
"
+ msg += _("You can also set default CWIP account in Company {}").format(", ".join(missing_cwip_accounts_for_company))
+ frappe.throw(msg, title=_("Missing Account"))
@frappe.whitelist()
diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py
index b32f9b5020..39b79d6c50 100644
--- a/erpnext/assets/doctype/asset_category/test_asset_category.py
+++ b/erpnext/assets/doctype/asset_category/test_asset_category.py
@@ -26,4 +26,22 @@ class TestAssetCategory(unittest.TestCase):
asset_category.insert()
except frappe.DuplicateEntryError:
pass
-
\ No newline at end of file
+
+ def test_cwip_accounting(self):
+ company_cwip_acc = frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account")
+ frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "")
+
+ asset_category = frappe.new_doc("Asset Category")
+ asset_category.asset_category_name = "Computers"
+ asset_category.enable_cwip_accounting = 1
+
+ asset_category.total_number_of_depreciations = 3
+ asset_category.frequency_of_depreciation = 3
+ asset_category.append("accounts", {
+ "company_name": "_Test Company",
+ "fixed_asset_account": "_Test Fixed Asset - _TC",
+ "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
+ "depreciation_expense_account": "_Test Depreciations - _TC"
+ })
+
+ self.assertRaises(frappe.ValidationError, asset_category.insert)
\ No newline at end of file