Fixed asset: status, restore, testcase and much more
This commit is contained in:
parent
4d668dbaa3
commit
7536349f17
@ -17,10 +17,16 @@ frappe.ui.form.on('Asset', {
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus==1 && frm.doc.status=='Available') {
|
||||
cur_frm.add_custom_button("Scrap", function() {
|
||||
erpnext.asset.scrap_asset(frm);
|
||||
});
|
||||
if (frm.doc.docstatus==1) {
|
||||
if (in_list(["Submittted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) {
|
||||
cur_frm.add_custom_button("Scrap Asset", function() {
|
||||
erpnext.asset.scrap_asset(frm);
|
||||
});
|
||||
} else if (frm.doc.status=='Scrapped') {
|
||||
cur_frm.add_custom_button("Restore Asset", function() {
|
||||
erpnext.asset.restore_asset(frm);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -37,4 +43,18 @@ erpnext.asset.scrap_asset = function(frm) {
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
erpnext.asset.restore_asset = function(frm) {
|
||||
frappe.confirm(__("Do you really want to restore this scrapped asset?"), function () {
|
||||
frappe.call({
|
||||
args: {
|
||||
"asset_name": frm.doc.name
|
||||
},
|
||||
method: "erpnext.accounts.doctype.asset.depreciation.restore_asset",
|
||||
callback: function(r) {
|
||||
cur_frm.reload_doc();
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
@ -90,7 +90,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "Available",
|
||||
"default": "Draft",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@ -101,7 +101,7 @@
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Available\nSold\nScrapped",
|
||||
"options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -240,6 +240,32 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "journal_entry_for_scrap",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Journal Entry for Scrap",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Journal Entry",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -356,7 +382,7 @@
|
||||
"in_list_view": 0,
|
||||
"label": "Next Depreciation Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -458,7 +484,7 @@
|
||||
"in_list_view": 0,
|
||||
"label": "Current Value (After Depreciation)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@ -557,7 +583,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-09 12:22:05.223886",
|
||||
"modified": "2016-03-11 12:23:37.114298",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Asset",
|
||||
|
@ -10,14 +10,20 @@ from frappe.model.document import Document
|
||||
|
||||
class Asset(Document):
|
||||
def validate(self):
|
||||
self.set_status()
|
||||
self.validate_fixed_asset_item()
|
||||
self.validate_asset_values()
|
||||
self.set_depreciation_settings()
|
||||
self.make_depreciation_schedule()
|
||||
self.validate_depreciation_settings_in_company()
|
||||
|
||||
def on_submit(self):
|
||||
self.set_status()
|
||||
|
||||
def on_cancel(self):
|
||||
self.validate_cancellation()
|
||||
self.delete_depreciation_entries()
|
||||
self.set_status()
|
||||
|
||||
def validate_fixed_asset_item(self):
|
||||
item = frappe.get_doc("Item", self.item_code)
|
||||
@ -49,7 +55,7 @@ class Asset(Document):
|
||||
|
||||
def make_depreciation_schedule(self):
|
||||
self.schedules = []
|
||||
if not self.get("schedules") and self.status == "Available":
|
||||
if not self.get("schedules"):
|
||||
accumulated_depreciation = 0
|
||||
value_after_depreciation = flt(self.current_value)
|
||||
for n in xrange(self.number_of_depreciations):
|
||||
@ -71,8 +77,8 @@ class Asset(Document):
|
||||
depreciation_amount = (flt(self.current_value) -
|
||||
flt(self.expected_value_after_useful_life)) / cint(self.number_of_depreciations)
|
||||
else:
|
||||
factor = 200 / cint(self.number_of_depreciations)
|
||||
depreciation_amount = depreciable_value * factor / 100
|
||||
factor = 200.0 / cint(self.number_of_depreciations)
|
||||
depreciation_amount = flt(depreciable_value * factor / 100, 0)
|
||||
|
||||
value_after_depreciation = flt(depreciable_value) - depreciation_amount
|
||||
if value_after_depreciation < flt(self.expected_value_after_useful_life):
|
||||
@ -81,9 +87,11 @@ class Asset(Document):
|
||||
return depreciation_amount
|
||||
|
||||
def validate_cancellation(self):
|
||||
if self.status != "Available":
|
||||
frappe.throw(_("Asset {0} cannot be cancelled, as it is already {1}")
|
||||
.format(self.name, self.status))
|
||||
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
|
||||
frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))
|
||||
|
||||
if self.purchase_invoice:
|
||||
frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
|
||||
|
||||
def delete_depreciation_entries(self):
|
||||
total_depreciation_amount = 0
|
||||
@ -94,4 +102,28 @@ class Asset(Document):
|
||||
d.db_set("journal_entry", None)
|
||||
total_depreciation_amount += flt(d.depreciation_amount)
|
||||
self.db_set("current_value", (self.current_value - total_depreciation_amount))
|
||||
|
||||
|
||||
def validate_depreciation_settings_in_company(self):
|
||||
company = frappe.get_doc("Company", self.company)
|
||||
for field in ("accumulated_depreciation_account", "depreciation_expense_account",
|
||||
"disposal_account", "depreciation_cost_center"):
|
||||
if not company.get(field):
|
||||
frappe.throw(_("Please set {0} in Company {1}")
|
||||
.format(company.meta.get_label(field), self.company))
|
||||
|
||||
def set_status(self, status=None):
|
||||
if not status:
|
||||
if self.docstatus == 0:
|
||||
status = "Draft"
|
||||
elif self.docstatus == 1:
|
||||
status = "Submitted"
|
||||
if self.journal_entry_for_scrap:
|
||||
status = "Scrapped"
|
||||
elif flt(self.current_value) <= flt(self.expected_value_after_useful_life):
|
||||
status = "Fully Depreciated"
|
||||
elif flt(self.current_value) < flt(self.gross_purchase_amount):
|
||||
status = 'Partially Depreciated'
|
||||
elif self.docstatus == 2:
|
||||
status = "Cancelled"
|
||||
|
||||
frappe.db.set_value(self.doctype, self.name, "status", status)
|
@ -17,7 +17,8 @@ def get_depreciable_assets(date):
|
||||
return frappe.db.sql_list("""select a.name
|
||||
from tabAsset a, `tabDepreciation Schedule` ds
|
||||
where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s
|
||||
and a.status = 'Available' and ifnull(ds.journal_entry, '')=''""", date)
|
||||
and a.status in ('Submitted', 'Partially Depreciated')
|
||||
and ifnull(ds.journal_entry, '')=''""", date)
|
||||
|
||||
def make_depreciation_entry(asset_name, date=None):
|
||||
if not date:
|
||||
@ -26,6 +27,8 @@ def make_depreciation_entry(asset_name, date=None):
|
||||
asset = frappe.get_doc("Asset", asset_name)
|
||||
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
|
||||
get_depreciation_accounts(asset)
|
||||
|
||||
depreciation_cost_center = frappe.db.get_value("Company", asset.company, "depreciation_cost_center")
|
||||
|
||||
for d in asset.get("schedules"):
|
||||
if not d.journal_entry and getdate(d.schedule_date) <= getdate(date):
|
||||
@ -34,7 +37,7 @@ def make_depreciation_entry(asset_name, date=None):
|
||||
je.posting_date = d.schedule_date
|
||||
je.company = asset.company
|
||||
je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount)
|
||||
|
||||
|
||||
je.append("accounts", {
|
||||
"account": accumulated_depreciation_account,
|
||||
"credit_in_account_currency": d.depreciation_amount,
|
||||
@ -46,15 +49,18 @@ def make_depreciation_entry(asset_name, date=None):
|
||||
"account": depreciation_expense_account,
|
||||
"debit_in_account_currency": d.depreciation_amount,
|
||||
"reference_type": "Asset",
|
||||
"reference_name": asset.name
|
||||
"reference_name": asset.name,
|
||||
"cost_center": depreciation_cost_center
|
||||
})
|
||||
|
||||
|
||||
je.flags.ignore_permissions = True
|
||||
je.submit()
|
||||
|
||||
d.db_set("journal_entry", je.name)
|
||||
asset.current_value -= d.depreciation_amount
|
||||
frappe.db.set_value("Asset", asset_name, "current_value", asset.current_value)
|
||||
|
||||
asset.db_set("current_value", asset.current_value)
|
||||
asset.set_status()
|
||||
|
||||
def get_depreciation_accounts(asset):
|
||||
accounts = frappe.db.sql("""select fixed_asset_account, accumulated_depreciation_account,
|
||||
@ -84,8 +90,10 @@ def get_depreciation_accounts(asset):
|
||||
def scrap_asset(asset_name):
|
||||
asset = frappe.get_doc("Asset", asset_name)
|
||||
|
||||
if asset.docstatus != 1 or asset.status != 'Available':
|
||||
frappe.throw(_("Asset {0} must be submitted and available").format(asset.name))
|
||||
if asset.docstatus != 1:
|
||||
frappe.throw(_("Asset {0} must be submitted").format(asset.name))
|
||||
elif asset.status in ("Cancelled", "Sold", "Scrapped"):
|
||||
frappe.throw(_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status))
|
||||
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.voucher_type = "Journal Entry"
|
||||
@ -103,12 +111,23 @@ def scrap_asset(asset_name):
|
||||
je.flags.ignore_permissions = True
|
||||
je.submit()
|
||||
|
||||
frappe.db.set_value("Asset", asset_name, "status", "Scrapped")
|
||||
frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
|
||||
asset.set_status("Scrapped")
|
||||
|
||||
@frappe.whitelist()
|
||||
def restore_asset(asset_name):
|
||||
asset = frappe.get_doc("Asset", asset_name)
|
||||
|
||||
je = asset.journal_entry_for_scrap
|
||||
asset.db_set("journal_entry_for_scrap", None)
|
||||
frappe.get_doc("Journal Entry", je).cancel()
|
||||
|
||||
asset.set_status()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
||||
fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset)
|
||||
disposal_account, disposal_cost_center = get_disposal_account_and_cost_center(asset.company)
|
||||
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
|
||||
accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(asset.current_value)
|
||||
|
||||
gl_entries = [
|
||||
@ -129,7 +148,7 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
||||
debit_or_credit = "debit" if profit_amount < 0 else "credit"
|
||||
gl_entries.append({
|
||||
"account": disposal_account,
|
||||
"cost_center": disposal_cost_center,
|
||||
"cost_center": depreciation_cost_center,
|
||||
debit_or_credit: abs(profit_amount),
|
||||
debit_or_credit + "_in_account_currency": abs(profit_amount)
|
||||
})
|
||||
@ -137,8 +156,12 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
||||
return gl_entries
|
||||
|
||||
def get_disposal_account_and_cost_center(company):
|
||||
disposal_account, disposal_cost_center = frappe.db.get_value("Company", company,
|
||||
["disposal_account", "disposal_cost_center"])
|
||||
if not disposal_account or not disposal_cost_center:
|
||||
frappe.throw(_("Please set 'Asset Disposal Account' and 'Asset Disposal Cost Center' in Company {0}").format(company))
|
||||
return disposal_account, disposal_cost_center
|
||||
disposal_account, depreciation_cost_center = frappe.db.get_value("Company", company,
|
||||
["disposal_account", "depreciation_cost_center"])
|
||||
|
||||
if not disposal_account:
|
||||
frappe.throw(_("Please set 'Asset Disposal Account' in Company {0}").format(company))
|
||||
if not depreciation_cost_center:
|
||||
frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company))
|
||||
|
||||
return disposal_account, depreciation_cost_center
|
@ -5,9 +5,13 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from frappe.utils import cstr
|
||||
from erpnext.accounts.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
|
||||
class TestAsset(unittest.TestCase):
|
||||
def setUp(self):
|
||||
set_depreciation_settings_in_company()
|
||||
create_asset()
|
||||
|
||||
def test_fixed_asset_must_be_non_stock_item(self):
|
||||
@ -15,11 +19,128 @@ class TestAsset(unittest.TestCase):
|
||||
item.is_stock_item = 1
|
||||
self.assertRaises(frappe.ValidationError, item.save)
|
||||
|
||||
def test_asset_purchase(self):
|
||||
asset = create_asset()
|
||||
def test_schedule_for_straight_line_method(self):
|
||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||
|
||||
self.assertEqual(asset.current_value, 100000)
|
||||
|
||||
self.assertEqual(asset.status, "Draft")
|
||||
|
||||
expected_schedules = [
|
||||
["2015-12-31", 30000, 30000],
|
||||
["2016-03-31", 30000, 60000],
|
||||
["2016-06-30", 30000, 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_double_declining_method(self):
|
||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||
asset.depreciation_method = "Double Declining Balance"
|
||||
asset.save()
|
||||
|
||||
expected_schedules = [
|
||||
["2015-12-31", 66667, 66667],
|
||||
["2016-03-31", 22222, 88889],
|
||||
["2016-06-30", 1111, 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_depreciation(self):
|
||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||
asset.submit()
|
||||
asset.load_from_db()
|
||||
self.assertEqual(asset.status, "Submitted")
|
||||
|
||||
post_depreciation_entries(date="2016-01-01")
|
||||
asset.load_from_db()
|
||||
|
||||
self.assertEqual(asset.status, "Partially Depreciated")
|
||||
|
||||
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("current_value"), 70000)
|
||||
|
||||
|
||||
def test_scrap_asset(self):
|
||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||
asset.submit()
|
||||
post_depreciation_entries(date="2016-01-01")
|
||||
|
||||
scrap_asset("Macbook Pro 1")
|
||||
|
||||
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("Macbook Pro 1")
|
||||
|
||||
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()
|
||||
post_depreciation_entries(date="2016-01-01")
|
||||
|
||||
si = create_sales_invoice(item_code="Macbook Pro", rate=25000, do_not_save=True)
|
||||
si.get("items")[0].asset = "Macbook Pro 1"
|
||||
si.submit()
|
||||
|
||||
self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Sold")
|
||||
|
||||
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", 45000.0, 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", "Macbook Pro 1", "status"), "Partially Depreciated")
|
||||
|
||||
def tearDown(self):
|
||||
asset = frappe.get_doc("Asset", "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")
|
||||
|
||||
frappe.delete_doc("Asset", "Macbook Pro 1")
|
||||
|
||||
def create_asset():
|
||||
if not frappe.db.exists("Asset Category", "Computers"):
|
||||
@ -33,6 +154,7 @@ def create_asset():
|
||||
"asset_name": "Macbook Pro 1",
|
||||
"asset_category": "Computers",
|
||||
"item_code": "Macbook Pro",
|
||||
"company": "_Test Company",
|
||||
"purchase_date": "2015-01-01",
|
||||
"next_depreciation_date": "2015-12-31",
|
||||
"gross_purchase_amount": 100000,
|
||||
@ -48,8 +170,8 @@ def create_asset():
|
||||
def create_asset_category():
|
||||
asset_category = frappe.new_doc("Asset Category")
|
||||
asset_category.asset_category_name = "Computers"
|
||||
asset_category.number_of_depreciations = 5
|
||||
asset_category.number_of_months_in_a_period = 12
|
||||
asset_category.number_of_depreciations = 3
|
||||
asset_category.number_of_months_in_a_period = 3
|
||||
asset_category.append("accounts", {
|
||||
"company": "_Test Company",
|
||||
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
||||
@ -73,4 +195,10 @@ def create_fixed_asset_item():
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
||||
|
||||
def set_depreciation_settings_in_company():
|
||||
company = frappe.get_doc("Company", "_Test Company")
|
||||
company.accumulated_depreciation_account = "_Test Accumulated Depreciations - _TC"
|
||||
company.depreciation_expense_account = "_Test Depreciations - _TC"
|
||||
company.disposal_account = "_Test Gain/Loss on Asset Disposal - _TC"
|
||||
company.depreciation_cost_center = "_Test Cost Center - _TC"
|
||||
company.save()
|
@ -18,7 +18,7 @@ class TestAssetCategory(unittest.TestCase):
|
||||
asset_category.append("accounts", {
|
||||
"company": "_Test Company",
|
||||
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
||||
"accumulated_depreciation_account": "_Test Accoumulated Depreciations - _TC",
|
||||
"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
|
||||
"depreciation_expense_account": "_Test Depreciations - _TC"
|
||||
})
|
||||
|
||||
|
@ -88,8 +88,8 @@ class GLEntry(Document):
|
||||
"Cost Center", self.cost_center, "company")
|
||||
|
||||
return self.cost_center_company[self.cost_center]
|
||||
|
||||
if self.cost_center and _get_cost_center_company() != self.company:
|
||||
|
||||
if self.cost_center and _get_cost_center_company() != self.company:
|
||||
frappe.throw(_("Cost Center {0} does not belong to Company {1}").format(self.cost_center, self.company))
|
||||
|
||||
def validate_party(self):
|
||||
|
@ -217,7 +217,7 @@ cur_frm.set_query("asset", "items", function(doc, cdt, cdn) {
|
||||
'item_code': d.item_code,
|
||||
'docstatus': 1,
|
||||
'company': doc.company,
|
||||
'status': 'Available'
|
||||
'status': 'Submitted'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -237,7 +237,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
def on_submit(self):
|
||||
self.check_prev_docstatus()
|
||||
self.post_asset_depreciation()
|
||||
self.validate_asset()
|
||||
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
||||
self.company, self.base_grand_total)
|
||||
@ -252,29 +252,30 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
self.update_project()
|
||||
|
||||
def post_asset_depreciation(self):
|
||||
def validate_asset(self):
|
||||
for d in self.get("items"):
|
||||
if frappe.db.get_value("Item", d.item_code, "is_fixed_asset"):
|
||||
if not d.asset:
|
||||
frappe.throw(_("Row #{0}: Asset is mandatory against a Fixed Asset Item").format(d.idx))
|
||||
else:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
self.validate_asset(asset, d)
|
||||
|
||||
super(PurchaseInvoice, self).validate_asset(asset, d)
|
||||
|
||||
if getdate(asset.purchase_date) != getdate(self.posting_date):
|
||||
frappe.throw(_("Purchase Date of asset {0} does not match with Purchase Invoice date")
|
||||
.format(d.asset))
|
||||
|
||||
if asset.supplier != self.supplier:
|
||||
frappe.throw(_("Supplier of asset {0} does not match with the supplier in the Purchase Invoice").format(d.asset))
|
||||
|
||||
if asset.status != "Available":
|
||||
frappe.throw(_("Row #{0}: Asset {1} is already {2}")
|
||||
.format(d.idx, d.asset, asset.status))
|
||||
|
||||
frappe.db.set_value("Asset", asset.name, "purchase_invoice",
|
||||
(self.name if self.docstatus==1 else None))
|
||||
|
||||
def validate_asset(self, asset, item_row):
|
||||
super(PurchaseInvoice, self).validate_asset(asset, item_row)
|
||||
|
||||
if getdate(asset.purchase_date) != getdate(self.posting_date):
|
||||
frappe.throw(_("Purchase Date of asset {0} does not match with Purchase Invoice date")
|
||||
.format(item_row.asset))
|
||||
|
||||
if asset.supplier != self.supplier:
|
||||
frappe.throw(_("Supplier of asset {0} does not match with the supplier in the Purchase Invoice")
|
||||
.format(item_row.asset))
|
||||
|
||||
|
||||
def make_gl_entries(self):
|
||||
auto_accounting_for_stock = \
|
||||
cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
|
||||
@ -441,7 +442,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
self.update_project()
|
||||
self.post_asset_depreciation()
|
||||
self.validate_asset()
|
||||
|
||||
def update_project(self):
|
||||
project_list = []
|
||||
|
@ -475,11 +475,11 @@ cur_frm.set_query("debit_to", function(doc) {
|
||||
cur_frm.set_query("asset", "items", function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
'item_code': d.item_code,
|
||||
'docstatus': 1,
|
||||
'company': doc.company,
|
||||
'status': 'Available'
|
||||
}
|
||||
filters: [
|
||||
["Asset", "item_code", "=", d.item_code],
|
||||
["Asset", "docstatus", "=", 1],
|
||||
["Asset", "status", "in", ["Submitted", "Partially Depreciated", "Fully Depreciated"]],
|
||||
["Asset", "company", "=", doc.company]
|
||||
]
|
||||
}
|
||||
});
|
@ -484,6 +484,13 @@ class SalesInvoice(SellingController):
|
||||
|
||||
if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
|
||||
throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
|
||||
|
||||
def validate_asset(self, asset, item_row):
|
||||
super(SalesInvoice, self).validate_asset(asset, item_row)
|
||||
|
||||
if self.docstatus == 1 and asset.status in ("Scrapped", "Cancelled", "Sold"):
|
||||
frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}")
|
||||
.format(item_row.idx, asset.name, asset.status))
|
||||
|
||||
def make_gl_entries(self, repost_future_gle=True):
|
||||
gl_entries = self.get_gl_entries()
|
||||
@ -582,7 +589,7 @@ class SalesInvoice(SellingController):
|
||||
for gle in fixed_asset_gl_entries:
|
||||
gl_entries.append(self.get_gl_dict(gle))
|
||||
|
||||
frappe.db.set_value("Asset", asset.name, "status", "Sold")
|
||||
asset.set_status("Sold" if self.docstatus==1 else None)
|
||||
else:
|
||||
account_currency = get_account_currency(item.income_account)
|
||||
gl_entries.append(
|
||||
|
@ -141,7 +141,7 @@ erpnext.company.setup_queries = function(frm) {
|
||||
["disposal_account", {"report_type": "Profit and Loss"}],
|
||||
["cost_center", {}],
|
||||
["round_off_cost_center", {}],
|
||||
["disposal_cost_center", {}]
|
||||
["depreciation_cost_center", {}]
|
||||
], function(i, v) {
|
||||
erpnext.company.set_custom_query(frm, v);
|
||||
});
|
||||
|
@ -1091,14 +1091,14 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "disposal_cost_center",
|
||||
"fieldname": "depreciation_cost_center",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Asset Disposal Cost Center",
|
||||
"label": "Asset Depreciation Cost Center",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Cost Center",
|
||||
@ -1387,7 +1387,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-03-09 12:06:12.189968",
|
||||
"modified": "2016-03-10 04:34:43.440914",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Company",
|
||||
@ -1536,6 +1536,5 @@
|
||||
],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"version": 0
|
||||
"sort_order": "ASC"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user