fixed asset depreciation
diff --git a/erpnext/accounts/doctype/asset/asset.js b/erpnext/accounts/doctype/asset/asset.js
index e961b7d..91d41e5 100644
--- a/erpnext/accounts/doctype/asset/asset.js
+++ b/erpnext/accounts/doctype/asset/asset.js
@@ -4,20 +4,37 @@
frappe.provide("erpnext.asset");
frappe.ui.form.on('Asset', {
- refresh: function(frm) {
- cur_frm.add_custom_button("Scrap", function() {
- erpnext.asset.scrap_asset();
+ onload: function(frm) {
+ frm.set_query("item_code", function() {
+ return {
+ "filters": {
+ "is_stock_item": 0,
+ "is_fixed_asset": 1,
+ "disabled": 0
+ }
+ };
});
},
+
+ refresh: function(frm) {
+ if(frm.doc.docstatus==1 && frm.doc.status=='Available') {
+ cur_frm.add_custom_button("Scrap", function() {
+ erpnext.asset.scrap_asset(frm);
+ });
+ }
+ }
});
-erpnext.asset.scrap_asset = function() {
+erpnext.asset.scrap_asset = function(frm) {
frappe.confirm(__("Do you really want to scrap this asset?"), function () {
frappe.call({
args: {
"asset_name": frm.doc.name
},
- method: "erpnext.accounts.doctype.asset.depreciation.scrap_asset"
+ method: "erpnext.accounts.doctype.asset.depreciation.scrap_asset",
+ callback: function(r) {
+ cur_frm.reload_doc();
+ }
})
})
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset/asset.json b/erpnext/accounts/doctype/asset/asset.json
index 760e00d..8c29c44 100644
--- a/erpnext/accounts/doctype/asset/asset.json
+++ b/erpnext/accounts/doctype/asset/asset.json
@@ -64,6 +64,32 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Item Code",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Item",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"default": "Available",
"fieldname": "status",
"fieldtype": "Select",
@@ -74,13 +100,13 @@
"in_list_view": 0,
"label": "Status",
"length": 0,
- "no_copy": 0,
+ "no_copy": 1,
"options": "Available\nSold\nScrapped",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -166,6 +192,32 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "fieldname": "purchase_invoice",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Purchase Invoice",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Purchase Invoice",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "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,
+ "collapsible": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -216,7 +268,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "default": "Straight Line",
+ "default": "",
"depends_on": "",
"fieldname": "depreciation_method",
"fieldtype": "Select",
@@ -244,15 +296,14 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "description": "The time period over which the company expects that the asset will be productive",
- "fieldname": "useful_life",
+ "fieldname": "number_of_depreciations",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Useful Life (Years)",
+ "label": "Number of Depreciations",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -270,14 +321,14 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "start_depreciation_from_purchase_date",
- "fieldtype": "Check",
+ "fieldname": "number_of_months_in_a_period",
+ "fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Start Depreciation from Purchase Date",
+ "label": "Number of Months in a Period",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -295,6 +346,32 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "depends_on": "",
+ "fieldname": "next_depreciation_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Next Depreciation Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"hidden": 0,
@@ -319,16 +396,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "gross_value",
+ "fieldname": "gross_purchase_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Gross Value",
+ "label": "Gross Purchase Amount",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -344,17 +422,18 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "description": "The estimated resale value of an asset at the end of its useful life",
- "fieldname": "salvage_value",
- "fieldtype": "Data",
+ "description": "",
+ "fieldname": "expected_value_after_useful_life",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Salvage Value",
+ "label": "Expected Value After Useful Life",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -369,7 +448,33 @@
{
"allow_on_submit": 0,
"bold": 0,
- "collapsible": 1,
+ "collapsible": 0,
+ "fieldname": "current_value",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Current Value (After Depreciation)",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"fieldname": "section_break_14",
"fieldtype": "Section Break",
"hidden": 0,
@@ -404,13 +509,38 @@
"in_list_view": 0,
"label": "Depreciation Schedules",
"length": 0,
- "no_copy": 0,
+ "no_copy": 1,
"options": "Depreciation Schedule",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Amended From",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Asset",
+ "permlevel": 0,
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -423,11 +553,11 @@
"idx": 0,
"in_create": 0,
"in_dialog": 0,
- "is_submittable": 0,
+ "is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-03-03 17:34:00.991228",
+ "modified": "2016-03-09 12:22:05.223886",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Asset",
@@ -437,7 +567,7 @@
{
"amend": 0,
"apply_user_permissions": 0,
- "cancel": 0,
+ "cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
@@ -451,7 +581,7 @@
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
- "submit": 0,
+ "submit": 1,
"write": 1
}
],
diff --git a/erpnext/accounts/doctype/asset/asset.py b/erpnext/accounts/doctype/asset/asset.py
index 0479d0a..fb1502e 100644
--- a/erpnext/accounts/doctype/asset/asset.py
+++ b/erpnext/accounts/doctype/asset/asset.py
@@ -5,61 +5,90 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import flt, add_years
+from frappe.utils import flt, add_months, cint
from frappe.model.document import Document
class Asset(Document):
def validate(self):
- self.validate_mandatory()
+ self.validate_fixed_asset_item()
+ self.validate_asset_values()
+ self.set_depreciation_settings()
self.make_depreciation_schedule()
-
- def validate_mandatory(self):
- if not self.useful_life:
- self.useful_life = frappe.db.get_value("Asset Category", self.asset_category, "useful_life")
- if not self.useful_life:
- frappe.throw(_("Useful Life is mandatory"))
-
+
+ def on_cancel(self):
+ self.validate_cancellation()
+ self.delete_depreciation_entries()
+
+ def validate_fixed_asset_item(self):
+ item = frappe.get_doc("Item", self.item_code)
+ if item.disabled:
+ frappe.throw(_("Item {0} has been disabled").format(self.item_code))
+ if item.is_stock_item:
+ frappe.throw(_("Item {0} must be a non-stock item").format(self.item_code))
+
+ def validate_asset_values(self):
+ if flt(self.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
+ frappe.throw(_("Expected Value After Useful Life must be less than Gross Purchase Amount"))
+
+ if not self.current_value:
+ self.current_value = flt(self.gross_purchase_amount)
+ else:
+ if flt(self.current_value) > flt(self.gross_purchase_amount):
+ frappe.throw(_("Current Value After Depreciation must be less than equal to {0}")
+ .format(flt(self.gross_purchase_amount)))
+
+ def set_depreciation_settings(self):
+ asset_category = frappe.get_doc("Asset Category", self.asset_category)
+
+ for field in ("depreciation_method", "number_of_depreciations", "number_of_months_in_a_period"):
+ if not self.get(field):
+ self.set(field, asset_category.get(field))
+
def make_depreciation_schedule(self):
self.schedules = []
if not self.get("schedules") and self.status == "Available":
- depreciation_method = self.get_depreciation_method()
-
accumulated_depreciation = 0
- value_after_depreciation = flt(self.gross_value)
- for n in xrange(self.useful_life):
- depreciation_date = add_years(self.purchase_date,
- n if self.start_depreciation_from_purchase_date else n+1)
- depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
- depreciation_method)
+ value_after_depreciation = flt(self.current_value)
+ for n in xrange(self.number_of_depreciations):
+ schedule_date = add_months(self.next_depreciation_date,
+ n * cint(self.number_of_months_in_a_period))
+
+ depreciation_amount = self.get_depreciation_amount(value_after_depreciation)
self.append("schedules", {
- "depreciation_date": depreciation_date,
+ "schedule_date": schedule_date,
"depreciation_amount": depreciation_amount,
"accumulated_depreciation_amount": accumulated_depreciation + depreciation_amount
})
-
- def get_depreciation_method(self):
- depreciation_method = self.depreciation_method or \
- frappe.db.get_value("Asset Category", self.asset_category, "depreciation_method") or \
- frappe.db.get_value("Company", self.company, "depreciation_method")
-
- if not depreciation_method:
- frappe.throw(_("Please set Depreciation Method in Asset Category {0} or Company {1}")
- .format(self.asset_category, self.company))
-
- def get_depreciation_amount(self, depreciable_value, depreciation_method=None):
- if not depreciation_method:
- depreciation_method = self.get_depreciation_method()
-
- if depreciation_method == "Straight Line":
- depreciation_amount = (flt(self.gross_value) - flt(self.salvage_value)) / flt(self.useful_life)
+ accumulated_depreciation += flt(depreciation_amount)
+ value_after_depreciation -= flt(depreciation_amount)
+
+ def get_depreciation_amount(self, depreciable_value):
+ if self.depreciation_method == "Straight Line":
+ depreciation_amount = (flt(self.current_value) -
+ flt(self.expected_value_after_useful_life)) / cint(self.number_of_depreciations)
else:
- factor = 200 / self.useful_life
+ factor = 200 / cint(self.number_of_depreciations)
depreciation_amount = depreciable_value * factor / 100
-
+
value_after_depreciation = flt(depreciable_value) - depreciation_amount
- if value_after_depreciation < self.salvage_value:
- depreciation_amount = flt(depreciable_value) - flt(self.salvage_value)
-
+ if value_after_depreciation < flt(self.expected_value_after_useful_life):
+ depreciation_amount = flt(depreciable_value) - flt(self.expected_value_after_useful_life)
+
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))
+
+ def delete_depreciation_entries(self):
+ total_depreciation_amount = 0
+ for d in self.get("schedules"):
+ if d.journal_entry:
+ frappe.get_doc("Journal Entry", d.journal_entry).cancel()
+
+ d.db_set("journal_entry", None)
+ total_depreciation_amount += flt(d.depreciation_amount)
+ self.db_set("current_value", (self.current_value - total_depreciation_amount))
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset/depreciation.py b/erpnext/accounts/doctype/asset/depreciation.py
index 48a964a..bd2c74f 100644
--- a/erpnext/accounts/doctype/asset/depreciation.py
+++ b/erpnext/accounts/doctype/asset/depreciation.py
@@ -5,113 +5,140 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import flt, today
+from frappe.utils import flt, today, getdate
-
-# Depreciate
-#------------
-
-def post_depreciation_entries(self):
- assets = get_depreciable_assets()
- for asset in assets:
- depreciate_asset(asset.asset_name, asset.depreciation_amount, asset.schedule_row)
-
-def get_depreciable_assets(date=None):
+def post_depreciation_entries(date=None):
if not date:
date = today()
-
- return frappe.db.sql("""
- select a.name as asset_name, ds.depreciation_amount, ds.name as schedule_row
+ for asset in get_depreciable_assets(date):
+ make_depreciation_entry(asset, date)
+
+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 ds.depreciation_date=%s
- and a.status = 'Available' and ds.posted=0 and a.docstatus < 2""", date, as_dict=1)
-
-def depreciate_asset(asset_name, depreciation_amount, schedule_row):
- asset = frappe.get_doc("Asset", asset_name)
- accumulated_depreciation_account, depreciation_expense_account = get_depreciation_accounts(asset)
-
- je = frappe.new_doc("Journal Entry")
- je.voucher_type = "Depreciation Entry"
- je.posting_date = today()
- je.company = asset.company
- je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, depreciation_amount)
-
- je.append("accounts", {
- "account": accumulated_depreciation_account,
- "credit_in_account_currency": depreciation_amount,
- "reference_type": "Asset",
- "reference_name": asset.name
- })
-
- je.append("accounts", {
- "account": depreciation_expense_account,
- "debit_in_account_currency": depreciation_amount,
- "reference_type": "Asset",
- "reference_name": asset.name
- })
-
- je.flags.ignore_permissions = True
- je.submit()
-
- frappe.db.sql("""update `tabDepreciation Schedule`
- set posted=1, journal_entry=%s, modified=now(), modified_by=%s where name=%s""",
- (je.name, frappe.session.user, schedule_row))
+ where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s
+ and a.status = 'Available' and ifnull(ds.journal_entry, '')=''""", date)
+def make_depreciation_entry(asset_name, date=None):
+ if not date:
+ date = today()
+
+ asset = frappe.get_doc("Asset", asset_name)
+ fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
+ get_depreciation_accounts(asset)
+
+ for d in asset.get("schedules"):
+ if not d.journal_entry and getdate(d.schedule_date) <= getdate(date):
+ je = frappe.new_doc("Journal Entry")
+ je.voucher_type = "Depreciation Entry"
+ 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,
+ "reference_type": "Asset",
+ "reference_name": asset.name
+ })
+
+ je.append("accounts", {
+ "account": depreciation_expense_account,
+ "debit_in_account_currency": d.depreciation_amount,
+ "reference_type": "Asset",
+ "reference_name": asset.name
+ })
+
+ 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)
+
def get_depreciation_accounts(asset):
- accumulated_depreciation_account, depreciation_expense_account = frappe.db.get_value("Asset Category",
- asset.asset_category, ["accumulated_depreciation_account", "depreciation_expense_account"])
-
+ accounts = frappe.db.sql("""select fixed_asset_account, accumulated_depreciation_account,
+ depreciation_expense_account from `tabAsset Category Account`
+ where parent=%s and company=%s""", (asset.asset_category, asset.company), as_dict=1)[0]
+
+ fixed_asset_account = accounts.fixed_asset_account
+ accumulated_depreciation_account = accounts.accumulated_depreciation_account
+ depreciation_expense_account = accounts.depreciation_expense_account
+
if not accumulated_depreciation_account or not depreciation_expense_account:
accounts = frappe.db.get_value("Company", asset.company,
["accumulated_depreciation_account", "depreciation_expense_account"])
+
if not accumulated_depreciation_account:
accumulated_depreciation_account = accounts[0]
if not depreciation_expense_account:
depreciation_expense_account = accounts[1]
- if not accumulated_depreciation_account or not depreciation_expense_account:
+ if not fixed_asset_account or not accumulated_depreciation_account or not depreciation_expense_account:
frappe.throw(_("Please set Depreciation related Accounts in Asset Category {0} or Company {1}")
.format(asset.asset_category, asset.company))
- return accumulated_depreciation_account, depreciation_expense_account
+ return fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account
-# Scrap
-#---------
-
@frappe.whitelist()
def scrap_asset(asset_name):
asset = frappe.get_doc("Asset", asset_name)
- asset.status = "Scrapped"
- accumulated_depr_amount = frappe.db.sql("""select accumulated_depreciation_amount
- from `tabDepreciation Schedule`
- where parent=%s and posted=1
- order by depreciation_date desc limit 1""")
-
- accumulated_depr_amount = flt(accumulated_depr_amount[0][0]) if accumulated_depr_amount else 0
-
- net_value_after_depreciation = flt(asset.gross_value) - accumulated_depr_amount
-
+ if asset.docstatus != 1 or asset.status != 'Available':
+ frappe.throw(_("Asset {0} must be submitted and available").format(asset.name))
+
je = frappe.new_doc("Journal Entry")
- je.voucher_type = "Depreciation Entry"
+ je.voucher_type = "Journal Entry"
je.posting_date = today()
je.company = asset.company
- je.remark = "Disposal Entry for asset {0}".format(asset_name)
+ je.remark = "Scrap Entry for asset {0}".format(asset_name)
- # je.append("accounts", {
- # "account": accumulated_depreciation_account,
- # "credit_in_account_currency": depreciation_amount,
- # "reference_type": "Asset",
- # "reference_name": asset.name
- # })
- #
- # je.append("accounts", {
- # "account": depreciation_expense_account,
- # "debit_in_account_currency": depreciation_amount,
- # "reference_type": "Asset",
- # "reference_name": asset.name
- # })
+ for entry in get_gl_entries_on_asset_disposal(asset):
+ entry.update({
+ "reference_type": "Asset",
+ "reference_name": asset_name
+ })
+ je.append("accounts", entry)
je.flags.ignore_permissions = True
- je.submit()
\ No newline at end of file
+ je.submit()
+
+ frappe.db.set_value("Asset", asset_name, "status", "Scrapped")
+
+@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)
+ accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(asset.current_value)
+
+ gl_entries = [
+ {
+ "account": fixed_asset_account,
+ "credit_in_account_currency": asset.gross_purchase_amount,
+ "credit": asset.gross_purchase_amount
+ },
+ {
+ "account": accumulated_depr_account,
+ "debit_in_account_currency": accumulated_depr_amount,
+ "debit": accumulated_depr_amount
+ }
+ ]
+
+ profit_amount = flt(selling_amount) - flt(asset.current_value)
+ if flt(asset.current_value) and profit_amount:
+ debit_or_credit = "debit" if profit_amount < 0 else "credit"
+ gl_entries.append({
+ "account": disposal_account,
+ "cost_center": disposal_cost_center,
+ debit_or_credit: abs(profit_amount),
+ debit_or_credit + "_in_account_currency": abs(profit_amount)
+ })
+
+ 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
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_category/asset_category.js b/erpnext/accounts/doctype/asset_category/asset_category.js
index 84f0dfc..862a202 100644
--- a/erpnext/accounts/doctype/asset_category/asset_category.js
+++ b/erpnext/accounts/doctype/asset_category/asset_category.js
@@ -1,8 +1,36 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-frappe.ui.form.on('Asset Category', {
- refresh: function(frm) {
+cur_frm.fields_dict['accounts'].grid.get_field('fixed_asset_account').get_query = function(doc, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ return {
+ "filters": {
+ "account_type": "Fixed Asset",
+ "root_type": "Asset",
+ "is_group": 0,
+ "company": d.company
+ }
+ };
+}
- }
-});
+cur_frm.fields_dict['accounts'].grid.get_field('accumulated_depreciation_account').get_query = function(doc, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ return {
+ "filters": {
+ "root_type": "Asset",
+ "is_group": 0,
+ "company": d.company
+ }
+ };
+}
+
+cur_frm.fields_dict['accounts'].grid.get_field('depreciation_expense_account').get_query = function(doc, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ return {
+ "filters": {
+ "root_type": "Expense",
+ "is_group": 0,
+ "company": d.company
+ }
+ };
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_category/asset_category.json b/erpnext/accounts/doctype/asset_category/asset_category.json
index 9338e22..9d8bd00 100644
--- a/erpnext/accounts/doctype/asset_category/asset_category.json
+++ b/erpnext/accounts/doctype/asset_category/asset_category.json
@@ -38,30 +38,6 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "section_break_2",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"default": "Straight Line",
"fieldname": "depreciation_method",
"fieldtype": "Select",
@@ -80,7 +56,7 @@
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -89,32 +65,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "useful_life",
- "fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "label": "Useful Life (Years)",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "fieldname": "column_break_5",
+ "fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -138,17 +89,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "fixed_asset_account",
- "fieldtype": "Link",
+ "fieldname": "number_of_depreciations",
+ "fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Fixed Asset Account",
+ "label": "Number of Depreciations",
"length": 0,
"no_copy": 0,
- "options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -164,17 +114,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "accumulated_depreciation_account",
- "fieldtype": "Link",
+ "fieldname": "number_of_months_in_a_period",
+ "fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Accumulated Depreciation Account",
+ "label": "Number of Months in a Period",
"length": 0,
"no_copy": 0,
- "options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -190,24 +139,49 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "depreciation_expense_account",
- "fieldtype": "Link",
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Depreciation Expense Account",
+ "label": "Accounts",
"length": 0,
"no_copy": 0,
- "options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "accounts",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Accounts",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Asset Category Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -222,7 +196,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-03-03 15:17:44.877003",
+ "modified": "2016-03-07 19:01:19.265210",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Asset Category",
diff --git a/erpnext/accounts/doctype/asset_category/asset_category.py b/erpnext/accounts/doctype/asset_category/asset_category.py
index 8f922d1..f139499 100644
--- a/erpnext/accounts/doctype/asset_category/asset_category.py
+++ b/erpnext/accounts/doctype/asset_category/asset_category.py
@@ -4,7 +4,12 @@
from __future__ import unicode_literals
import frappe
+from frappe import _
from frappe.model.document import Document
class AssetCategory(Document):
- pass
+ def validate(self):
+ for field in ("depreciation_method", "number_of_depreciations",
+ "number_of_months_in_a_period", "accounts"):
+ if not self.get(field):
+ frappe.throw(_("{0} is mandatory").format(self.meta.get_label(field)))
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_category_account/__init__.py b/erpnext/accounts/doctype/asset_category_account/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_category_account/__init__.py
diff --git a/erpnext/accounts/doctype/asset_category_account/asset_category_account.json b/erpnext/accounts/doctype/asset_category_account/asset_category_account.json
new file mode 100644
index 0000000..5144e85
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_category_account/asset_category_account.json
@@ -0,0 +1,136 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "creation": "2016-03-07 15:55:18.806409",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Company",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "fixed_asset_account",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Fixed Asset Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "accumulated_depreciation_account",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Accumulated Depreciation Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "depreciation_expense_account",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Depreciation Expense Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-03-07 19:02:09.879979",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Asset Category Account",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_category_account/asset_category_account.py b/erpnext/accounts/doctype/asset_category_account/asset_category_account.py
new file mode 100644
index 0000000..67925f4
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_category_account/asset_category_account.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class AssetCategoryAccount(Document):
+ pass
diff --git a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json
index 89685cc..50fba88 100644
--- a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json
+++ b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json
@@ -13,21 +13,21 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "depreciation_date",
+ "fieldname": "schedule_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
- "label": "Depreciation Date",
+ "label": "Schedule Date",
"length": 0,
- "no_copy": 0,
+ "no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -47,6 +47,31 @@
"in_list_view": 1,
"label": "Depreciation Amount",
"length": 0,
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
@@ -54,7 +79,7 @@
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -72,12 +97,13 @@
"in_list_view": 1,
"label": "Accumulated Depreciation Amount",
"length": 0,
- "no_copy": 0,
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -88,47 +114,22 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "posted",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "label": "Posted",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"fieldname": "journal_entry",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"label": "Journal Entry",
"length": 0,
- "no_copy": 0,
+ "no_copy": 1,
"options": "Journal Entry",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -145,7 +146,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2016-03-03 14:50:39.794061",
+ "modified": "2016-03-09 12:21:27.938215",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Depreciation Schedule",
diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
index 9277da5..28b57bd 100644
--- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
+++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
@@ -16,6 +16,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Account",
@@ -44,6 +45,7 @@
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Account Type",
@@ -68,6 +70,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Account Balance",
@@ -96,6 +99,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Cost Center",
@@ -124,6 +128,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -146,6 +151,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Party Type",
@@ -170,6 +176,7 @@
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Party",
@@ -194,6 +201,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Party Balance",
@@ -221,6 +229,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Currency",
@@ -245,6 +254,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Account Currency",
@@ -270,6 +280,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -293,6 +304,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Exchange Rate",
@@ -317,6 +329,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Amount",
@@ -340,6 +353,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Debit",
@@ -365,6 +379,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Debit in Company Currency",
@@ -392,6 +407,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -414,6 +430,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Credit",
@@ -439,6 +456,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Credit in Company Currency",
@@ -466,6 +484,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference",
@@ -489,12 +508,13 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Type",
"length": 0,
"no_copy": 0,
- "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim",
+ "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -514,6 +534,7 @@
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Reference Name",
@@ -539,6 +560,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -561,6 +583,7 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Is Advance",
@@ -587,6 +610,7 @@
"fieldtype": "Text",
"hidden": 1,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Against Account",
@@ -614,12 +638,13 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2015-12-02 04:14:37.571883",
+ "modified": "2016-03-07 19:10:27.135795",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",
"owner": "Administrator",
"permissions": [],
"read_only": 0,
- "read_only_onload": 0
+ "read_only_onload": 0,
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 8ab7651..0143a4f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -210,6 +210,18 @@
}
});
+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'
+ }
+ }
+});
+
cur_frm.cscript.expense_account = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.idx == 1 && d.expense_account){
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 5edfcb9..06b2ece 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -253,19 +253,28 @@
self.update_project()
def post_asset_depreciation(self):
- from erpnext.accounts.doctype.asset.asset import depreciate_asset
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)
- if asset.start_depreciation_from_purchase_date:
- for schedule in asset.get("schedules"):
- if schedule.depreciation_date == asset.purchase_date:
- depreciate_asset(asset.name, schedule.depreciation_amount, schedule.name)
- break
-
+ self.validate_asset(asset, d)
+
+ 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"))
@@ -432,6 +441,7 @@
self.make_gl_entries_on_cancel()
self.update_project()
+ self.post_asset_depreciation()
def update_project(self):
project_list = []
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 89af721..265e697 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -471,3 +471,15 @@
}
}
});
+
+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'
+ }
+ }
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 7b97013..9758067 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -13,6 +13,7 @@
from erpnext.controllers.selling_controller import SellingController
from erpnext.accounts.utils import get_account_currency
from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
+from erpnext.accounts.doctype.asset.depreciation import get_gl_entries_on_asset_disposal
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -59,6 +60,7 @@
self.validate_advance_jv("Sales Order")
self.add_remarks()
self.validate_write_off_account()
+ self.set_income_account_for_fixed_assets()
if cint(self.is_pos):
self.validate_pos()
@@ -447,6 +449,17 @@
msgprint(_("POS Profile required to make POS Entry"), raise_exception=True)
return warehouse
+
+ def set_income_account_for_fixed_assets(self):
+ disposal_account = None
+ for d in self.get("items"):
+ if frappe.db.get_value("Item", d.item_code, "is_fixed_asset"):
+ if not disposal_account:
+ disposal_account = frappe.db.get_value("Company", self.company, "disposal_account")
+ if not disposal_account:
+ frappe.throw(_("Please mention 'Gain/Loss Account on Asset Disposal' in Company"))
+
+ d.income_account = disposal_account
def on_update(self):
if cint(self.is_pos) == 1:
@@ -557,17 +570,31 @@
# income account gl entries
for item in self.get("items"):
if flt(item.base_net_amount):
- account_currency = get_account_currency(item.income_account)
- gl_entries.append(
- self.get_gl_dict({
- "account": item.income_account,
- "against": self.customer,
- "credit": item.base_net_amount,
- "credit_in_account_currency": item.base_net_amount \
- if account_currency==self.company_currency else item.net_amount,
- "cost_center": item.cost_center
- }, account_currency)
- )
+ if frappe.db.get_value("Item", item.item_code, "is_fixed_asset"):
+ if not item.asset:
+ frappe.throw(_("Row #{0}: Asset is mandatory against a Fixed Asset Item")
+ .format(item.idx))
+ else:
+ asset = frappe.get_doc("Asset", item.asset)
+ self.validate_asset(asset, item)
+
+ fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount)
+ for gle in fixed_asset_gl_entries:
+ gl_entries.append(self.get_gl_dict(gle))
+
+ frappe.db.set_value("Asset", asset.name, "status", "Sold")
+ else:
+ account_currency = get_account_currency(item.income_account)
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": item.income_account,
+ "against": self.customer,
+ "credit": item.base_net_amount,
+ "credit_in_account_currency": item.base_net_amount \
+ if account_currency==self.company_currency else item.net_amount,
+ "cost_center": item.cost_center
+ }, account_currency)
+ )
# expense account gl entries
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index e14f0da..3ab22c5 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -458,7 +458,20 @@
# Note: not validating with gle account because we don't have the account
# at quotation / sales order level and we shouldn't stop someone
# from creating a sales invoice if sales order is already created
-
+
+ def validate_asset(self, asset, item_row):
+ if asset.company != self.company:
+ frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}")
+ .format(item_row.idx, item_row.asset, self.company))
+
+ elif asset.item_code != item_row.item_code:
+ frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}")
+ .format(item_row.idx, item_row.asset, item_row.item_code))
+ elif asset.docstatus != 1:
+ frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(item_row.idx, item_row.asset))
+ elif item_row.qty > 1:
+ frappe.throw(_("Row #{0}: Qty must be 1, as item is linked to an asset").format(item_row.idx))
+
@frappe.whitelist()
def get_tax_rate(account_head):
return frappe.db.get_value("Account", account_head, "tax_rate")
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 0ccc82a..56c0d16 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -137,7 +137,8 @@
"erpnext.support.doctype.issue.issue.auto_close_tickets",
"erpnext.accounts.doctype.fiscal_year.fiscal_year.auto_create_fiscal_year",
"erpnext.hr.doctype.employee.employee.send_birthday_reminders",
- "erpnext.projects.doctype.task.task.set_tasks_as_overdue"
+ "erpnext.projects.doctype.task.task.set_tasks_as_overdue",
+ "erpnext.accounts.doctype.asset.depreciation.post_depreciation_entries"
]
}
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 01a2d1d..777fe1e 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -136,8 +136,12 @@
["default_expense_account", {"root_type": "Expense"}],
["default_income_account", {"root_type": "Income"}],
["round_off_account", {"root_type": "Expense"}],
+ ["accumulated_depreciation_account", {"root_type": "Asset"}],
+ ["depreciation_expense_account", {"root_type": "Expense"}],
+ ["disposal_account", {"report_type": "Profit and Loss"}],
["cost_center", {}],
- ["round_off_cost_center", {}]
+ ["round_off_cost_center", {}],
+ ["disposal_cost_center", {}]
], function(i, v) {
erpnext.company.set_custom_query(frm, v);
});
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 3de72fd..95b17c4 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -253,12 +253,11 @@
"no_copy": 0,
"options": "Terms and Conditions",
"permlevel": 0,
- "precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -990,18 +989,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "default": "Straight Line",
- "fieldname": "depreciation_method",
- "fieldtype": "Select",
+ "fieldname": "accumulated_depreciation_account",
+ "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Depreciation Method",
+ "label": "Accumulated Depreciation Account",
"length": 0,
- "no_copy": 0,
- "options": "Straight Line\nDouble Declining Balance",
+ "no_copy": 1,
+ "options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -1017,16 +1015,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "accumulated_depreciation_account",
+ "fieldname": "depreciation_expense_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Accumulated Depreciation Account",
+ "label": "Depreciation Expense Account",
"length": 0,
- "no_copy": 0,
+ "no_copy": 1,
"options": "Account",
"permlevel": 0,
"precision": "",
@@ -1067,16 +1065,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "depreciation_expense_account",
+ "fieldname": "disposal_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Depreciation Expense Account",
+ "label": "Gain/Loss Account on Asset Disposal",
"length": 0,
- "no_copy": 0,
+ "no_copy": 1,
"options": "Account",
"permlevel": 0,
"precision": "",
@@ -1093,17 +1091,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "gain_loss_account",
+ "fieldname": "disposal_cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Gain/Loss Account on Asset Sale/Disposal",
+ "label": "Asset Disposal Cost Center",
"length": 0,
- "no_copy": 0,
- "options": "Account",
+ "no_copy": 1,
+ "options": "Cost Center",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -1389,7 +1387,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-03-08 20:21:46.331870",
+ "modified": "2016-03-09 12:06:12.189968",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index e628d0d..99afe33 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -255,6 +255,36 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "default": "",
+ "depends_on": "",
+ "description": "",
+ "fieldname": "is_fixed_asset",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Is Fixed Asset",
+ "length": 0,
+ "no_copy": 0,
+ "oldfieldname": "is_asset_item",
+ "oldfieldtype": "Select",
+ "options": "",
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
@@ -604,36 +634,6 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "default": "",
- "depends_on": "eval:doc.is_stock_item",
- "description": "",
- "fieldname": "is_fixed_asset",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "label": "Is Fixed Asset",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "is_asset_item",
- "oldfieldtype": "Select",
- "options": "",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"depends_on": "is_stock_item",
"fieldname": "column_break1",
"fieldtype": "Column Break",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 39ef7e2..cc8886b 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -80,10 +80,12 @@
self.validate_variant_attributes()
self.validate_website_image()
self.make_thumbnail()
+ self.validate_fixed_asset_item()
if not self.get("__islocal"):
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
- self.old_website_item_groups = frappe.db.sql_list("""select item_group from `tabWebsite Item Group`
+ self.old_website_item_groups = frappe.db.sql_list("""select item_group
+ from `tabWebsite Item Group`
where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name)
def on_update(self):
@@ -566,6 +568,10 @@
if variant:
frappe.throw(_("Item variant {0} exists with same attributes")
.format(variant), ItemVariantExistsError)
+
+ def validate_fixed_asset_item(self):
+ if self.is_fixed_asset and self.is_stock_item:
+ frappe.throw(_("Fixed Asset Item must be a non-stock item"))
def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1):
if (not end_of_life) or (disabled is None):