Merge pull request #5262 from nabinhait/fixed_asset_update
Fixed asset graphs and movement
diff --git a/erpnext/accounts/doctype/asset/asset.js b/erpnext/accounts/doctype/asset/asset.js
index 0dfdb21..0479a4e 100644
--- a/erpnext/accounts/doctype/asset/asset.js
+++ b/erpnext/accounts/doctype/asset/asset.js
@@ -24,6 +24,7 @@
refresh: function(frm) {
frappe.ui.form.trigger("Asset", "is_existing_asset");
+ frm.toggle_display("next_depreciation_date", frm.doc.docstatus < 1);
if (frm.doc.docstatus==1) {
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
@@ -32,6 +33,10 @@
});
}
if (in_list(["Submitted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) {
+ frm.add_custom_button("Transfer Asset", function() {
+ erpnext.asset.transfer_asset(frm);
+ });
+
frm.add_custom_button("Scrap Asset", function() {
erpnext.asset.scrap_asset(frm);
});
@@ -45,9 +50,56 @@
erpnext.asset.restore_asset(frm);
});
}
+
+ frm.trigger("show_graph");
}
},
+ show_graph: function(frm) {
+ var x_intervals = ["x", frm.doc.purchase_date];
+ var asset_values = ["Asset Value", frm.doc.gross_purchase_amount];
+ var last_depreciation_date = frm.doc.purchase_date;
+
+ if(frm.doc.opening_accumulated_depreciation) {
+ last_depreciation_date = frappe.datetime.add_months(frm.doc.next_depreciation_date,
+ -1*frm.doc.frequency_of_depreciation);
+
+ x_intervals.push(last_depreciation_date);
+ asset_values.push(flt(frm.doc.gross_purchase_amount) -
+ flt(frm.doc.opening_accumulated_depreciation));
+ }
+
+ $.each(frm.doc.schedules || [], function(i, v) {
+ x_intervals.push(v.schedule_date);
+ asset_value = flt(frm.doc.gross_purchase_amount) - flt(v.accumulated_depreciation_amount);
+ if(v.journal_entry) {
+ last_depreciation_date = v.schedule_date;
+ asset_values.push(asset_value)
+ } else {
+ if (in_list(["Scrapped", "Sold"], frm.doc.status)) {
+ asset_values.push(null)
+ } else {
+ asset_values.push(asset_value)
+ }
+ }
+ })
+
+ if(in_list(["Scrapped", "Sold"], frm.doc.status)) {
+ x_intervals.push(frm.doc.disposal_date);
+ asset_values.push(0);
+ last_depreciation_date = frm.doc.disposal_date;
+ }
+
+ frm.dashboard.reset();
+ frm.dashboard.add_graph({
+ x: 'x',
+ columns: [x_intervals, asset_values],
+ regions: {
+ 'Asset Value': [{'start': last_depreciation_date, 'style':'dashed'}]
+ }
+ });
+ },
+
is_existing_asset: function(frm) {
frm.toggle_enable("supplier", frm.doc.is_existing_asset);
frm.toggle_reqd("next_depreciation_date", !frm.doc.is_existing_asset);
@@ -112,4 +164,55 @@
}
})
})
+}
+
+erpnext.asset.transfer_asset = function(frm) {
+ var dialog = new frappe.ui.Dialog({
+ title: __("Transfer Asset"),
+ fields: [
+ {
+ "label": __("Target Warehouse"),
+ "fieldname": "target_warehouse",
+ "fieldtype": "Link",
+ "options": "Warehouse",
+ "get_query": function () {
+ return {
+ filters: [["Warehouse", "company", "in", ["", cstr(frm.doc.company)]]]
+ }
+ },
+ "reqd": 1
+ },
+ {
+ "label": __("Date"),
+ "fieldname": "transfer_date",
+ "fieldtype": "Datetime",
+ "reqd": 1,
+ "default": frappe.datetime.now_datetime()
+ }
+ ]
+ });
+
+ dialog.set_primary_action(__("Transfer"), function() {
+ args = dialog.get_values();
+ if(!args) return;
+ dialog.hide();
+ return frappe.call({
+ type: "GET",
+ method: "erpnext.accounts.doctype.asset.asset.transfer_asset",
+ args: {
+ args: {
+ "asset": frm.doc.name,
+ "transaction_date": args.transfer_date,
+ "source_warehouse": frm.doc.warehouse,
+ "target_warehouse": args.target_warehouse,
+ "company": frm.doc.company
+ }
+ },
+ freeze: true,
+ callback: function(r) {
+ cur_frm.reload_doc();
+ }
+ })
+ });
+ dialog.show();
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset/asset.json b/erpnext/accounts/doctype/asset/asset.json
index 70c1c16..c272a58 100644
--- a/erpnext/accounts/doctype/asset/asset.json
+++ b/erpnext/accounts/doctype/asset/asset.json
@@ -97,7 +97,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
- "in_list_view": 0,
+ "in_list_view": 1,
"label": "Status",
"length": 0,
"no_copy": 1,
@@ -114,6 +114,31 @@
"unique": 0
},
{
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Image",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "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,
@@ -706,13 +731,14 @@
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 72,
+ "image_field": "image",
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-04-20 18:09:07.573716",
+ "modified": "2016-04-22 11:15:40.055518",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Asset",
diff --git a/erpnext/accounts/doctype/asset/asset.py b/erpnext/accounts/doctype/asset/asset.py
index da229fe..23bb08b 100644
--- a/erpnext/accounts/doctype/asset/asset.py
+++ b/erpnext/accounts/doctype/asset/asset.py
@@ -190,4 +190,17 @@
"qty": 1
})
si.set_missing_values()
- return si
\ No newline at end of file
+ return si
+
+@frappe.whitelist()
+def transfer_asset(args):
+ import json
+ args = json.loads(args)
+ movement_entry = frappe.new_doc("Asset Movement")
+ movement_entry.update(args)
+ movement_entry.insert()
+ movement_entry.submit()
+
+ frappe.db.commit()
+
+ frappe.msgprint(_("Asset Movement record {0} created").format("<a href='#Form/Asset Movement/{0}'>{0}</a>".format(movement_entry.name)))
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_movement/__init__.py b/erpnext/accounts/doctype/asset_movement/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_movement/__init__.py
diff --git a/erpnext/accounts/doctype/asset_movement/asset_movement.js b/erpnext/accounts/doctype/asset_movement/asset_movement.js
new file mode 100644
index 0000000..680eedc
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_movement/asset_movement.js
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Asset Movement', {
+ onload: function(frm) {
+ frm.add_fetch("asset", "warehouse", "source_warehouse");
+
+ frm.set_query("target_warehouse", function() {
+ return {
+ filters: [["Warehouse", "company", "in", ["", cstr(frm.doc.company)]]]
+ }
+ })
+
+ }
+});
diff --git a/erpnext/accounts/doctype/asset_movement/asset_movement.json b/erpnext/accounts/doctype/asset_movement/asset_movement.json
new file mode 100644
index 0000000..59b8823
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_movement/asset_movement.json
@@ -0,0 +1,274 @@
+{
+ "allow_copy": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "autoname": "AM-.#####",
+ "creation": "2016-04-25 18:00:23.559973",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "asset",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Asset",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Asset",
+ "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": "transaction_date",
+ "fieldtype": "Datetime",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Transaction 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": "company",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "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": "column_break_4",
+ "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": "",
+ "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": "source_warehouse",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Source Warehouse",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Warehouse",
+ "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": "target_warehouse",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Target Warehouse",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Warehouse",
+ "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": "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 Movement",
+ "permlevel": 0,
+ "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
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 1,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2016-04-25 19:14:08.853429",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Asset Movement",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_movement/asset_movement.py b/erpnext/accounts/doctype/asset_movement/asset_movement.py
new file mode 100644
index 0000000..574c499
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_movement/asset_movement.py
@@ -0,0 +1,48 @@
+# -*- 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 import _
+from frappe.model.document import Document
+
+class AssetMovement(Document):
+ def validate(self):
+ self.validate_asset()
+ self.validate_warehouses()
+
+ def validate_asset(self):
+ status, company = frappe.db.get_value("Asset", self.asset, ["status", "company"])
+ if status in ("Draft", "Scrapped", "Sold"):
+ frappe.throw(_("{0} asset cannot be transferred").format(status))
+
+ if company != self.company:
+ frappe.throw(_("Asset {0} does not belong to company {1}").format(self.asset, self.company))
+
+ def validate_warehouses(self):
+ if not self.source_warehouse:
+ self.source_warehouse = frappe.db.get_value("Asset", self.asset, "warehouse")
+
+ if self.source_warehouse == self.target_warehouse:
+ frappe.throw(_("Source and Target Warehouse cannot be same"))
+
+ def on_submit(self):
+ self.set_latest_warehouse_in_asset()
+
+ def on_cancel(self):
+ self.set_latest_warehouse_in_asset()
+
+ def set_latest_warehouse_in_asset(self):
+ latest_movement_entry = frappe.db.sql("""select target_warehouse from `tabAsset Movement`
+ where asset=%s and docstatus=1 and company=%s
+ order by transaction_date desc limit 1""", (self.asset, self.company))
+
+ if latest_movement_entry:
+ warehouse = latest_movement_entry[0][0]
+ else:
+ warehouse = frappe.db.sql("""select source_warehouse from `tabAsset Movement`
+ where asset=%s and docstatus=2 and company=%s
+ order by transaction_date asc limit 1""", (self.asset, self.company))[0][0]
+
+ frappe.db.set_value("Asset", self.asset, "warehouse", warehouse)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/asset_movement/test_asset_movement.py b/erpnext/accounts/doctype/asset_movement/test_asset_movement.py
new file mode 100644
index 0000000..9880efc
--- /dev/null
+++ b/erpnext/accounts/doctype/asset_movement/test_asset_movement.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+from frappe.utils import now
+import unittest
+from erpnext.accounts.doctype.asset.test_asset import create_asset
+
+
+class TestAssetMovement(unittest.TestCase):
+ def test_movement(self):
+ asset = create_asset()
+
+ if asset.docstatus == 0:
+ asset.submit()
+
+ movement1 = create_asset_movement(asset, target_warehouse="_Test Warehouse 1 - _TC")
+ self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 1 - _TC")
+
+ movement2 = create_asset_movement(asset, target_warehouse="_Test Warehouse 2 - _TC")
+ self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 2 - _TC")
+
+ movement1.cancel()
+ self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 2 - _TC")
+
+ movement2.cancel()
+ self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse - _TC")
+
+ asset.load_from_db()
+ asset.cancel()
+ frappe.delete_doc("Asset", asset.name)
+
+
+def create_asset_movement(asset, target_warehouse, transaction_date=None):
+ if not transaction_date:
+ transaction_date = now()
+
+ movement = frappe.new_doc("Asset Movement")
+ movement.update({
+ "asset": asset.name,
+ "transaction_date": transaction_date,
+ "target_warehouse": target_warehouse,
+ "company": asset.company
+ })
+
+ movement.insert()
+ movement.submit()
+
+ return movement
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index 72ed0f9..d0629e7 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -221,6 +221,11 @@
"name": "Period Closing Voucher",
"description": _("Close Balance Sheet and book Profit or Loss.")
},
+ {
+ "type": "doctype",
+ "name": "Asset Movement",
+ "description": _("Transfer an asset from one warehouse to another")
+ },
]
},
{
diff --git a/erpnext/docs/assets/img/accounts/asset-graph.png b/erpnext/docs/assets/img/accounts/asset-graph.png
new file mode 100644
index 0000000..5b300bb
--- /dev/null
+++ b/erpnext/docs/assets/img/accounts/asset-graph.png
Binary files differ
diff --git a/erpnext/docs/assets/img/accounts/asset-movement-using-button.png b/erpnext/docs/assets/img/accounts/asset-movement-using-button.png
new file mode 100644
index 0000000..b9ca68d
--- /dev/null
+++ b/erpnext/docs/assets/img/accounts/asset-movement-using-button.png
Binary files differ
diff --git a/erpnext/docs/assets/img/accounts/asset-movement.png b/erpnext/docs/assets/img/accounts/asset-movement.png
new file mode 100644
index 0000000..39f7b34
--- /dev/null
+++ b/erpnext/docs/assets/img/accounts/asset-movement.png
Binary files differ
diff --git a/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md b/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md
index 2acdd37..1cdbd1e 100644
--- a/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md
+++ b/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md
@@ -45,6 +45,10 @@
In the depreciation entry, the "Accumulated Depreciation Account" is credited and "Depreciation Expense Account" is debited. The related accounts can be set in the Asset Category or Company.
+For better visibility, net value of the asset on different depreciation dates are shown in a line graph.
+
+<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset-graph.png">
+
## Purchase an asset
@@ -71,4 +75,14 @@
You can scrap an asset anytime using the "Scrap Asset" button in the Asset record. The "Gain/Loss Account on Asset Disposal" mentioned in the Company is debited by the Current Value (After Depreciation) of the asset. After scrapping, you can also restore the asset using "Restore Asset" button.
-<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/scrap-journal-entry.png">
\ No newline at end of file
+<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/scrap-journal-entry.png">
+
+## Asset Movement
+
+The movement of the assets (from one warehouse to another) is also tracked via Asset Movement form.
+
+<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset-movement.png">
+
+There is also a dedicated button "Transfer Asset" inside the Asset form to track the Asset Movement.
+
+<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset-movement-using-button.png">
\ No newline at end of file