Merge pull request #13750 from rohitwaghchaure/asset_purchase_link
Asset linked to purchase and serial no
diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json
index 668164c..de28a59 100644
--- a/erpnext/accounts/doctype/account/account.json
+++ b/erpnext/accounts/doctype/account/account.json
@@ -412,7 +412,7 @@
"no_copy": 0,
"oldfieldname": "account_type",
"oldfieldtype": "Select",
- "options": "\nAccumulated Depreciation\nBank\nCash\nChargeable\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nTax\nTemporary",
+ "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nTax\nTemporary",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -625,7 +625,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-05-02 11:00:34.108490",
+ "modified": "2018-05-07 15:37:25.962506",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py
index 5452040..6e16371 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py
@@ -63,7 +63,10 @@
},
_("Accumulated Depreciation"): {
"account_type": "Accumulated Depreciation"
- }
+ },
+ _("CWIP Account"): {
+ "account_type": "Capital Work in Progress",
+ }
},
_("Investments"): {
"is_group": 1
@@ -81,6 +84,9 @@
_("Cost of Goods Sold"): {
"account_type": "Cost of Goods Sold"
},
+ _("Expenses Included In Asset Valuation"): {
+ "account_type": "Expenses Included In Asset Valuation"
+ },
_("Expenses Included In Valuation"): {
"account_type": "Expenses Included In Valuation"
},
@@ -146,6 +152,9 @@
_("Stock Received But Not Billed"): {
"account_type": "Stock Received But Not Billed"
},
+ _("Asset Received But Not Billed"): {
+ "account_type": "Asset Received But Not Billed"
+ }
},
_("Duties and Taxes"): {
"account_type": "Tax",
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py
index bad8453..5ed3e45 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py
@@ -85,6 +85,10 @@
"account_type": "Accumulated Depreciation",
"account_number": "1780"
},
+ _("CWIP Account"): {
+ "account_type": "Capital Work in Progress",
+ "account_number": "1790"
+ },
"account_number": "1700"
},
_("Investments"): {
@@ -108,6 +112,10 @@
"account_type": "Cost of Goods Sold",
"account_number": "5111"
},
+ _("Expenses Included In Asset Valuation"): {
+ "account_type": "Expenses Included In Asset Valuation",
+ "account_number": "5112"
+ },
_("Expenses Included In Valuation"): {
"account_type": "Expenses Included In Valuation",
"account_number": "5118"
@@ -228,6 +236,10 @@
"account_type": "Stock Received But Not Billed",
"account_number": "2210"
},
+ _("Asset Received But Not Billed"): {
+ "account_type": "Asset Received But Not Billed",
+ "account_number": "2211"
+ },
"account_number": "2200"
},
_("Duties and Taxes"): {
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 51308e50..9bbd137 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe, erpnext, json
-from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, nowdate
+from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, nowdate, cint
from frappe import msgprint, _, scrub
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on, get_account_currency
@@ -92,6 +92,7 @@
self.unlink_advance_entry_reference()
self.unlink_asset_reference()
self.unlink_inter_company_jv()
+ self.unlink_asset_adjustment_entry()
def unlink_advance_entry_reference(self):
for d in self.get("accounts"):
@@ -109,9 +110,12 @@
for s in asset.get("schedules"):
if s.journal_entry == self.name:
s.db_set("journal_entry", None)
- asset.value_after_depreciation += s.depreciation_amount
- asset.db_set("value_after_depreciation", asset.value_after_depreciation)
+ idx = cint(s.finance_book_id) or 1
+ finance_books = asset.get('finance_books')[idx - 1]
+ finance_books.value_after_depreciation += s.depreciation_amount
+ finance_books.db_update()
+
asset.set_status()
def unlink_inter_company_jv(self):
@@ -121,6 +125,10 @@
frappe.db.set_value("Journal Entry", self.name,\
"inter_company_journal_entry_reference", "")
+ def unlink_asset_adjustment_entry(self):
+ frappe.db.sql(""" update `tabAsset Adjustment`
+ set journal_entry = null where journal_entry = %s""", self.name)
+
def validate_party(self):
for d in self.get("accounts"):
account_type = frappe.db.get_value("Account", d.account, "account_type")
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index e7fdd64..d2c4193 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -205,9 +205,10 @@
var row = locals[cdt][cdn];
if(row.asset) {
frappe.call({
- method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.get_fixed_asset_account",
+ method: "erpnext.assets.doctype.asset_category.asset_category.get_asset_category_account",
args: {
"asset": row.asset,
+ "fieldname": "fixed_asset_account",
"account": row.expense_account
},
callback: function(r, rt) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 67b41a3..3e375e5 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -19,6 +19,7 @@
from frappe.model.mapper import get_mapped_doc
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\
unlink_inter_company_invoice
+from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -305,24 +306,8 @@
self.make_gl_entries()
self.update_project()
- self.update_fixed_asset()
update_linked_invoice(self.doctype, self.name, self.inter_company_invoice_reference)
- def update_fixed_asset(self):
- for d in self.get("items"):
- 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.purchase_invoice = None
- asset.supplier = None
-
- asset.flags.ignore_validate_update_after_submit = True
- asset.save()
-
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
if not self.grand_total:
return
@@ -438,6 +423,50 @@
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.rm_supp_cost)
}, warehouse_account[self.supplier_warehouse]["account_currency"]))
+
+ elif item.is_fixed_asset:
+ asset_accounts = self.get_company_default(["asset_received_but_not_billed",
+ "expenses_included_in_asset_valuation", "capital_work_in_progress_account"])
+
+ asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate)
+ base_asset_amount = flt(item.base_net_amount + item.item_tax_amount)
+
+ if not self.update_stock:
+ asset_rbnb_currency = get_account_currency(asset_accounts[0])
+ gl_entries.append(self.get_gl_dict({
+ "account": asset_accounts[0],
+ "against": self.supplier,
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "debit": base_asset_amount,
+ "debit_in_account_currency": (base_asset_amount
+ if asset_rbnb_currency == self.company_currency else asset_amount)
+ }))
+ else:
+ cwip_account = get_asset_category_account(item.asset,
+ 'capital_work_in_progress_account') or asset_accounts[2]
+
+ cwip_account_currency = get_account_currency(cwip_account)
+ gl_entries.append(self.get_gl_dict({
+ "account": cwip_account,
+ "against": self.supplier,
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "debit": base_asset_amount,
+ "debit_in_account_currency": (base_asset_amount
+ if cwip_account_currency == self.company_currency else asset_amount)
+ }))
+
+ if item.item_tax_amount:
+ asset_eiiav_currency = get_account_currency(asset_accounts[0])
+ gl_entries.append(self.get_gl_dict({
+ "account": asset_accounts[1],
+ "against": self.supplier,
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "cost_center": item.cost_center,
+ "credit": item.item_tax_amount,
+ "credit_in_account_currency": (item.item_tax_amount
+ if asset_eiiav_currency == self.company_currency else
+ item.item_tax_amount / self.conversion_rate)
+ }))
else:
gl_entries.append(
self.get_gl_dict({
@@ -636,7 +665,6 @@
self.make_gl_entries_on_cancel()
self.update_project()
- self.update_fixed_asset()
frappe.db.set(self, 'status', 'Cancelled')
unlink_inter_company_invoice(self.doctype, self.name, self.inter_company_invoice_reference)
@@ -709,20 +737,6 @@
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
-
-@frappe.whitelist()
def make_stock_entry(source_name, target_doc=None):
doc = get_mapped_doc("Purchase Invoice", source_name, {
"Purchase Invoice": {
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index d1f99ab..ef9b2f6 100755
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -2258,7 +2258,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-02-22 15:15:25.297672",
+ "modified": "2018-04-23 14:07:33.576495",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index f4a01ae..c05667a 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -57,6 +57,19 @@
erpnext.asset.restore_asset(frm);
});
}
+
+ if (frm.doc.purchase_receipt) {
+ frm.add_custom_button("General Ledger", function() {
+ frappe.route_options = {
+ "voucher_no": frm.doc.name,
+ "from_date": frm.doc.available_for_use_date,
+ "to_date": frm.doc.available_for_use_date,
+ "company": frm.doc.company
+ };
+ frappe.set_route("query-report", "General Ledger");
+ });
+ }
+
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
frm.add_custom_button(__("Purchase Invoice"), function() {
frm.trigger("make_purchase_invoice");
@@ -67,6 +80,12 @@
frm.trigger("create_asset_maintenance");
}, __("Make"));
}
+ if (frm.doc.status != 'Fully Depreciated') {
+ frm.add_custom_button(__("Asset Adjustment"), function() {
+ frm.trigger("create_asset_maintenance");
+ }, __("Make"));
+ }
+
frm.page.set_inner_btn_group_as_primary(__("Make"));
frm.trigger("setup_chart");
}
@@ -131,9 +150,7 @@
},
callback: function(r, rt) {
if(r.message) {
- $.each(r.message, function(field, value) {
- frm.set_value(field, value);
- })
+ frm.set_value('finance_books', r.message);
}
}
})
@@ -141,7 +158,7 @@
},
is_existing_asset: function(frm) {
- frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
+ // frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
},
opening_accumulated_depreciation: function(frm) {
@@ -181,7 +198,8 @@
args: {
"asset": frm.doc.name,
"item_code": frm.doc.item_code,
- "company": frm.doc.company
+ "company": frm.doc.company,
+ "serial_no": frm.doc.serial_no
},
method: "erpnext.assets.doctype.asset.asset.make_sales_invoice",
callback: function(r) {
@@ -290,15 +308,14 @@
title: __("Transfer Asset"),
fields: [
{
- "label": __("Target Warehouse"),
- "fieldname": "target_warehouse",
+ "label": __("Target Location"),
+ "fieldname": "target_location",
"fieldtype": "Link",
- "options": "Warehouse",
+ "options": "Location",
"get_query": function () {
return {
filters: [
- ["Warehouse", "company", "in", ["", cstr(frm.doc.company)]],
- ["Warehouse", "is_group", "=", 0]
+ ["Location", "is_group", "=", 0]
]
}
},
@@ -325,8 +342,8 @@
args: {
"asset": frm.doc.name,
"transaction_date": args.transfer_date,
- "source_warehouse": frm.doc.warehouse,
- "target_warehouse": args.target_warehouse,
+ "source_warehouse": frm.doc.location,
+ "target_warehouse": args.target_location,
"company": frm.doc.company
}
},
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index 49b574d..49a010d 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -3,7 +3,7 @@
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
- "autoname": "field:asset_name",
+ "autoname": "naming_series:",
"beta": 0,
"creation": "2016-03-01 17:01:27.920130",
"custom": 0,
@@ -18,6 +18,38 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "default": "AST",
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Naming Series",
+ "length": 0,
+ "no_copy": 0,
+ "options": "AST\nAT",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "asset_name",
"fieldtype": "Data",
"hidden": 0,
@@ -137,38 +169,6 @@
},
{
"allow_bulk_edit": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Draft",
- "fieldname": "status",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Status",
- "length": 0,
- "no_copy": 1,
- "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -390,7 +390,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "warehouse",
+ "fieldname": "location",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -398,11 +398,11 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Warehouse",
+ "in_standard_filter": 0,
+ "label": "Location",
"length": 0,
"no_copy": 0,
- "options": "Warehouse",
+ "options": "Location",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -421,6 +421,37 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "custodian",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Custodian",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Employee",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "department",
"fieldtype": "Link",
"hidden": 0,
@@ -482,97 +513,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "purchase_invoice",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Purchase Invoice",
- "length": 0,
- "no_copy": 1,
- "options": "Purchase Invoice",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "available_for_use_date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Available-for-use Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "is_existing_asset",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 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,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "disposal_date",
"fieldtype": "Date",
"hidden": 0,
@@ -694,6 +634,36 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "available_for_use_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Available-for-use Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "column_break_18",
"fieldtype": "Column Break",
"hidden": 0,
@@ -723,99 +693,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "description": "",
- "fieldname": "expected_value_after_useful_life",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Expected Value After Useful Life",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "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_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Opening Accumulated Depreciation",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_20",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "calculate_depreciation",
"fieldtype": "Check",
"hidden": 0,
@@ -844,7 +721,100 @@
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
- "collapsible": 1,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "is_existing_asset",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 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,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "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_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Opening Accumulated Depreciation",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 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_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 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,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"columns": 0,
"depends_on": "calculate_depreciation",
"fieldname": "section_break_23",
@@ -877,6 +847,66 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "finance_books",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Finance Books",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Asset Finance Book",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "section_break_33",
+ "fieldtype": "Section Break",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"default": "",
"depends_on": "",
"fieldname": "depreciation_method",
@@ -1000,37 +1030,6 @@
"bold": 0,
"collapsible": 0,
"columns": 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_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 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,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "frequency_of_depreciation",
"fieldtype": "Int",
"hidden": 0,
@@ -1152,6 +1151,245 @@
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
+ "collapsible": 1,
+ "columns": 0,
+ "fieldname": "insurance_details",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Insurance details",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "policy_number",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Policy number",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "insurer",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Insurer",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "insured_value",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Insured value",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_48",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "insurance_start_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Insurance Start Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "insurance_end_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Insurance End Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "comprehensive_insurance",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Comprehensive Insurance",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_31",
@@ -1213,6 +1451,220 @@
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
+ "collapsible": 1,
+ "columns": 0,
+ "fieldname": "other_details",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Other Details",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "Draft",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Status",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order\nIssue\nReceipt",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "fieldname": "booked_fixed_asset",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Booked Fixed Asset",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_51",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "purchase_receipt",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Purchase Receipt",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Purchase Receipt",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "purchase_receipt_amount",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Purchase Receipt Amount",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "purchase_invoice",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Purchase Invoice",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Purchase Invoice",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
@@ -1251,7 +1703,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-01-05 09:53:05.945328",
+ "modified": "2018-05-11 10:41:45.972686",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
@@ -1307,4 +1759,4 @@
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
-}
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index baffdd7..55a29bc 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -7,11 +7,14 @@
from frappe import _
from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff
from frappe.model.document import Document
-from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_fixed_asset_account
+from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.assets.doctype.asset.depreciation \
import get_disposal_account_and_cost_center, get_depreciation_accounts
+from erpnext.accounts.general_ledger import make_gl_entries
+from erpnext.accounts.utils import get_account_currency
+from erpnext.controllers.accounts_controller import AccountsController
-class Asset(Document):
+class Asset(AccountsController):
def validate(self):
self.status = self.get_status()
self.validate_item()
@@ -26,6 +29,7 @@
def on_submit(self):
self.set_status()
+ self.update_stock_movement()
def on_cancel(self):
self.validate_cancellation()
@@ -45,11 +49,12 @@
frappe.throw(_("Item {0} must be a non-stock item").format(self.item_code))
def set_missing_values(self):
- if self.item_code:
- item_details = get_item_details(self.item_code)
- for field, value in item_details.items():
- if not self.get(field):
- self.set(field, value)
+ if not self.asset_category:
+ self.asset_category = frappe.db.get_value("Item", self.item_code, "asset_category")
+
+ if self.item_code and not self.get('finance_books'):
+ finance_books = get_item_details(self.item_code, self.asset_category)
+ self.set('finance_books', finance_books)
def validate_asset_values(self):
if not flt(self.gross_purchase_amount):
@@ -58,16 +63,105 @@
if not self.calculate_depreciation:
return
- 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 self.available_for_use_date and getdate(self.available_for_use_date) < getdate(nowdate()):
+ frappe.throw(_("Available-for-use Date is entered as past date"))
+
+ def make_depreciation_schedule(self):
+ if self.depreciation_method != 'Manual':
+ self.schedules = []
+
+ if not self.get("schedules") and self.available_for_use_date:
+ total_depreciations = sum([d.total_number_of_depreciations for d in self.get('finance_books')])
+
+ for d in self.get('finance_books'):
+ self.validate_asset_finance_books(d)
+
+ value_after_depreciation = (flt(self.gross_purchase_amount) -
+ flt(self.opening_accumulated_depreciation))
+
+ d.value_after_depreciation = value_after_depreciation
+
+ no_of_depreciations = cint(d.total_number_of_depreciations - 1) - cint(self.number_of_depreciations_booked)
+ end_date = add_months(d.depreciation_start_date,
+ no_of_depreciations * cint(d.frequency_of_depreciation))
+
+ total_days = date_diff(end_date, self.available_for_use_date)
+ rate_per_day = value_after_depreciation / total_days
+
+ number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
+ cint(self.number_of_depreciations_booked)
+
+ from_date = self.available_for_use_date
+ if number_of_pending_depreciations:
+ next_depr_date = getdate(add_months(self.available_for_use_date,
+ number_of_pending_depreciations * 12))
+ if (cint(frappe.db.get_value("Asset Settings", None, "schedule_based_on_fiscal_year")) == 1
+ and getdate(d.depreciation_start_date) < next_depr_date):
+
+ number_of_pending_depreciations += 1
+ for n in range(number_of_pending_depreciations):
+ if n == range(number_of_pending_depreciations)[-1]:
+ schedule_date = add_months(self.available_for_use_date, n * 12)
+ previous_scheduled_date = add_months(d.depreciation_start_date, (n-1) * 12)
+ depreciation_amount = \
+ self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
+ d, previous_scheduled_date, schedule_date)
+
+ elif n == range(number_of_pending_depreciations)[0]:
+ schedule_date = d.depreciation_start_date
+ depreciation_amount = \
+ self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
+ d, self.available_for_use_date, schedule_date)
+
+ else:
+ schedule_date = add_months(d.depreciation_start_date, n * 12)
+ depreciation_amount = \
+ self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d)
+
+ if value_after_depreciation != 0:
+ value_after_depreciation -= flt(depreciation_amount)
+
+ self.append("schedules", {
+ "schedule_date": schedule_date,
+ "depreciation_amount": depreciation_amount,
+ "depreciation_method": d.depreciation_method,
+ "finance_book": d.finance_book,
+ "finance_book_id": d.idx
+ })
+ else:
+ for n in range(number_of_pending_depreciations):
+ schedule_date = add_months(d.depreciation_start_date,
+ n * cint(d.frequency_of_depreciation))
+
+ if d.depreciation_method in ("Straight Line", "Manual"):
+ days = date_diff(schedule_date, from_date)
+ depreciation_amount = days * rate_per_day
+ from_date = schedule_date
+ else:
+ depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
+ d.total_number_of_depreciations, d)
+
+ if depreciation_amount:
+ value_after_depreciation -= flt(depreciation_amount)
+
+ self.append("schedules", {
+ "schedule_date": schedule_date,
+ "depreciation_amount": depreciation_amount,
+ "depreciation_method": d.depreciation_method,
+ "finance_book": d.finance_book,
+ "finance_book_id": d.idx
+ })
+
+ def validate_asset_finance_books(self, row):
+ if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
+ frappe.throw(_("Row {0}: Expected Value After Useful Life must be less than Gross Purchase Amount")
+ .format(row.idx))
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:
- depreciable_amount = flt(self.gross_purchase_amount) - flt(self.expected_value_after_useful_life)
+ depreciable_amount = flt(self.gross_purchase_amount) - flt(row.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))
@@ -78,139 +172,89 @@
else:
self.number_of_depreciations_booked = 0
- if cint(self.number_of_depreciations_booked) > cint(self.total_number_of_depreciations):
+ if cint(self.number_of_depreciations_booked) > cint(row.total_number_of_depreciations):
frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations"))
- self.value_after_depreciation = (flt(self.gross_purchase_amount) -
- flt(self.opening_accumulated_depreciation))
+ if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(nowdate()):
+ frappe.msgprint(_("Depreciation Row {0}: Depreciation Start Date is entered as past date")
+ .format(row.idx), title=_('Warning'), indicator='red')
- if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(nowdate()):
- frappe.msgprint(_("Next Depreciation Date is entered as past date"), title=_('Warning'), indicator='red')
+ if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(self.purchase_date):
+ frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Purchase Date")
+ .format(row.idx))
- if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(self.purchase_date):
- frappe.throw(_("Next Depreciation Date cannot be before Purchase Date"))
+ if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(self.available_for_use_date):
+ frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date")
+ .format(row.idx))
- if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(self.available_for_use_date):
- frappe.throw(_("Next Depreciation Date cannot be before Available-for-use Date"))
+ def set_accumulated_depreciation(self, ignore_booked_entry = False):
+ straight_line_idx = [d.idx for d in self.get("schedules") if d.depreciation_method == 'Straight Line']
+ finance_books = []
- if (flt(self.value_after_depreciation) > flt(self.expected_value_after_useful_life)
- and not self.next_depreciation_date and self.calculate_depreciation):
- frappe.throw(_("Please set Next Depreciation Date"))
-
- def make_depreciation_schedule(self):
-
- if self.depreciation_method != 'Manual':
- self.schedules = []
-
- if not self.get("schedules") and self.next_depreciation_date:
- 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:
- next_depr_date = getdate(add_months(self.available_for_use_date,
- number_of_pending_depreciations * 12))
- if (cint(frappe.db.get_value("Asset Settings", None, "schedule_based_on_fiscal_year")) == 1
- and getdate(self.next_depreciation_date) < next_depr_date):
-
- number_of_pending_depreciations += 1
- for n in range(number_of_pending_depreciations):
- if n == range(number_of_pending_depreciations)[-1]:
- schedule_date = add_months(self.available_for_use_date, n * 12)
- previous_scheduled_date = add_months(self.next_depreciation_date, (n-1) * 12)
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
- previous_scheduled_date, schedule_date)
-
- elif n == range(number_of_pending_depreciations)[0]:
- schedule_date = self.next_depreciation_date
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
- self.available_for_use_date, schedule_date)
-
- else:
- schedule_date = add_months(self.next_depreciation_date, n * 12)
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation)
-
- if value_after_depreciation != 0:
- value_after_depreciation -= flt(depreciation_amount)
-
- self.append("schedules", {
- "schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount
- })
- else:
- for n in range(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)
- if depreciation_amount:
- value_after_depreciation -= flt(depreciation_amount)
-
- self.append("schedules", {
- "schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount
- })
-
- def set_accumulated_depreciation(self):
- accumulated_depreciation = flt(self.opening_accumulated_depreciation)
- value_after_depreciation = flt(self.value_after_depreciation)
for i, d in enumerate(self.get("schedules")):
+ if ignore_booked_entry and d.journal_entry:
+ continue
+
+ if d.finance_book_id not in finance_books:
+ accumulated_depreciation = flt(self.opening_accumulated_depreciation)
+ value_after_depreciation = flt(self.get_value_after_depreciation(d.finance_book_id))
+ finance_books.append(d.finance_book_id)
+
depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
value_after_depreciation -= flt(depreciation_amount)
- if i==len(self.get("schedules"))-1 and self.depreciation_method == "Straight Line":
+ if straight_line_idx and i == max(straight_line_idx) - 1:
+ book = self.get('finance_books')[cint(d.finance_book_id) - 1]
depreciation_amount += flt(value_after_depreciation -
- flt(self.expected_value_after_useful_life), d.precision("depreciation_amount"))
+ flt(book.expected_value_after_useful_life), d.precision("depreciation_amount"))
d.depreciation_amount = depreciation_amount
accumulated_depreciation += d.depreciation_amount
d.accumulated_depreciation_amount = flt(accumulated_depreciation,
d.precision("accumulated_depreciation_amount"))
- def get_depreciation_amount(self, depreciable_value):
- if self.depreciation_method in ("Straight Line", "Manual"):
- 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 / self.total_number_of_depreciations
- depreciation_amount = flt(depreciable_value * factor / 100, 0)
+ def get_value_after_depreciation(self, idx):
+ return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)
- value_after_depreciation = flt(depreciable_value) - depreciation_amount
- if value_after_depreciation < flt(self.expected_value_after_useful_life):
- depreciation_amount = flt(depreciable_value) - flt(self.expected_value_after_useful_life)
+ def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
+ percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
+
+ factor = percentage_value / total_number_of_depreciations
+ depreciation_amount = flt(depreciable_value * factor / 100, 0)
+
+ value_after_depreciation = flt(depreciable_value) - depreciation_amount
+ if value_after_depreciation < flt(row.expected_value_after_useful_life):
+ depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life)
return depreciation_amount
- def get_depreciation_amount_prorata_temporis(self, depreciable_value, start_date=None, end_date=None):
+ def get_depreciation_amount_prorata_temporis(self, depreciable_value, row, start_date=None, end_date=None):
if start_date and end_date:
prorata_temporis = min(abs(flt(date_diff(str(end_date), str(start_date)))) / flt(frappe.db.get_value("Asset Settings", None, "number_of_days_in_fiscal_year")), 1)
else:
prorata_temporis = 1
- if self.depreciation_method in ("Straight Line", "Manual"):
- depreciation_amount = (flt(self.value_after_depreciation) -
- flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) -
+ if row.depreciation_method in ("Straight Line", "Manual"):
+ depreciation_amount = (flt(row.value_after_depreciation) -
+ flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked)) * prorata_temporis
-
- return depreciation_amount
else:
- self.get_depreciation_amount(depreciable_value)
+ depreciation_amount = self.get_depreciation_amount(depreciable_value, row)
+
+ return depreciation_amount
def validate_expected_value_after_useful_life(self):
- accumulated_depreciation_after_full_schedule = \
- max([d.accumulated_depreciation_amount for d in self.get("schedules")])
+ for row in self.get('finance_books'):
+ accumulated_depreciation_after_full_schedule = \
+ max([d.accumulated_depreciation_amount for d in self.get("schedules") if d.finance_book_id == row.idx])
- asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
- flt(accumulated_depreciation_after_full_schedule),
- self.precision('expected_value_after_useful_life'))
+ asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
+ flt(accumulated_depreciation_after_full_schedule),
+ self.precision('gross_purchase_amount'))
- if self.expected_value_after_useful_life < asset_value_after_full_schedule:
- frappe.throw(_("Expected value after useful life must be greater than or equal to {0}")
- .format(asset_value_after_full_schedule))
+ if row.expected_value_after_useful_life < asset_value_after_full_schedule:
+ frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
+ .format(row.idx, asset_value_after_full_schedule))
def validate_cancellation(self):
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
@@ -219,6 +263,9 @@
if self.purchase_invoice:
frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
+ if self.purchase_receipt:
+ frappe.throw(_("Please cancel Purchase Receipt {0} first").format(self.purchase_receipt))
+
def delete_depreciation_entries(self):
for d in self.get("schedules"):
if d.journal_entry:
@@ -240,9 +287,15 @@
status = "Draft"
elif self.docstatus == 1:
status = "Submitted"
+ expected_value_after_useful_life = flt(sum([d.expected_value_after_useful_life
+ for d in self.get('finance_books')]))
+
+ value_after_depreciation = flt(sum([d.value_after_depreciation
+ for d in self.get('finance_books')]))
+
if self.journal_entry_for_scrap:
status = "Scrapped"
- elif flt(self.value_after_depreciation) <= flt(self.expected_value_after_useful_life):
+ elif flt(value_after_depreciation) <= expected_value_after_useful_life:
status = "Fully Depreciated"
elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount):
status = 'Partially Depreciated'
@@ -250,6 +303,45 @@
status = "Cancelled"
return status
+ def update_stock_movement(self):
+ asset_movement = frappe.db.get_value('Asset Movement',
+ {'asset': self.name, 'reference_name': self.purchase_receipt, 'docstatus': 0}, 'name')
+
+ if asset_movement:
+ doc = frappe.get_doc('Asset Movement', asset_movement)
+ doc.submit()
+
+ def make_gl_entries(self):
+ if self.purchase_receipt and self.purchase_receipt_amount:
+ from erpnext.accounts.general_ledger import make_gl_entries
+
+ gl_entries = []
+
+ cwip_account = get_cwip_account(self.name, self.asset_category, self.company)
+ fixed_aseet_account = get_asset_category_account(self.name, 'fixed_asset_account',
+ asset_category = self.asset_category, company = self.company)
+
+ gl_entries.append(self.get_gl_dict({
+ "account": cwip_account,
+ "against": fixed_aseet_account,
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "posting_date": self.available_for_use_date,
+ "credit": self.purchase_receipt_amount,
+ "credit_in_account_currency": self.purchase_receipt_amount
+ }))
+
+ gl_entries.append(self.get_gl_dict({
+ "account": fixed_aseet_account,
+ "against": cwip_account,
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "posting_date": self.available_for_use_date,
+ "debit": self.purchase_receipt_amount,
+ "debit_in_account_currency": self.purchase_receipt_amount
+ }))
+
+ make_gl_entries(gl_entries)
+ self.db_set('booked_fixed_asset', 1)
+
def update_maintenance_status():
assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
@@ -260,6 +352,18 @@
if frappe.db.exists('Asset Repair', {'asset_name': asset.name, 'repair_status': 'Pending'}):
asset.set_status('Out of Order')
+def make_post_gl_entry():
+ assets = frappe.db.sql_list(""" select name from `tabAsset`
+ where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
+
+ for asset in assets:
+ doc = frappe.get_doc('Asset', asset)
+ doc.make_gl_entries()
+
+def get_asset_naming_series():
+ meta = frappe.get_meta('Asset')
+ return meta.get_field("naming_series").options
+
@frappe.whitelist()
def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, posting_date):
pi = frappe.new_doc("Purchase Invoice")
@@ -271,7 +375,7 @@
"item_code": item_code,
"is_fixed_asset": 1,
"asset": asset,
- "expense_account": get_fixed_asset_account(asset),
+ "expense_account": get_asset_category_account(asset, 'fixed_asset_account'),
"qty": 1,
"price_list_rate": gross_purchase_amount,
"rate": gross_purchase_amount
@@ -280,7 +384,7 @@
return pi
@frappe.whitelist()
-def make_sales_invoice(asset, item_code, company):
+def make_sales_invoice(asset, item_code, company, serial_no=None):
si = frappe.new_doc("Sales Invoice")
si.company = company
si.currency = frappe.db.get_value("Company", company, "default_currency")
@@ -290,6 +394,7 @@
"is_fixed_asset": 1,
"asset": asset,
"income_account": disposal_account,
+ "serial_no": serial_no,
"cost_center": depreciation_cost_center,
"qty": 1
})
@@ -322,17 +427,32 @@
frappe.msgprint(_("Asset Movement record {0} created").format("<a href='#Form/Asset Movement/{0}'>{0}</a>".format(movement_entry.name)))
@frappe.whitelist()
-def get_item_details(item_code):
- asset_category = frappe.db.get_value("Item", item_code, "asset_category")
-
+def get_item_details(item_code, asset_category=None):
if not asset_category:
frappe.throw(_("Please enter Asset Category in Item {0}").format(item_code))
- ret = frappe.db.get_value("Asset Category", asset_category,
- ["depreciation_method", "total_number_of_depreciations", "frequency_of_depreciation"], as_dict=1)
+ asset_category_doc = frappe.get_doc('Asset Category', asset_category)
+ books = []
+ for d in asset_category_doc.finance_books:
+ books.append({
+ 'finance_book': d.finance_book,
+ 'depreciation_method': d.depreciation_method,
+ 'total_number_of_depreciations': d.total_number_of_depreciations,
+ 'frequency_of_depreciation': d.frequency_of_depreciation,
+ 'start_date': nowdate()
+ })
- ret.update({
- "asset_category": asset_category
- })
+ return books
- return ret
+def get_cwip_account(asset, asset_category=None, company=None):
+ cwip_account = get_asset_category_account(asset, 'capital_work_in_progress_account',
+ asset_category = asset_category, company = company)
+
+ if not cwip_account:
+ cwip_account = frappe.db.get_value('Company', company, 'capital_work_in_progress_account')
+
+ if not cwip_account:
+ frappe.throw(_("Set Capital Work In Progress Account in asset category {0} or company {1}")
+ .format(asset_category, company))
+
+ return cwip_account
diff --git a/erpnext/assets/doctype/asset/asset_dashboard.py b/erpnext/assets/doctype/asset/asset_dashboard.py
index 94dad1b..89699f3 100644
--- a/erpnext/assets/doctype/asset/asset_dashboard.py
+++ b/erpnext/assets/doctype/asset/asset_dashboard.py
@@ -1,6 +1,9 @@
def get_data():
return {
'fieldname': 'asset_name',
+ 'non_standard_fieldnames': {
+ 'Asset Movement': 'asset'
+ },
'transactions': [
{
'label': ['Maintenance'],
@@ -9,6 +12,10 @@
{
'label': ['Repair'],
'items': ['Asset Repair']
+ },
+ {
+ 'label': ['Movement'],
+ 'items': ['Asset Movement']
}
]
}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 92a251e..aacaef5 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import flt, today, getdate
+from frappe.utils import flt, today, getdate, cint
def post_depreciation_entries(date=None):
# Return if automatic booking of asset depreciation is disabled
@@ -47,6 +47,7 @@
je.naming_series = depreciation_series
je.posting_date = d.schedule_date
je.company = asset.company
+ je.finance_book = d.finance_book
je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount)
je.append("accounts", {
@@ -68,9 +69,12 @@
je.submit()
d.db_set("journal_entry", je.name)
- asset.value_after_depreciation -= d.depreciation_amount
+
+ idx = cint(d.finance_book_id)
+ finance_books = asset.get('finance_books')[idx - 1]
+ finance_books.value_after_depreciation -= d.depreciation_amount
+ finance_books.db_update()
- asset.db_set("value_after_depreciation", asset.value_after_depreciation)
asset.set_status()
return asset
diff --git a/erpnext/assets/doctype/asset_adjustment/__init__.py b/erpnext/assets/doctype/asset_adjustment/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/assets/doctype/asset_adjustment/__init__.py
diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js
new file mode 100644
index 0000000..11c02e1
--- /dev/null
+++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js
@@ -0,0 +1,30 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Asset Adjustment', {
+ asset: function(frm) {
+ frm.trigger("set_current_asset_value");
+ },
+
+ finance_book: function(frm) {
+ frm.trigger("set_current_asset_value");
+ },
+
+ set_current_asset_value: function(frm) {
+ debugger
+ if (frm.doc.finance_book && frm.doc.asset) {
+ frm.call({
+ method: "erpnext.assets.doctype.asset_adjustment.asset_adjustment.get_current_asset_value",
+ args: {
+ asset: frm.doc.asset,
+ finance_book: frm.doc.finance_book
+ },
+ callback: function(r) {
+ if (r.message) {
+ frm.set_value('current_asset_value', r.message);
+ }
+ }
+ });
+ }
+ }
+});
diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json
new file mode 100644
index 0000000..faa36ef
--- /dev/null
+++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json
@@ -0,0 +1,437 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-05-11 00:22:43.695151",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 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,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "asset",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Asset",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "asset_category",
+ "fieldtype": "Read Only",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset Category",
+ "length": 0,
+ "no_copy": 0,
+ "options": "asset.asset_category",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "finance_book",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Finance Book",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Finance Book",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "journal_entry",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Journal Entry",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Journal Entry",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "date",
+ "fieldtype": "Datetime",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "current_asset_value",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Current Asset Value",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "new_asset_value",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "New Asset Value",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "difference_amount",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Difference Amount",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Amended From",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Asset Adjustment",
+ "permlevel": 0,
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 1,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-05-11 21:45:03.459696",
+ "modified_by": "Administrator",
+ "module": "Assets",
+ "name": "Asset Adjustment",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "asset",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py
new file mode 100644
index 0000000..6b4b752
--- /dev/null
+++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, 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 flt, getdate, cint, date_diff
+from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
+from frappe.model.document import Document
+
+class AssetAdjustment(Document):
+ def validate(self):
+ self.set_difference_amount()
+ self.set_current_asset_value()
+
+ def on_submit(self):
+ self.make_depreciation_entry()
+ self.reschedule_depreciations()
+
+ def on_cancel(self):
+ if self.journal_entry:
+ frappe.throw(_("Cancel the journal entry {0} first").format(self.journal_entry))
+
+ def set_difference_amount(self):
+ self.difference_amount = flt(self.current_asset_value - self.new_asset_value)
+
+ def set_current_asset_value(self):
+ if not self.current_asset_value and self.asset and self.finance_book:
+ self.current_asset_value = get_current_asset_value(self.asset, self.finance_book)
+
+ def make_depreciation_entry(self):
+ asset = frappe.get_doc("Asset", self.asset)
+ fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
+ get_depreciation_accounts(asset)
+
+ depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company,
+ ["depreciation_cost_center", "series_for_depreciation_entry"])
+
+ je = frappe.new_doc("Journal Entry")
+ je.voucher_type = "Depreciation Entry"
+ je.naming_series = depreciation_series
+ je.posting_date = self.date
+ je.company = self.company
+ je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount)
+
+ je.append("accounts", {
+ "account": accumulated_depreciation_account,
+ "credit_in_account_currency": self.difference_amount,
+ })
+
+ je.append("accounts", {
+ "account": depreciation_expense_account,
+ "debit_in_account_currency": self.difference_amount,
+ "cost_center": depreciation_cost_center
+ })
+
+ je.flags.ignore_permissions = True
+ je.submit()
+
+ self.db_set("journal_entry", je.name)
+
+ def reschedule_depreciations(self):
+ asset = frappe.get_doc('Asset', self.asset)
+
+ for d in asset.finance_books:
+ d.value_after_depreciation = self.new_asset_value
+
+ if d.depreciation_method in ("Straight Line", "Manual"):
+ end_date = max([s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx])
+ total_days = date_diff(end_date, self.date)
+ rate_per_day = flt(d.value_after_depreciation) / flt(total_days)
+ from_date = self.date
+ else:
+ no_of_depreciations = len([e.name for e in asset.schedules
+ if (cint(s.finance_book_id) == d.idx and not e.journal_entry)])
+
+ value_after_depreciation = d.value_after_depreciation
+ for data in asset.schedules:
+ if cint(data.finance_book_id) == d.idx and not data.journal_entry:
+ if d.depreciation_method in ("Straight Line", "Manual"):
+ days = date_diff(data.schedule_date, from_date)
+ depreciation_amount = days * rate_per_day
+ from_date = data.schedule_date
+ else:
+ depreciation_amount = asset.get_depreciation_amount(value_after_depreciation,
+ no_of_depreciations, d)
+
+ if depreciation_amount:
+ value_after_depreciation -= flt(depreciation_amount)
+ data.depreciation_amount = depreciation_amount
+
+ d.db_update()
+
+ asset.set_accumulated_depreciation(ignore_booked_entry=True)
+ for asset_data in asset.schedules:
+ if not asset_data.journal_entry:
+ asset_data.db_update()
+
+@frappe.whitelist()
+def get_current_asset_value(asset, finance_book):
+ return frappe.db.get_value('Asset Finance Book',
+ {'parent': asset, 'parenttype': 'Asset', 'finance_book': finance_book}, 'value_after_depreciation', debug=1)
diff --git a/erpnext/assets/doctype/asset_adjustment/test_asset_adjustment.js b/erpnext/assets/doctype/asset_adjustment/test_asset_adjustment.js
new file mode 100644
index 0000000..29d070a
--- /dev/null
+++ b/erpnext/assets/doctype/asset_adjustment/test_asset_adjustment.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Asset Adjustment", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Asset Adjustment
+ () => frappe.tests.make('Asset Adjustment', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/assets/doctype/asset_adjustment/test_asset_adjustment.py b/erpnext/assets/doctype/asset_adjustment/test_asset_adjustment.py
new file mode 100644
index 0000000..209692e
--- /dev/null
+++ b/erpnext/assets/doctype/asset_adjustment/test_asset_adjustment.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestAssetAdjustment(unittest.TestCase):
+ pass
diff --git a/erpnext/assets/doctype/asset_category/asset_category.js b/erpnext/assets/doctype/asset_category/asset_category.js
index aafe8a6..6f0c428 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.js
+++ b/erpnext/assets/doctype/asset_category/asset_category.js
@@ -40,5 +40,16 @@
};
});
+ frm.set_query('capital_work_in_progress_account', 'accounts', function(doc, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ return {
+ "filters": {
+ "account_type": "Capital Work in Progress",
+ "is_group": 0,
+ "company": d.company_name
+ }
+ };
+ });
+
}
});
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset_category/asset_category.json b/erpnext/assets/doctype/asset_category/asset_category.json
index 3331d05..882cbe2 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.json
+++ b/erpnext/assets/doctype/asset_category/asset_category.json
@@ -49,38 +49,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "Straight Line",
- "fieldname": "depreciation_method",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Depreciation Method",
- "length": 0,
- "no_copy": 0,
- "options": "\nStraight Line\nDouble Declining Balance\nManual",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -110,16 +78,16 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "total_number_of_depreciations",
- "fieldtype": "Int",
+ "fieldname": "finance_book_detail",
+ "fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 1,
+ "in_list_view": 0,
"in_standard_filter": 0,
- "label": "Total Number of Depreciations",
+ "label": "Finance Book Detail",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -129,7 +97,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -140,18 +108,19 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "frequency_of_depreciation",
- "fieldtype": "Int",
+ "fieldname": "finance_books",
+ "fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 1,
+ "in_list_view": 0,
"in_standard_filter": 0,
- "label": "Frequency of Depreciation (Months)",
+ "label": "Finance Books",
"length": 0,
"no_copy": 0,
+ "options": "Asset Finance Book",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -159,7 +128,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -236,7 +205,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-12-01 15:14:25.645077",
+ "modified": "2018-05-12 14:56:04.116425",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Category",
@@ -312,4 +281,4 @@
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
-}
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 542bd12..bbdc6ec 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -10,6 +10,22 @@
class AssetCategory(Document):
def validate(self):
- 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)
+ for d in self.finance_books:
+ for field in ("Total Number of Depreciations", "Frequency of Depreciation"):
+ if cint(d.get(frappe.scrub(field)))<1:
+ frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError)
+
+@frappe.whitelist()
+def get_asset_category_account(asset, fieldname, account=None, asset_category = None, company = None):
+ if not asset_category and company:
+ 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=fieldname)
+
+ return account
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset_category_account/asset_category_account.json b/erpnext/assets/doctype/asset_category_account/asset_category_account.json
index 679cc52..b7df557 100644
--- a/erpnext/assets/doctype/asset_category_account/asset_category_account.json
+++ b/erpnext/assets/doctype/asset_category_account/asset_category_account.json
@@ -17,7 +17,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "columns": 3,
+ "columns": 2,
"fieldname": "company_name",
"fieldtype": "Link",
"hidden": 0,
@@ -48,7 +48,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "columns": 3,
+ "columns": 2,
"fieldname": "fixed_asset_account",
"fieldtype": "Link",
"hidden": 0,
@@ -135,6 +135,37 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 2,
+ "fieldname": "capital_work_in_progress_account",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Capital Work In Progress Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
}
],
"has_web_view": 0,
@@ -147,7 +178,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-11-28 16:54:12.252271",
+ "modified": "2018-05-10 17:06:48.839347",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Category Account",
diff --git a/erpnext/assets/doctype/asset_finance_book/__init__.py b/erpnext/assets/doctype/asset_finance_book/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/assets/doctype/asset_finance_book/__init__.py
diff --git a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json
new file mode 100644
index 0000000..f75c851
--- /dev/null
+++ b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json
@@ -0,0 +1,289 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-05-08 14:44:37.095570",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "finance_book",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Finance Book",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Finance Book",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "depreciation_method",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Depreciation Method",
+ "length": 0,
+ "no_copy": 0,
+ "options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "total_number_of_depreciations",
+ "fieldtype": "Int",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 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,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "frequency_of_depreciation",
+ "fieldtype": "Int",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 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,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "eval:parent.doctype == 'Asset'",
+ "fieldname": "depreciation_start_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Depreciation Start Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "depends_on": "eval:parent.doctype == 'Asset'",
+ "fieldname": "expected_value_after_useful_life",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Expected Value After Useful Life",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "value_after_depreciation",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Value After Depreciation",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2018-05-12 14:56:44.800046",
+ "modified_by": "Administrator",
+ "module": "Assets",
+ "name": "Asset Finance Book",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py
new file mode 100644
index 0000000..bdc2acf
--- /dev/null
+++ b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class AssetFinanceBook(Document):
+ pass
diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.json b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.json
index 72d96b0..f36fe4e 100644
--- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.json
+++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.json
@@ -42,6 +42,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -73,6 +74,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -104,6 +106,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -135,6 +138,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -164,6 +168,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -195,6 +200,39 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "serial_no",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Serial No",
+ "length": 0,
+ "no_copy": 0,
+ "options": "asset_name.serial_no",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -224,6 +262,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -255,6 +294,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -284,6 +324,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -315,6 +356,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -346,6 +388,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -376,6 +419,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -407,6 +451,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
}
],
@@ -420,7 +465,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-12-01 15:13:29.816396",
+ "modified": "2018-04-20 08:39:27.072622",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Maintenance",
@@ -429,7 +474,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -449,7 +493,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
index 7551eae..b30685f 100644
--- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
+++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
@@ -11,6 +11,9 @@
class AssetMaintenance(Document):
def validate(self):
+ if not self.serial_no:
+ self.serial_no = frappe.db.get_value("Asset", self.asset_name, 'serial_no')
+
for task in self.get('asset_maintenance_tasks'):
if task.end_date and (getdate(task.start_date) >= getdate(task.end_date)):
throw(_("Start date should be less than end date for task {0}").format(task.maintenance_task))
diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.json b/erpnext/assets/doctype/asset_movement/asset_movement.json
index 0c05552..8adbf57 100644
--- a/erpnext/assets/doctype/asset_movement/asset_movement.json
+++ b/erpnext/assets/doctype/asset_movement/asset_movement.json
@@ -18,6 +18,69 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Company",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 1,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "Transfer",
+ "fieldname": "purpose",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Purpose",
+ "length": 0,
+ "no_copy": 0,
+ "options": "\nIssue\nReceipt\nTransfer",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "asset",
"fieldtype": "Link",
"hidden": 0,
@@ -79,37 +142,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -139,7 +171,96 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "source_warehouse",
+ "fieldname": "quantity",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Quantity",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "serial_no",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Serial No",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "source_location",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -147,11 +268,194 @@
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Source Warehouse",
+ "in_standard_filter": 0,
+ "label": "Source Location",
"length": 0,
"no_copy": 0,
- "options": "Warehouse",
+ "options": "Location",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "target_location",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Target Location",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Location",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_10",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "from_employee",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "From Employee",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Employee",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "to_employee",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "To Employee",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Employee",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "reference",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Reference",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "reference_doctype",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Reference DocType",
+ "length": 0,
+ "no_copy": 1,
+ "options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -170,27 +474,27 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "target_warehouse",
- "fieldtype": "Link",
+ "fieldname": "reference_name",
+ "fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Target Warehouse",
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Reference Name",
"length": 0,
- "no_copy": 0,
- "options": "Warehouse",
+ "no_copy": 1,
+ "options": "reference_doctype",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 0,
+ "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -236,7 +540,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-10-19 16:08:17.389257",
+ "modified": "2018-05-10 23:16:20.791672",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Movement",
diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py
index 574c499..32fc663 100644
--- a/erpnext/assets/doctype/asset_movement/asset_movement.py
+++ b/erpnext/assets/doctype/asset_movement/asset_movement.py
@@ -5,44 +5,60 @@
from __future__ import unicode_literals
import frappe
from frappe import _
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from frappe.model.document import Document
class AssetMovement(Document):
def validate(self):
self.validate_asset()
self.validate_warehouses()
-
+
def validate_asset(self):
- status, company = frappe.db.get_value("Asset", self.asset, ["status", "company"])
- if status in ("Draft", "Scrapped", "Sold"):
+ status, company, serial_no = frappe.db.get_value("Asset", self.asset, ["status", "company", "serial_no"])
+ if self.purpose == 'Transfer' and status in ("Draft", "Scrapped", "Sold"):
frappe.throw(_("{0} asset cannot be transferred").format(status))
-
+
if company != self.company:
frappe.throw(_("Asset {0} does not belong to company {1}").format(self.asset, self.company))
-
+
+ if serial_no and not self.serial_no:
+ self.serial_no = serial_no
+
+ if self.serial_no and len(get_serial_nos(self.serial_no)) != self.quantity:
+ frappe.throw(_("Number of serial nos and quantity must be the same"))
+
+ if not(self.source_location or self.target_location or self.from_employee or self.to_employee):
+ frappe.throw(_("Either location or employee must be required"))
+
def validate_warehouses(self):
- if not self.source_warehouse:
- self.source_warehouse = frappe.db.get_value("Asset", self.asset, "warehouse")
-
- if self.source_warehouse == self.target_warehouse:
- frappe.throw(_("Source and Target Warehouse cannot be same"))
+ if self.purpose in ['Transfer', 'Issue']:
+ self.source_location = frappe.db.get_value("Asset", self.asset, "location")
+
+ if self.source_location == self.target_location:
+ frappe.throw(_("Source and Target Location cannot be same"))
def on_submit(self):
- self.set_latest_warehouse_in_asset()
+ self.set_latest_location_in_asset()
def on_cancel(self):
- self.set_latest_warehouse_in_asset()
-
- def set_latest_warehouse_in_asset(self):
- latest_movement_entry = frappe.db.sql("""select target_warehouse from `tabAsset Movement`
+ self.set_latest_location_in_asset()
+
+ def set_latest_location_in_asset(self):
+ latest_movement_entry = frappe.db.sql("""select target_location from `tabAsset Movement`
where asset=%s and docstatus=1 and company=%s
order by transaction_date desc limit 1""", (self.asset, self.company))
if latest_movement_entry:
- warehouse = latest_movement_entry[0][0]
+ location = latest_movement_entry[0][0]
else:
- warehouse = frappe.db.sql("""select source_warehouse from `tabAsset Movement`
+ location = frappe.db.sql("""select source_location from `tabAsset Movement`
where asset=%s and docstatus=2 and company=%s
order by transaction_date asc limit 1""", (self.asset, self.company))[0][0]
-
- frappe.db.set_value("Asset", self.asset, "warehouse", warehouse)
\ No newline at end of file
+
+ frappe.db.set_value("Asset", self.asset, "location", location)
+
+ if self.serial_no:
+ serial_nos = get_serial_nos(self.serial_no)
+
+ frappe.db.sql(""" update `tabSerial No` set location = %s where name in (%s)"""
+ %('%s', ','.join(['%s'] * len(serial_nos))), (location, tuple(serial_nos)))
diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json
index 3303472..35a2c9d 100644
--- a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json
+++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json
@@ -19,6 +19,37 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "finance_book",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Finance Book",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Finance Book",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "schedule_date",
"fieldtype": "Date",
"hidden": 0,
@@ -196,6 +227,67 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "finance_book_id",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Finance Book Id",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "depreciation_method",
+ "fieldtype": "Select",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Depreciation Method",
+ "length": 0,
+ "no_copy": 1,
+ "options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
}
],
"has_web_view": 0,
@@ -208,7 +300,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-10-19 16:30:13.738170",
+ "modified": "2018-05-10 15:12:41.679436",
"modified_by": "Administrator",
"module": "Assets",
"name": "Depreciation Schedule",
diff --git a/erpnext/assets/doctype/location/__init__.py b/erpnext/assets/doctype/location/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/assets/doctype/location/__init__.py
diff --git a/erpnext/assets/doctype/location/location.js b/erpnext/assets/doctype/location/location.js
new file mode 100644
index 0000000..c3783df
--- /dev/null
+++ b/erpnext/assets/doctype/location/location.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Location', {
+ refresh: function(frm) {
+
+ }
+});
diff --git a/erpnext/assets/doctype/location/location.json b/erpnext/assets/doctype/location/location.json
new file mode 100644
index 0000000..d83fdf3
--- /dev/null
+++ b/erpnext/assets/doctype/location/location.json
@@ -0,0 +1,306 @@
+{
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:location_name",
+ "beta": 0,
+ "creation": "2018-05-07 12:49:22.595974",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "location_name",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Location Name",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "is_group",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Is Group",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "parent_location",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Parent Location",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Location",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 1,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "lft",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "lft",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "rgt",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "rgt",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "old_parent",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Old Parent",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-05-07 19:21:06.051414",
+ "modified_by": "Administrator",
+ "module": "Assets",
+ "name": "Location",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/location/location.py b/erpnext/assets/doctype/location/location.py
new file mode 100644
index 0000000..9d05720
--- /dev/null
+++ b/erpnext/assets/doctype/location/location.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe.utils.nestedset import NestedSet
+
+class Location(NestedSet):
+ def on_update(self):
+ self.update_nsm_model()
+
+ def on_trash(self):
+ self.update_nsm_model()
+
+ def update_nsm_model(self):
+ frappe.utils.nestedset.update_nsm(self)
+
+@frappe.whitelist()
+def get_children(doctype, parent=None, location=None, is_root=False):
+ if parent == None or parent == "All Locations":
+ parent = ""
+
+ return frappe.db.sql("""
+ select
+ name as value,
+ is_group as expandable
+ from
+ `tab{doctype}` comp
+ where
+ ifnull(parent_location, "")="{parent}"
+ """.format(
+ doctype = frappe.db.escape(doctype),
+ parent=frappe.db.escape(parent)
+ ), as_dict=1)
+
+@frappe.whitelist()
+def add_node():
+ from frappe.desk.treeview import make_tree_args
+ args = frappe.form_dict
+ args = make_tree_args(**args)
+
+ if args.parent_location == 'All Locations':
+ args.parent_location = None
+
+ frappe.get_doc(args).insert()
\ No newline at end of file
diff --git a/erpnext/assets/doctype/location/location_tree.js b/erpnext/assets/doctype/location/location_tree.js
new file mode 100644
index 0000000..523dd63
--- /dev/null
+++ b/erpnext/assets/doctype/location/location_tree.js
@@ -0,0 +1,28 @@
+frappe.treeview_settings["Location"] = {
+ ignore_fields:["parent_location"],
+ get_tree_nodes: 'erpnext.assets.doctype.location.location.get_children',
+ add_tree_node: 'erpnext.assets.doctype.location.location.add_node',
+ filters: [
+ {
+ fieldname: "location",
+ fieldtype:"Link",
+ options: "Location",
+ label: __("Location")
+ },
+ ],
+ breadcrumb: "Assets",
+ root_label: "All Locations",
+ get_tree_root: false,
+ menu_items: [
+ {
+ label: __("New Location"),
+ action: function() {
+ frappe.new_doc("Location", true);
+ },
+ condition: 'frappe.boot.user.can_create.indexOf("Location") !== -1'
+ }
+ ],
+ onload: function(treeview) {
+ treeview.make_tree();
+ }
+};
\ No newline at end of file
diff --git a/erpnext/assets/doctype/location/test_location.js b/erpnext/assets/doctype/location/test_location.js
new file mode 100644
index 0000000..236b5c6
--- /dev/null
+++ b/erpnext/assets/doctype/location/test_location.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Location", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Location
+ () => frappe.tests.make('Location', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});
diff --git a/erpnext/assets/doctype/location/test_location.py b/erpnext/assets/doctype/location/test_location.py
new file mode 100644
index 0000000..9a46fd9
--- /dev/null
+++ b/erpnext/assets/doctype/location/test_location.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestLocation(unittest.TestCase):
+ pass
diff --git a/erpnext/config/assets.py b/erpnext/config/assets.py
index 73c1aee..d52f142 100644
--- a/erpnext/config/assets.py
+++ b/erpnext/config/assets.py
@@ -12,6 +12,10 @@
},
{
"type": "doctype",
+ "name": "Location",
+ },
+ {
+ "type": "doctype",
"name": "Asset Category",
},
{
@@ -41,6 +45,10 @@
},
{
"type": "doctype",
+ "name": "Asset Adjustment",
+ },
+ {
+ "type": "doctype",
"name": "Asset Repair",
},
]
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index c70cfcd..186aad3 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -273,15 +273,16 @@
def get_gl_dict(self, args, account_currency=None):
"""this method populates the common properties of a gl entry record"""
- fiscal_years = get_fiscal_years(self.posting_date, company=self.company)
+ posting_date = args.get('posting_date') or self.get('posting_date')
+ fiscal_years = get_fiscal_years(posting_date, company=self.company)
if len(fiscal_years) > 1:
- frappe.throw(_("Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year").format(formatdate(self.posting_date)))
+ frappe.throw(_("Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year").format(formatdate(posting_date)))
else:
fiscal_year = fiscal_years[0][0]
gl_dict = frappe._dict({
'company': self.company,
- 'posting_date': self.posting_date,
+ 'posting_date': posting_date,
'fiscal_year': fiscal_year,
'voucher_type': self.doctype,
'voucher_no': self.name,
@@ -600,40 +601,36 @@
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))
- 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 d.meta.get_field("asset") and d.asset:
+ 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))
+ 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.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 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.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 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))
+ 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))
def delink_advance_entries(self, linked_doc_name):
total_allocated_amount = 0
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index de6ed79..85fb3f0 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -11,6 +11,7 @@
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
from erpnext.stock.stock_ledger import get_valuation_rate
from erpnext.stock.doctype.stock_entry.stock_entry import get_used_alternative_items
+from erpnext.stock.doctype.serial_no.serial_no import get_auto_serial_nos, auto_make_serial_nos, get_serial_nos
from erpnext.controllers.stock_controller import StockController
@@ -78,7 +79,7 @@
break
def validate_stock_or_nonstock_items(self):
- if self.meta.get_field("taxes") and not self.get_stock_items():
+ if self.meta.get_field("taxes") and not self.get_stock_items() and not self.get_asset_items():
tax_for_valuation = [d for d in self.get("taxes")
if d.category in ["Valuation", "Valuation and Total"]]
@@ -87,6 +88,12 @@
d.category = 'Total'
msgprint(_('Tax Category has been changed to "Total" because all the Items are non-stock items'))
+ def get_asset_items(self):
+ if self.doctype not in ['Purchase Invoice', 'Purchase Receipt']:
+ return []
+
+ return [d.item_code for d in self.items if d.is_fixed_asset]
+
def set_landed_cost_voucher_amount(self):
for d in self.get("items"):
lc_voucher_data = frappe.db.sql("""select sum(applicable_charges), cost_center
@@ -111,7 +118,7 @@
TODO: rename item_tax_amount to valuation_tax_amount
"""
- stock_items = self.get_stock_items()
+ stock_items = self.get_stock_items() + self.get_asset_items()
stock_items_qty, stock_items_amount = 0, 0
last_stock_item_idx = 1
@@ -439,6 +446,12 @@
if self.get('is_return'):
return
+ if self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
+ field = 'purchase_invoice' if self.doctype == 'Purchase Invoice' else 'purchase_receipt'
+
+ self.process_fixed_asset()
+ self.update_fixed_asset(field)
+
update_last_purchase_rate(self, is_submit = 1)
def on_cancel(self):
@@ -446,6 +459,133 @@
return
update_last_purchase_rate(self, is_submit = 0)
+ if self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
+ field = 'purchase_invoice' if self.doctype == 'Purchase Invoice' else 'purchase_receipt'
+
+ self.delete_linked_asset()
+ self.update_fixed_asset(field, delete_asset=True)
+
+ def process_fixed_asset(self):
+ if self.doctype == 'Purchase Invoice' and not self.update_stock:
+ return
+
+ asset_items = self.get_asset_items()
+ if asset_items:
+ self.make_serial_nos_for_asset(asset_items)
+
+ def make_serial_nos_for_asset(self, asset_items):
+ items_data = get_asset_item_details(asset_items)
+
+ for d in self.items:
+ if d.is_fixed_asset:
+ item_data = items_data.get(d.item_code)
+ if not d.asset:
+ asset = self.make_asset(d)
+ d.db_set('asset', asset)
+
+ if item_data.get('has_serial_no'):
+ # If item has serial no
+ if item_data.get('serial_no_series') and not d.serial_no:
+ serial_nos = get_auto_serial_nos(item_data.get('serial_no_series'), d.qty)
+ elif d.serial_no:
+ serial_nos = d.serial_no
+ elif not d.serial_no:
+ frappe.throw(_("Serial no is mandatory for the item {0}").format(d.item_code))
+
+ auto_make_serial_nos({
+ 'serial_no': serial_nos,
+ 'item_code': d.item_code,
+ 'via_stock_ledger': False,
+ 'company': self.company,
+ 'actual_qty': d.qty,
+ 'purchase_document_type': self.doctype,
+ 'purchase_document_no': self.name,
+ 'asset': d.asset
+ })
+ d.db_set('serial_no', serial_nos)
+
+ if d.asset:
+ self.make_asset_movement(d)
+
+ def make_asset(self, row):
+ if not row.asset_location:
+ frappe.throw(_("Row {0}: Enter location for the asset item {1}").format(row.idx, row.item_code))
+
+ item_data = frappe.db.get_value('Item',
+ row.item_code, ['asset_naming_series', 'asset_category'], as_dict=1)
+
+ purchase_amount = flt(row.base_net_amount + row.item_tax_amount)
+ asset = frappe.get_doc({
+ 'doctype': 'Asset',
+ 'item_code': row.item_code,
+ 'asset_name': row.item_name,
+ 'status': 'Receipt',
+ 'naming_series': item_data.get('asset_naming_series') or 'AST',
+ 'asset_category': item_data.get('asset_category'),
+ 'location': row.asset_location,
+ 'company': self.company,
+ 'purchase_date': self.posting_date,
+ 'calculate_depreciation': 1,
+ 'purchase_receipt_amount': purchase_amount,
+ 'gross_purchase_amount': purchase_amount,
+ 'purchase_receipt': self.name if self.doctype == 'Purchase Receipt' else None,
+ 'purchase_invoice': self.name if self.doctype == 'Purchase Invoice' else None
+ })
+
+ asset.flags.ignore_validate = True
+ asset.flags.ignore_mandatory = True
+ asset.set_missing_values()
+ asset.insert()
+
+ frappe.msgprint(_("Asset {0} created").format(asset.name))
+ return asset.name
+
+ def make_asset_movement(self, row):
+ asset_movement = frappe.get_doc({
+ 'doctype': 'Asset Movement',
+ 'asset': row.asset,
+ 'target_location': row.asset_location,
+ 'purpose': 'Receipt',
+ 'serial_no': row.serial_no,
+ 'quantity': len(get_serial_nos(row.serial_no)),
+ 'company': self.company,
+ 'transaction_date': self.posting_date,
+ 'reference_doctype': self.doctype,
+ 'reference_name': self.name
+ }).insert()
+
+ return asset_movement.name
+
+ def update_fixed_asset(self, field, delete_asset = False):
+ for d in self.get("items"):
+ if d.is_fixed_asset and d.asset:
+ asset = frappe.get_doc("Asset", d.asset)
+
+ if delete_asset and asset.docstatus == 0:
+ frappe.delete_doc("Asset", asset.name)
+ d.db_set('asset', None)
+ continue
+
+ if self.docstatus in [0, 1] and not asset.get(field):
+ asset.set(field, self.name)
+ asset.purchase_date = self.posting_date
+ asset.supplier = self.supplier
+ elif self.docstatus == 2:
+ asset.set(field, None)
+ asset.supplier = None
+
+ asset.flags.ignore_validate_update_after_submit = True
+ if asset.docstatus == 0:
+ asset.flags.ignore_validate = True
+
+ asset.save()
+
+ def delete_linked_asset(self):
+ if self.doctype == 'Purchase Invoice' and not self.get('update_stock'):
+ return
+
+ frappe.db.sql("delete from `tabAsset Movement` where reference_name=%s and docstatus = 0", self.name)
+ frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
def validate_schedule_date(self):
if not self.schedule_date:
@@ -480,3 +620,11 @@
msgprint(_("Specified BOM {0} does not exist for Item {1}").format(bom, item_code), raise_exception=1)
return bom_items
+
+def get_asset_item_details(asset_items):
+ asset_items_data = {}
+ for d in frappe.get_all('Item', fields = ["name", "has_serial_no", "serial_no_series"],
+ filters = {'name': ('in', asset_items)}):
+ asset_items_data.setdefault(d.name, d)
+
+ return asset_items_data
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 57e83e6..627455b 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -234,7 +234,8 @@
"erpnext.buying.doctype.supplier_scorecard.supplier_scorecard.refresh_scorecards",
"erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history",
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
- "erpnext.assets.doctype.asset.asset.update_maintenance_status"
+ "erpnext.assets.doctype.asset.asset.update_maintenance_status",
+ "erpnext.assets.doctype.asset.asset.make_post_gl_entry"
]
}
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 4bbb3e9..69b11d6 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -528,3 +528,5 @@
erpnext.patches.v11_0.rename_health_insurance
erpnext.patches.v11_0.rebuild_tree_for_company
erpnext.patches.v11_0.create_department_records_for_each_company
+erpnext.patches.v11_0.make_location_from_warehouse
+erpnext.patches.v11_0.make_asset_finance_book_against_old_entries
\ No newline at end of file
diff --git a/erpnext/patches/v11_0/make_asset_finance_book_against_old_entries.py b/erpnext/patches/v11_0/make_asset_finance_book_against_old_entries.py
new file mode 100644
index 0000000..18622f2
--- /dev/null
+++ b/erpnext/patches/v11_0/make_asset_finance_book_against_old_entries.py
@@ -0,0 +1,47 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils.nestedset import rebuild_tree
+
+def execute():
+ frappe.reload_doc('assets', 'doctype', 'asset_finance_book')
+ frappe.reload_doc('assets', 'doctype', 'depreciation_schedule')
+ frappe.reload_doc('assets', 'doctype', 'asset_category')
+ frappe.reload_doc('assets', 'doctype', 'asset')
+ frappe.reload_doc('assets', 'doctype', 'asset_movement')
+
+ frappe.db.sql(""" update `tabAsset` ast, `tabWarehouse` wh
+ set ast.location = wh.warehouse_name where ast.warehouse = wh.name""")
+
+ frappe.db.sql(""" update `tabAsset Movement` ast_mv
+ set ast_mv.source_location = (select warehouse_name from `tabWarehouse` where name = ast_mv.source_warehouse),
+ ast_mv.target_location = (select warehouse_name from `tabWarehouse` where name = ast_mv.target_warehouse)""")
+
+ for d in frappe.get_all('Asset'):
+ doc = frappe.get_doc('Asset', d.name)
+ if doc.calculate_depreciation:
+ fb = doc.append('finance_books', {
+ 'depreciation_method': doc.depreciation_method,
+ 'total_number_of_depreciations': doc.total_number_of_depreciations,
+ 'frequency_of_depreciation': doc.frequency_of_depreciation,
+ 'depreciation_start_date': doc.next_depreciation_date,
+ 'expected_value_after_useful_life': doc.expected_value_after_useful_life,
+ 'value_after_depreciation': doc.value_after_depreciation
+ })
+
+ fb.db_update()
+
+ frappe.db.sql(""" update `tabDepreciation Schedule` ds, `tabAsset` ast
+ set ds.depreciation_method = ast.depreciation_method, ds.finance_book_id = 1 where ds.parent = ast.name """)
+
+ for catergory in frappe.get_all('Asset Category'):
+ asset_category_doc = frappe.get_doc("Asset Category", catergory)
+ row = asset_category_doc.append('finance_books', {
+ 'depreciation_method': asset_category_doc.depreciation_method,
+ 'total_number_of_depreciations': asset_category_doc.total_number_of_depreciations,
+ 'frequency_of_depreciation': asset_category_doc.frequency_of_depreciation
+ })
+
+ row.db_update()
\ No newline at end of file
diff --git a/erpnext/patches/v11_0/make_location_from_warehouse.py b/erpnext/patches/v11_0/make_location_from_warehouse.py
new file mode 100644
index 0000000..b838ec9
--- /dev/null
+++ b/erpnext/patches/v11_0/make_location_from_warehouse.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils.nestedset import rebuild_tree
+
+def execute():
+ frappe.reload_doc('assets', 'doctype', 'location')
+ frappe.reload_doc('stock', 'doctype', 'warehouse')
+
+ for d in frappe.get_all('Warehouse',
+ fields = ['warehouse_name', 'is_group', 'parent_warehouse'], order_by="is_group desc"):
+ try:
+ loc = frappe.new_doc('Location')
+ loc.location_name = d.warehouse_name
+ loc.is_group = d.is_group
+ loc.flags.ignore_mandatory = True
+ if d.parent_warehouse:
+ loc.parent_location = get_parent_warehouse_name(d.parent_warehouse)
+
+ loc.save(ignore_permissions=True)
+ except frappe.DuplicateEntryError:
+ continue
+
+ rebuild_tree("Location", "parent_location")
+
+def get_parent_warehouse_name(warehouse):
+ return frappe.db.get_value('Warehouse', warehouse, 'warehouse_name')
+
\ No newline at end of file
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index e164d69..5ca2885 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -207,6 +207,9 @@
["round_off_cost_center", {}],
["depreciation_cost_center", {}],
["default_employee_advance_account", {"root_type": "Asset"}],
+ ["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
+ ["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
+ ["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}]
], function(i, v) {
erpnext.company.set_custom_query(frm, v);
});
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index d236dda..07051ee 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -1791,6 +1791,38 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "expenses_included_in_asset_valuation",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Expenses Included In Asset Valuation",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "column_break_40",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1885,6 +1917,70 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "capital_work_in_progress_account",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Capital Work In Progress Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "asset_received_but_not_billed",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset Received But Not Billed",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"description": "For reference only.",
"fieldname": "company_info",
"fieldtype": "Section Break",
@@ -2400,7 +2496,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2018-05-05 13:08:07.351655",
+ "modified": "2018-05-07 15:35:06.736602",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 1b68b8a..9040bb7 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -168,6 +168,9 @@
self._set_default_account("round_off_account", "Round Off")
self._set_default_account("accumulated_depreciation_account", "Accumulated Depreciation")
self._set_default_account("depreciation_expense_account", "Depreciation")
+ self._set_default_account("capital_work_in_progress_account", "Capital Work in Progress")
+ self._set_default_account("asset_received_but_not_billed", "Asset Received But Not Billed")
+ self._set_default_account("expenses_included_in_asset_valuation", "Expenses Included In Asset Valuation")
if self.enable_perpetual_inventory:
self._set_default_account("stock_received_but_not_billed", "Stock Received But Not Billed")
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index f98cbb6..fbf0ded 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -19,7 +19,9 @@
// should never check Private
frm.fields_dict["website_image"].df.is_private = 0;
-
+ if (frm.doc.is_fixed_asset) {
+ frm.trigger("set_asset_naming_series");
+ }
},
refresh: function(frm) {
@@ -124,7 +126,20 @@
},
is_fixed_asset: function(frm) {
- frm.set_value("is_stock_item", frm.doc.is_fixed_asset ? 0 : 1);
+ frm.call({
+ method: "set_asset_naming_series",
+ doc: frm.doc,
+ callback: function() {
+ frm.set_value("is_stock_item", frm.doc.is_fixed_asset ? 0 : 1);
+ frm.trigger("set_asset_naming_series");
+ }
+ })
+ },
+
+ set_asset_naming_series: function(frm) {
+ if (frm.doc.__onload && frm.doc.__onload.asset_naming_series) {
+ frm.set_df_property("asset_naming_series", "options", frm.doc.__onload.asset_naming_series);
+ }
},
page_name: frappe.utils.warn_page_name_change,
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 21900ad..b862171 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -395,7 +395,7 @@
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
- "unique": 0
+ "unique": 0
},
{
"allow_bulk_edit": 0,
@@ -566,6 +566,38 @@
"collapsible": 0,
"columns": 0,
"depends_on": "is_fixed_asset",
+ "fieldname": "asset_naming_series",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset Naming Series",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "is_fixed_asset",
"fieldname": "asset_category",
"fieldtype": "Link",
"hidden": 0,
@@ -1285,7 +1317,7 @@
"collapsible": 1,
"collapsible_depends_on": "eval:doc.has_batch_no || doc.has_serial_no",
"columns": 0,
- "depends_on": "is_stock_item",
+ "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset",
"fieldname": "serial_nos_and_batches",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1513,7 +1545,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
- "depends_on": "eval:doc.is_stock_item",
+ "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset",
"description": "",
"fieldname": "has_serial_no",
"fieldtype": "Check",
@@ -3717,7 +3749,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 1,
- "modified": "2018-04-30 12:21:48.715529",
+ "modified": "2018-05-07 14:54:24.479267",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
@@ -3725,7 +3757,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -3745,7 +3776,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -3765,7 +3795,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -3785,7 +3814,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -3805,7 +3833,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -3825,7 +3852,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -3845,7 +3871,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -3865,7 +3890,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 123e73f..94b907b 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -16,6 +16,7 @@
from frappe.utils.html_utils import clean_html
from frappe.website.doctype.website_slideshow.website_slideshow import \
get_slideshow
+
from frappe.website.render import clear_cache
from frappe.website.website_generator import WebsiteGenerator
@@ -42,10 +43,18 @@
super(Item, self).onload()
self.set_onload('stock_exists', self.stock_ledger_created())
+ self.set_asset_naming_series()
if self.is_fixed_asset:
asset = frappe.db.get_all("Asset", filters={"item_code": self.name, "docstatus": 1}, limit=1)
self.set_onload("asset_exists", True if asset else False)
+ def set_asset_naming_series(self):
+ if not hasattr(self, '_asset_naming_series'):
+ from erpnext.assets.doctype.asset.asset import get_asset_naming_series
+ self._asset_naming_series = get_asset_naming_series()
+
+ self.set_onload('asset_naming_series', self._asset_naming_series)
+
def autoname(self):
if frappe.db.get_default("item_naming_by") == "Naming Series":
if self.variant_of:
@@ -444,7 +453,7 @@
_("Conversion factor for default Unit of Measure must be 1 in row {0}").format(d.idx))
def validate_item_type(self):
- if self.has_serial_no == 1 and self.is_stock_item == 0:
+ if self.has_serial_no == 1 and self.is_stock_item == 0 and not self.is_fixed_asset:
msgprint(_("'Has Serial No' can not be 'Yes' for non-stock item"), raise_exception=1)
if self.has_serial_no == 0 and self.serial_no_series:
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 791b253..69d2f2a 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -65,6 +65,20 @@
if (erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
this.show_general_ledger();
}
+
+ this.frm.add_custom_button(__('Asset'), function() {
+ frappe.route_options = {
+ purchase_receipt: me.frm.doc.name,
+ };
+ frappe.set_route("List", "Asset");
+ }, __("View"));
+
+ this.frm.add_custom_button(__('Asset Movement'), function() {
+ frappe.route_options = {
+ reference_name: me.frm.doc.name,
+ };
+ frappe.set_route("List", "Asset Movement");
+ }, __("View"));
}
if(!this.frm.doc.is_return && this.frm.doc.status!="Closed") {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 46eee31..573f7ed 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -13,6 +13,7 @@
from erpnext.accounts.utils import get_account_currency
from frappe.desk.notifications import clear_doctype_notifications
from erpnext.buying.utils import check_for_closed_status
+from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -253,6 +254,40 @@
d.rejected_warehouse not in warehouse_with_no_account:
warehouse_with_no_account.append(d.warehouse)
+ elif d.is_fixed_asset:
+ asset_accounts = self.get_company_default(["capital_work_in_progress_account",
+ "asset_received_but_not_billed"])
+
+ # CWIP entry
+ cwip_account = get_asset_category_account(d.asset,
+ 'capital_work_in_progress_account') or asset_accounts[0]
+
+ asset_amount = flt(d.net_amount) + flt(d.item_tax_amount/self.conversion_rate)
+ base_asset_amount = flt(d.base_net_amount + d.item_tax_amount)
+
+ cwip_account_currency = get_account_currency(cwip_account)
+ gl_entries.append(self.get_gl_dict({
+ "account": cwip_account,
+ "against": asset_accounts[1],
+ "cost_center": d.cost_center,
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "debit": base_asset_amount,
+ "debit_in_account_currency": (base_asset_amount
+ if cwip_account_currency == self.company_currency else asset_amount)
+ }))
+
+ # Asset received but not billed
+ asset_rbnb_currency = get_account_currency(asset_accounts[1])
+ gl_entries.append(self.get_gl_dict({
+ "account": asset_accounts[1],
+ "against": asset_accounts[0],
+ "cost_center": d.cost_center,
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "credit": base_asset_amount,
+ "credit_in_account_currency": (base_asset_amount
+ if asset_rbnb_currency == self.company_currency else asset_amount)
+ }))
+
# Cost center-wise amount breakup for other charges included for valuation
valuation_tax = {}
for tax in self.get("taxes"):
@@ -393,6 +428,8 @@
"parent": "purchase_receipt",
"purchase_order_item": "po_detail",
"purchase_order": "purchase_order",
+ "is_fixed_asset": "is_fixed_asset",
+ "asset": "asset",
},
"postprocess": update_item,
"filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
index 9ade1af..bcedd71 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
@@ -5,6 +5,7 @@
'fieldname': 'purchase_receipt_no',
'non_standard_fieldnames': {
'Purchase Invoice': 'purchase_receipt',
+ 'Asset': 'purchase_receipt',
'Landed Cost Voucher': 'receipt_document',
'Subscription': 'reference_document'
},
@@ -16,7 +17,7 @@
'transactions': [
{
'label': _('Related'),
- 'items': ['Purchase Invoice', 'Landed Cost Voucher']
+ 'items': ['Purchase Invoice', 'Landed Cost Voucher', 'Asset']
},
{
'label': _('Reference'),
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index d9f40cc..ffcc954 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -289,13 +289,53 @@
serial_no=serial_no, basic_rate=100, do_not_submit=True)
self.assertRaises(SerialNoDuplicateError, se.submit)
+ def test_serialized_asset_item(self):
+ asset_item = "Test Serialized Asset Item"
+
+ if not frappe.db.exists('Item', asset_item):
+ asset_category = frappe.get_all('Asset Category')
+
+ if asset_category:
+ asset_category = asset_category[0].name
+
+ if not asset_category:
+ doc = frappe.get_doc({
+ 'doctype': 'Asset Category',
+ 'asset_category_name': 'Test Asset Category',
+ 'depreciation_method': 'Straight Line',
+ 'total_number_of_depreciations': 12,
+ 'frequency_of_depreciation': 1,
+ 'accounts': [{
+ 'company_name': '_Test Company',
+ 'fixed_asset_account': '_Test Fixed Asset - _TC',
+ 'accumulated_depreciation_account': 'Depreciation - _TC',
+ 'depreciation_expense_account': 'Depreciation - _TC'
+ }]
+ }).insert()
+
+ asset_category = doc.name
+
+ asset_item = make_item(asset_item, {'is_stock_item':0,
+ 'stock_uom': 'Box', 'is_fixed_asset': 1, 'has_serial_no': 1,
+ 'asset_category': asset_category, 'serial_no_series': 'ABC.###'})
+
+ pr = make_purchase_receipt(item_code=asset_item, qty=3)
+ asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name}, 'name')
+ asset_movement = frappe.db.get_value('Asset Movement', {'reference_name': pr.name}, 'name')
+ serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name')
+
+ self.assertEquals(len(serial_nos), 3)
+ pr.cancel()
+ serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or []
+ self.assertEquals(len(serial_nos), 0)
+ frappe.db.sql("delete from `tabAsset Category`")
+ frappe.db.sql("delete from `tabAsset`")
def get_gl_entries(voucher_type, voucher_no):
return frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account desc""", (voucher_type, voucher_no), as_dict=1)
-
def make_purchase_receipt(**args):
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
pr = frappe.new_doc("Purchase Receipt")
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 754bd71..87c9a75 100755
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -1583,6 +1583,103 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "is_fixed_asset",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Is Fixed Asset",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "is_fixed_asset",
+ "fieldname": "asset",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Asset",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "is_fixed_asset",
+ "fieldname": "asset_location",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset Location",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Location",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "purchase_order",
"fieldtype": "Link",
"hidden": 0,
@@ -2395,7 +2492,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-02-22 15:15:38.793425",
+ "modified": "2018-05-07 13:42:05.061386",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index b37713b..f84cbef 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.json
+++ b/erpnext/stock/doctype/serial_no/serial_no.json
@@ -625,6 +625,190 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "asset_details",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset Details",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "asset",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Asset",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "asset",
+ "fieldname": "asset_status",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Asset Status",
+ "length": 0,
+ "no_copy": 0,
+ "options": "\nIssue\nReceipt\nTransfer",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_24",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "location",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Location",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Location",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Employee",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Employee",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "delivery_details",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1270,7 +1454,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-05-15 18:22:23.685286",
+ "modified": "2018-05-10 23:38:20.646770",
"modified_by": "Administrator",
"module": "Stock",
"name": "Serial No",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 98f15a8..333963b 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
+from frappe.model.naming import make_autoname
from frappe.utils import cint, cstr, flt, add_days, nowdate, getdate
from frappe import _, ValidationError
@@ -276,24 +277,31 @@
def update_serial_nos(sle, item_det):
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
and item_det.has_serial_no == 1 and item_det.serial_no_series:
- from frappe.model.naming import make_autoname
- serial_nos = []
- for i in range(cint(sle.actual_qty)):
- serial_nos.append(make_autoname(item_det.serial_no_series, "Serial No"))
- frappe.db.set(sle, "serial_no", "\n".join(serial_nos))
+ serial_nos = get_auto_serial_nos(item_det.serial_no_series, sle.actual_qty)
+ frappe.db.set(sle, "serial_no", serial_nos)
validate_serial_no(sle, item_det)
if sle.serial_no:
- serial_nos = get_serial_nos(sle.serial_no)
- for serial_no in serial_nos:
- if frappe.db.exists("Serial No", serial_no):
- sr = frappe.get_doc("Serial No", serial_no)
- sr.via_stock_ledger = True
- sr.item_code = sle.item_code
- sr.warehouse = sle.warehouse if sle.actual_qty > 0 else None
- sr.save(ignore_permissions=True)
- elif sle.actual_qty > 0:
- make_serial_no(serial_no, sle)
+ auto_make_serial_nos(sle)
+
+def get_auto_serial_nos(serial_no_series, qty):
+ serial_nos = []
+ for i in range(cint(qty)):
+ serial_nos.append(make_autoname(serial_no_series, "Serial No"))
+
+ return "\n".join(serial_nos)
+
+def auto_make_serial_nos(args):
+ serial_nos = get_serial_nos(args.get('serial_no'))
+ for serial_no in serial_nos:
+ if frappe.db.exists("Serial No", serial_no):
+ sr = frappe.get_doc("Serial No", serial_no)
+ sr.via_stock_ledger = True
+ sr.item_code = args.get('item_code')
+ sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None
+ sr.save(ignore_permissions=True)
+ elif args.get('actual_qty', 0) > 0:
+ make_serial_no(serial_no, args)
def get_item_details(item_code):
return frappe.db.sql("""select name, has_batch_no, docstatus,
@@ -304,20 +312,27 @@
return [s.strip() for s in cstr(serial_no).strip().upper().replace(',', '\n').split('\n')
if s.strip()]
-def make_serial_no(serial_no, sle):
+def make_serial_no(serial_no, args):
sr = frappe.new_doc("Serial No")
sr.warehouse = None
sr.dont_update_if_missing.append("warehouse")
sr.flags.ignore_permissions = True
sr.serial_no = serial_no
- sr.item_code = sle.item_code
- sr.company = sle.company
- sr.via_stock_ledger = True
- sr.insert()
+ sr.item_code = args.get('item_code')
+ sr.company = args.get('company')
+ sr.via_stock_ledger = args.get('via_stock_ledger') or True
+ sr.asset = args.get('asset')
- sr.warehouse = sle.warehouse
- sr.save()
+ if args.get('purchase_document_type'):
+ sr.purchase_document_type = args.get('purchase_document_type')
+ sr.purchase_document_no = args.get('purchase_document_no')
+
+ sr.insert()
+ if args.get('warehouse'):
+ sr.warehouse = args.get('warehouse')
+ sr.save()
+
frappe.msgprint(_("Serial No {0} created").format(sr.name))
return sr.name
diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.js b/erpnext/stock/doctype/serial_no/test_serial_no.js
new file mode 100644
index 0000000..bf82932
--- /dev/null
+++ b/erpnext/stock/doctype/serial_no/test_serial_no.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Serial No", function (assert) {
+ let done = assert.async();
+
+ // number of asserts
+ assert.expect(1);
+
+ frappe.run_serially([
+ // insert a new Serial No
+ () => frappe.tests.make('Serial No', [
+ // values to be set
+ {key: 'value'}
+ ]),
+ () => {
+ assert.equal(cur_frm.doc.key, 'value');
+ },
+ () => done()
+ ]);
+
+});