commit
202cb7cdf1
@ -8,29 +8,84 @@ frappe.ui.form.on('Asset', {
|
||||
frm.set_query("item_code", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"is_stock_item": 0,
|
||||
"is_fixed_asset": 1,
|
||||
"disabled": 0
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("warehouse", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"company": frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frappe.ui.form.trigger("Asset", "is_existing_asset");
|
||||
|
||||
if (frm.doc.docstatus==1) {
|
||||
if (in_list(["Submittted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) {
|
||||
cur_frm.add_custom_button("Scrap Asset", function() {
|
||||
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
|
||||
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);
|
||||
});
|
||||
|
||||
frm.add_custom_button("Sale Asset", function() {
|
||||
erpnext.asset.make_sales_invoice(frm);
|
||||
});
|
||||
|
||||
} 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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) {
|
||||
frappe.confirm(__("Do you really want to scrap this asset?"), function () {
|
||||
frappe.call({
|
||||
|
@ -137,6 +137,83 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "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,
|
||||
"bold": 0,
|
||||
@ -218,24 +295,23 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "disposal_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Company",
|
||||
"label": "Disposal Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -290,134 +366,6 @@
|
||||
"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": "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,
|
||||
"bold": 0,
|
||||
@ -475,14 +423,15 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "current_value",
|
||||
"depends_on": "is_existing_asset",
|
||||
"fieldname": "opening_accumulated_depreciation",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Current Value (After Depreciation)",
|
||||
"label": "Opening Accumulated Depreciation",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
@ -497,6 +446,186 @@
|
||||
"set_only_once": 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,
|
||||
"bold": 0,
|
||||
@ -583,7 +712,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-31 05:02:49.890116",
|
||||
"modified": "2016-04-20 18:09:07.573716",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Asset",
|
||||
@ -611,8 +740,9 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"read_only_onload": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
|
@ -5,17 +5,21 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
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 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):
|
||||
def validate(self):
|
||||
self.status = self.get_status()
|
||||
self.validate_fixed_asset_item()
|
||||
self.validate_item()
|
||||
self.validate_asset_values()
|
||||
self.set_depreciation_settings()
|
||||
self.make_depreciation_schedule()
|
||||
self.validate_depreciation_settings_in_company()
|
||||
# Validate depreciation related accounts
|
||||
get_depreciation_accounts(self)
|
||||
|
||||
def on_submit(self):
|
||||
self.set_status()
|
||||
@ -25,59 +29,87 @@ class Asset(Document):
|
||||
self.delete_depreciation_entries()
|
||||
self.set_status()
|
||||
|
||||
def validate_fixed_asset_item(self):
|
||||
def validate_item(self):
|
||||
item = frappe.get_doc("Item", self.item_code)
|
||||
if item.disabled:
|
||||
frappe.throw(_("Item {0} has been disabled").format(self.item_code))
|
||||
if item.is_stock_item:
|
||||
frappe.throw(_("Item {0} must be a non-stock item").format(self.item_code))
|
||||
|
||||
def validate_asset_values(self):
|
||||
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):
|
||||
frappe.throw(_("Expected Value After Useful Life must be less than Gross Purchase Amount"))
|
||||
|
||||
if not flt(self.gross_purchase_amount):
|
||||
frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError)
|
||||
|
||||
if not self.current_value and self.next_depreciation_date:
|
||||
self.current_value = flt(self.gross_purchase_amount)
|
||||
|
||||
if not self.is_existing_asset:
|
||||
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:
|
||||
if flt(self.current_value) > flt(self.gross_purchase_amount):
|
||||
frappe.throw(_("Current Value After Depreciation must be less than equal to {0}")
|
||||
.format(flt(self.gross_purchase_amount)))
|
||||
depreciable_amount = flt(self.gross_purchase_amount) - flt(self.expected_value_after_useful_life)
|
||||
if flt(self.opening_accumulated_depreciation) > depreciable_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):
|
||||
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):
|
||||
self.set(field, asset_category.get(field))
|
||||
|
||||
def make_depreciation_schedule(self):
|
||||
self.schedules = []
|
||||
if not self.get("schedules") and self.next_depreciation_date:
|
||||
accumulated_depreciation = 0
|
||||
value_after_depreciation = flt(self.current_value)
|
||||
for n in xrange(self.number_of_depreciations):
|
||||
schedule_date = add_months(self.next_depreciation_date,
|
||||
n * cint(self.number_of_months_in_a_period))
|
||||
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
||||
value_after_depreciation = flt(self.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))
|
||||
|
||||
depreciation_amount = self.get_depreciation_amount(value_after_depreciation)
|
||||
depreciation_amount = self.get_depreciation_amount(value_after_depreciation)
|
||||
|
||||
accumulated_depreciation += flt(depreciation_amount)
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
|
||||
self.append("schedules", {
|
||||
"schedule_date": schedule_date,
|
||||
"depreciation_amount": depreciation_amount,
|
||||
"accumulated_depreciation_amount": accumulated_depreciation + depreciation_amount
|
||||
})
|
||||
accumulated_depreciation += flt(depreciation_amount)
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
self.append("schedules", {
|
||||
"schedule_date": schedule_date,
|
||||
"depreciation_amount": depreciation_amount,
|
||||
"accumulated_depreciation_amount": accumulated_depreciation
|
||||
})
|
||||
|
||||
def get_depreciation_amount(self, depreciable_value):
|
||||
if self.depreciation_method == "Straight Line":
|
||||
depreciation_amount = (flt(self.current_value) -
|
||||
flt(self.expected_value_after_useful_life)) / cint(self.number_of_depreciations)
|
||||
depreciation_amount = (flt(self.value_after_depreciation) -
|
||||
flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) -
|
||||
cint(self.number_of_depreciations_booked))
|
||||
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)
|
||||
|
||||
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))
|
||||
|
||||
def delete_depreciation_entries(self):
|
||||
total_depreciation_amount = 0
|
||||
for d in self.get("schedules"):
|
||||
if d.journal_entry:
|
||||
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
|
||||
|
||||
d.db_set("journal_entry", None)
|
||||
total_depreciation_amount += flt(d.depreciation_amount)
|
||||
self.db_set("current_value", (self.current_value + total_depreciation_amount))
|
||||
|
||||
def validate_depreciation_settings_in_company(self):
|
||||
company = frappe.get_doc("Company", self.company)
|
||||
for field in ("accumulated_depreciation_account", "depreciation_expense_account",
|
||||
"disposal_account", "depreciation_cost_center"):
|
||||
if not company.get(field):
|
||||
frappe.throw(_("Please set {0} in Company {1}")
|
||||
.format(company.meta.get_label(field), self.company))
|
||||
|
||||
self.db_set("value_after_depreciation",
|
||||
(flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)))
|
||||
|
||||
def set_status(self, status=None):
|
||||
'''Set asset and update status'''
|
||||
'''Get and update status'''
|
||||
if not status:
|
||||
status = self.get_status()
|
||||
self.db_set("status", status)
|
||||
@ -125,11 +148,46 @@ class Asset(Document):
|
||||
status = "Submitted"
|
||||
if self.journal_entry_for_scrap:
|
||||
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"
|
||||
elif flt(self.current_value) < flt(self.gross_purchase_amount):
|
||||
elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount):
|
||||
status = 'Partially Depreciated'
|
||||
elif self.docstatus == 2:
|
||||
status = "Cancelled"
|
||||
|
||||
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()
|
||||
|
||||
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()
|
||||
|
||||
def get_depreciation_accounts(asset):
|
||||
@ -115,7 +115,8 @@ def scrap_asset(asset_name):
|
||||
|
||||
je.flags.ignore_permissions = True
|
||||
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)
|
||||
asset.set_status("Scrapped")
|
||||
|
||||
@ -124,7 +125,10 @@ def restore_asset(asset_name):
|
||||
asset = frappe.get_doc("Asset", asset_name)
|
||||
|
||||
je = asset.journal_entry_for_scrap
|
||||
|
||||
asset.db_set("disposal_date", None)
|
||||
asset.db_set("journal_entry_for_scrap", None)
|
||||
|
||||
frappe.get_doc("Journal Entry", je).cancel()
|
||||
|
||||
asset.set_status()
|
||||
@ -133,7 +137,7 @@ def restore_asset(asset_name):
|
||||
def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
||||
fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset)
|
||||
disposal_account, 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 = [
|
||||
{
|
||||
@ -148,8 +152,8 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
||||
}
|
||||
]
|
||||
|
||||
profit_amount = flt(selling_amount) - flt(asset.current_value)
|
||||
if flt(asset.current_value) and profit_amount:
|
||||
profit_amount = flt(selling_amount) - flt(asset.value_after_depreciation)
|
||||
if flt(asset.value_after_depreciation) and profit_amount:
|
||||
debit_or_credit = "debit" if profit_amount < 0 else "credit"
|
||||
gl_entries.append({
|
||||
"account": disposal_account,
|
||||
@ -160,12 +164,13 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0):
|
||||
|
||||
return gl_entries
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_disposal_account_and_cost_center(company):
|
||||
disposal_account, depreciation_cost_center = frappe.db.get_value("Company", company,
|
||||
["disposal_account", "depreciation_cost_center"])
|
||||
|
||||
if not disposal_account:
|
||||
frappe.throw(_("Please set 'Asset Disposal Account' in Company {0}").format(company))
|
||||
frappe.throw(_("Please set 'Gain/Loss Account on Asset Disposal' in Company {0}").format(company))
|
||||
if not depreciation_cost_center:
|
||||
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 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.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):
|
||||
def setUp(self):
|
||||
set_depreciation_settings_in_company()
|
||||
create_asset()
|
||||
|
||||
def test_purchase_asset(self):
|
||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||
asset.submit()
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
def test_fixed_asset_must_be_non_stock_item(self):
|
||||
item = frappe.get_doc("Item", "Macbook Pro")
|
||||
item.is_stock_item = 1
|
||||
self.assertRaises(frappe.ValidationError, item.save)
|
||||
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):
|
||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||
@ -25,9 +56,28 @@ class TestAsset(unittest.TestCase):
|
||||
self.assertEqual(asset.status, "Draft")
|
||||
|
||||
expected_schedules = [
|
||||
["2015-12-31", 30000, 30000],
|
||||
["2016-03-31", 30000, 60000],
|
||||
["2016-06-30", 30000, 90000]
|
||||
["2020-12-31", 30000, 30000],
|
||||
["2021-03-31", 30000, 60000],
|
||||
["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]
|
||||
@ -42,9 +92,27 @@ class TestAsset(unittest.TestCase):
|
||||
asset.save()
|
||||
|
||||
expected_schedules = [
|
||||
["2015-12-31", 66667, 66667],
|
||||
["2016-03-31", 22222, 88889],
|
||||
["2016-06-30", 1111, 90000]
|
||||
["2020-12-31", 66667, 66667],
|
||||
["2021-03-31", 22222, 88889],
|
||||
["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]
|
||||
@ -58,7 +126,7 @@ class TestAsset(unittest.TestCase):
|
||||
asset.load_from_db()
|
||||
self.assertEqual(asset.status, "Submitted")
|
||||
|
||||
post_depreciation_entries(date="2016-01-01")
|
||||
post_depreciation_entries(date="2021-01-01")
|
||||
asset.load_from_db()
|
||||
|
||||
self.assertEqual(asset.status, "Partially Depreciated")
|
||||
@ -73,13 +141,12 @@ class TestAsset(unittest.TestCase):
|
||||
order by account""", asset.name)
|
||||
|
||||
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):
|
||||
asset = frappe.get_doc("Asset", "Macbook Pro 1")
|
||||
asset.submit()
|
||||
post_depreciation_entries(date="2016-01-01")
|
||||
post_depreciation_entries(date="2021-01-01")
|
||||
|
||||
scrap_asset("Macbook Pro 1")
|
||||
|
||||
@ -107,10 +174,13 @@ class TestAsset(unittest.TestCase):
|
||||
|
||||
def test_asset_sale(self):
|
||||
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.get("items")[0].asset = "Macbook Pro 1"
|
||||
si = make_sales_invoice(asset="Macbook Pro 1", item_code="Macbook Pro", company="_Test Company")
|
||||
si.customer = "_Test Customer"
|
||||
si.due_date = nowdate()
|
||||
si.get("items")[0].rate = 25000
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Sold")
|
||||
@ -156,9 +226,10 @@ def create_asset():
|
||||
"item_code": "Macbook Pro",
|
||||
"company": "_Test Company",
|
||||
"purchase_date": "2015-01-01",
|
||||
"next_depreciation_date": "2015-12-31",
|
||||
"next_depreciation_date": "2020-12-31",
|
||||
"gross_purchase_amount": 100000,
|
||||
"expected_value_after_useful_life": 10000
|
||||
"expected_value_after_useful_life": 10000,
|
||||
"warehouse": "_Test Warehouse - _TC"
|
||||
})
|
||||
try:
|
||||
asset.save()
|
||||
@ -170,8 +241,8 @@ def create_asset():
|
||||
def create_asset_category():
|
||||
asset_category = frappe.new_doc("Asset Category")
|
||||
asset_category.asset_category_name = "Computers"
|
||||
asset_category.number_of_depreciations = 3
|
||||
asset_category.number_of_months_in_a_period = 3
|
||||
asset_category.total_number_of_depreciations = 3
|
||||
asset_category.frequency_of_depreciation = 3
|
||||
asset_category.append("accounts", {
|
||||
"company_name": "_Test Company",
|
||||
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
||||
@ -189,8 +260,7 @@ def create_fixed_asset_item():
|
||||
"description": "Macbook Pro Retina Display",
|
||||
"item_group": "All Item Groups",
|
||||
"stock_uom": "Nos",
|
||||
"is_stock_item": 0,
|
||||
"is_fixed_asset": 1
|
||||
"is_stock_item": 0
|
||||
}).insert()
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
@ -89,14 +89,14 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "number_of_depreciations",
|
||||
"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": "Number of Depreciations",
|
||||
"label": "Total Number of Depreciations",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -114,14 +114,14 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "number_of_months_in_a_period",
|
||||
"fieldname": "frequency_of_depreciation",
|
||||
"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",
|
||||
"label": "Frequency of Depreciation (Months)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -196,7 +196,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-31 05:37:48.481012",
|
||||
"modified": "2016-04-20 13:23:09.890324",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Asset Category",
|
||||
@ -244,6 +244,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
|
@ -10,6 +10,6 @@ from frappe.model.document import Document
|
||||
|
||||
class AssetCategory(Document):
|
||||
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:
|
||||
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)
|
||||
|
||||
asset_category.number_of_depreciations = 3
|
||||
asset_category.number_of_months_in_a_period = 3
|
||||
asset_category.total_number_of_depreciations = 3
|
||||
asset_category.frequency_of_depreciation = 3
|
||||
asset_category.append("accounts", {
|
||||
"company_name": "_Test Company",
|
||||
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
||||
|
@ -146,15 +146,17 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-09 12:21:27.938215",
|
||||
"modified": "2016-04-20 16:43:21.407123",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Depreciation Schedule",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
}
|
@ -34,5 +34,29 @@
|
||||
"year": "_Test Fiscal Year 2017",
|
||||
"year_end_date": "2017-12-31",
|
||||
"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
|
||||
})
|
||||
},
|
||||
|
||||
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);
|
||||
|
@ -62,6 +62,7 @@ class PurchaseInvoice(BuyingController):
|
||||
self.set_against_expense_account()
|
||||
self.validate_write_off_account()
|
||||
self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items")
|
||||
self.validate_fixed_asset()
|
||||
self.validate_fixed_asset_account()
|
||||
self.create_remarks()
|
||||
|
||||
@ -165,11 +166,10 @@ class PurchaseInvoice(BuyingController):
|
||||
# in case of auto inventory accounting,
|
||||
# expense account is always "Stock Received But Not Billed" for a stock item
|
||||
# except epening entry, drop-ship entry and fixed asset items
|
||||
|
||||
if auto_accounting_for_stock and self.is_opening == 'No' \
|
||||
and item.item_code in stock_items and ((not item.po_detail
|
||||
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 auto_accounting_for_stock and item.item_code in stock_items and self.is_opening == 'No' \
|
||||
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")):
|
||||
|
||||
if self.update_stock:
|
||||
item.expense_account = warehouse_account[item.warehouse]["name"]
|
||||
@ -290,8 +290,6 @@ class PurchaseInvoice(BuyingController):
|
||||
self.check_prev_docstatus()
|
||||
self.update_status_updater_args()
|
||||
|
||||
self.validate_asset()
|
||||
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
||||
self.company, self.base_grand_total)
|
||||
|
||||
@ -312,34 +310,23 @@ class PurchaseInvoice(BuyingController):
|
||||
self.make_gl_entries()
|
||||
|
||||
self.update_project()
|
||||
self.update_fixed_asset()
|
||||
|
||||
def validate_asset(self):
|
||||
def update_fixed_asset(self):
|
||||
for d in self.get("items"):
|
||||
if frappe.db.get_value("Item", d.item_code, "is_fixed_asset"):
|
||||
if not d.asset:
|
||||
frappe.throw(_("Row #{0}: Asset is mandatory against a Fixed Asset Item").format(d.idx))
|
||||
if d.is_fixed_asset:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
if self.docstatus==1:
|
||||
asset.purchase_invoice = self.name
|
||||
asset.purchase_date = self.posting_date
|
||||
asset.supplier = self.supplier
|
||||
else:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
asset.purchase_invoice = None
|
||||
asset.supplier = None
|
||||
|
||||
super(PurchaseInvoice, self).validate_asset(asset, d)
|
||||
|
||||
if getdate(asset.purchase_date) != getdate(self.posting_date):
|
||||
frappe.throw(_("Purchase Date of asset {0} does not match with Purchase Invoice date")
|
||||
.format(d.asset))
|
||||
asset.flags.ignore_validate_update_after_submit = True
|
||||
asset.save()
|
||||
|
||||
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):
|
||||
self.auto_accounting_for_stock = \
|
||||
cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
|
||||
@ -612,7 +599,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
self.update_project()
|
||||
self.validate_asset()
|
||||
self.update_fixed_asset()
|
||||
|
||||
def update_project(self):
|
||||
project_list = []
|
||||
@ -666,7 +653,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
def validate_fixed_asset_account(self):
|
||||
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")
|
||||
if account_type != 'Fixed Asset':
|
||||
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):
|
||||
from erpnext.controllers.sales_and_purchase_return import make_return_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,
|
||||
"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,
|
||||
"bold": 0,
|
||||
@ -1098,6 +1123,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": ":Company",
|
||||
"depends_on": "eval:!doc.is_fixed_asset",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1335,6 +1361,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "is_fixed_asset",
|
||||
"fieldname": "asset",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1545,7 +1572,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-04-18 08:08:53.056818",
|
||||
"modified": "2016-04-18 08:08:53.056819",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"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",
|
||||
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.accounts.utils import get_account_currency
|
||||
from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
|
||||
from erpnext.accounts.doctype.asset.depreciation import get_gl_entries_on_asset_disposal
|
||||
from erpnext.accounts.doctype.asset.depreciation \
|
||||
import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal
|
||||
|
||||
form_grid_templates = {
|
||||
"items": "templates/form_grid/item_grid.html"
|
||||
@ -60,8 +61,9 @@ class SalesInvoice(SellingController):
|
||||
self.validate_advance_jv("Sales Order")
|
||||
self.add_remarks()
|
||||
self.validate_write_off_account()
|
||||
self.validate_fixed_asset()
|
||||
self.set_income_account_for_fixed_assets()
|
||||
|
||||
|
||||
if cint(self.is_pos):
|
||||
self.validate_pos()
|
||||
|
||||
@ -454,16 +456,15 @@ class SalesInvoice(SellingController):
|
||||
return warehouse
|
||||
|
||||
def set_income_account_for_fixed_assets(self):
|
||||
disposal_account = None
|
||||
disposal_account = depreciation_cost_center = None
|
||||
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:
|
||||
disposal_account = frappe.db.get_value("Company", self.company, "disposal_account")
|
||||
if not disposal_account:
|
||||
frappe.throw(_("Please mention 'Gain/Loss Account on Asset Disposal' in Company"))
|
||||
|
||||
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(self.company)
|
||||
|
||||
d.income_account = disposal_account
|
||||
|
||||
if not d.cost_center:
|
||||
d.cost_center = depreciation_cost_center
|
||||
|
||||
def check_prev_docstatus(self):
|
||||
for d in self.get('items'):
|
||||
@ -472,13 +473,6 @@ class SalesInvoice(SellingController):
|
||||
|
||||
if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
|
||||
throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
|
||||
|
||||
def validate_asset(self, asset, item_row):
|
||||
super(SalesInvoice, self).validate_asset(asset, item_row)
|
||||
|
||||
if self.docstatus == 1 and asset.status in ("Scrapped", "Cancelled", "Sold"):
|
||||
frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}")
|
||||
.format(item_row.idx, asset.name, asset.status))
|
||||
|
||||
def make_gl_entries(self, repost_future_gle=True):
|
||||
gl_entries = self.get_gl_entries()
|
||||
@ -565,19 +559,16 @@ class SalesInvoice(SellingController):
|
||||
# income account gl entries
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount):
|
||||
if frappe.db.get_value("Item", item.item_code, "is_fixed_asset"):
|
||||
if not item.asset:
|
||||
frappe.throw(_("Row #{0}: Asset is mandatory against a Fixed Asset Item")
|
||||
.format(item.idx))
|
||||
else:
|
||||
asset = frappe.get_doc("Asset", item.asset)
|
||||
self.validate_asset(asset, item)
|
||||
if item.is_fixed_asset:
|
||||
asset = frappe.get_doc("Asset", item.asset)
|
||||
|
||||
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount)
|
||||
for gle in fixed_asset_gl_entries:
|
||||
gle["against"] = self.customer
|
||||
gl_entries.append(self.get_gl_dict(gle))
|
||||
|
||||
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount)
|
||||
for gle in fixed_asset_gl_entries:
|
||||
gl_entries.append(self.get_gl_dict(gle))
|
||||
|
||||
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:
|
||||
account_currency = get_account_currency(item.income_account)
|
||||
gl_entries.append(
|
||||
@ -743,4 +734,4 @@ def make_delivery_note(source_name, target_doc=None):
|
||||
@frappe.whitelist()
|
||||
def make_sales_return(source_name, target_doc=None):
|
||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||
return make_return_doc("Sales Invoice", source_name, target_doc)
|
||||
return make_return_doc("Sales Invoice", source_name, target_doc)
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
]
|
@ -79,18 +79,4 @@ class PurchaseCommon(BuyingController):
|
||||
status = frappe.db.get_value(doctype, docname, "status")
|
||||
|
||||
if status == "Closed":
|
||||
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]))
|
||||
frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
import json
|
||||
from frappe.utils import cstr, flt
|
||||
from frappe import msgprint, _, throw
|
||||
from frappe import msgprint, _
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from erpnext.controllers.buying_controller import BuyingController
|
||||
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')
|
||||
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')
|
||||
|
||||
self.update_prevdoc_status()
|
||||
|
@ -340,6 +340,18 @@ def get_data():
|
||||
"label": _("Other Reports"),
|
||||
"icon": "icon-table",
|
||||
"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",
|
||||
"name": "Trial Balance for Party",
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
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.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
|
||||
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
|
||||
# from creating a sales invoice if sales order is already created
|
||||
|
||||
def validate_asset(self, asset, item_row):
|
||||
if asset.company != self.company:
|
||||
frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}")
|
||||
.format(item_row.idx, item_row.asset, self.company))
|
||||
def validate_fixed_asset(self):
|
||||
for d in self.get("items"):
|
||||
if d.is_fixed_asset:
|
||||
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:
|
||||
frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}")
|
||||
.format(item_row.idx, item_row.asset, item_row.item_code))
|
||||
elif asset.docstatus != 1:
|
||||
frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(item_row.idx, item_row.asset))
|
||||
elif item_row.qty > 1:
|
||||
frappe.throw(_("Row #{0}: Qty must be 1, as item is linked to an asset").format(item_row.idx))
|
||||
if d.meta.get_field("asset"):
|
||||
if not d.asset:
|
||||
frappe.throw(_("Row #{0}: Asset is mandatory for fixed asset purchase/sale")
|
||||
.format(d.idx))
|
||||
else:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
|
||||
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()
|
||||
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 >
|
||||
<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 class="info">
|
||||
Column Break</td>
|
||||
@ -321,7 +342,7 @@
|
||||
</tr>
|
||||
|
||||
<tr >
|
||||
<td>20</td>
|
||||
<td>21</td>
|
||||
<td ><code>min_order_qty</code></td>
|
||||
<td >
|
||||
Float</td>
|
||||
@ -333,7 +354,7 @@
|
||||
</tr>
|
||||
|
||||
<tr >
|
||||
<td>21</td>
|
||||
<td>22</td>
|
||||
<td ><code>projected_qty</code></td>
|
||||
<td >
|
||||
Float</td>
|
||||
@ -345,7 +366,7 @@
|
||||
</tr>
|
||||
|
||||
<tr >
|
||||
<td>22</td>
|
||||
<td>23</td>
|
||||
<td ><code>ordered_qty</code></td>
|
||||
<td >
|
||||
Float</td>
|
||||
@ -357,7 +378,7 @@
|
||||
</tr>
|
||||
|
||||
<tr >
|
||||
<td>23</td>
|
||||
<td>24</td>
|
||||
<td ><code>page_break</code></td>
|
||||
<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
|
||||
|
||||
@ -11,24 +11,27 @@ To start first you should create Asset Category, depending on the type of assets
|
||||
|
||||
## 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">
|
||||
|
||||
Explanation of the fields:
|
||||
|
||||
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.
|
||||
4. Gross Purchase Amount: The purchase cost 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.
|
||||
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.
|
||||
7. Depreciation Method: There are two options: Straight Line and Double Declining Balance.
|
||||
4. Warehouse: Set the location of the asset.
|
||||
5. Gross Purchase Amount: The purchase cost of the asset
|
||||
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. 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.
|
||||
- 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.
|
||||
9. Number of Months in a Period: The number of months between two depreciations.
|
||||
10. Next Depreciation Date: Mention the next depreciation date, even if it is the first one. If depreciation already completed, leave it blank.
|
||||
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.
|
||||
11. Number of Depreciations Booked: Enter the number of already booked depreciations for an existing asset.
|
||||
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
|
||||
|
||||
@ -45,16 +48,16 @@ In the depreciation entry, the "Accumulated Depreciation Account" is credited an
|
||||
|
||||
## 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">
|
||||
|
||||
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.
|
||||
- "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
|
||||
|
||||
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">
|
@ -3,7 +3,6 @@ auto-creation-of-material-request
|
||||
depreciation-entry
|
||||
maintain-stock-field-frozen-in-item-master
|
||||
manage-rejected-finished-goods-items
|
||||
managing-assets
|
||||
managing-batch-wise-inventory
|
||||
managing-fractions-in-uom
|
||||
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()
|
||||
|
||||
def get_item_det(self, item_code):
|
||||
item = frappe.db.sql("""select name, item_name, is_fixed_asset,
|
||||
docstatus, description, image, is_sub_contracted_item, stock_uom, default_bom,
|
||||
last_purchase_rate
|
||||
item = frappe.db.sql("""select name, item_name, docstatus, description, image,
|
||||
is_sub_contracted_item, stock_uom, default_bom, last_purchase_rate
|
||||
from `tabItem` where name=%s""", item_code, as_dict = 1)
|
||||
|
||||
if not item:
|
||||
|
@ -1,12 +1,12 @@
|
||||
[
|
||||
{
|
||||
"bom_no": "BOM-_Test FG Item-001",
|
||||
"company": "_Test Company",
|
||||
"doctype": "Production Order",
|
||||
"fg_warehouse": "_Test Warehouse 1 - _TC",
|
||||
"production_item": "_Test FG Item",
|
||||
"qty": 10.0,
|
||||
"stock_uom": "_Test UOM",
|
||||
"bom_no": "BOM-_Test FG Item-001",
|
||||
"company": "_Test Company",
|
||||
"doctype": "Production Order",
|
||||
"fg_warehouse": "_Test Warehouse 1 - _TC",
|
||||
"production_item": "_Test FG Item",
|
||||
"qty": 10.0,
|
||||
"stock_uom": "_Test UOM",
|
||||
"wip_warehouse": "_Test Warehouse - _TC"
|
||||
}
|
||||
]
|
||||
|
@ -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,
|
||||
"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,
|
||||
"bold": 1,
|
||||
@ -2256,7 +2226,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 1,
|
||||
"modified": "2016-04-15 07:10:24.271811",
|
||||
"modified": "2016-04-15 07:10:24.271815",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item",
|
||||
|
@ -88,7 +88,6 @@ class Item(WebsiteGenerator):
|
||||
self.validate_variant_attributes()
|
||||
self.validate_website_image()
|
||||
self.make_thumbnail()
|
||||
self.validate_fixed_asset_item()
|
||||
|
||||
if not self.get("__islocal"):
|
||||
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
||||
@ -609,11 +608,6 @@ class Item(WebsiteGenerator):
|
||||
frappe.throw(_("Item variant {0} exists with same attributes")
|
||||
.format(variant), ItemVariantExistsError)
|
||||
|
||||
def validate_fixed_asset_item(self):
|
||||
if self.is_fixed_asset and self.is_stock_item:
|
||||
frappe.throw(_("Fixed Asset Item must be a non-stock item"))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_dashboard_data(name):
|
||||
'''load dashboard related data'''
|
||||
|
@ -9,7 +9,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -39,7 +38,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -60,7 +58,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -87,7 +84,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_sub_contracted_item": 0,
|
||||
"item_code": "_Test Item Home Desktop 200",
|
||||
@ -104,7 +100,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_stock_item": 0,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -123,7 +118,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 1,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 1,
|
||||
@ -138,7 +132,6 @@
|
||||
"has_batch_no": 0,
|
||||
"has_serial_no": 0,
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_stock_item": 0,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -154,7 +147,6 @@
|
||||
"has_batch_no": 0,
|
||||
"has_serial_no": 1,
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -170,7 +162,6 @@
|
||||
"has_batch_no": 0,
|
||||
"has_serial_no": 1,
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -190,7 +181,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 1,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 0,
|
||||
@ -209,7 +199,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 1,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 1,
|
||||
@ -228,7 +217,6 @@
|
||||
"has_serial_no": 0,
|
||||
"income_account": "Sales - _TC",
|
||||
"inspection_required": 0,
|
||||
"is_fixed_asset": 0,
|
||||
"is_pro_applicable": 1,
|
||||
"is_stock_item": 1,
|
||||
"is_sub_contracted_item": 1,
|
||||
|
@ -115,7 +115,6 @@ class MaterialRequest(BuyingController):
|
||||
pc_obj = frappe.get_doc('Purchase Common')
|
||||
|
||||
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()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user