commit
202cb7cdf1
@ -8,29 +8,84 @@ frappe.ui.form.on('Asset', {
|
|||||||
frm.set_query("item_code", function() {
|
frm.set_query("item_code", function() {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
"is_stock_item": 0,
|
|
||||||
"is_fixed_asset": 1,
|
|
||||||
"disabled": 0
|
"disabled": 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("warehouse", function() {
|
||||||
|
return {
|
||||||
|
"filters": {
|
||||||
|
"company": frm.doc.company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
frappe.ui.form.trigger("Asset", "is_existing_asset");
|
||||||
|
|
||||||
if (frm.doc.docstatus==1) {
|
if (frm.doc.docstatus==1) {
|
||||||
if (in_list(["Submittted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) {
|
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
|
||||||
cur_frm.add_custom_button("Scrap Asset", function() {
|
frm.add_custom_button("Make Purchase Invoice", function() {
|
||||||
|
erpnext.asset.make_purchase_invoice(frm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (in_list(["Submitted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) {
|
||||||
|
frm.add_custom_button("Scrap Asset", function() {
|
||||||
erpnext.asset.scrap_asset(frm);
|
erpnext.asset.scrap_asset(frm);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.add_custom_button("Sale Asset", function() {
|
||||||
|
erpnext.asset.make_sales_invoice(frm);
|
||||||
|
});
|
||||||
|
|
||||||
} else if (frm.doc.status=='Scrapped') {
|
} else if (frm.doc.status=='Scrapped') {
|
||||||
cur_frm.add_custom_button("Restore Asset", function() {
|
frm.add_custom_button("Restore Asset", function() {
|
||||||
erpnext.asset.restore_asset(frm);
|
erpnext.asset.restore_asset(frm);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
erpnext.asset.make_purchase_invoice = function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
args: {
|
||||||
|
"asset": frm.doc.name,
|
||||||
|
"item_code": frm.doc.item_code,
|
||||||
|
"gross_purchase_amount": frm.doc.gross_purchase_amount,
|
||||||
|
"company": frm.doc.company,
|
||||||
|
"posting_date": frm.doc.purchase_date
|
||||||
|
},
|
||||||
|
method: "erpnext.accounts.doctype.asset.asset.make_purchase_invoice",
|
||||||
|
callback: function(r) {
|
||||||
|
var doclist = frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
erpnext.asset.make_sales_invoice = function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
args: {
|
||||||
|
"asset": frm.doc.name,
|
||||||
|
"item_code": frm.doc.item_code,
|
||||||
|
"company": frm.doc.company
|
||||||
|
},
|
||||||
|
method: "erpnext.accounts.doctype.asset.asset.make_sales_invoice",
|
||||||
|
callback: function(r) {
|
||||||
|
var doclist = frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
erpnext.asset.scrap_asset = function(frm) {
|
erpnext.asset.scrap_asset = function(frm) {
|
||||||
frappe.confirm(__("Do you really want to scrap this asset?"), function () {
|
frappe.confirm(__("Do you really want to scrap this asset?"), function () {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
|
@ -137,6 +137,83 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 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": "warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "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": "is_existing_asset",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Is Existing Asset",
|
||||||
|
"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,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -218,24 +295,23 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "company",
|
"fieldname": "disposal_date",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Company",
|
"label": "Disposal Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Company",
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 1,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
@ -290,134 +366,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"default": "",
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "depreciation_method",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Depreciation Method",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStraight Line\nDouble Declining Balance",
|
|
||||||
"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": "number_of_depreciations",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Number of Depreciations",
|
|
||||||
"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": "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": "Number of Months in a Period",
|
|
||||||
"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,
|
|
||||||
"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": 1,
|
|
||||||
"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_11",
|
|
||||||
"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,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -475,14 +423,15 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "current_value",
|
"depends_on": "is_existing_asset",
|
||||||
|
"fieldname": "opening_accumulated_depreciation",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Current Value (After Depreciation)",
|
"label": "Opening Accumulated Depreciation",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
@ -497,6 +446,186 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "value_after_depreciation",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "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": 1,
|
||||||
|
"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_11",
|
||||||
|
"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,
|
||||||
|
"default": "",
|
||||||
|
"depends_on": "",
|
||||||
|
"fieldname": "depreciation_method",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Depreciation Method",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "\nStraight Line\nDouble Declining Balance",
|
||||||
|
"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": "total_number_of_depreciations",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Total Number of Depreciations",
|
||||||
|
"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,
|
||||||
|
"depends_on": "eval:(doc.is_existing_asset && doc.opening_accumulated_depreciation)",
|
||||||
|
"fieldname": "number_of_depreciations_booked",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Number of Depreciations Booked",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"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": "frequency_of_depreciation",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Frequency of Depreciation (Months)",
|
||||||
|
"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,
|
||||||
|
"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": 1,
|
||||||
|
"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,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -583,7 +712,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-03-31 05:02:49.890116",
|
"modified": "2016-04-20 18:09:07.573716",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Asset",
|
"name": "Asset",
|
||||||
@ -611,8 +740,9 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
|
@ -5,17 +5,21 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, add_months, cint
|
from frappe.utils import flt, add_months, cint, nowdate, getdate
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_fixed_asset_account
|
||||||
|
from erpnext.accounts.doctype.asset.depreciation \
|
||||||
|
import get_disposal_account_and_cost_center, get_depreciation_accounts
|
||||||
|
|
||||||
class Asset(Document):
|
class Asset(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.status = self.get_status()
|
self.status = self.get_status()
|
||||||
self.validate_fixed_asset_item()
|
self.validate_item()
|
||||||
self.validate_asset_values()
|
self.validate_asset_values()
|
||||||
self.set_depreciation_settings()
|
self.set_depreciation_settings()
|
||||||
self.make_depreciation_schedule()
|
self.make_depreciation_schedule()
|
||||||
self.validate_depreciation_settings_in_company()
|
# Validate depreciation related accounts
|
||||||
|
get_depreciation_accounts(self)
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.set_status()
|
self.set_status()
|
||||||
@ -25,59 +29,87 @@ class Asset(Document):
|
|||||||
self.delete_depreciation_entries()
|
self.delete_depreciation_entries()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
|
|
||||||
def validate_fixed_asset_item(self):
|
def validate_item(self):
|
||||||
item = frappe.get_doc("Item", self.item_code)
|
item = frappe.get_doc("Item", self.item_code)
|
||||||
if item.disabled:
|
if item.disabled:
|
||||||
frappe.throw(_("Item {0} has been disabled").format(self.item_code))
|
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):
|
def validate_asset_values(self):
|
||||||
|
self.value_after_depreciation = flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)
|
||||||
|
|
||||||
if flt(self.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
|
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"))
|
frappe.throw(_("Expected Value After Useful Life must be less than Gross Purchase Amount"))
|
||||||
|
|
||||||
if not flt(self.gross_purchase_amount):
|
if not flt(self.gross_purchase_amount):
|
||||||
frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError)
|
frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError)
|
||||||
|
|
||||||
if not self.current_value and self.next_depreciation_date:
|
if not self.is_existing_asset:
|
||||||
self.current_value = flt(self.gross_purchase_amount)
|
self.opening_accumulated_depreciation = 0
|
||||||
|
self.number_of_depreciations_booked = 0
|
||||||
|
if not self.next_depreciation_date:
|
||||||
|
frappe.throw(_("Next Depreciation Date is mandatory for new asset"))
|
||||||
else:
|
else:
|
||||||
if flt(self.current_value) > flt(self.gross_purchase_amount):
|
depreciable_amount = flt(self.gross_purchase_amount) - flt(self.expected_value_after_useful_life)
|
||||||
frappe.throw(_("Current Value After Depreciation must be less than equal to {0}")
|
if flt(self.opening_accumulated_depreciation) > depreciable_amount:
|
||||||
.format(flt(self.gross_purchase_amount)))
|
frappe.throw(_("Opening Accumulated Depreciation must be less than equal to {0}")
|
||||||
|
.format(depreciable_amount))
|
||||||
|
|
||||||
|
if self.opening_accumulated_depreciation:
|
||||||
|
if not self.number_of_depreciations_booked:
|
||||||
|
frappe.throw(_("Please set Number of Depreciations Booked"))
|
||||||
|
else:
|
||||||
|
self.number_of_depreciations_booked = 0
|
||||||
|
|
||||||
|
if cint(self.number_of_depreciations_booked) > cint(self.total_number_of_depreciations):
|
||||||
|
frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations"))
|
||||||
|
|
||||||
|
if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(nowdate()):
|
||||||
|
frappe.throw(_("Next Depreciation Date must be on or after today"))
|
||||||
|
|
||||||
|
if (flt(self.value_after_depreciation) > flt(self.expected_value_after_useful_life)
|
||||||
|
and not self.next_depreciation_date):
|
||||||
|
frappe.throw(_("Please set Next Depreciation Date"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def set_depreciation_settings(self):
|
def set_depreciation_settings(self):
|
||||||
asset_category = frappe.get_doc("Asset Category", self.asset_category)
|
asset_category = frappe.get_doc("Asset Category", self.asset_category)
|
||||||
|
|
||||||
for field in ("depreciation_method", "number_of_depreciations", "number_of_months_in_a_period"):
|
for field in ("depreciation_method", "total_number_of_depreciations", "frequency_of_depreciation"):
|
||||||
if not self.get(field):
|
if not self.get(field):
|
||||||
self.set(field, asset_category.get(field))
|
self.set(field, asset_category.get(field))
|
||||||
|
|
||||||
def make_depreciation_schedule(self):
|
def make_depreciation_schedule(self):
|
||||||
self.schedules = []
|
self.schedules = []
|
||||||
if not self.get("schedules") and self.next_depreciation_date:
|
if not self.get("schedules") and self.next_depreciation_date:
|
||||||
accumulated_depreciation = 0
|
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
||||||
value_after_depreciation = flt(self.current_value)
|
value_after_depreciation = flt(self.value_after_depreciation)
|
||||||
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)
|
number_of_pending_depreciations = cint(self.total_number_of_depreciations) - \
|
||||||
|
cint(self.number_of_depreciations_booked)
|
||||||
|
if number_of_pending_depreciations:
|
||||||
|
for n in xrange(number_of_pending_depreciations):
|
||||||
|
schedule_date = add_months(self.next_depreciation_date,
|
||||||
|
n * cint(self.frequency_of_depreciation))
|
||||||
|
|
||||||
self.append("schedules", {
|
depreciation_amount = self.get_depreciation_amount(value_after_depreciation)
|
||||||
"schedule_date": schedule_date,
|
|
||||||
"depreciation_amount": depreciation_amount,
|
accumulated_depreciation += flt(depreciation_amount)
|
||||||
"accumulated_depreciation_amount": accumulated_depreciation + depreciation_amount
|
value_after_depreciation -= flt(depreciation_amount)
|
||||||
})
|
|
||||||
accumulated_depreciation += flt(depreciation_amount)
|
self.append("schedules", {
|
||||||
value_after_depreciation -= flt(depreciation_amount)
|
"schedule_date": schedule_date,
|
||||||
|
"depreciation_amount": depreciation_amount,
|
||||||
|
"accumulated_depreciation_amount": accumulated_depreciation
|
||||||
|
})
|
||||||
|
|
||||||
def get_depreciation_amount(self, depreciable_value):
|
def get_depreciation_amount(self, depreciable_value):
|
||||||
if self.depreciation_method == "Straight Line":
|
if self.depreciation_method == "Straight Line":
|
||||||
depreciation_amount = (flt(self.current_value) -
|
depreciation_amount = (flt(self.value_after_depreciation) -
|
||||||
flt(self.expected_value_after_useful_life)) / cint(self.number_of_depreciations)
|
flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) -
|
||||||
|
cint(self.number_of_depreciations_booked))
|
||||||
else:
|
else:
|
||||||
factor = 200.0 / cint(self.number_of_depreciations)
|
factor = 200.0 / self.total_number_of_depreciations
|
||||||
depreciation_amount = flt(depreciable_value * factor / 100, 0)
|
depreciation_amount = flt(depreciable_value * factor / 100, 0)
|
||||||
|
|
||||||
value_after_depreciation = flt(depreciable_value) - depreciation_amount
|
value_after_depreciation = flt(depreciable_value) - depreciation_amount
|
||||||
@ -94,25 +126,16 @@ class Asset(Document):
|
|||||||
frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
|
frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
|
||||||
|
|
||||||
def delete_depreciation_entries(self):
|
def delete_depreciation_entries(self):
|
||||||
total_depreciation_amount = 0
|
|
||||||
for d in self.get("schedules"):
|
for d in self.get("schedules"):
|
||||||
if d.journal_entry:
|
if d.journal_entry:
|
||||||
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
|
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
|
||||||
|
|
||||||
d.db_set("journal_entry", None)
|
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):
|
self.db_set("value_after_depreciation",
|
||||||
company = frappe.get_doc("Company", self.company)
|
(flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)))
|
||||||
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):
|
def set_status(self, status=None):
|
||||||
'''Set asset and update status'''
|
'''Get and update status'''
|
||||||
if not status:
|
if not status:
|
||||||
status = self.get_status()
|
status = self.get_status()
|
||||||
self.db_set("status", status)
|
self.db_set("status", status)
|
||||||
@ -125,11 +148,46 @@ class Asset(Document):
|
|||||||
status = "Submitted"
|
status = "Submitted"
|
||||||
if self.journal_entry_for_scrap:
|
if self.journal_entry_for_scrap:
|
||||||
status = "Scrapped"
|
status = "Scrapped"
|
||||||
elif flt(self.current_value) <= flt(self.expected_value_after_useful_life):
|
elif flt(self.value_after_depreciation) <= flt(self.expected_value_after_useful_life):
|
||||||
status = "Fully Depreciated"
|
status = "Fully Depreciated"
|
||||||
elif flt(self.current_value) < flt(self.gross_purchase_amount):
|
elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount):
|
||||||
status = 'Partially Depreciated'
|
status = 'Partially Depreciated'
|
||||||
elif self.docstatus == 2:
|
elif self.docstatus == 2:
|
||||||
status = "Cancelled"
|
status = "Cancelled"
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, posting_date):
|
||||||
|
pi = frappe.new_doc("Purchase Invoice")
|
||||||
|
pi.company = company
|
||||||
|
pi.currency = frappe.db.get_value("Company", company, "default_currency")
|
||||||
|
pi.posting_date = posting_date
|
||||||
|
pi.append("items", {
|
||||||
|
"item_code": item_code,
|
||||||
|
"is_fixed_asset": 1,
|
||||||
|
"asset": asset,
|
||||||
|
"expense_account": get_fixed_asset_account(asset),
|
||||||
|
"qty": 1,
|
||||||
|
"price_list_rate": gross_purchase_amount,
|
||||||
|
"rate": gross_purchase_amount
|
||||||
|
})
|
||||||
|
pi.set_missing_values()
|
||||||
|
return pi
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def make_sales_invoice(asset, item_code, company):
|
||||||
|
si = frappe.new_doc("Sales Invoice")
|
||||||
|
si.company = company
|
||||||
|
si.currency = frappe.db.get_value("Company", company, "default_currency")
|
||||||
|
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(company)
|
||||||
|
si.append("items", {
|
||||||
|
"item_code": item_code,
|
||||||
|
"is_fixed_asset": 1,
|
||||||
|
"asset": asset,
|
||||||
|
"income_account": disposal_account,
|
||||||
|
"cost_center": depreciation_cost_center,
|
||||||
|
"qty": 1
|
||||||
|
})
|
||||||
|
si.set_missing_values()
|
||||||
|
return si
|
@ -58,9 +58,9 @@ def make_depreciation_entry(asset_name, date=None):
|
|||||||
je.submit()
|
je.submit()
|
||||||
|
|
||||||
d.db_set("journal_entry", je.name)
|
d.db_set("journal_entry", je.name)
|
||||||
asset.current_value -= d.depreciation_amount
|
asset.value_after_depreciation -= d.depreciation_amount
|
||||||
|
|
||||||
asset.db_set("current_value", asset.current_value)
|
asset.db_set("value_after_depreciation", asset.value_after_depreciation)
|
||||||
asset.set_status()
|
asset.set_status()
|
||||||
|
|
||||||
def get_depreciation_accounts(asset):
|
def get_depreciation_accounts(asset):
|
||||||
@ -116,6 +116,7 @@ def scrap_asset(asset_name):
|
|||||||
je.flags.ignore_permissions = True
|
je.flags.ignore_permissions = True
|
||||||
je.submit()
|
je.submit()
|
||||||
|
|
||||||
|
frappe.db.set_value("Asset", asset_name, "disposal_date", today())
|
||||||
frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
|
frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
|
||||||
asset.set_status("Scrapped")
|
asset.set_status("Scrapped")
|
||||||
|
|
||||||
@ -124,7 +125,10 @@ def restore_asset(asset_name):
|
|||||||
asset = frappe.get_doc("Asset", asset_name)
|
asset = frappe.get_doc("Asset", asset_name)
|
||||||
|
|
||||||
je = asset.journal_entry_for_scrap
|
je = asset.journal_entry_for_scrap
|
||||||
|
|
||||||
|
asset.db_set("disposal_date", None)
|
||||||
asset.db_set("journal_entry_for_scrap", None)
|
asset.db_set("journal_entry_for_scrap", None)
|
||||||
|
|
||||||
frappe.get_doc("Journal Entry", je).cancel()
|
frappe.get_doc("Journal Entry", je).cancel()
|
||||||
|
|
||||||
asset.set_status()
|
asset.set_status()
|
||||||
@ -133,7 +137,7 @@ def restore_asset(asset_name):
|
|||||||
def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
||||||
fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset)
|
fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset)
|
||||||
disposal_account, depreciation_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)
|
accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(asset.value_after_depreciation)
|
||||||
|
|
||||||
gl_entries = [
|
gl_entries = [
|
||||||
{
|
{
|
||||||
@ -148,8 +152,8 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
profit_amount = flt(selling_amount) - flt(asset.current_value)
|
profit_amount = flt(selling_amount) - flt(asset.value_after_depreciation)
|
||||||
if flt(asset.current_value) and profit_amount:
|
if flt(asset.value_after_depreciation) and profit_amount:
|
||||||
debit_or_credit = "debit" if profit_amount < 0 else "credit"
|
debit_or_credit = "debit" if profit_amount < 0 else "credit"
|
||||||
gl_entries.append({
|
gl_entries.append({
|
||||||
"account": disposal_account,
|
"account": disposal_account,
|
||||||
@ -160,12 +164,13 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
|||||||
|
|
||||||
return gl_entries
|
return gl_entries
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
def get_disposal_account_and_cost_center(company):
|
def get_disposal_account_and_cost_center(company):
|
||||||
disposal_account, depreciation_cost_center = frappe.db.get_value("Company", company,
|
disposal_account, depreciation_cost_center = frappe.db.get_value("Company", company,
|
||||||
["disposal_account", "depreciation_cost_center"])
|
["disposal_account", "depreciation_cost_center"])
|
||||||
|
|
||||||
if not disposal_account:
|
if not disposal_account:
|
||||||
frappe.throw(_("Please set 'Asset Disposal Account' in Company {0}").format(company))
|
frappe.throw(_("Please set 'Gain/Loss Account on Asset Disposal' in Company {0}").format(company))
|
||||||
if not depreciation_cost_center:
|
if not depreciation_cost_center:
|
||||||
frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company))
|
frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company))
|
||||||
|
|
||||||
|
@ -5,19 +5,50 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
from frappe.utils import cstr
|
from frappe.utils import cstr, nowdate, getdate
|
||||||
from erpnext.accounts.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
|
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
|
from erpnext.accounts.doctype.asset.asset import make_sales_invoice, make_purchase_invoice
|
||||||
|
|
||||||
class TestAsset(unittest.TestCase):
|
class TestAsset(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
set_depreciation_settings_in_company()
|
set_depreciation_settings_in_company()
|
||||||
create_asset()
|
create_asset()
|
||||||
|
|
||||||
def test_fixed_asset_must_be_non_stock_item(self):
|
def test_purchase_asset(self):
|
||||||
item = frappe.get_doc("Item", "Macbook Pro")
|
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||||
item.is_stock_item = 1
|
asset.submit()
|
||||||
self.assertRaises(frappe.ValidationError, item.save)
|
|
||||||
|
pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount,
|
||||||
|
asset.company, asset.purchase_date)
|
||||||
|
pi.supplier = "_Test Supplier"
|
||||||
|
pi.insert()
|
||||||
|
pi.submit()
|
||||||
|
|
||||||
|
asset.load_from_db()
|
||||||
|
self.assertEqual(asset.supplier, "_Test Supplier")
|
||||||
|
self.assertEqual(asset.purchase_date, getdate("2015-01-01"))
|
||||||
|
self.assertEqual(asset.purchase_invoice, pi.name)
|
||||||
|
|
||||||
|
expected_gle = (
|
||||||
|
("_Test Fixed Asset - _TC", 100000.0, 0.0),
|
||||||
|
("Creditors - _TC", 0.0, 100000.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
||||||
|
where voucher_type='Purchase Invoice' and voucher_no = %s
|
||||||
|
order by account""", pi.name)
|
||||||
|
|
||||||
|
self.assertEqual(gle, expected_gle)
|
||||||
|
|
||||||
|
pi.cancel()
|
||||||
|
|
||||||
|
asset.load_from_db()
|
||||||
|
self.assertEqual(asset.supplier, None)
|
||||||
|
self.assertEqual(asset.purchase_invoice, None)
|
||||||
|
|
||||||
|
self.assertFalse(frappe.db.get_value("GL Entry",
|
||||||
|
{"voucher_type": "Purchase Invoice", "voucher_no": pi.name}))
|
||||||
|
|
||||||
|
|
||||||
def test_schedule_for_straight_line_method(self):
|
def test_schedule_for_straight_line_method(self):
|
||||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||||
@ -25,9 +56,28 @@ class TestAsset(unittest.TestCase):
|
|||||||
self.assertEqual(asset.status, "Draft")
|
self.assertEqual(asset.status, "Draft")
|
||||||
|
|
||||||
expected_schedules = [
|
expected_schedules = [
|
||||||
["2015-12-31", 30000, 30000],
|
["2020-12-31", 30000, 30000],
|
||||||
["2016-03-31", 30000, 60000],
|
["2021-03-31", 30000, 60000],
|
||||||
["2016-06-30", 30000, 90000]
|
["2021-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_straight_line_method_for_existing_asset(self):
|
||||||
|
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||||
|
asset.is_existing_asset = 1
|
||||||
|
asset.number_of_depreciations_booked = 1
|
||||||
|
asset.opening_accumulated_depreciation = 40000
|
||||||
|
asset.save()
|
||||||
|
|
||||||
|
self.assertEqual(asset.status, "Draft")
|
||||||
|
|
||||||
|
expected_schedules = [
|
||||||
|
["2020-12-31", 25000, 65000],
|
||||||
|
["2021-03-31", 25000, 90000]
|
||||||
]
|
]
|
||||||
|
|
||||||
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||||
@ -42,9 +92,27 @@ class TestAsset(unittest.TestCase):
|
|||||||
asset.save()
|
asset.save()
|
||||||
|
|
||||||
expected_schedules = [
|
expected_schedules = [
|
||||||
["2015-12-31", 66667, 66667],
|
["2020-12-31", 66667, 66667],
|
||||||
["2016-03-31", 22222, 88889],
|
["2021-03-31", 22222, 88889],
|
||||||
["2016-06-30", 1111, 90000]
|
["2021-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_schedule_for_double_declining_method_for_existing_asset(self):
|
||||||
|
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||||
|
asset.depreciation_method = "Double Declining Balance"
|
||||||
|
asset.is_existing_asset = 1
|
||||||
|
asset.number_of_depreciations_booked = 1
|
||||||
|
asset.opening_accumulated_depreciation = 50000
|
||||||
|
asset.save()
|
||||||
|
|
||||||
|
expected_schedules = [
|
||||||
|
["2020-12-31", 33333, 83333],
|
||||||
|
["2021-03-31", 6667, 90000]
|
||||||
]
|
]
|
||||||
|
|
||||||
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||||
@ -58,7 +126,7 @@ class TestAsset(unittest.TestCase):
|
|||||||
asset.load_from_db()
|
asset.load_from_db()
|
||||||
self.assertEqual(asset.status, "Submitted")
|
self.assertEqual(asset.status, "Submitted")
|
||||||
|
|
||||||
post_depreciation_entries(date="2016-01-01")
|
post_depreciation_entries(date="2021-01-01")
|
||||||
asset.load_from_db()
|
asset.load_from_db()
|
||||||
|
|
||||||
self.assertEqual(asset.status, "Partially Depreciated")
|
self.assertEqual(asset.status, "Partially Depreciated")
|
||||||
@ -73,13 +141,12 @@ class TestAsset(unittest.TestCase):
|
|||||||
order by account""", asset.name)
|
order by account""", asset.name)
|
||||||
|
|
||||||
self.assertEqual(gle, expected_gle)
|
self.assertEqual(gle, expected_gle)
|
||||||
self.assertEqual(asset.get("current_value"), 70000)
|
self.assertEqual(asset.get("value_after_depreciation"), 70000)
|
||||||
|
|
||||||
|
|
||||||
def test_scrap_asset(self):
|
def test_scrap_asset(self):
|
||||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||||
asset.submit()
|
asset.submit()
|
||||||
post_depreciation_entries(date="2016-01-01")
|
post_depreciation_entries(date="2021-01-01")
|
||||||
|
|
||||||
scrap_asset("Macbook Pro 1")
|
scrap_asset("Macbook Pro 1")
|
||||||
|
|
||||||
@ -107,10 +174,13 @@ class TestAsset(unittest.TestCase):
|
|||||||
|
|
||||||
def test_asset_sale(self):
|
def test_asset_sale(self):
|
||||||
frappe.get_doc("Asset", "Macbook Pro 1").submit()
|
frappe.get_doc("Asset", "Macbook Pro 1").submit()
|
||||||
post_depreciation_entries(date="2016-01-01")
|
post_depreciation_entries(date="2021-01-01")
|
||||||
|
|
||||||
si = create_sales_invoice(item_code="Macbook Pro", rate=25000, do_not_save=True)
|
si = make_sales_invoice(asset="Macbook Pro 1", item_code="Macbook Pro", company="_Test Company")
|
||||||
si.get("items")[0].asset = "Macbook Pro 1"
|
si.customer = "_Test Customer"
|
||||||
|
si.due_date = nowdate()
|
||||||
|
si.get("items")[0].rate = 25000
|
||||||
|
si.insert()
|
||||||
si.submit()
|
si.submit()
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Sold")
|
self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Sold")
|
||||||
@ -156,9 +226,10 @@ def create_asset():
|
|||||||
"item_code": "Macbook Pro",
|
"item_code": "Macbook Pro",
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"purchase_date": "2015-01-01",
|
"purchase_date": "2015-01-01",
|
||||||
"next_depreciation_date": "2015-12-31",
|
"next_depreciation_date": "2020-12-31",
|
||||||
"gross_purchase_amount": 100000,
|
"gross_purchase_amount": 100000,
|
||||||
"expected_value_after_useful_life": 10000
|
"expected_value_after_useful_life": 10000,
|
||||||
|
"warehouse": "_Test Warehouse - _TC"
|
||||||
})
|
})
|
||||||
try:
|
try:
|
||||||
asset.save()
|
asset.save()
|
||||||
@ -170,8 +241,8 @@ def create_asset():
|
|||||||
def create_asset_category():
|
def create_asset_category():
|
||||||
asset_category = frappe.new_doc("Asset Category")
|
asset_category = frappe.new_doc("Asset Category")
|
||||||
asset_category.asset_category_name = "Computers"
|
asset_category.asset_category_name = "Computers"
|
||||||
asset_category.number_of_depreciations = 3
|
asset_category.total_number_of_depreciations = 3
|
||||||
asset_category.number_of_months_in_a_period = 3
|
asset_category.frequency_of_depreciation = 3
|
||||||
asset_category.append("accounts", {
|
asset_category.append("accounts", {
|
||||||
"company_name": "_Test Company",
|
"company_name": "_Test Company",
|
||||||
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
||||||
@ -189,8 +260,7 @@ def create_fixed_asset_item():
|
|||||||
"description": "Macbook Pro Retina Display",
|
"description": "Macbook Pro Retina Display",
|
||||||
"item_group": "All Item Groups",
|
"item_group": "All Item Groups",
|
||||||
"stock_uom": "Nos",
|
"stock_uom": "Nos",
|
||||||
"is_stock_item": 0,
|
"is_stock_item": 0
|
||||||
"is_fixed_asset": 1
|
|
||||||
}).insert()
|
}).insert()
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
@ -89,14 +89,14 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "number_of_depreciations",
|
"fieldname": "total_number_of_depreciations",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Number of Depreciations",
|
"label": "Total Number of Depreciations",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -114,14 +114,14 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "number_of_months_in_a_period",
|
"fieldname": "frequency_of_depreciation",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Number of Months in a Period",
|
"label": "Frequency of Depreciation (Months)",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -196,7 +196,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-03-31 05:37:48.481012",
|
"modified": "2016-04-20 13:23:09.890324",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Asset Category",
|
"name": "Asset Category",
|
||||||
@ -244,6 +244,7 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
|
@ -10,6 +10,6 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
class AssetCategory(Document):
|
class AssetCategory(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
for field in ("number_of_depreciations", "number_of_months_in_a_period"):
|
for field in ("total_number_of_depreciations", "frequency_of_depreciation"):
|
||||||
if cint(self.get(field))<1:
|
if cint(self.get(field))<1:
|
||||||
frappe.throw(_("{0} must be greater than 0").format(self.meta.get_label(field)), frappe.MandatoryError)
|
frappe.throw(_("{0} must be greater than 0").format(self.meta.get_label(field)), frappe.MandatoryError)
|
@ -13,8 +13,8 @@ class TestAssetCategory(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(frappe.MandatoryError, asset_category.insert)
|
self.assertRaises(frappe.MandatoryError, asset_category.insert)
|
||||||
|
|
||||||
asset_category.number_of_depreciations = 3
|
asset_category.total_number_of_depreciations = 3
|
||||||
asset_category.number_of_months_in_a_period = 3
|
asset_category.frequency_of_depreciation = 3
|
||||||
asset_category.append("accounts", {
|
asset_category.append("accounts", {
|
||||||
"company_name": "_Test Company",
|
"company_name": "_Test Company",
|
||||||
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
||||||
|
@ -146,15 +146,17 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-03-09 12:21:27.938215",
|
"modified": "2016-04-20 16:43:21.407123",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Depreciation Schedule",
|
"name": "Depreciation Schedule",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC",
|
||||||
|
"track_seen": 0
|
||||||
}
|
}
|
@ -34,5 +34,29 @@
|
|||||||
"year": "_Test Fiscal Year 2017",
|
"year": "_Test Fiscal Year 2017",
|
||||||
"year_end_date": "2017-12-31",
|
"year_end_date": "2017-12-31",
|
||||||
"year_start_date": "2017-01-01"
|
"year_start_date": "2017-01-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Fiscal Year",
|
||||||
|
"year": "_Test Fiscal Year 2018",
|
||||||
|
"year_end_date": "2018-12-31",
|
||||||
|
"year_start_date": "2018-01-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Fiscal Year",
|
||||||
|
"year": "_Test Fiscal Year 2019",
|
||||||
|
"year_end_date": "2019-12-31",
|
||||||
|
"year_start_date": "2019-01-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Fiscal Year",
|
||||||
|
"year": "_Test Fiscal Year 2020",
|
||||||
|
"year_end_date": "2020-12-31",
|
||||||
|
"year_start_date": "2020-01-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Fiscal Year",
|
||||||
|
"year": "_Test Fiscal Year 2021",
|
||||||
|
"year_end_date": "2021-12-31",
|
||||||
|
"year_start_date": "2021-01-01"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -156,6 +156,22 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
frm: cur_frm
|
frm: cur_frm
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
asset: function(frm, cdt, cdn) {
|
||||||
|
var row = locals[cdt][cdn];
|
||||||
|
if(row.asset) {
|
||||||
|
frappe.call({
|
||||||
|
method: erpnext.accounts.doctype.purchase_invoice.purchase_invoice.get_fixed_asset_account,
|
||||||
|
args: {
|
||||||
|
"asset": row.asset,
|
||||||
|
"account": row.expense_account
|
||||||
|
},
|
||||||
|
callback: function(r, rt) {
|
||||||
|
frappe.model.set_value(cdt, cdn, "expense_account", r.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
|
cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
|
||||||
|
@ -62,6 +62,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.set_against_expense_account()
|
self.set_against_expense_account()
|
||||||
self.validate_write_off_account()
|
self.validate_write_off_account()
|
||||||
self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items")
|
self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items")
|
||||||
|
self.validate_fixed_asset()
|
||||||
self.validate_fixed_asset_account()
|
self.validate_fixed_asset_account()
|
||||||
self.create_remarks()
|
self.create_remarks()
|
||||||
|
|
||||||
@ -166,10 +167,9 @@ class PurchaseInvoice(BuyingController):
|
|||||||
# expense account is always "Stock Received But Not Billed" for a stock item
|
# expense account is always "Stock Received But Not Billed" for a stock item
|
||||||
# except epening entry, drop-ship entry and fixed asset items
|
# except epening entry, drop-ship entry and fixed asset items
|
||||||
|
|
||||||
if auto_accounting_for_stock and self.is_opening == 'No' \
|
if auto_accounting_for_stock and item.item_code in stock_items and self.is_opening == 'No' \
|
||||||
and item.item_code in stock_items and ((not item.po_detail
|
and (not item.po_detail or not item.is_fixed_asset
|
||||||
or not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier"))
|
or not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier")):
|
||||||
or not frappe.db.get_value("Item", item.item_code, "is_fixed_asset")):
|
|
||||||
|
|
||||||
if self.update_stock:
|
if self.update_stock:
|
||||||
item.expense_account = warehouse_account[item.warehouse]["name"]
|
item.expense_account = warehouse_account[item.warehouse]["name"]
|
||||||
@ -290,8 +290,6 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.check_prev_docstatus()
|
self.check_prev_docstatus()
|
||||||
self.update_status_updater_args()
|
self.update_status_updater_args()
|
||||||
|
|
||||||
self.validate_asset()
|
|
||||||
|
|
||||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
||||||
self.company, self.base_grand_total)
|
self.company, self.base_grand_total)
|
||||||
|
|
||||||
@ -312,33 +310,22 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
self.update_project()
|
self.update_project()
|
||||||
|
self.update_fixed_asset()
|
||||||
|
|
||||||
def validate_asset(self):
|
def update_fixed_asset(self):
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_fixed_asset"):
|
if d.is_fixed_asset:
|
||||||
if not d.asset:
|
asset = frappe.get_doc("Asset", d.asset)
|
||||||
frappe.throw(_("Row #{0}: Asset is mandatory against a Fixed Asset Item").format(d.idx))
|
if self.docstatus==1:
|
||||||
|
asset.purchase_invoice = self.name
|
||||||
|
asset.purchase_date = self.posting_date
|
||||||
|
asset.supplier = self.supplier
|
||||||
else:
|
else:
|
||||||
asset = frappe.get_doc("Asset", d.asset)
|
asset.purchase_invoice = None
|
||||||
|
asset.supplier = None
|
||||||
|
|
||||||
super(PurchaseInvoice, self).validate_asset(asset, d)
|
asset.flags.ignore_validate_update_after_submit = True
|
||||||
|
asset.save()
|
||||||
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 and 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 != "Submitted":
|
|
||||||
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))
|
|
||||||
|
|
||||||
if self.docstatus==1 and not asset.supplier:
|
|
||||||
frappe.db.set_value("Asset", asset.name, "supplier", self.supplier)
|
|
||||||
|
|
||||||
def make_gl_entries(self, repost_future_gle=False):
|
def make_gl_entries(self, repost_future_gle=False):
|
||||||
self.auto_accounting_for_stock = \
|
self.auto_accounting_for_stock = \
|
||||||
@ -612,7 +599,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
self.make_gl_entries_on_cancel()
|
self.make_gl_entries_on_cancel()
|
||||||
self.update_project()
|
self.update_project()
|
||||||
self.validate_asset()
|
self.update_fixed_asset()
|
||||||
|
|
||||||
def update_project(self):
|
def update_project(self):
|
||||||
project_list = []
|
project_list = []
|
||||||
@ -666,7 +653,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
def validate_fixed_asset_account(self):
|
def validate_fixed_asset_account(self):
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_fixed_asset"):
|
if d.is_fixed_asset:
|
||||||
account_type = frappe.db.get_value("Account", d.expense_account, "account_type")
|
account_type = frappe.db.get_value("Account", d.expense_account, "account_type")
|
||||||
if account_type != 'Fixed Asset':
|
if account_type != 'Fixed Asset':
|
||||||
frappe.throw(_("Row {0}# Account must be of type 'Fixed Asset'").format(d.idx))
|
frappe.throw(_("Row {0}# Account must be of type 'Fixed Asset'").format(d.idx))
|
||||||
@ -678,3 +665,18 @@ class PurchaseInvoice(BuyingController):
|
|||||||
def make_debit_note(source_name, target_doc=None):
|
def make_debit_note(source_name, target_doc=None):
|
||||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||||
return make_return_doc("Purchase Invoice", source_name, target_doc)
|
return make_return_doc("Purchase Invoice", source_name, target_doc)
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_fixed_asset_account(asset, account=None):
|
||||||
|
if account:
|
||||||
|
if frappe.db.get_value("Account", account, "account_type") != "Fixed Asset":
|
||||||
|
account=None
|
||||||
|
|
||||||
|
if not account:
|
||||||
|
asset_category, company = frappe.db.get_value("Asset", asset, ["asset_category", "company"])
|
||||||
|
|
||||||
|
account = frappe.db.get_value("Asset Category Account",
|
||||||
|
filters={"parent": asset_category, "company_name": company}, fieldname="fixed_asset_account")
|
||||||
|
|
||||||
|
return account
|
||||||
|
|
@ -1016,6 +1016,31 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"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,
|
||||||
|
"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,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -1098,6 +1123,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"default": ":Company",
|
"default": ":Company",
|
||||||
|
"depends_on": "eval:!doc.is_fixed_asset",
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1335,6 +1361,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"depends_on": "is_fixed_asset",
|
||||||
"fieldname": "asset",
|
"fieldname": "asset",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1545,7 +1572,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-04-18 08:08:53.056818",
|
"modified": "2016-04-18 08:08:53.056819",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice Item",
|
"name": "Purchase Invoice Item",
|
||||||
|
@ -269,6 +269,22 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_sales_return",
|
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_sales_return",
|
||||||
frm: cur_frm
|
frm: cur_frm
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
asset: function(frm, cdt, cdn) {
|
||||||
|
var row = locals[cdt][cdn];
|
||||||
|
if(row.asset) {
|
||||||
|
frappe.call({
|
||||||
|
method: erpnext.accounts.doctype.asset.depreciation.get_disposal_account_and_cost_center,
|
||||||
|
args: {
|
||||||
|
"company": frm.doc.company
|
||||||
|
},
|
||||||
|
callback: function(r, rt) {
|
||||||
|
frappe.model.set_value(cdt, cdn, "income_account", r.message[0]);
|
||||||
|
frappe.model.set_value(cdt, cdn, "cost_center", r.message[1]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ from frappe.model.mapper import get_mapped_doc
|
|||||||
from erpnext.controllers.selling_controller import SellingController
|
from erpnext.controllers.selling_controller import SellingController
|
||||||
from erpnext.accounts.utils import get_account_currency
|
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.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
|
from erpnext.accounts.doctype.asset.depreciation \
|
||||||
|
import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal
|
||||||
|
|
||||||
form_grid_templates = {
|
form_grid_templates = {
|
||||||
"items": "templates/form_grid/item_grid.html"
|
"items": "templates/form_grid/item_grid.html"
|
||||||
@ -60,6 +61,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.validate_advance_jv("Sales Order")
|
self.validate_advance_jv("Sales Order")
|
||||||
self.add_remarks()
|
self.add_remarks()
|
||||||
self.validate_write_off_account()
|
self.validate_write_off_account()
|
||||||
|
self.validate_fixed_asset()
|
||||||
self.set_income_account_for_fixed_assets()
|
self.set_income_account_for_fixed_assets()
|
||||||
|
|
||||||
if cint(self.is_pos):
|
if cint(self.is_pos):
|
||||||
@ -454,16 +456,15 @@ class SalesInvoice(SellingController):
|
|||||||
return warehouse
|
return warehouse
|
||||||
|
|
||||||
def set_income_account_for_fixed_assets(self):
|
def set_income_account_for_fixed_assets(self):
|
||||||
disposal_account = None
|
disposal_account = depreciation_cost_center = None
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_fixed_asset"):
|
if d.is_fixed_asset:
|
||||||
if not disposal_account:
|
if not disposal_account:
|
||||||
disposal_account = frappe.db.get_value("Company", self.company, "disposal_account")
|
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(self.company)
|
||||||
if not disposal_account:
|
|
||||||
frappe.throw(_("Please mention 'Gain/Loss Account on Asset Disposal' in Company"))
|
|
||||||
|
|
||||||
d.income_account = disposal_account
|
d.income_account = disposal_account
|
||||||
|
if not d.cost_center:
|
||||||
|
d.cost_center = depreciation_cost_center
|
||||||
|
|
||||||
def check_prev_docstatus(self):
|
def check_prev_docstatus(self):
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
@ -473,13 +474,6 @@ class SalesInvoice(SellingController):
|
|||||||
if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
|
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))
|
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):
|
def make_gl_entries(self, repost_future_gle=True):
|
||||||
gl_entries = self.get_gl_entries()
|
gl_entries = self.get_gl_entries()
|
||||||
|
|
||||||
@ -565,19 +559,16 @@ class SalesInvoice(SellingController):
|
|||||||
# income account gl entries
|
# income account gl entries
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if flt(item.base_net_amount):
|
if flt(item.base_net_amount):
|
||||||
if frappe.db.get_value("Item", item.item_code, "is_fixed_asset"):
|
if item.is_fixed_asset:
|
||||||
if not item.asset:
|
asset = frappe.get_doc("Asset", 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)
|
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount)
|
||||||
for gle in fixed_asset_gl_entries:
|
for gle in fixed_asset_gl_entries:
|
||||||
gl_entries.append(self.get_gl_dict(gle))
|
gle["against"] = self.customer
|
||||||
|
gl_entries.append(self.get_gl_dict(gle))
|
||||||
|
|
||||||
asset.set_status("Sold" if self.docstatus==1 else None)
|
asset.db_set("disposal_date", self.posting_date)
|
||||||
|
asset.set_status("Sold" if self.docstatus==1 else None)
|
||||||
else:
|
else:
|
||||||
account_currency = get_account_currency(item.income_account)
|
account_currency = get_account_currency(item.income_account)
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
|
@ -974,6 +974,31 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"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,
|
||||||
|
"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,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -1657,7 +1682,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-03-29 11:09:35.263924",
|
"modified": "2016-04-06 12:26:19.052860",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice Item",
|
"name": "Sales Invoice Item",
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.query_reports["Asset Depreciation Ledger"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname":"company",
|
||||||
|
"label": __("Company"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company",
|
||||||
|
"default": frappe.defaults.get_user_default("Company"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"from_date",
|
||||||
|
"label": __("From Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"to_date",
|
||||||
|
"label": __("To Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.datetime.get_today(),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"asset",
|
||||||
|
"label": __("Asset"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Asset"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"asset_category",
|
||||||
|
"label": __("Asset Category"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Asset Category"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"apply_user_permissions": 1,
|
||||||
|
"creation": "2016-04-08 14:49:58.133098",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2016-04-08 14:49:58.133098",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Asset Depreciation Ledger",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"ref_doctype": "Asset",
|
||||||
|
"report_name": "Asset Depreciation Ledger",
|
||||||
|
"report_type": "Script Report"
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
columns, data = get_columns(), get_data(filters)
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_data(filters):
|
||||||
|
data = frappe.db.sql("""
|
||||||
|
select
|
||||||
|
a.name as asset, a.asset_category, a.status,
|
||||||
|
a.depreciation_method, a.purchase_date, a.gross_purchase_amount,
|
||||||
|
ds.schedule_date as depreciation_date, ds.depreciation_amount,
|
||||||
|
ds.accumulated_depreciation_amount,
|
||||||
|
(a.gross_purchase_amount - ds.accumulated_depreciation_amount) as amount_after_depreciation,
|
||||||
|
ds.journal_entry as depreciation_entry
|
||||||
|
from
|
||||||
|
`tabAsset` a, `tabDepreciation Schedule` ds
|
||||||
|
where
|
||||||
|
a.name = ds.parent
|
||||||
|
and a.docstatus=1
|
||||||
|
and ifnull(ds.journal_entry, '') != ''
|
||||||
|
and ds.schedule_date between %(from_date)s and %(to_date)s
|
||||||
|
and a.company = %(company)s
|
||||||
|
{conditions}
|
||||||
|
order by
|
||||||
|
a.name asc, ds.schedule_date asc
|
||||||
|
""".format(conditions=get_filter_conditions(filters)), filters, as_dict=1)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_filter_conditions(filters):
|
||||||
|
conditions = ""
|
||||||
|
|
||||||
|
if filters.get("asset"):
|
||||||
|
conditions += " and a.name = %(asset)s"
|
||||||
|
|
||||||
|
if filters.get("asset_category"):
|
||||||
|
conditions += " and a.asset_category = %(asset_category)s"
|
||||||
|
|
||||||
|
return conditions
|
||||||
|
|
||||||
|
def get_columns():
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"label": _("Asset"),
|
||||||
|
"fieldname": "asset",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Asset",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Depreciation Date"),
|
||||||
|
"fieldname": "depreciation_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Purchase Amount"),
|
||||||
|
"fieldname": "gross_purchase_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Depreciation Amount"),
|
||||||
|
"fieldname": "depreciation_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Accumulated Depreciation Amount"),
|
||||||
|
"fieldname": "accumulated_depreciation_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 210
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Amount After Depreciation"),
|
||||||
|
"fieldname": "amount_after_depreciation",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Depreciation Entry"),
|
||||||
|
"fieldname": "depreciation_entry",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Journal Entry",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Asset Category"),
|
||||||
|
"fieldname": "asset_category",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Asset Category",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Current Status"),
|
||||||
|
"fieldname": "status",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Depreciation Method"),
|
||||||
|
"fieldname": "depreciation_method",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Purchase Date"),
|
||||||
|
"fieldname": "purchase_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"width": 120
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.query_reports["Asset Depreciations and Balances"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname":"company",
|
||||||
|
"label": __("Company"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company",
|
||||||
|
"default": frappe.defaults.get_user_default("Company"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"from_date",
|
||||||
|
"label": __("From Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.defaults.get_user_default("year_start_date"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"to_date",
|
||||||
|
"label": __("To Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.defaults.get_user_default("year_end_date"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"asset_category",
|
||||||
|
"label": __("Asset Category"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Asset Category"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"apply_user_permissions": 1,
|
||||||
|
"creation": "2016-04-08 14:56:37.235981",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2016-04-08 14:56:37.235981",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Asset Depreciations and Balances",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"ref_doctype": "Asset",
|
||||||
|
"report_name": "Asset Depreciations and Balances",
|
||||||
|
"report_type": "Script Report"
|
||||||
|
}
|
@ -0,0 +1,184 @@
|
|||||||
|
# Copyright (c) 2013, 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.utils import formatdate, getdate, flt, add_days
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
filters.day_before_from_date = add_days(filters.from_date, -1)
|
||||||
|
columns, data = get_columns(filters), get_data(filters)
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_data(filters):
|
||||||
|
data = []
|
||||||
|
|
||||||
|
asset_categories = get_asset_categories(filters)
|
||||||
|
assets = get_assets(filters)
|
||||||
|
asset_costs = get_asset_costs(assets, filters)
|
||||||
|
asset_depreciations = get_accumulated_depreciations(assets, filters)
|
||||||
|
|
||||||
|
for asset_category in asset_categories:
|
||||||
|
row = frappe._dict()
|
||||||
|
row.asset_category = asset_category
|
||||||
|
row.update(asset_costs.get(asset_category))
|
||||||
|
|
||||||
|
row.cost_as_on_to_date = (flt(row.cost_as_on_from_date) + flt(row.cost_of_new_purchase)
|
||||||
|
- flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset))
|
||||||
|
|
||||||
|
row.update(asset_depreciations.get(asset_category))
|
||||||
|
row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) +
|
||||||
|
flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
|
||||||
|
|
||||||
|
row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) -
|
||||||
|
flt(row.accumulated_depreciation_as_on_from_date))
|
||||||
|
|
||||||
|
row.net_asset_value_as_on_to_date = (flt(row.cost_as_on_to_date) -
|
||||||
|
flt(row.accumulated_depreciation_as_on_to_date))
|
||||||
|
|
||||||
|
data.append(row)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_asset_categories(filters):
|
||||||
|
return frappe.db.sql_list("""
|
||||||
|
select distinct asset_category from `tabAsset`
|
||||||
|
where docstatus=1 and company=%s and purchase_date <= %s
|
||||||
|
""", (filters.company, filters.to_date))
|
||||||
|
|
||||||
|
def get_assets(filters):
|
||||||
|
return frappe.db.sql("""
|
||||||
|
select name, asset_category, purchase_date, gross_purchase_amount, disposal_date, status
|
||||||
|
from `tabAsset`
|
||||||
|
where docstatus=1 and company=%s and purchase_date <= %s""",
|
||||||
|
(filters.company, filters.to_date), as_dict=1)
|
||||||
|
|
||||||
|
def get_asset_costs(assets, filters):
|
||||||
|
asset_costs = frappe._dict()
|
||||||
|
for d in assets:
|
||||||
|
asset_costs.setdefault(d.asset_category, frappe._dict({
|
||||||
|
"cost_as_on_from_date": 0,
|
||||||
|
"cost_of_new_purchase": 0,
|
||||||
|
"cost_of_sold_asset": 0,
|
||||||
|
"cost_of_scrapped_asset": 0
|
||||||
|
}))
|
||||||
|
|
||||||
|
costs = asset_costs[d.asset_category]
|
||||||
|
|
||||||
|
if getdate(d.purchase_date) < getdate(filters.from_date):
|
||||||
|
if not d.disposal_date or getdate(d.disposal_date) >= getdate(filters.from_date):
|
||||||
|
costs.cost_as_on_from_date += flt(d.gross_purchase_amount)
|
||||||
|
else:
|
||||||
|
costs.cost_of_new_purchase += flt(d.gross_purchase_amount)
|
||||||
|
|
||||||
|
if d.disposal_date and getdate(d.disposal_date) >= getdate(filters.from_date) \
|
||||||
|
and getdate(d.disposal_date) <= getdate(filters.to_date):
|
||||||
|
if d.status == "Sold":
|
||||||
|
costs.cost_of_sold_asset += flt(d.gross_purchase_amount)
|
||||||
|
elif d.status == "Scrapped":
|
||||||
|
costs.cost_of_scrapped_asset += flt(d.gross_purchase_amount)
|
||||||
|
|
||||||
|
return asset_costs
|
||||||
|
|
||||||
|
def get_accumulated_depreciations(assets, filters):
|
||||||
|
asset_depreciations = frappe._dict()
|
||||||
|
for d in assets:
|
||||||
|
asset = frappe.get_doc("Asset", d.name)
|
||||||
|
|
||||||
|
asset_depreciations.setdefault(d.asset_category, frappe._dict({
|
||||||
|
"accumulated_depreciation_as_on_from_date": asset.opening_accumulated_depreciation,
|
||||||
|
"depreciation_amount_during_the_period": 0,
|
||||||
|
"depreciation_eliminated_during_the_period": 0
|
||||||
|
}))
|
||||||
|
|
||||||
|
depr = asset_depreciations[d.asset_category]
|
||||||
|
|
||||||
|
for schedule in asset.get("schedules"):
|
||||||
|
if getdate(schedule.schedule_date) < getdate(filters.from_date):
|
||||||
|
if not asset.disposal_date and getdate(asset.disposal_date) >= getdate(filters.from_date):
|
||||||
|
depr.accumulated_depreciation_as_on_from_date += flt(schedule.depreciation_amount)
|
||||||
|
elif getdate(schedule.schedule_date) <= getdate(filters.to_date):
|
||||||
|
depr.depreciation_amount_during_the_period += flt(schedule.depreciation_amount)
|
||||||
|
|
||||||
|
if asset.disposal_date and getdate(schedule.schedule_date) > getdate(asset.disposal_date):
|
||||||
|
depr.depreciation_eliminated_during_the_period += flt(schedule.depreciation_amount)
|
||||||
|
|
||||||
|
return asset_depreciations
|
||||||
|
|
||||||
|
def get_columns(filters):
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"label": _("Asset Category"),
|
||||||
|
"fieldname": "asset_category",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Asset Category",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Cost as on") + " " + formatdate(filters.day_before_from_date),
|
||||||
|
"fieldname": "cost_as_on_from_date",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Cost of New Purchase"),
|
||||||
|
"fieldname": "cost_of_new_purchase",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Cost of Sold Asset"),
|
||||||
|
"fieldname": "cost_of_sold_asset",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Cost of Scrapped Asset"),
|
||||||
|
"fieldname": "cost_of_scrapped_asset",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Cost as on") + " " + formatdate(filters.to_date),
|
||||||
|
"fieldname": "cost_as_on_to_date",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Accumulated Depreciation as on") + " " + formatdate(filters.day_before_from_date),
|
||||||
|
"fieldname": "accumulated_depreciation_as_on_from_date",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 270
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Depreciation Amount during the period"),
|
||||||
|
"fieldname": "depreciation_amount_during_the_period",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 240
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Depreciation Eliminated due to disposal of assets"),
|
||||||
|
"fieldname": "depreciation_eliminated_during_the_period",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Accumulated Depreciation as on") + " " + formatdate(filters.to_date),
|
||||||
|
"fieldname": "accumulated_depreciation_as_on_to_date",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 270
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Net Asset value as on") + " " + formatdate(filters.day_before_from_date),
|
||||||
|
"fieldname": "net_asset_value_as_on_from_date",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Net Asset value as on") + " " + formatdate(filters.to_date),
|
||||||
|
"fieldname": "net_asset_value_as_on_to_date",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 200
|
||||||
|
}
|
||||||
|
]
|
@ -80,17 +80,3 @@ class PurchaseCommon(BuyingController):
|
|||||||
|
|
||||||
if status == "Closed":
|
if status == "Closed":
|
||||||
frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)
|
frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)
|
||||||
|
|
||||||
def check_docstatus(self, check, doctype, docname, detail_doctype = ''):
|
|
||||||
if check == 'Next':
|
|
||||||
submitted = frappe.db.sql("""select t1.name from `tab%s` t1,`tab%s` t2
|
|
||||||
where t1.name = t2.parent and t2.prevdoc_docname = %s and t1.docstatus = 1"""
|
|
||||||
% (doctype, detail_doctype, '%s'), docname)
|
|
||||||
if submitted:
|
|
||||||
frappe.throw(_("{0} {1} has already been submitted").format(doctype, submitted[0][0]))
|
|
||||||
|
|
||||||
if check == 'Previous':
|
|
||||||
submitted = frappe.db.sql("""select name from `tab%s`
|
|
||||||
where docstatus = 1 and name = %s""" % (doctype, '%s'), docname)
|
|
||||||
if not submitted:
|
|
||||||
frappe.throw(_("{0} {1} is not submitted").format(doctype, submitted[0][0]))
|
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import json
|
import json
|
||||||
from frappe.utils import cstr, flt
|
from frappe.utils import cstr, flt
|
||||||
from frappe import msgprint, _, throw
|
from frappe import msgprint, _
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from erpnext.controllers.buying_controller import BuyingController
|
from erpnext.controllers.buying_controller import BuyingController
|
||||||
from erpnext.stock.doctype.item.item import get_last_purchase_details
|
from erpnext.stock.doctype.item.item import get_last_purchase_details
|
||||||
@ -189,17 +189,6 @@ class PurchaseOrder(BuyingController):
|
|||||||
pc_obj = frappe.get_doc('Purchase Common')
|
pc_obj = frappe.get_doc('Purchase Common')
|
||||||
self.check_for_closed_status(pc_obj)
|
self.check_for_closed_status(pc_obj)
|
||||||
|
|
||||||
# Check if Purchase Receipt has been submitted against current Purchase Order
|
|
||||||
pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Receipt', docname = self.name, detail_doctype = 'Purchase Receipt Item')
|
|
||||||
|
|
||||||
# Check if Purchase Invoice has been submitted against current Purchase Order
|
|
||||||
submitted = frappe.db.sql_list("""select t1.name
|
|
||||||
from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2
|
|
||||||
where t1.name = t2.parent and t2.purchase_order = %s and t1.docstatus = 1""",
|
|
||||||
self.name)
|
|
||||||
if submitted:
|
|
||||||
throw(_("Purchase Invoice {0} is already submitted").format(", ".join(submitted)))
|
|
||||||
|
|
||||||
frappe.db.set(self,'status','Cancelled')
|
frappe.db.set(self,'status','Cancelled')
|
||||||
|
|
||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
|
@ -340,6 +340,18 @@ def get_data():
|
|||||||
"label": _("Other Reports"),
|
"label": _("Other Reports"),
|
||||||
"icon": "icon-table",
|
"icon": "icon-table",
|
||||||
"items": [
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "report",
|
||||||
|
"name": "Asset Depreciation Ledger",
|
||||||
|
"doctype": "Asset",
|
||||||
|
"is_query_report": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "report",
|
||||||
|
"name": "Asset Depreciations and Balances",
|
||||||
|
"doctype": "Asset",
|
||||||
|
"is_query_report": True,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "report",
|
"type": "report",
|
||||||
"name": "Trial Balance for Party",
|
"name": "Trial Balance for Party",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _, throw
|
from frappe import _, throw
|
||||||
from frappe.utils import today, flt, cint, fmt_money, formatdate
|
from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate
|
||||||
from erpnext.setup.utils import get_company_currency, get_exchange_rate
|
from erpnext.setup.utils import get_company_currency, get_exchange_rate
|
||||||
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
|
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
|
||||||
from erpnext.utilities.transaction_base import TransactionBase
|
from erpnext.utilities.transaction_base import TransactionBase
|
||||||
@ -470,18 +470,46 @@ class AccountsController(TransactionBase):
|
|||||||
# at quotation / sales order level and we shouldn't stop someone
|
# at quotation / sales order level and we shouldn't stop someone
|
||||||
# from creating a sales invoice if sales order is already created
|
# from creating a sales invoice if sales order is already created
|
||||||
|
|
||||||
def validate_asset(self, asset, item_row):
|
def validate_fixed_asset(self):
|
||||||
if asset.company != self.company:
|
for d in self.get("items"):
|
||||||
frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}")
|
if d.is_fixed_asset:
|
||||||
.format(item_row.idx, item_row.asset, self.company))
|
if d.qty > 1:
|
||||||
|
frappe.throw(_("Row #{0}: Qty must be 1, as item is a fixed asset. Please use separate row for multiple qty.").format(d.idx))
|
||||||
|
|
||||||
elif asset.item_code != item_row.item_code:
|
if d.meta.get_field("asset"):
|
||||||
frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}")
|
if not d.asset:
|
||||||
.format(item_row.idx, item_row.asset, item_row.item_code))
|
frappe.throw(_("Row #{0}: Asset is mandatory for fixed asset purchase/sale")
|
||||||
elif asset.docstatus != 1:
|
.format(d.idx))
|
||||||
frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(item_row.idx, item_row.asset))
|
else:
|
||||||
elif item_row.qty > 1:
|
asset = frappe.get_doc("Asset", d.asset)
|
||||||
frappe.throw(_("Row #{0}: Qty must be 1, as item is linked to an asset").format(item_row.idx))
|
|
||||||
|
if asset.company != self.company:
|
||||||
|
frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}")
|
||||||
|
.format(d.idx, d.asset, self.company))
|
||||||
|
|
||||||
|
elif asset.item_code != d.item_code:
|
||||||
|
frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}")
|
||||||
|
.format(d.idx, d.asset, d.item_code))
|
||||||
|
|
||||||
|
elif asset.docstatus != 1:
|
||||||
|
frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(d.idx, d.asset))
|
||||||
|
|
||||||
|
elif self.doctype == "Purchase Invoice":
|
||||||
|
if asset.status != "Submitted":
|
||||||
|
frappe.throw(_("Row #{0}: Asset {1} is already {2}")
|
||||||
|
.format(d.idx, d.asset, asset.status))
|
||||||
|
elif getdate(asset.purchase_date) != getdate(self.posting_date):
|
||||||
|
frappe.throw(_("Row #{0}: Posting Date must be same as purchase date {1} of asset {2}").format(d.idx, asset.purchase_date, d.asset))
|
||||||
|
elif asset.is_existing_asset:
|
||||||
|
frappe.throw(_("Row #{0}: Purchase Invoice cannot be made against an existing asset {1}").format(d.idx, d.asset))
|
||||||
|
|
||||||
|
elif self.docstatus=="Sales Invoice" and self.docstatus == 1:
|
||||||
|
if self.update_stock:
|
||||||
|
frappe.throw(_("'Update Stock' cannot be checked for fixed asset sale"))
|
||||||
|
|
||||||
|
elif asset.status in ("Scrapped", "Cancelled", "Sold"):
|
||||||
|
frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}")
|
||||||
|
.format(d.idx, d.asset, asset.status))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_tax_rate(account_head):
|
def get_tax_rate(account_head):
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 164 KiB |
Binary file not shown.
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 288 KiB |
@ -310,6 +310,27 @@
|
|||||||
|
|
||||||
<tr >
|
<tr >
|
||||||
<td>19</td>
|
<td>19</td>
|
||||||
|
<td ><code>project</code></td>
|
||||||
|
<td >
|
||||||
|
Link</td>
|
||||||
|
<td >
|
||||||
|
Project
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href="https://frappe.github.io/erpnext/current/models/projects/project">Project</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr >
|
||||||
|
<td>20</td>
|
||||||
<td ><code>col_break3</code></td>
|
<td ><code>col_break3</code></td>
|
||||||
<td class="info">
|
<td class="info">
|
||||||
Column Break</td>
|
Column Break</td>
|
||||||
@ -321,7 +342,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr >
|
<tr >
|
||||||
<td>20</td>
|
<td>21</td>
|
||||||
<td ><code>min_order_qty</code></td>
|
<td ><code>min_order_qty</code></td>
|
||||||
<td >
|
<td >
|
||||||
Float</td>
|
Float</td>
|
||||||
@ -333,7 +354,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr >
|
<tr >
|
||||||
<td>21</td>
|
<td>22</td>
|
||||||
<td ><code>projected_qty</code></td>
|
<td ><code>projected_qty</code></td>
|
||||||
<td >
|
<td >
|
||||||
Float</td>
|
Float</td>
|
||||||
@ -345,7 +366,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr >
|
<tr >
|
||||||
<td>22</td>
|
<td>23</td>
|
||||||
<td ><code>ordered_qty</code></td>
|
<td ><code>ordered_qty</code></td>
|
||||||
<td >
|
<td >
|
||||||
Float</td>
|
Float</td>
|
||||||
@ -357,7 +378,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr >
|
<tr >
|
||||||
<td>23</td>
|
<td>24</td>
|
||||||
<td ><code>page_break</code></td>
|
<td ><code>page_break</code></td>
|
||||||
<td >
|
<td >
|
||||||
Check</td>
|
Check</td>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
In ERPNext, you can maintain your fixed asset records like Computers, Building, Cars etc and manage depreciations, sell or disposal of those assets.
|
In ERPNext, you can maintain fixed asset records like Computers, Furnitures, Cars etc and manage depreciations, sell or disposal of those assets.
|
||||||
|
|
||||||
## Asset Category
|
## Asset Category
|
||||||
|
|
||||||
@ -11,24 +11,27 @@ To start first you should create Asset Category, depending on the type of assets
|
|||||||
|
|
||||||
## Asset
|
## Asset
|
||||||
|
|
||||||
Next step will be creating the fixed asset records. The assets which are partially / fully depreciated can also be created/maintained for the future reference.
|
Next step will be creating the fixed asset records. Asset record is the heart of fixed asset management, all the activities like purchasing, depreciation, scrapping or sales are managed against it.
|
||||||
|
|
||||||
<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset.png">
|
<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset.png">
|
||||||
|
|
||||||
Explanation of the fields:
|
Explanation of the fields:
|
||||||
|
|
||||||
1. Asset Category: The category of assets it belongs to.
|
1. Asset Category: The category of assets it belongs to.
|
||||||
2. Item Code: The item/product code for the asset, which must be marked as a fixed asset and a non-stock item.
|
2. Is Existing Asset: Check if the asset is being carried forward from the previous Fiscal Year. The existing assets which are partially / fully depreciated can also be created/maintained for the future reference.
|
||||||
3. Status: The options are - Draft, Submitted, Partially Depreciated, Fully Depreciated, Sold and Scrapped.
|
3. Status: The options are - Draft, Submitted, Partially Depreciated, Fully Depreciated, Sold and Scrapped.
|
||||||
4. Gross Purchase Amount: The purchase cost of the asset
|
4. Warehouse: Set the location of the asset.
|
||||||
5. Expected Value After Useful Life: Useful Life is the time period over in which the company expects that the asset will be productive. After that period, either the asset is scrapped or sold. In case it is sold, mention the estimated value here. This value is also known as Salvage Value, Scrap Value or Residual Value.
|
5. Gross Purchase Amount: The purchase cost of the asset
|
||||||
6. Current Value (After Depreciation): In case you are creating record of an existing asset which has already been partially/fully depreciated, mention the currect value of the asset. In case of new asset, mention the purchase amount or leave it blank.
|
6. Expected Value After Useful Life: Useful Life is the time period over in which the company expects that the asset will be productive. After that period, either the asset is scrapped or sold. In case it is sold, mention the estimated value here. This value is also known as Salvage Value, Scrap Value or Residual Value.
|
||||||
7. Depreciation Method: There are two options: Straight Line and Double Declining Balance.
|
7. Opening Accumulated Depreciation: The accumulated depreciation amount which has already been booked for an existing asset.
|
||||||
|
8. Current Value (After Depreciation): In case you are creating record of an existing asset which has already been partially/fully depreciated, mention the currect value of the asset. In case of new asset, mention the purchase amount or leave it blank.
|
||||||
|
9. Depreciation Method: There are two options: Straight Line and Double Declining Balance.
|
||||||
- Straight Line: This method spreads the cost of the fixed asset evenly over its useful life.
|
- Straight Line: This method spreads the cost of the fixed asset evenly over its useful life.
|
||||||
- Double Declining Method: An accelerated method of depreciation, it results in higher depreciation expense in the earlier years of ownership.
|
- Double Declining Method: An accelerated method of depreciation, it results in higher depreciation expense in the earlier years of ownership.
|
||||||
8. Number of Depreciations: The number of depreciations during the useful life. In case of existing assets which are partially depreciated, mention the number of pending depreciations.
|
10. Total Number of Depreciations: The total number of depreciations during the useful life. In case of existing assets which are partially depreciated, mention the number of pending depreciations.
|
||||||
9. Number of Months in a Period: The number of months between two depreciations.
|
11. Number of Depreciations Booked: Enter the number of already booked depreciations for an existing asset.
|
||||||
10. Next Depreciation Date: Mention the next depreciation date, even if it is the first one. If depreciation already completed, leave it blank.
|
12. Frequency of Depreciation (Months): The number of months between two depreciations.
|
||||||
|
13. Next Depreciation Date: Mention the next depreciation date, even if it is the first one. If the asset is an existing one and depreciation has already been completed, leave it blank.
|
||||||
|
|
||||||
### Depreciations
|
### Depreciations
|
||||||
|
|
||||||
@ -45,16 +48,16 @@ In the depreciation entry, the "Accumulated Depreciation Account" is credited an
|
|||||||
|
|
||||||
## Purchase an asset
|
## Purchase an asset
|
||||||
|
|
||||||
For purchasing an asset, first create an item for the asset with "Is Fixed Asset" checked. Then create a Purchase Invoice against that item. In the Purchase Invoice Item row, you have to mention Asset name and associated fixed asset account should be set as Expense Account. Fixed asset accounts are identified based on "Fixed Asset" account type.
|
For purchasing a new asset, create and submit the asset record with all the depreciation settings. Then create a Purchase Invoice via "Make Purchase Invoice" button. On clicking the button, system will load a new Purchase Invoice form with pre-loaded items table. It will also set proper fixed asset account (defined in teh Asset Category) in the Expense Account field. You need to select Supplier and other necessary details and submit the Purchase Invoice.
|
||||||
|
|
||||||
<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset-purchase-invoice.png">
|
<img class="screenshot" alt="Asset" src="{{docs_base_url}}/assets/img/accounts/asset-purchase-invoice.png">
|
||||||
|
|
||||||
System will validate purchase date, supplier with the value mentioned in the Asset record. On submission of the Invoice, the "Fixed Asset Account" will be debited. It will also update Purchase Invoice number in the Asset.
|
On submission of the invoice, the "Fixed Asset Account" will be debited and payable account will be credited. It also updates purchase date, supplier and Purchase Invoice no in the Asset record.
|
||||||
|
|
||||||
|
|
||||||
## Sell an ssset
|
## Sale an ssset
|
||||||
|
|
||||||
To sale an asset, create a Sales Invoice against the item linked with the asset. On submission of Sales Invoice, following entries will take place:
|
To sale an asset, open the asset record and create a Sales Invoice using "Sale Asset" button. On submission of the Sales Invoice, following entries will take place:
|
||||||
|
|
||||||
- "Receivable Account" (Debtors) will be debited by the sales amount.
|
- "Receivable Account" (Debtors) will be debited by the sales amount.
|
||||||
- "Fixed Asset Account" will be credited by the purchase amount of asset.
|
- "Fixed Asset Account" will be credited by the purchase amount of asset.
|
||||||
@ -66,6 +69,6 @@ To sale an asset, create a Sales Invoice against the item linked with the asset.
|
|||||||
|
|
||||||
## Scrap an Asset
|
## Scrap an Asset
|
||||||
|
|
||||||
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.
|
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">
|
@ -3,7 +3,6 @@ auto-creation-of-material-request
|
|||||||
depreciation-entry
|
depreciation-entry
|
||||||
maintain-stock-field-frozen-in-item-master
|
maintain-stock-field-frozen-in-item-master
|
||||||
manage-rejected-finished-goods-items
|
manage-rejected-finished-goods-items
|
||||||
managing-assets
|
|
||||||
managing-batch-wise-inventory
|
managing-batch-wise-inventory
|
||||||
managing-fractions-in-uom
|
managing-fractions-in-uom
|
||||||
opening-stock-balance-entry-for-the-serialized-and-batch-item
|
opening-stock-balance-entry-for-the-serialized-and-batch-item
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
#Managing Assets
|
|
||||||
|
|
||||||
Items like machinery, furniture, land and property, patents etc. can be categorized as fixed asset of a company. In ERPNext, you can maintain fixed asset items, mainly stock items in a separate Warehouse.
|
|
||||||
|
|
||||||
For the high value asset items, serialized inventory can be maintained. It will allow assigning unique Serial No. to each unit of an asset item.
|
|
||||||
|
|
||||||
####Fixed Asset Master
|
|
||||||
|
|
||||||
While creating Item Code for the fixed asset item, you should check "Is Fixed Asset" field.
|
|
||||||
|
|
||||||
<img alt ="Fixed Asset Item" class="screenshot" src="{{docs_base_url}}/assets/img/articles/managing-assets-1.png">
|
|
||||||
|
|
||||||
Other item properties like Stock/Non-stock item can be updated on the nature of asset. Like patent and trademarks will be non-stock assets.
|
|
||||||
|
|
||||||
If your asset item is serialized, click [here]({{docs_base_url}}/user/videos/learn/serialized-inventory.html) to learn how serialized inventory is managed in ERPNext.
|
|
||||||
|
|
||||||
####Warehouse for Fixed Asset
|
|
||||||
|
|
||||||
Separate Warehouse should be created for the fixed asset items. All the sales, purchase and stock transactions for asset items should be done for fixed asset warehouse only.
|
|
||||||
|
|
||||||
As per the perpetual inventory valuation system, accounting ledger is auto-created for a warehouse. You can move the accounting ledger of fixed asset from Stock Asset (default group) to Fixed Asset's group account.
|
|
||||||
|
|
||||||
<!-- markdown -->
|
|
@ -64,9 +64,8 @@ class BOM(Document):
|
|||||||
self.manage_default_bom()
|
self.manage_default_bom()
|
||||||
|
|
||||||
def get_item_det(self, item_code):
|
def get_item_det(self, item_code):
|
||||||
item = frappe.db.sql("""select name, item_name, is_fixed_asset,
|
item = frappe.db.sql("""select name, item_name, docstatus, description, image,
|
||||||
docstatus, description, image, is_sub_contracted_item, stock_uom, default_bom,
|
is_sub_contracted_item, stock_uom, default_bom, last_purchase_rate
|
||||||
last_purchase_rate
|
|
||||||
from `tabItem` where name=%s""", item_code, as_dict = 1)
|
from `tabItem` where name=%s""", item_code, as_dict = 1)
|
||||||
|
|
||||||
if not item:
|
if not item:
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
|
||||||
# License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe.model.utils.rename_field import rename_field
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
frappe.reload_doctype("Item")
|
|
||||||
rename_field("Item", "is_asset_item", "is_fixed_asset")
|
|
@ -276,36 +276,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"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,
|
"allow_on_submit": 0,
|
||||||
"bold": 1,
|
"bold": 1,
|
||||||
@ -2256,7 +2226,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2016-04-15 07:10:24.271811",
|
"modified": "2016-04-15 07:10:24.271815",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item",
|
"name": "Item",
|
||||||
|
@ -88,7 +88,6 @@ class Item(WebsiteGenerator):
|
|||||||
self.validate_variant_attributes()
|
self.validate_variant_attributes()
|
||||||
self.validate_website_image()
|
self.validate_website_image()
|
||||||
self.make_thumbnail()
|
self.make_thumbnail()
|
||||||
self.validate_fixed_asset_item()
|
|
||||||
|
|
||||||
if not self.get("__islocal"):
|
if not self.get("__islocal"):
|
||||||
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
||||||
@ -609,11 +608,6 @@ class Item(WebsiteGenerator):
|
|||||||
frappe.throw(_("Item variant {0} exists with same attributes")
|
frappe.throw(_("Item variant {0} exists with same attributes")
|
||||||
.format(variant), ItemVariantExistsError)
|
.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"))
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_dashboard_data(name):
|
def get_dashboard_data(name):
|
||||||
'''load dashboard related data'''
|
'''load dashboard related data'''
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -39,7 +38,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -60,7 +58,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -87,7 +84,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Item Home Desktop 200",
|
"item_code": "_Test Item Home Desktop 200",
|
||||||
@ -104,7 +100,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_stock_item": 0,
|
"is_stock_item": 0,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -123,7 +118,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 1,
|
"is_pro_applicable": 1,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 1,
|
"is_sub_contracted_item": 1,
|
||||||
@ -138,7 +132,6 @@
|
|||||||
"has_batch_no": 0,
|
"has_batch_no": 0,
|
||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_stock_item": 0,
|
"is_stock_item": 0,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -154,7 +147,6 @@
|
|||||||
"has_batch_no": 0,
|
"has_batch_no": 0,
|
||||||
"has_serial_no": 1,
|
"has_serial_no": 1,
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -170,7 +162,6 @@
|
|||||||
"has_batch_no": 0,
|
"has_batch_no": 0,
|
||||||
"has_serial_no": 1,
|
"has_serial_no": 1,
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 0,
|
"is_pro_applicable": 0,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -190,7 +181,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 1,
|
"is_pro_applicable": 1,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 0,
|
"is_sub_contracted_item": 0,
|
||||||
@ -209,7 +199,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 1,
|
"is_pro_applicable": 1,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 1,
|
"is_sub_contracted_item": 1,
|
||||||
@ -228,7 +217,6 @@
|
|||||||
"has_serial_no": 0,
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": 0,
|
"inspection_required": 0,
|
||||||
"is_fixed_asset": 0,
|
|
||||||
"is_pro_applicable": 1,
|
"is_pro_applicable": 1,
|
||||||
"is_stock_item": 1,
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": 1,
|
"is_sub_contracted_item": 1,
|
||||||
|
@ -115,7 +115,6 @@ class MaterialRequest(BuyingController):
|
|||||||
pc_obj = frappe.get_doc('Purchase Common')
|
pc_obj = frappe.get_doc('Purchase Common')
|
||||||
|
|
||||||
pc_obj.check_for_closed_status(self.doctype, self.name)
|
pc_obj.check_for_closed_status(self.doctype, self.name)
|
||||||
pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Order', docname = self.name, detail_doctype = 'Purchase Order Item')
|
|
||||||
|
|
||||||
self.update_requested_qty()
|
self.update_requested_qty()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user