Merge pull request #5262 from nabinhait/fixed_asset_update

Fixed asset graphs and movement
This commit is contained in:
Nabin Hait 2016-04-29 11:42:53 +05:30
commit fecccbfbb3
13 changed files with 553 additions and 4 deletions

View File

@ -24,6 +24,7 @@ frappe.ui.form.on('Asset', {
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 @@ frappe.ui.form.on('Asset', {
});
}
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 @@ frappe.ui.form.on('Asset', {
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.restore_asset = function(frm) {
}
})
})
}
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();
}

View File

@ -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,
@ -113,6 +113,31 @@
"set_only_once": 0,
"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,
@ -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",

View File

@ -190,4 +190,17 @@ def make_sales_invoice(asset, item_code, company):
"qty": 1
})
si.set_missing_values()
return si
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)))

View File

@ -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)]]]
}
})
}
});

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -221,6 +221,11 @@ def get_data():
"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")
},
]
},
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -45,6 +45,10 @@ On the scheduled date, system creates depreciation entry by creating a Journal E
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 @@ To sale an asset, open the asset record and create a Sales Invoice using "Sale A
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">
<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">