diff --git a/erpnext/accounts/doctype/asset/asset.js b/erpnext/accounts/doctype/asset/asset.js index e3afc359b6..6693d3be0d 100644 --- a/erpnext/accounts/doctype/asset/asset.js +++ b/erpnext/accounts/doctype/asset/asset.js @@ -1,299 +1,8 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -frappe.provide("erpnext.asset"); - frappe.ui.form.on('Asset', { - onload: function(frm) { - frm.set_query("item_code", function() { - return { - "filters": { - "disabled": 0, - "is_fixed_asset": 1, - "is_stock_item": 0 - } - }; - }); - - frm.set_query("warehouse", function() { - return { - "filters": { - "company": frm.doc.company, - "is_group": 0 - } - }; - }); - }, - refresh: function(frm) { - frappe.ui.form.trigger("Asset", "is_existing_asset"); - frm.toggle_display("next_depreciation_date", frm.doc.docstatus < 1); - frm.events.make_schedules_editable(frm); - if (frm.doc.docstatus==1) { - if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) { - frm.add_custom_button("Make Purchase Invoice", function() { - erpnext.asset.make_purchase_invoice(frm); - }); - } - if (in_list(["Submitted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) { - frm.add_custom_button("Transfer Asset", function() { - erpnext.asset.transfer_asset(frm); - }); - - frm.add_custom_button("Scrap Asset", function() { - erpnext.asset.scrap_asset(frm); - }); - - frm.add_custom_button("Sell Asset", function() { - erpnext.asset.make_sales_invoice(frm); - }); - - } else if (frm.doc.status=='Scrapped') { - frm.add_custom_button("Restore Asset", function() { - erpnext.asset.restore_asset(frm); - }); - } - - frm.trigger("setup_chart"); - } - }, - - setup_chart: function(frm) { - var x_intervals = [frm.doc.purchase_date]; - var asset_values = [frm.doc.gross_purchase_amount]; - var last_depreciation_date = frm.doc.purchase_date; - - if(frm.doc.opening_accumulated_depreciation) { - last_depreciation_date = frappe.datetime.add_months(frm.doc.next_depreciation_date, - -1*frm.doc.frequency_of_depreciation); - - x_intervals.push(last_depreciation_date); - asset_values.push(flt(frm.doc.gross_purchase_amount) - - flt(frm.doc.opening_accumulated_depreciation)); - } - - $.each(frm.doc.schedules || [], function(i, v) { - x_intervals.push(v.schedule_date); - var asset_value = flt(frm.doc.gross_purchase_amount) - flt(v.accumulated_depreciation_amount); - if(v.journal_entry) { - last_depreciation_date = v.schedule_date; - asset_values.push(asset_value) - } else { - if (in_list(["Scrapped", "Sold"], frm.doc.status)) { - asset_values.push(null) - } else { - asset_values.push(asset_value) - } - } - }) - - if(in_list(["Scrapped", "Sold"], frm.doc.status)) { - x_intervals.push(frm.doc.disposal_date); - asset_values.push(0); - last_depreciation_date = frm.doc.disposal_date; - } - - frm.dashboard.render_graph({ - title: "Asset Value", - data: { - labels: x_intervals, - datasets: [{ - color: 'green', - values: asset_values, - formatted: asset_values.map(d => d.toFixed(2)) - }] - }, - type: 'line' - }); - }, - - - item_code: function(frm) { - if(frm.doc.item_code) { - frappe.call({ - method: "erpnext.accounts.doctype.asset.asset.get_item_details", - args: { - item_code: frm.doc.item_code - }, - callback: function(r, rt) { - if(r.message) { - $.each(r.message, function(field, value) { - frm.set_value(field, value); - }) - } - } - }) - } - }, - - is_existing_asset: function(frm) { - frm.toggle_enable("supplier", frm.doc.is_existing_asset); - frm.toggle_reqd("next_depreciation_date", !frm.doc.is_existing_asset); - }, - - opening_accumulated_depreciation: function(frm) { - erpnext.asset.set_accululated_depreciation(frm); - }, - - depreciation_method: function(frm) { - frm.events.make_schedules_editable(frm); - }, - - make_schedules_editable: function(frm) { - var is_editable = frm.doc.depreciation_method==="Manual" ? true : false; - frm.toggle_enable("schedules", is_editable); - frm.fields_dict["schedules"].grid.toggle_enable("schedule_date", is_editable); - frm.fields_dict["schedules"].grid.toggle_enable("depreciation_amount", is_editable); } - }); - -frappe.ui.form.on('Depreciation Schedule', { - make_depreciation_entry: function(frm, cdt, cdn) { - var row = locals[cdt][cdn]; - if (!row.journal_entry) { - frappe.call({ - method: "erpnext.accounts.doctype.asset.depreciation.make_depreciation_entry", - args: { - "asset_name": frm.doc.name, - "date": row.schedule_date - }, - callback: function(r) { - frappe.model.sync(r.message); - frm.refresh(); - } - }) - } - }, - - depreciation_amount: function(frm, cdt, cdn) { - erpnext.asset.set_accululated_depreciation(frm); - } - -}) - -erpnext.asset.set_accululated_depreciation = function(frm) { - if(frm.doc.depreciation_method != "Manual") return; - - var accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation); - $.each(frm.doc.schedules || [], function(i, row) { - accumulated_depreciation += flt(row.depreciation_amount); - frappe.model.set_value(row.doctype, row.name, - "accumulated_depreciation_amount", accumulated_depreciation); - }) -} - -erpnext.asset.make_purchase_invoice = function(frm) { - frappe.call({ - args: { - "asset": frm.doc.name, - "item_code": frm.doc.item_code, - "gross_purchase_amount": frm.doc.gross_purchase_amount, - "company": frm.doc.company, - "posting_date": frm.doc.purchase_date - }, - method: "erpnext.accounts.doctype.asset.asset.make_purchase_invoice", - callback: function(r) { - var doclist = frappe.model.sync(r.message); - frappe.set_route("Form", doclist[0].doctype, doclist[0].name); - } - }) -} - -erpnext.asset.make_sales_invoice = function(frm) { - frappe.call({ - args: { - "asset": frm.doc.name, - "item_code": frm.doc.item_code, - "company": frm.doc.company - }, - method: "erpnext.accounts.doctype.asset.asset.make_sales_invoice", - callback: function(r) { - var doclist = frappe.model.sync(r.message); - frappe.set_route("Form", doclist[0].doctype, doclist[0].name); - } - }) -} - -erpnext.asset.scrap_asset = function(frm) { - frappe.confirm(__("Do you really want to scrap this asset?"), function () { - frappe.call({ - args: { - "asset_name": frm.doc.name - }, - method: "erpnext.accounts.doctype.asset.depreciation.scrap_asset", - callback: function(r) { - cur_frm.reload_doc(); - } - }) - }) -} - -erpnext.asset.restore_asset = function(frm) { - frappe.confirm(__("Do you really want to restore this scrapped asset?"), function () { - frappe.call({ - args: { - "asset_name": frm.doc.name - }, - method: "erpnext.accounts.doctype.asset.depreciation.restore_asset", - callback: function(r) { - cur_frm.reload_doc(); - } - }) - }) -} - -erpnext.asset.transfer_asset = function(frm) { - var dialog = new frappe.ui.Dialog({ - title: __("Transfer Asset"), - fields: [ - { - "label": __("Target Warehouse"), - "fieldname": "target_warehouse", - "fieldtype": "Link", - "options": "Warehouse", - "get_query": function () { - return { - filters: [ - ["Warehouse", "company", "in", ["", cstr(frm.doc.company)]], - ["Warehouse", "is_group", "=", 0] - ] - } - }, - "reqd": 1 - }, - { - "label": __("Date"), - "fieldname": "transfer_date", - "fieldtype": "Datetime", - "reqd": 1, - "default": frappe.datetime.now_datetime() - } - ] - }); - - dialog.set_primary_action(__("Transfer"), function() { - var args = dialog.get_values(); - if(!args) return; - dialog.hide(); - return frappe.call({ - type: "GET", - method: "erpnext.accounts.doctype.asset.asset.transfer_asset", - args: { - args: { - "asset": frm.doc.name, - "transaction_date": args.transfer_date, - "source_warehouse": frm.doc.warehouse, - "target_warehouse": args.target_warehouse, - "company": frm.doc.company - } - }, - freeze: true, - callback: function(r) { - cur_frm.reload_doc(); - } - }) - }); - dialog.show(); -} \ No newline at end of file diff --git a/erpnext/accounts/doctype/asset/asset.json b/erpnext/accounts/doctype/asset/asset.json index 469daa05ae..727645516d 100644 --- a/erpnext/accounts/doctype/asset/asset.json +++ b/erpnext/accounts/doctype/asset/asset.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, "autoname": "field:asset_name", @@ -12,6 +13,7 @@ "editable_grid": 0, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -41,6 +43,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -71,6 +74,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -101,6 +105,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -131,6 +136,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -148,7 +154,7 @@ "label": "Status", "length": 0, "no_copy": 1, - "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped", + "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Repair\nOut of Order", "permlevel": 0, "precision": "", "print_hide": 0, @@ -162,6 +168,102 @@ "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "asset_owner", + "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 Owner", + "length": 0, + "no_copy": 0, + "options": "Company\nSupplier\nCustomer", + "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.asset_owner == \"Supplier\"", + "fieldname": "supplier", + "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": "Supplier", + "length": 0, + "no_copy": 0, + "options": "Supplier", + "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.asset_owner == \"Customer\"", + "fieldname": "customer", + "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": "Customer", + "length": 0, + "no_copy": 0, + "options": "Customer", + "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, @@ -191,6 +293,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -219,6 +322,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -249,6 +353,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -279,12 +384,13 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "is_existing_asset", - "fieldtype": "Check", + "fieldname": "department", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -292,9 +398,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Is Existing Asset", + "label": "Department", "length": 0, "no_copy": 0, + "options": "Department", "permlevel": 0, "precision": "", "print_hide": 0, @@ -308,6 +415,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -337,36 +445,7 @@ "unique": 0 }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "supplier", - "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": "Supplier", - "length": 0, - "no_copy": 0, - "options": "Supplier", - "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, @@ -397,6 +476,37 @@ "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, @@ -426,6 +536,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -456,6 +567,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -484,6 +596,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -514,6 +627,36 @@ "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, + "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, @@ -545,6 +688,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -576,42 +720,13 @@ "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": 0, - "options": "Company:company:default_currency", - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_11", - "fieldtype": "Column Break", + "fieldname": "section_break_20", + "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -634,6 +749,68 @@ "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "calculate_depreciation", + "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": "Calculate Depreciation", + "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": 1, + "columns": 0, + "depends_on": "calculate_depreciation", + "fieldname": "section_break_23", + "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": "Depreciation", + "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, @@ -666,6 +843,38 @@ "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": 0, + "options": "Company:company:default_currency", + "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, @@ -695,6 +904,36 @@ "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, @@ -725,6 +964,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -754,6 +994,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -784,10 +1025,12 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "calculate_depreciation", "fieldname": "section_break_14", "fieldtype": "Section Break", "hidden": 0, @@ -813,6 +1056,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -843,6 +1087,68 @@ "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_31", + "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": "Maintenance", + "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, + "description": "Check if Asset requires Preventive Maintenance or Calibration", + "fieldname": "maintenance_required", + "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": "Maintenance Required", + "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, @@ -872,18 +1178,18 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 72, "image_field": "image", "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 1, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-17 16:26:19.111939", + "modified": "2017-10-28 19:59:17.040684", "modified_by": "Administrator", "module": "Accounts", "name": "Asset", diff --git a/erpnext/accounts/doctype/asset/asset.py b/erpnext/accounts/doctype/asset/asset.py index dd1e491680..942a59e135 100644 --- a/erpnext/accounts/doctype/asset/asset.py +++ b/erpnext/accounts/doctype/asset/asset.py @@ -1,260 +1,10 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +# Copyright (c) 2017, 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, add_months, cint, nowdate, getdate from frappe.model.document import Document -from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_fixed_asset_account -from erpnext.accounts.doctype.asset.depreciation \ - import get_disposal_account_and_cost_center, get_depreciation_accounts class Asset(Document): - def validate(self): - self.status = self.get_status() - self.validate_item() - self.set_missing_values() - self.validate_asset_values() - self.make_depreciation_schedule() - self.set_accumulated_depreciation() - if self.get("schedules"): - self.validate_expected_value_after_useful_life() - # Validate depreciation related accounts - get_depreciation_accounts(self) - - def on_submit(self): - self.set_status() - - def on_cancel(self): - self.validate_cancellation() - self.delete_depreciation_entries() - self.set_status() - - def validate_item(self): - item = frappe.db.get_value("Item", self.item_code, - ["is_fixed_asset", "is_stock_item", "disabled"], as_dict=1) - if not item: - frappe.throw(_("Item {0} does not exist").format(self.item_code)) - elif item.disabled: - frappe.throw(_("Item {0} has been disabled").format(self.item_code)) - elif not item.is_fixed_asset: - frappe.throw(_("Item {0} must be a Fixed Asset Item").format(self.item_code)) - elif item.is_stock_item: - 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) - - self.value_after_depreciation = (flt(self.gross_purchase_amount) - - flt(self.opening_accumulated_depreciation)) - - def validate_asset_values(self): - if flt(self.expected_value_after_useful_life) >= flt(self.gross_purchase_amount): - frappe.throw(_("Expected Value After Useful Life must be less than Gross Purchase Amount")) - - if not flt(self.gross_purchase_amount): - frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) - - if not self.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) - if flt(self.opening_accumulated_depreciation) > depreciable_amount: - frappe.throw(_("Opening Accumulated Depreciation must be less than equal to {0}") - .format(depreciable_amount)) - - if self.opening_accumulated_depreciation: - if not self.number_of_depreciations_booked: - frappe.throw(_("Please set Number of Depreciations Booked")) - else: - self.number_of_depreciations_booked = 0 - - if cint(self.number_of_depreciations_booked) > cint(self.total_number_of_depreciations): - frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations")) - - if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(nowdate()): - frappe.msgprint(_("Next Depreciation Date is entered as past date"), title=_('Warning'), indicator='red') - - 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 (flt(self.value_after_depreciation) > flt(self.expected_value_after_useful_life) - and not self.next_depreciation_date): - frappe.throw(_("Please set Next Depreciation Date")) - - def 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: - for n in xrange(number_of_pending_depreciations): - schedule_date = add_months(self.next_depreciation_date, - n * cint(self.frequency_of_depreciation)) - - depreciation_amount = self.get_depreciation_amount(value_after_depreciation) - 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")): - 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": - depreciation_amount += flt(value_after_depreciation - flt(self.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) - - 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) - - 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")]) - - asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) - - flt(accumulated_depreciation_after_full_schedule), - self.precision('expected_value_after_useful_life')) - - 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)) - - def validate_cancellation(self): - if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"): - frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status)) - - if self.purchase_invoice: - frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice)) - - def delete_depreciation_entries(self): - for d in self.get("schedules"): - if d.journal_entry: - frappe.get_doc("Journal Entry", d.journal_entry).cancel() - d.db_set("journal_entry", None) - - self.db_set("value_after_depreciation", - (flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation))) - - def set_status(self, status=None): - '''Get and update status''' - if not status: - status = self.get_status() - self.db_set("status", status) - - def get_status(self): - '''Returns status based on whether it is draft, submitted, scrapped or depreciated''' - if self.docstatus == 0: - status = "Draft" - elif self.docstatus == 1: - status = "Submitted" - if self.journal_entry_for_scrap: - status = "Scrapped" - elif flt(self.value_after_depreciation) <= flt(self.expected_value_after_useful_life): - status = "Fully Depreciated" - elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount): - status = 'Partially Depreciated' - elif self.docstatus == 2: - status = "Cancelled" - - return status - -@frappe.whitelist() -def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, posting_date): - pi = frappe.new_doc("Purchase Invoice") - pi.company = company - pi.currency = frappe.db.get_value("Company", company, "default_currency") - pi.set_posting_time = 1 - pi.posting_date = posting_date - pi.append("items", { - "item_code": item_code, - "is_fixed_asset": 1, - "asset": asset, - "expense_account": get_fixed_asset_account(asset), - "qty": 1, - "price_list_rate": gross_purchase_amount, - "rate": gross_purchase_amount - }) - pi.set_missing_values() - return pi - -@frappe.whitelist() -def make_sales_invoice(asset, item_code, company): - si = frappe.new_doc("Sales Invoice") - si.company = company - si.currency = frappe.db.get_value("Company", company, "default_currency") - disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(company) - si.append("items", { - "item_code": item_code, - "is_fixed_asset": 1, - "asset": asset, - "income_account": disposal_account, - "cost_center": depreciation_cost_center, - "qty": 1 - }) - si.set_missing_values() - return si - -@frappe.whitelist() -def transfer_asset(args): - import json - args = json.loads(args) - movement_entry = frappe.new_doc("Asset Movement") - movement_entry.update(args) - movement_entry.insert() - movement_entry.submit() - - frappe.db.commit() - - frappe.msgprint(_("Asset Movement record {0} created").format("{0}".format(movement_entry.name))) - -@frappe.whitelist() -def get_item_details(item_code): - asset_category = frappe.db.get_value("Item", item_code, "asset_category") - - 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) - - ret.update({ - "asset_category": asset_category - }) - - return ret + pass diff --git a/erpnext/accounts/doctype/asset/test_asset.js b/erpnext/accounts/doctype/asset/test_asset.js new file mode 100644 index 0000000000..6119e38217 --- /dev/null +++ b/erpnext/accounts/doctype/asset/test_asset.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", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset + () => frappe.tests.make('Asset', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/asset/test_asset.py b/erpnext/accounts/doctype/asset/test_asset.py index fd66d1fb67..22baae36df 100644 --- a/erpnext/accounts/doctype/asset/test_asset.py +++ b/erpnext/accounts/doctype/asset/test_asset.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals import frappe import unittest from frappe.utils import cstr, nowdate, getdate, flt -from erpnext.accounts.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset -from erpnext.accounts.doctype.asset.asset import make_sales_invoice, make_purchase_invoice +from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset +from erpnext.assets.doctype.asset.asset import make_sales_invoice, make_purchase_invoice class TestAsset(unittest.TestCase): def setUp(self): @@ -340,4 +340,4 @@ def set_depreciation_settings_in_company(): company.save() # Enable booking asset depreciation entry automatically - frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) \ No newline at end of file + frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) diff --git a/erpnext/accounts/doctype/asset_category/asset_category.js b/erpnext/accounts/doctype/asset_category/asset_category.js index aafe8a69a0..f3bb802633 100644 --- a/erpnext/accounts/doctype/asset_category/asset_category.js +++ b/erpnext/accounts/doctype/asset_category/asset_category.js @@ -1,44 +1,8 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt frappe.ui.form.on('Asset Category', { - onload: function(frm) { - frm.add_fetch('company_name', 'accumulated_depreciation_account', 'accumulated_depreciation_account'); - frm.add_fetch('company_name', 'depreciation_expense_account', 'accumulated_depreciation_account'); - - frm.set_query('fixed_asset_account', 'accounts', function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - return { - "filters": { - "account_type": "Fixed Asset", - "root_type": "Asset", - "is_group": 0, - "company": d.company_name - } - }; - }); - - frm.set_query('accumulated_depreciation_account', 'accounts', function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - return { - "filters": { - "root_type": "Asset", - "is_group": 0, - "company": d.company_name - } - }; - }); - - frm.set_query('depreciation_expense_account', 'accounts', function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - return { - "filters": { - "root_type": "Expense", - "is_group": 0, - "company": d.company_name - } - }; - }); + refresh: function(frm) { } -}); \ No newline at end of file +}); diff --git a/erpnext/accounts/doctype/asset_category/asset_category.json b/erpnext/accounts/doctype/asset_category/asset_category.json index 74762d790c..d34ec5ce3f 100644 --- a/erpnext/accounts/doctype/asset_category/asset_category.json +++ b/erpnext/accounts/doctype/asset_category/asset_category.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, "autoname": "field:asset_category_name", @@ -13,6 +14,7 @@ "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -24,7 +26,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Asset Category Name", "length": 0, @@ -42,6 +44,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -54,7 +57,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 1, "label": "Depreciation Method", "length": 0, @@ -73,6 +76,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -101,6 +105,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -112,7 +117,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Total Number of Depreciations", "length": 0, @@ -130,6 +135,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -141,7 +147,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Frequency of Depreciation (Months)", "length": 0, @@ -159,6 +165,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -188,6 +195,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -218,17 +226,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-17 16:09:52.955332", + "modified": "2017-10-28 19:59:31.819567", "modified_by": "Administrator", "module": "Accounts", "name": "Asset Category", diff --git a/erpnext/accounts/doctype/asset_category/asset_category.py b/erpnext/accounts/doctype/asset_category/asset_category.py index 5279c37ea8..dc454abe54 100644 --- a/erpnext/accounts/doctype/asset_category/asset_category.py +++ b/erpnext/accounts/doctype/asset_category/asset_category.py @@ -1,15 +1,10 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors +# Copyright (c) 2017, 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 cint from frappe.model.document import Document 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) \ No newline at end of file + pass diff --git a/erpnext/accounts/doctype/asset_category/test_asset_category.js b/erpnext/accounts/doctype/asset_category/test_asset_category.js new file mode 100644 index 0000000000..7e343b7519 --- /dev/null +++ b/erpnext/accounts/doctype/asset_category/test_asset_category.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 Category", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Category + () => frappe.tests.make('Asset Category', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/asset_category/test_asset_category.py b/erpnext/accounts/doctype/asset_category/test_asset_category.py index b32f9b5020..4d5169a0a6 100644 --- a/erpnext/accounts/doctype/asset_category/test_asset_category.py +++ b/erpnext/accounts/doctype/asset_category/test_asset_category.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals @@ -7,23 +7,4 @@ import frappe import unittest class TestAssetCategory(unittest.TestCase): - def test_mandatory_fields(self): - asset_category = frappe.new_doc("Asset Category") - asset_category.asset_category_name = "Computers" - - self.assertRaises(frappe.MandatoryError, asset_category.insert) - - asset_category.total_number_of_depreciations = 3 - asset_category.frequency_of_depreciation = 3 - asset_category.append("accounts", { - "company_name": "_Test Company", - "fixed_asset_account": "_Test Fixed Asset - _TC", - "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC", - "depreciation_expense_account": "_Test Depreciations - _TC" - }) - - try: - asset_category.insert() - except frappe.DuplicateEntryError: - pass - \ No newline at end of file + pass diff --git a/erpnext/accounts/doctype/asset_movement/asset_movement.js b/erpnext/accounts/doctype/asset_movement/asset_movement.js index 70c4080d1c..f2d82beaa2 100644 --- a/erpnext/accounts/doctype/asset_movement/asset_movement.js +++ b/erpnext/accounts/doctype/asset_movement/asset_movement.js @@ -1,18 +1,8 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt frappe.ui.form.on('Asset Movement', { - onload: function(frm) { - frm.add_fetch("asset", "warehouse", "source_warehouse"); - - frm.set_query("target_warehouse", function() { - return { - filters: [ - ["Warehouse", "company", "in", ["", cstr(frm.doc.company)]], - ["Warehouse", "is_group", "=", 0] - ] - } - }) + refresh: function(frm) { } }); diff --git a/erpnext/accounts/doctype/asset_movement/asset_movement.json b/erpnext/accounts/doctype/asset_movement/asset_movement.json index a1189f5035..7d7c12730a 100644 --- a/erpnext/accounts/doctype/asset_movement/asset_movement.json +++ b/erpnext/accounts/doctype/asset_movement/asset_movement.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, "autoname": "AM-.#####", @@ -12,6 +13,7 @@ "editable_grid": 0, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -23,7 +25,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 1, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 1, "label": "Asset", "length": 0, @@ -42,6 +44,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -53,7 +56,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Transaction Date", "length": 0, @@ -71,6 +74,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -82,7 +86,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 1, "label": "Company", "length": 0, @@ -101,6 +105,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -129,6 +134,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -159,6 +165,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -170,7 +177,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 1, "label": "Target Warehouse", "length": 0, @@ -189,6 +196,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -218,17 +226,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 1, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-17 16:09:32.069344", + "modified": "2017-10-28 20:01:49.372952", "modified_by": "Administrator", "module": "Accounts", "name": "Asset Movement", diff --git a/erpnext/accounts/doctype/asset_movement/asset_movement.py b/erpnext/accounts/doctype/asset_movement/asset_movement.py index 574c49992b..5acd4f1e82 100644 --- a/erpnext/accounts/doctype/asset_movement/asset_movement.py +++ b/erpnext/accounts/doctype/asset_movement/asset_movement.py @@ -1,48 +1,10 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt from __future__ import unicode_literals import frappe -from frappe import _ from frappe.model.document import Document class AssetMovement(Document): - def validate(self): - self.validate_asset() - self.validate_warehouses() - - def validate_asset(self): - status, company = frappe.db.get_value("Asset", self.asset, ["status", "company"]) - if status in ("Draft", "Scrapped", "Sold"): - frappe.throw(_("{0} asset cannot be transferred").format(status)) - - if company != self.company: - frappe.throw(_("Asset {0} does not belong to company {1}").format(self.asset, self.company)) - - def validate_warehouses(self): - if not self.source_warehouse: - self.source_warehouse = frappe.db.get_value("Asset", self.asset, "warehouse") - - if self.source_warehouse == self.target_warehouse: - frappe.throw(_("Source and Target Warehouse cannot be same")) - - def on_submit(self): - self.set_latest_warehouse_in_asset() - - def on_cancel(self): - self.set_latest_warehouse_in_asset() - - def set_latest_warehouse_in_asset(self): - latest_movement_entry = frappe.db.sql("""select target_warehouse from `tabAsset Movement` - where asset=%s and docstatus=1 and company=%s - order by transaction_date desc limit 1""", (self.asset, self.company)) - - if latest_movement_entry: - warehouse = latest_movement_entry[0][0] - else: - warehouse = frappe.db.sql("""select source_warehouse from `tabAsset Movement` - where asset=%s and docstatus=2 and company=%s - order by transaction_date asc limit 1""", (self.asset, self.company))[0][0] - - frappe.db.set_value("Asset", self.asset, "warehouse", warehouse) \ No newline at end of file + pass diff --git a/erpnext/accounts/doctype/asset_movement/test_asset_movement.js b/erpnext/accounts/doctype/asset_movement/test_asset_movement.js new file mode 100644 index 0000000000..b9515763c4 --- /dev/null +++ b/erpnext/accounts/doctype/asset_movement/test_asset_movement.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 Movement", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Movement + () => frappe.tests.make('Asset Movement', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/asset_movement/test_asset_movement.py b/erpnext/accounts/doctype/asset_movement/test_asset_movement.py index 9880efc37f..6f750a4c50 100644 --- a/erpnext/accounts/doctype/asset_movement/test_asset_movement.py +++ b/erpnext/accounts/doctype/asset_movement/test_asset_movement.py @@ -1,51 +1,10 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt from __future__ import unicode_literals import frappe -from frappe.utils import now import unittest -from erpnext.accounts.doctype.asset.test_asset import create_asset - class TestAssetMovement(unittest.TestCase): - def test_movement(self): - asset = create_asset() - - if asset.docstatus == 0: - asset.submit() - - movement1 = create_asset_movement(asset, target_warehouse="_Test Warehouse 1 - _TC") - self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 1 - _TC") - - movement2 = create_asset_movement(asset, target_warehouse="_Test Warehouse 2 - _TC") - self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 2 - _TC") - - movement1.cancel() - self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 2 - _TC") - - movement2.cancel() - self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse - _TC") - - asset.load_from_db() - asset.cancel() - frappe.delete_doc("Asset", asset.name) - - -def create_asset_movement(asset, target_warehouse, transaction_date=None): - if not transaction_date: - transaction_date = now() - - movement = frappe.new_doc("Asset Movement") - movement.update({ - "asset": asset.name, - "transaction_date": transaction_date, - "target_warehouse": target_warehouse, - "company": asset.company - }) - - movement.insert() - movement.submit() - - return movement + pass diff --git a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json index 1fadf5eb4f..29dcdfb04b 100644 --- a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json +++ b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 1, "autoname": "", @@ -13,6 +14,7 @@ "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -23,7 +25,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Schedule Date", "length": 0, "no_copy": 1, @@ -40,6 +44,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -50,7 +55,9 @@ "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 Amount", "length": 0, "no_copy": 1, @@ -68,6 +75,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -78,7 +86,9 @@ "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, @@ -94,6 +104,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -104,7 +115,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Accumulated Depreciation Amount", "length": 0, "no_copy": 1, @@ -122,6 +135,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -133,7 +147,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Journal Entry", "length": 0, "no_copy": 1, @@ -151,6 +167,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -162,7 +179,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Make Depreciation Entry", "length": 0, "no_copy": 0, @@ -179,17 +198,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-11-18 16:42:19.543657", + "modified": "2017-10-28 20:02:11.376361", "modified_by": "Administrator", "module": "Accounts", "name": "Depreciation Schedule", @@ -199,7 +218,9 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", + "track_changes": 0, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.py b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.py index 957d6d119f..54fba3f68c 100644 --- a/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.py +++ b/erpnext/accounts/doctype/depreciation_schedule/depreciation_schedule.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt from __future__ import unicode_literals diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index ccaae49670..82d8de541d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -298,7 +298,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte var row = locals[cdt][cdn]; if(row.asset) { frappe.call({ - method: erpnext.accounts.doctype.asset.depreciation.get_disposal_account_and_cost_center, + method: erpnext.assets.doctype.asset.depreciation.get_disposal_account_and_cost_center, args: { "company": frm.doc.company }, diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ee2b5542fb..8edeb99ae0 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -15,7 +15,7 @@ from erpnext.controllers.selling_controller import SellingController from erpnext.accounts.utils import get_account_currency from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data -from erpnext.accounts.doctype.asset.depreciation \ +from erpnext.assets.doctype.asset.depreciation \ import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal from erpnext.stock.doctype.batch.batch import set_batch_nos from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, get_delivery_note_serial_no diff --git a/erpnext/assets/__init__.py b/erpnext/assets/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/__init__.py b/erpnext/assets/doctype/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset/__init__.py b/erpnext/assets/doctype/asset/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js new file mode 100644 index 0000000000..e7459259c8 --- /dev/null +++ b/erpnext/assets/doctype/asset/asset.js @@ -0,0 +1,304 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.provide("erpnext.asset"); + +frappe.ui.form.on('Asset', { + onload: function(frm) { + frm.set_query("item_code", function() { + return { + "filters": { + "disabled": 0, + "is_fixed_asset": 1, + "is_stock_item": 0 + } + }; + }); + + frm.set_query("warehouse", function() { + return { + "filters": { + "company": frm.doc.company, + "is_group": 0 + } + }; + }); + }, + + refresh: function(frm) { + frappe.ui.form.trigger("Asset", "is_existing_asset"); + frm.toggle_display("next_depreciation_date", frm.doc.docstatus < 1); + frm.events.make_schedules_editable(frm); + + if (frm.doc.docstatus==1) { + if (in_list(["Submitted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) { + frm.add_custom_button("Transfer Asset", function() { + erpnext.asset.transfer_asset(frm); + }); + + frm.add_custom_button("Scrap Asset", function() { + erpnext.asset.scrap_asset(frm); + }); + + frm.add_custom_button("Sell Asset", function() { + erpnext.asset.make_sales_invoice(frm); + }); + + } else if (frm.doc.status=='Scrapped') { + frm.add_custom_button("Restore Asset", function() { + erpnext.asset.restore_asset(frm); + }); + } + 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"); + }, __("Make")); + } + if (frm.doc.maintenance_required && !frm.doc.maintenance_schedule) { + frm.add_custom_button(__("Asset Maintenance"), function() { + frm.trigger("create_asset_maintenance"); + }, __("Make")); + } + frm.page.set_inner_btn_group_as_primary(__("Make")); + frm.trigger("setup_chart"); + } + }, + + setup_chart: function(frm) { + var x_intervals = [frm.doc.purchase_date]; + var asset_values = [frm.doc.gross_purchase_amount]; + var last_depreciation_date = frm.doc.purchase_date; + + if(frm.doc.opening_accumulated_depreciation) { + last_depreciation_date = frappe.datetime.add_months(frm.doc.next_depreciation_date, + -1*frm.doc.frequency_of_depreciation); + + x_intervals.push(last_depreciation_date); + asset_values.push(flt(frm.doc.gross_purchase_amount) - + flt(frm.doc.opening_accumulated_depreciation)); + } + + $.each(frm.doc.schedules || [], function(i, v) { + x_intervals.push(v.schedule_date); + var asset_value = flt(frm.doc.gross_purchase_amount) - flt(v.accumulated_depreciation_amount); + if(v.journal_entry) { + last_depreciation_date = v.schedule_date; + asset_values.push(asset_value); + } else { + if (in_list(["Scrapped", "Sold"], frm.doc.status)) { + asset_values.push(null); + } else { + asset_values.push(asset_value) + } + } + }); + + if(in_list(["Scrapped", "Sold"], frm.doc.status)) { + x_intervals.push(frm.doc.disposal_date); + asset_values.push(0); + last_depreciation_date = frm.doc.disposal_date; + } + + frm.dashboard.render_graph({ + title: "Asset Value", + data: { + labels: x_intervals, + datasets: [{ + color: 'green', + values: asset_values, + formatted: asset_values.map(d => d.toFixed(2)) + }] + }, + type: 'line' + }); + }, + + + item_code: function(frm) { + if(frm.doc.item_code) { + frappe.call({ + method: "erpnext.assets.doctype.asset.asset.get_item_details", + args: { + item_code: frm.doc.item_code + }, + callback: function(r, rt) { + if(r.message) { + $.each(r.message, function(field, value) { + frm.set_value(field, value); + }) + } + } + }) + } + }, + + is_existing_asset: function(frm) { + frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation)); + }, + + opening_accumulated_depreciation: function(frm) { + erpnext.asset.set_accululated_depreciation(frm); + }, + + depreciation_method: function(frm) { + frm.events.make_schedules_editable(frm); + }, + + make_schedules_editable: function(frm) { + var is_editable = frm.doc.depreciation_method==="Manual" ? true : false; + frm.toggle_enable("schedules", is_editable); + frm.fields_dict["schedules"].grid.toggle_enable("schedule_date", is_editable); + frm.fields_dict["schedules"].grid.toggle_enable("depreciation_amount", is_editable); + }, + + make_purchase_invoice: function(frm) { + frappe.call({ + args: { + "asset": frm.doc.name, + "item_code": frm.doc.item_code, + "gross_purchase_amount": frm.doc.gross_purchase_amount, + "company": frm.doc.company, + "posting_date": frm.doc.purchase_date + }, + method: "erpnext.assets.doctype.asset.asset.make_purchase_invoice", + callback: function(r) { + var doclist = frappe.model.sync(r.message); + frappe.set_route("Form", doclist[0].doctype, doclist[0].name); + } + }) + }, + + create_asset_maintenance: function(frm) { + frappe.call({ + args: { + "asset": frm.doc.name, + "item_code": frm.doc.item_code, + "item_name": frm.doc.item_name, + "asset_category": frm.doc.asset_category, + "company": frm.doc.company + }, + method: "erpnext.assets.doctype.asset.asset.create_asset_maintenance", + callback: function(r) { + var doclist = frappe.model.sync(r.message); + frappe.set_route("Form", doclist[0].doctype, doclist[0].name); + } + }) + } +}); + +frappe.ui.form.on('Depreciation Schedule', { + make_depreciation_entry: function(frm, cdt, cdn) { + var row = locals[cdt][cdn]; + if (!row.journal_entry) { + frappe.call({ + method: "erpnext.assets.doctype.asset.depreciation.make_depreciation_entry", + args: { + "asset_name": frm.doc.name, + "date": row.schedule_date + }, + callback: function(r) { + frappe.model.sync(r.message); + frm.refresh(); + } + }) + } + }, + + depreciation_amount: function(frm, cdt, cdn) { + erpnext.asset.set_accululated_depreciation(frm); + } + +}) + +erpnext.asset.set_accululated_depreciation = function(frm) { + if(frm.doc.depreciation_method != "Manual") return; + + var accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation); + $.each(frm.doc.schedules || [], function(i, row) { + accumulated_depreciation += flt(row.depreciation_amount); + frappe.model.set_value(row.doctype, row.name, + "accumulated_depreciation_amount", accumulated_depreciation); + }) +}; + +erpnext.asset.scrap_asset = function(frm) { + frappe.confirm(__("Do you really want to scrap this asset?"), function () { + frappe.call({ + args: { + "asset_name": frm.doc.name + }, + method: "erpnext.assets.doctype.asset.depreciation.scrap_asset", + callback: function(r) { + cur_frm.reload_doc(); + } + }) + }) +}; + +erpnext.asset.restore_asset = function(frm) { + frappe.confirm(__("Do you really want to restore this scrapped asset?"), function () { + frappe.call({ + args: { + "asset_name": frm.doc.name + }, + method: "erpnext.assets.doctype.asset.depreciation.restore_asset", + callback: function(r) { + cur_frm.reload_doc(); + } + }) + }) +}; + +erpnext.asset.transfer_asset = function(frm) { + var dialog = new frappe.ui.Dialog({ + title: __("Transfer Asset"), + fields: [ + { + "label": __("Target Warehouse"), + "fieldname": "target_warehouse", + "fieldtype": "Link", + "options": "Warehouse", + "get_query": function () { + return { + filters: [ + ["Warehouse", "company", "in", ["", cstr(frm.doc.company)]], + ["Warehouse", "is_group", "=", 0] + ] + } + }, + "reqd": 1 + }, + { + "label": __("Date"), + "fieldname": "transfer_date", + "fieldtype": "Datetime", + "reqd": 1, + "default": frappe.datetime.now_datetime() + } + ] + }); + + dialog.set_primary_action(__("Transfer"), function() { + var args = dialog.get_values(); + if(!args) return; + dialog.hide(); + return frappe.call({ + type: "GET", + method: "erpnext.assets.doctype.asset.asset.transfer_asset", + args: { + args: { + "asset": frm.doc.name, + "transaction_date": args.transfer_date, + "source_warehouse": frm.doc.warehouse, + "target_warehouse": args.target_warehouse, + "company": frm.doc.company + } + }, + freeze: true, + callback: function(r) { + cur_frm.reload_doc(); + } + }) + }); + dialog.show(); +}; \ No newline at end of file diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json new file mode 100644 index 0000000000..e0ed56acc5 --- /dev/null +++ b/erpnext/assets/doctype/asset/asset.json @@ -0,0 +1,1228 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:asset_name", + "beta": 0, + "creation": "2016-03-01 17:01:27.920130", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 0, + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "asset_name", + "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": "Asset 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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_code", + "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": 1, + "label": "Item Code", + "length": 0, + "no_copy": 0, + "options": "Item", + "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": "item_name", + "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": "Item Name", + "length": 0, + "no_copy": 0, + "options": "item_code.item_name", + "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_category", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 1, + "in_list_view": 0, + "in_standard_filter": 1, + "label": "Asset Category", + "length": 0, + "no_copy": 0, + "options": "Asset Category", + "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": 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 Repair\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, + "columns": 0, + "fieldname": "asset_owner", + "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 Owner", + "length": 0, + "no_copy": 0, + "options": "Company\nSupplier\nCustomer", + "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.asset_owner == \"Supplier\"", + "fieldname": "supplier", + "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": "Supplier", + "length": 0, + "no_copy": 0, + "options": "Supplier", + "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.asset_owner == \"Customer\"", + "fieldname": "customer", + "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": "Customer", + "length": 0, + "no_copy": 0, + "options": "Customer", + "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, + "fieldname": "image", + "fieldtype": "Attach Image", + "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": "Image", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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_3", + "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": "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": 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": "warehouse", + "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": 1, + "label": "Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "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": "department", + "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": "Department", + "length": 0, + "no_copy": 0, + "options": "Department", + "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_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": "Purchase 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": 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": "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": "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, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Disposal Date", + "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": "journal_entry_for_scrap", + "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 for Scrap", + "length": 0, + "no_copy": 1, + "options": "Journal Entry", + "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": "section_break_5", + "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": "gross_purchase_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": "Gross Purchase Amount", + "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": 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_18", + "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, + "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, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Calculate Depreciation", + "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": 1, + "columns": 0, + "depends_on": "calculate_depreciation", + "fieldname": "section_break_23", + "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": "Depreciation", + "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", + "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": "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": 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": 0, + "options": "Company:company:default_currency", + "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": "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": 0, + "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": 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, + "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, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "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": 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": "", + "fieldname": "next_depreciation_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": "Next Depreciation Date", + "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_14", + "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": "Depreciation Schedule", + "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": "schedules", + "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": "Depreciation Schedules", + "length": 0, + "no_copy": 1, + "options": "Depreciation Schedule", + "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", + "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": "Maintenance", + "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, + "description": "Check if Asset requires Preventive Maintenance or Calibration", + "fieldname": "maintenance_required", + "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": "Maintenance Required", + "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": "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", + "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": 72, + "image_field": "image", + "image_view": 0, + "in_create": 0, + "is_submittable": 1, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2017-11-21 04:45:24.039059", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset", + "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": 1, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 1, + "show_name_in_global_search": 1, + "sort_field": "modified", + "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 new file mode 100644 index 0000000000..97cb876930 --- /dev/null +++ b/erpnext/assets/doctype/asset/asset.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2016, 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, add_months, cint, nowdate, getdate +from frappe.model.document import Document +from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_fixed_asset_account +from erpnext.assets.doctype.asset.depreciation \ + import get_disposal_account_and_cost_center, get_depreciation_accounts + +class Asset(Document): + def validate(self): + self.status = self.get_status() + self.validate_item() + self.set_missing_values() + self.validate_asset_values() + self.make_depreciation_schedule() + self.set_accumulated_depreciation() + if self.get("schedules"): + self.validate_expected_value_after_useful_life() + # Validate depreciation related accounts + get_depreciation_accounts(self) + + def on_submit(self): + self.set_status() + + def on_cancel(self): + self.validate_cancellation() + self.delete_depreciation_entries() + self.set_status() + + def validate_item(self): + item = frappe.db.get_value("Item", self.item_code, + ["is_fixed_asset", "is_stock_item", "disabled"], as_dict=1) + if not item: + frappe.throw(_("Item {0} does not exist").format(self.item_code)) + elif item.disabled: + frappe.throw(_("Item {0} has been disabled").format(self.item_code)) + elif not item.is_fixed_asset: + frappe.throw(_("Item {0} must be a Fixed Asset Item").format(self.item_code)) + elif item.is_stock_item: + 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) + + self.value_after_depreciation = (flt(self.gross_purchase_amount) - + flt(self.opening_accumulated_depreciation)) + + def validate_asset_values(self): + if flt(self.expected_value_after_useful_life) >= flt(self.gross_purchase_amount): + frappe.throw(_("Expected Value After Useful Life must be less than Gross Purchase Amount")) + + if not flt(self.gross_purchase_amount): + frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) + + if not self.is_existing_asset and self.calculate_depreciation: + 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) + if flt(self.opening_accumulated_depreciation) > depreciable_amount: + frappe.throw(_("Opening Accumulated Depreciation must be less than equal to {0}") + .format(depreciable_amount)) + + if self.opening_accumulated_depreciation: + if not self.number_of_depreciations_booked: + frappe.throw(_("Please set Number of Depreciations Booked")) + else: + self.number_of_depreciations_booked = 0 + + if cint(self.number_of_depreciations_booked) > cint(self.total_number_of_depreciations): + frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations")) + + if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(nowdate()): + frappe.msgprint(_("Next Depreciation Date is entered as past date"), title=_('Warning'), indicator='red') + + 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 (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: + for n in xrange(number_of_pending_depreciations): + schedule_date = add_months(self.next_depreciation_date, + n * cint(self.frequency_of_depreciation)) + + depreciation_amount = self.get_depreciation_amount(value_after_depreciation) + 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")): + 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": + depreciation_amount += flt(value_after_depreciation - flt(self.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) + + 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) + + 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")]) + + asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) - + flt(accumulated_depreciation_after_full_schedule), + self.precision('expected_value_after_useful_life')) + + 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)) + + def validate_cancellation(self): + if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"): + frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status)) + + if self.purchase_invoice: + frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice)) + + def delete_depreciation_entries(self): + for d in self.get("schedules"): + if d.journal_entry: + frappe.get_doc("Journal Entry", d.journal_entry).cancel() + d.db_set("journal_entry", None) + + self.db_set("value_after_depreciation", + (flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation))) + + def set_status(self, status=None): + '''Get and update status''' + if not status: + status = self.get_status() + self.db_set("status", status) + + def get_status(self): + '''Returns status based on whether it is draft, submitted, scrapped or depreciated''' + if self.docstatus == 0: + status = "Draft" + elif self.docstatus == 1: + status = "Submitted" + if self.journal_entry_for_scrap: + status = "Scrapped" + elif flt(self.value_after_depreciation) <= flt(self.expected_value_after_useful_life): + status = "Fully Depreciated" + elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount): + status = 'Partially Depreciated' + elif self.docstatus == 2: + status = "Cancelled" + return status + +@frappe.whitelist() +def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, posting_date): + pi = frappe.new_doc("Purchase Invoice") + pi.company = company + pi.currency = frappe.db.get_value("Company", company, "default_currency") + pi.set_posting_time = 1 + pi.posting_date = posting_date + pi.append("items", { + "item_code": item_code, + "is_fixed_asset": 1, + "asset": asset, + "expense_account": get_fixed_asset_account(asset), + "qty": 1, + "price_list_rate": gross_purchase_amount, + "rate": gross_purchase_amount + }) + pi.set_missing_values() + return pi + +@frappe.whitelist() +def make_sales_invoice(asset, item_code, company): + si = frappe.new_doc("Sales Invoice") + si.company = company + si.currency = frappe.db.get_value("Company", company, "default_currency") + disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(company) + si.append("items", { + "item_code": item_code, + "is_fixed_asset": 1, + "asset": asset, + "income_account": disposal_account, + "cost_center": depreciation_cost_center, + "qty": 1 + }) + si.set_missing_values() + return si + +@frappe.whitelist() +def create_asset_maintenance(asset, item_code, item_name, asset_category, company): + asset_maintenance = frappe.new_doc("Asset Maintenance") + asset_maintenance.update({ + "asset_name": asset, + "company": company, + "item_code": item_code, + "item_name": item_name, + "asset_category": asset_category + }) + return asset_maintenance + +@frappe.whitelist() +def transfer_asset(args): + import json + args = json.loads(args) + movement_entry = frappe.new_doc("Asset Movement") + movement_entry.update(args) + movement_entry.insert() + movement_entry.submit() + + frappe.db.commit() + + frappe.msgprint(_("Asset Movement record {0} created").format("{0}".format(movement_entry.name))) + +@frappe.whitelist() +def get_item_details(item_code): + asset_category = frappe.db.get_value("Item", item_code, "asset_category") + + 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) + + ret.update({ + "asset_category": asset_category + }) + + return ret diff --git a/erpnext/assets/doctype/asset/asset_dashboard.py b/erpnext/assets/doctype/asset/asset_dashboard.py new file mode 100644 index 0000000000..94dad1b311 --- /dev/null +++ b/erpnext/assets/doctype/asset/asset_dashboard.py @@ -0,0 +1,14 @@ +def get_data(): + return { + 'fieldname': 'asset_name', + 'transactions': [ + { + 'label': ['Maintenance'], + 'items': ['Asset Maintenance', 'Asset Maintenance Log'] + }, + { + 'label': ['Repair'], + 'items': ['Asset Repair'] + } + ] + } \ No newline at end of file diff --git a/erpnext/accounts/doctype/asset/asset_list.js b/erpnext/assets/doctype/asset/asset_list.js similarity index 100% rename from erpnext/accounts/doctype/asset/asset_list.js rename to erpnext/assets/doctype/asset/asset_list.js diff --git a/erpnext/accounts/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py similarity index 100% rename from erpnext/accounts/doctype/asset/depreciation.py rename to erpnext/assets/doctype/asset/depreciation.py diff --git a/erpnext/assets/doctype/asset/test_asset.js b/erpnext/assets/doctype/asset/test_asset.js new file mode 100644 index 0000000000..6119e38217 --- /dev/null +++ b/erpnext/assets/doctype/asset/test_asset.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", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset + () => frappe.tests.make('Asset', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py new file mode 100644 index 0000000000..9c3ed80b72 --- /dev/null +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -0,0 +1,343 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest +from frappe.utils import cstr, nowdate, getdate, flt +from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset +from erpnext.assets.doctype.asset.asset import make_sales_invoice, make_purchase_invoice + +class TestAsset(unittest.TestCase): + def setUp(self): + set_depreciation_settings_in_company() + create_asset() + frappe.db.sql("delete from `tabTax Rule`") + + def test_purchase_asset(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.submit() + + pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount, + asset.company, asset.purchase_date) + pi.supplier = "_Test Supplier" + pi.insert() + pi.submit() + + asset.load_from_db() + self.assertEqual(asset.supplier, "_Test Supplier") + self.assertEqual(asset.purchase_date, getdate("2015-01-01")) + self.assertEqual(asset.purchase_invoice, pi.name) + + expected_gle = ( + ("_Test Fixed Asset - _TC", 100000.0, 0.0), + ("Creditors - _TC", 0.0, 100000.0) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where voucher_type='Purchase Invoice' and voucher_no = %s + order by account""", pi.name) + + self.assertEqual(gle, expected_gle) + + pi.cancel() + + asset.load_from_db() + self.assertEqual(asset.supplier, None) + self.assertEqual(asset.purchase_invoice, None) + + self.assertFalse(frappe.db.get_value("GL Entry", + {"voucher_type": "Purchase Invoice", "voucher_no": pi.name})) + + + def test_schedule_for_straight_line_method(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + + self.assertEqual(asset.status, "Draft") + + expected_schedules = [ + ["2020-12-31", 30000, 30000], + ["2021-03-31", 30000, 60000], + ["2021-06-30", 30000, 90000] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_schedule_for_straight_line_method_for_existing_asset(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.is_existing_asset = 1 + asset.number_of_depreciations_booked = 1 + asset.opening_accumulated_depreciation = 40000 + asset.save() + + self.assertEqual(asset.status, "Draft") + + expected_schedules = [ + ["2020-12-31", 25000, 65000], + ["2021-03-31", 25000, 90000] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + + def test_schedule_for_double_declining_method(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.depreciation_method = "Double Declining Balance" + asset.save() + + expected_schedules = [ + ["2020-12-31", 66667, 66667], + ["2021-03-31", 22222, 88889], + ["2021-06-30", 1111, 90000] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_schedule_for_double_declining_method_for_existing_asset(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.depreciation_method = "Double Declining Balance" + asset.is_existing_asset = 1 + asset.number_of_depreciations_booked = 1 + asset.opening_accumulated_depreciation = 50000 + asset.save() + + expected_schedules = [ + ["2020-12-31", 33333, 83333], + ["2021-03-31", 6667, 90000] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_schedule_for_manual_method(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.depreciation_method = "Manual" + asset.schedules = [] + for schedule_date, amount in [["2020-12-31", 40000], ["2021-06-30", 30000], ["2021-10-31", 20000]]: + asset.append("schedules", { + "schedule_date": schedule_date, + "depreciation_amount": amount + }) + asset.save() + + self.assertEqual(asset.status, "Draft") + + expected_schedules = [ + ["2020-12-31", 40000, 40000], + ["2021-06-30", 30000, 70000], + ["2021-10-31", 20000, 90000] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_depreciation(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.submit() + asset.load_from_db() + self.assertEqual(asset.status, "Submitted") + + frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") + + post_depreciation_entries(date="2021-01-01") + asset.load_from_db() + + self.assertEqual(asset.status, "Partially Depreciated") + + # check depreciation entry series + self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR") + + expected_gle = ( + ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), + ("_Test Depreciations - _TC", 30000.0, 0.0) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where against_voucher_type='Asset' and against_voucher = %s + order by account""", asset.name) + + self.assertEqual(gle, expected_gle) + self.assertEqual(asset.get("value_after_depreciation"), 70000) + + def test_depreciation_entry_cancellation(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.submit() + post_depreciation_entries(date="2021-01-01") + + asset.load_from_db() + + # cancel depreciation entry + depr_entry = asset.get("schedules")[0].journal_entry + self.assertTrue(depr_entry) + frappe.get_doc("Journal Entry", depr_entry).cancel() + + asset.load_from_db() + depr_entry = asset.get("schedules")[0].journal_entry + self.assertFalse(depr_entry) + + + def test_scrap_asset(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.submit() + post_depreciation_entries(date="2021-01-01") + + scrap_asset("Macbook Pro 1") + + asset.load_from_db() + self.assertEqual(asset.status, "Scrapped") + self.assertTrue(asset.journal_entry_for_scrap) + + expected_gle = ( + ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0), + ("_Test Fixed Asset - _TC", 0.0, 100000.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 70000.0, 0.0) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where voucher_type='Journal Entry' and voucher_no = %s + order by account""", asset.journal_entry_for_scrap) + + self.assertEqual(gle, expected_gle) + + restore_asset("Macbook Pro 1") + + asset.load_from_db() + self.assertFalse(asset.journal_entry_for_scrap) + self.assertEqual(asset.status, "Partially Depreciated") + + def test_asset_sale(self): + frappe.get_doc("Asset", "Macbook Pro 1").submit() + post_depreciation_entries(date="2021-01-01") + + si = make_sales_invoice(asset="Macbook Pro 1", item_code="Macbook Pro", company="_Test Company") + si.customer = "_Test Customer" + si.due_date = nowdate() + si.get("items")[0].rate = 25000 + si.insert() + si.submit() + + self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Sold") + + expected_gle = ( + ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0), + ("_Test Fixed Asset - _TC", 0.0, 100000.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 45000.0, 0.0), + ("Debtors - _TC", 25000.0, 0.0) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no = %s + order by account""", si.name) + + self.assertEqual(gle, expected_gle) + + si.cancel() + + self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Partially Depreciated") + + def test_asset_expected_value_after_useful_life(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.depreciation_method = "Straight Line" + asset.is_existing_asset = 1 + asset.total_number_of_depreciations = 400 + asset.gross_purchase_amount = 16866177.00 + asset.expected_value_after_useful_life = 500000 + asset.save() + + accumulated_depreciation_after_full_schedule = \ + max([d.accumulated_depreciation_amount for d in asset.get("schedules")]) + + asset_value_after_full_schedule = (flt(asset.gross_purchase_amount) - + flt(accumulated_depreciation_after_full_schedule)) + + self.assertTrue(asset.expected_value_after_useful_life >= asset_value_after_full_schedule) + + def tearDown(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + + if asset.docstatus == 1 and asset.status not in ("Scrapped", "Sold", "Draft", "Cancelled"): + asset.cancel() + + self.assertEqual(frappe.db.get_value("Asset", "Macbook Pro 1", "status"), "Cancelled") + + frappe.delete_doc("Asset", "Macbook Pro 1") + +def create_asset(): + if not frappe.db.exists("Asset Category", "Computers"): + create_asset_category() + + if not frappe.db.exists("Item", "Macbook Pro"): + create_fixed_asset_item() + + asset = frappe.get_doc({ + "doctype": "Asset", + "asset_name": "Macbook Pro 1", + "asset_category": "Computers", + "item_code": "Macbook Pro", + "company": "_Test Company", + "purchase_date": "2015-01-01", + "next_depreciation_date": "2020-12-31", + "gross_purchase_amount": 100000, + "expected_value_after_useful_life": 10000, + "warehouse": "_Test Warehouse - _TC" + }) + try: + asset.save() + except frappe.DuplicateEntryError: + pass + + return asset + +def create_asset_category(): + asset_category = frappe.new_doc("Asset Category") + asset_category.asset_category_name = "Computers" + asset_category.total_number_of_depreciations = 3 + asset_category.frequency_of_depreciation = 3 + asset_category.append("accounts", { + "company_name": "_Test Company", + "fixed_asset_account": "_Test Fixed Asset - _TC", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC", + "depreciation_expense_account": "_Test Depreciations - _TC" + }) + asset_category.insert() + +def create_fixed_asset_item(): + try: + frappe.get_doc({ + "doctype": "Item", + "item_code": "Macbook Pro", + "item_name": "Macbook Pro", + "description": "Macbook Pro Retina Display", + "asset_category": "Computers", + "item_group": "All Item Groups", + "stock_uom": "Nos", + "is_stock_item": 0, + "is_fixed_asset": 1 + }).insert() + except frappe.DuplicateEntryError: + pass + +def set_depreciation_settings_in_company(): + company = frappe.get_doc("Company", "_Test Company") + company.accumulated_depreciation_account = "_Test Accumulated Depreciations - _TC" + company.depreciation_expense_account = "_Test Depreciations - _TC" + company.disposal_account = "_Test Gain/Loss on Asset Disposal - _TC" + company.depreciation_cost_center = "_Test Cost Center - _TC" + company.save() + + # Enable booking asset depreciation entry automatically + frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_category/__init__.py b/erpnext/assets/doctype/asset_category/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_category/asset_category.js b/erpnext/assets/doctype/asset_category/asset_category.js new file mode 100644 index 0000000000..aafe8a69a0 --- /dev/null +++ b/erpnext/assets/doctype/asset_category/asset_category.js @@ -0,0 +1,44 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Asset Category', { + onload: function(frm) { + frm.add_fetch('company_name', 'accumulated_depreciation_account', 'accumulated_depreciation_account'); + frm.add_fetch('company_name', 'depreciation_expense_account', 'accumulated_depreciation_account'); + + frm.set_query('fixed_asset_account', 'accounts', function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + return { + "filters": { + "account_type": "Fixed Asset", + "root_type": "Asset", + "is_group": 0, + "company": d.company_name + } + }; + }); + + frm.set_query('accumulated_depreciation_account', 'accounts', function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + return { + "filters": { + "root_type": "Asset", + "is_group": 0, + "company": d.company_name + } + }; + }); + + frm.set_query('depreciation_expense_account', 'accounts', function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + return { + "filters": { + "root_type": "Expense", + "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 new file mode 100644 index 0000000000..39b3978383 --- /dev/null +++ b/erpnext/assets/doctype/asset_category/asset_category.json @@ -0,0 +1,295 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:asset_category_name", + "beta": 0, + "creation": "2016-03-01 17:41:39.778765", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 0, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "asset_category_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": "Asset Category 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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "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", + "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, + "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": "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": "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, + "fieldname": "section_break_2", + "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": "Accounts", + "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": "accounts", + "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": "Accounts", + "length": 0, + "no_copy": 0, + "options": "Asset Category 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": 1, + "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": 0, + "max_attachments": 0, + "modified": "2017-10-19 16:08:02.114363", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Category", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 1, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 1, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 1, + "sort_field": "modified", + "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 new file mode 100644 index 0000000000..5279c37ea8 --- /dev/null +++ b/erpnext/assets/doctype/asset_category/asset_category.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.utils import cint +from frappe.model.document import Document + +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) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.js b/erpnext/assets/doctype/asset_category/test_asset_category.js new file mode 100644 index 0000000000..7e343b7519 --- /dev/null +++ b/erpnext/assets/doctype/asset_category/test_asset_category.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 Category", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Category + () => frappe.tests.make('Asset Category', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py new file mode 100644 index 0000000000..b32f9b5020 --- /dev/null +++ b/erpnext/assets/doctype/asset_category/test_asset_category.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +class TestAssetCategory(unittest.TestCase): + def test_mandatory_fields(self): + asset_category = frappe.new_doc("Asset Category") + asset_category.asset_category_name = "Computers" + + self.assertRaises(frappe.MandatoryError, asset_category.insert) + + asset_category.total_number_of_depreciations = 3 + asset_category.frequency_of_depreciation = 3 + asset_category.append("accounts", { + "company_name": "_Test Company", + "fixed_asset_account": "_Test Fixed Asset - _TC", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC", + "depreciation_expense_account": "_Test Depreciations - _TC" + }) + + try: + asset_category.insert() + except frappe.DuplicateEntryError: + pass + \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance/__init__.py b/erpnext/assets/doctype/asset_maintenance/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.js b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.js new file mode 100644 index 0000000000..6a6e72f546 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.js @@ -0,0 +1,105 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Asset Maintenance', { + setup: (frm) => { + frm.fields_dict["asset_maintenance_tasks"].grid.get_field("assign_to").get_query = function(){ + return { + filters: { + parent: frm.doc.maintenance_team + } + }; + }, + frm.set_indicator_formatter('maintenance_status', + function(doc) { + let indicator = 'blue'; + if (doc.maintenance_status == 'Overdue') { + indicator = 'orange'; + } + if (doc.maintenance_status == 'Cancelled') { + indicator = 'red'; + } + return indicator; + } + ); + }, + refresh: (frm) => { + if(!frm.is_new()) { + frm.trigger('make_dashboard'); + } + }, + make_dashboard: (frm) => { + if(!frm.is_new()) { + frappe.call({ + method: 'erpnext.assets.doctype.asset_maintenance.asset_maintenance.get_maintenance_log', + args: {asset_name: frm.doc.asset_name}, + callback: (r) => { + if(!r.message) { + return; + } + var section = frm.dashboard.add_section(`
+ ${ __("Maintenance Log") }
`); + var rows = $('
').appendTo(section); + // show + (r.message || []).forEach(function(d) { + $(`
+
+ + ${d.maintenance_status} ${d.count} + +
+
`).appendTo(rows); + }); + frm.dashboard.show(); + } + }); + } + } +}); + +frappe.ui.form.on('Asset Maintenance Task', { + start_date: (frm, cdt, cdn) => { + get_next_due_date(frm, cdt, cdn); + }, + periodicity: (frm, cdt, cdn) => { + get_next_due_date(frm, cdt, cdn); + }, + last_completion_date: (frm, cdt, cdn) => { + get_next_due_date(frm, cdt, cdn); + }, + end_date: (frm, cdt, cdn) => { + get_next_due_date(frm, cdt, cdn); + }, + assign_to: (frm, cdt, cdn) => { + if (frm.doc.__islocal) { + frappe.model.set_value(cdt, cdn, "assign_to", ""); + frappe.model.set_value(cdt, cdn, "assign_to_name", ""); + frappe.throw(__("Please save before assigning task.")); + } + } +}); + +var get_next_due_date = function (frm, cdt, cdn) { + var d = locals[cdt][cdn]; + if (d.start_date && d.periodicity) { + return frappe.call({ + method: 'erpnext.assets.doctype.asset_maintenance.asset_maintenance.calculate_next_due_date', + args: { + start_date: d.start_date, + periodicity: d.periodicity, + end_date: d.end_date, + last_completion_date: d.last_completion_date, + next_due_date: d.next_due_date + }, + callback: function(r) { + if (r.message) { + frappe.model.set_value(cdt, cdn, "next_due_date", r.message); + } + else { + frappe.model.set_value(cdt, cdn, "next_due_date", ""); + } + } + }); + } +}; \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.json b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.json new file mode 100644 index 0000000000..f526bb8d72 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.json @@ -0,0 +1,459 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "field:asset_name", + "beta": 0, + "creation": "2017-10-19 16:50:22.879545", + "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": "asset_name", + "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": "Asset Name", + "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_name.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": "item_code", + "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": "Item Code", + "length": 0, + "no_copy": 0, + "options": "asset_name.item_code", + "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": "item_name", + "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": "Item Name", + "length": 0, + "no_copy": 0, + "options": "asset_name.item_name", + "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_3", + "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": "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": 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": "section_break_6", + "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": "maintenance_team", + "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": "Maintenance Team", + "length": 0, + "no_copy": 0, + "options": "Asset Maintenance Team", + "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_9", + "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": "maintenance_manager", + "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": "Maintenance Manager", + "length": 0, + "no_copy": 0, + "options": "maintenance_team.maintenance_manager", + "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": "maintenance_manager_name", + "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": "Maintenance Manager Name", + "length": 0, + "no_copy": 0, + "options": "maintenance_team.maintenance_manager_name", + "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_8", + "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": "Tasks", + "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_maintenance_tasks", + "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": "Maintenance Tasks", + "length": 0, + "no_copy": 0, + "options": "Asset Maintenance Task", + "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 + } + ], + "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": "2017-11-21 04:42:54.893169", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Maintenance", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 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": "Quality Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "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_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py new file mode 100644 index 0000000000..0ddb5d1687 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, 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.desk.form import assign_to +from frappe import throw, _ +from frappe.utils import add_days, add_months, add_years, getdate, nowdate + +class AssetMaintenance(Document): + def validate(self): + 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)) + if getdate(task.next_due_date) < getdate(nowdate()): + task.maintenance_status = "Overdue" + if not self.get("__islocal"): + if not task.assign_to: + task.assign_to = self.maintenance_manager + if task.assign_to: + self.assign_tasks(task) + + def assign_tasks(self, task): + team_member = frappe.get_doc('User', task.assign_to).email + args = { + 'doctype' : self.doctype, + 'assign_to' : team_member, + 'name' : self.name, + 'description' : task.maintenance_task, + 'date' : task.next_due_date + } + if not frappe.db.sql("""select owner from `tabToDo` + where reference_type=%(doctype)s and reference_name=%(name)s and status="Open" + and owner=%(assign_to)s""", args): + assign_to.add(args) + + +@frappe.whitelist() +def calculate_next_due_date(periodicity, start_date = None, end_date = None, last_completion_date = None, next_due_date = None): + if not start_date and not last_completion_date: + start_date = frappe.utils.now() + + if last_completion_date and (last_completion_date > start_date or not start_date): + start_date = last_completion_date + + if periodicity == 'Daily': + next_due_date = add_days(start_date, 1) + if periodicity == 'Weekly': + next_due_date = add_days(start_date, 7) + if periodicity == 'Monthly': + next_due_date = add_months(start_date, 1) + if periodicity == 'Yearly': + next_due_date = add_years(start_date, 1) + if periodicity == '2 Yearly': + next_due_date = add_years(start_date, 2) + if periodicity == 'Quarterly': + next_due_date = add_months(start_date, 3) + if end_date and (start_date >= end_date or last_completion_date >= end_date or next_due_date): + next_due_date = "" + return next_due_date + +@frappe.whitelist() +def get_maintenance_log(asset_name): + return frappe.db.sql(""" + select maintenance_status, count(asset_name) as count, asset_name + from `tabAsset Maintenance Log` + where asset_name=%s group by maintenance_status""", + (asset_name), as_dict=1) + \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.js b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.js new file mode 100644 index 0000000000..f9b38a1020 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.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 Maintenance", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Maintenance + () => frappe.tests.make('Asset Maintenance', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py new file mode 100644 index 0000000000..139d20210a --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest +from frappe.utils import nowdate, add_days +from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate_next_due_date + +class TestAssetMaintenance(unittest.TestCase): + def setUp(self): + set_depreciation_settings_in_company() + create_asset() + create_maintenance_team() + + def test_create_asset_maintenance(self): + if not frappe.db.exists("Asset Maintenance", "Photocopier"): + asset_maintenance = frappe.get_doc({ + "doctype": "Asset Maintenance", + "asset_name": "Photocopier", + "maintenance_team": "Team Awesome", + "company": "_Test Company", + "asset_maintenance_tasks": get_maintenance_tasks() + }).insert() + + next_due_date = calculate_next_due_date(nowdate(), "Monthly") + self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date) + + def test_create_asset_maintenance_log(self): + if not frappe.db.exists("Asset Maintenance Log", "Photocopier"): + asset_maintenance_log = frappe.get_doc({ + "doctype": "Asset Maintenance Log", + "asset_maintenance": "Photocopier", + "task": "Change Oil", + "completion_date": add_days(nowdate(), 2), + "maintenance_status": "Completed" + }).insert() + asset_maintenance = frappe.get_doc("Asset Maintenance", "Photocopier") + next_due_date = calculate_next_due_date(asset_maintenance_log.completion_date, "Monthly") + self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date) + +def create_asset(): + if not frappe.db.exists("Asset Category", "Equipment"): + create_asset_category() + + if not frappe.db.exists("Item", "Photocopier"): + frappe.get_doc({ + "doctype": "Item", + "item_code": "Photocopier", + "item_name": "Photocopier", + "item_group": "All Item Groups", + "company": "_Test Company", + "is_fixed_asset": 1, + "is_stock_item": 0, + "asset_category": "Equipment" + }).insert() + + if not frappe.db.exists("Asset", "Photocopier"): + frappe.get_doc({ + "doctype": "Asset", + "asset_name": "Photocopier", + "item_code": "Photocopier", + "asset_category": "Equipment", + "gross_purchase_amount": 100000, + "expected_value_after_useful_life": 10000, + "warehouse": "_Test Warehouse - _TC", + "company": "_Test Company", + "purchase_date": nowdate(), + "maintenance_required": 1 + }).insert() + +def create_maintenance_team(): + user_list = ["marcus@abc.com", "thalia@abc.com", "mathias@abc.com"] + if not frappe.db.exists("Role", "Technician"): + frappe.get_doc({"doctype": "Role", "role_name": "Technician"}).insert() + for user in user_list: + if not frappe.db.get_value("User", user): + frappe.get_doc({ + "doctype": "User", + "email": user, + "first_name": user, + "new_password": "password", + "roles": [{"doctype": "Has Role", "role": "Technician"}] + }).insert() + + if not frappe.db.exists("Asset Maintenance Team", "Team Awesome"): + frappe.get_doc({ + "doctype": "Asset Maintenance Team", + "maintenance_team_name": "Team Awesome", + "company": "_Test Company", + "maintenance_team_members": get_maintenance_team(user_list) + }).insert() + +def get_maintenance_team(user_list): + return [{"team_member": user_list[0], + "full_name": user_list[0], + "maintenance_role": "Technician" + } + ] + +def get_maintenance_tasks(): + return [{"maintenance_task": "Change Oil", + "start_date": nowdate(), + "periodicity": "Monthly", + "maintenance_type": "Preventive Maintenance", + "maintenance_status": "Planned" + }, + {"maintenance_task": "Check Gears", + "start_date": nowdate(), + "periodicity": "Yearly", + "maintenance_type": "Calibration", + "maintenance_status": "Planned" + } + ] + +def create_asset_category(): + asset_category = frappe.new_doc("Asset Category") + asset_category.asset_category_name = "Equipment" + asset_category.total_number_of_depreciations = 3 + asset_category.frequency_of_depreciation = 3 + asset_category.append("accounts", { + "company_name": "_Test Company", + "fixed_asset_account": "_Test Fixed Asset - _TC", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC", + "depreciation_expense_account": "_Test Depreciations - _TC" + }) + asset_category.insert() + +def set_depreciation_settings_in_company(): + company = frappe.get_doc("Company", "_Test Company") + company.accumulated_depreciation_account = "_Test Accumulated Depreciations - _TC" + company.depreciation_expense_account = "_Test Depreciations - _TC" + company.disposal_account = "_Test Gain/Loss on Asset Disposal - _TC" + company.depreciation_cost_center = "_Test Cost Center - _TC" + company.save() + + # Enable booking asset depreciation entry automatically + frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance_log/__init__.py b/erpnext/assets/doctype/asset_maintenance_log/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.js b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.js new file mode 100644 index 0000000000..c5db90ad37 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.js @@ -0,0 +1,15 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Asset Maintenance Log', { + asset_maintenance: (frm) => { + frm.set_query('task', function(doc) { + return { + query: "erpnext.assets.doctype.asset_maintenance_log.asset_maintenance_log.get_maintenance_tasks", + filters: { + 'asset_maintenance': doc.asset_maintenance + } + }; + }); + } +}); \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json new file mode 100644 index 0000000000..61ce35af7f --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json @@ -0,0 +1,763 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "naming_series:", + "beta": 0, + "creation": "2017-10-23 16:58:44.424309", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "asset_maintenance", + "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 Maintenance", + "length": 0, + "no_copy": 0, + "options": "Asset Maintenance", + "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": "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": "Series", + "length": 0, + "no_copy": 0, + "options": "AML-", + "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_name", + "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 Name", + "length": 0, + "no_copy": 0, + "options": "asset_maintenance.asset_name", + "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_2", + "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": "item_code", + "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": "Item Code", + "length": 0, + "no_copy": 0, + "options": "asset_maintenance.item_code", + "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": "item_name", + "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": "Item Name", + "length": 0, + "no_copy": 0, + "options": "asset_maintenance.item_name", + "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_5", + "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": "task", + "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": "Task", + "length": 0, + "no_copy": 0, + "options": "Asset Maintenance Task", + "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": "maintenance_type", + "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": "Maintenance Type", + "length": 0, + "no_copy": 0, + "options": "task.maintenance_type", + "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": "periodicity", + "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": "Periodicity", + "length": 0, + "no_copy": 0, + "options": "task.periodicity", + "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": "assign_to_name", + "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": "Assign To", + "length": 0, + "no_copy": 0, + "options": "task.assign_to_name", + "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_6", + "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": "due_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": "Due Date", + "length": 0, + "no_copy": 0, + "options": "task.next_due_date", + "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": "completion_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": "Completion 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": "maintenance_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": 1, + "label": "Maintenance Status", + "length": 0, + "no_copy": 0, + "options": "Pending\nCompleted\nCancelled\nOverdue", + "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": "section_break_12", + "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": "has_certificate", + "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": "Has Certificate ", + "length": 0, + "no_copy": 0, + "options": "task.has_certificate", + "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.has_certificate", + "fieldname": "certificate_attachement", + "fieldtype": "Attach", + "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": "Certificate", + "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_6", + "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": "description", + "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": "Description", + "length": 0, + "no_copy": 0, + "options": "task.description", + "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_9", + "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "actions_performed", + "fieldtype": "Text Editor", + "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": "Actions performed", + "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": "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 Maintenance Log", + "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": 1, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2017-10-29 08:38:55.707903", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Maintenance Log", + "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": "Manufacturing User", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "", + "track_changes": 1, + "track_seen": 1 +} \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py new file mode 100644 index 0000000000..4e50751607 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, 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 import _ +from frappe.utils import nowdate, getdate +from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate_next_due_date + +class AssetMaintenanceLog(Document): + def validate(self): + # if getdate(self.due_date) > getdate(nowdate()): + # self.maintenance_status = "Overdue" + + if self.maintenance_status == "Completed" and not self.completion_date: + frappe.throw(_("Please select Completion Date for Completed Asset Maintenance Log")) + + # if self.maintenance_status != "Completed" and self.completion_date: +# frappe.throw(_("Please select Maintenance Status as Completed or remove Completion Date")) + + def on_submit(self): + if self.maintenance_status not in ['Completed', 'Cancelled']: + frappe.throw(_("Maintenance Status has to be Cancelled or Completed to Submit")) + self.update_maintenance_task() + + def update_maintenance_task(self): + asset_maintenance_doc = frappe.get_doc('Asset Maintenance Task', self.task) + if self.maintenance_status == "Completed": + if asset_maintenance_doc.last_completion_date != self.completion_date: + next_due_date = calculate_next_due_date(periodicity = self.periodicity, last_completion_date = self.completion_date) + asset_maintenance_doc.last_completion_date = self.completion_date + asset_maintenance_doc.next_due_date = next_due_date + asset_maintenance_doc.maintenance_status = "Planned" + asset_maintenance_doc.save() + if self.maintenance_status == "Cancelled": + asset_maintenance_doc.maintenance_status = "Cancelled" + asset_maintenance_doc.save() + + +@frappe.whitelist() +def get_maintenance_tasks(doctype, txt, searchfield, start, page_len, filters): + asset_maintenance_tasks = frappe.db.get_values('Asset Maintenance Task', {'parent':filters.get("asset_maintenance")}, 'maintenance_task') + return asset_maintenance_tasks + +@frappe.whitelist() +def get_events(start, end, filters=None): + """Returns events for Gantt / Calendar view rendering. + + :param start: Start date-time. + :param end: End date-time. + :param filters: Filters (JSON). + """ + from frappe.desk.calendar import get_event_conditions + conditions = get_event_conditions("Asset Maintenance Log", filters) + data = frappe.db.sql("""select name, due_date, due_date, + task, maintenance_status, asset_name from `tabAsset Maintenance Log` + where ((ifnull(due_date, '0000-00-00')!= '0000-00-00') \ + and (due_date <= %(end)s) \ + or ((ifnull(due_date, '0000-00-00')!= '0000-00-00') \ + and due_date >= %(start)s)) + {conditions}""".format(conditions=conditions), { + "start": start, + "end": end + }, as_dict=True, update={"allDay": 0}) + + return data \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_calendar.js b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_calendar.js new file mode 100644 index 0000000000..a4978849f0 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_calendar.js @@ -0,0 +1,22 @@ +// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +// License: GNU General Public License v3. See license.txt + +frappe.views.calendar["Asset Maintenance Log"] = { + field_map: { + "start": "due_date", + "end": "due_date", + "id": "name", + "title": "task", + "allDay": "allDay", + "progress": "progress" + }, + filters: [ + { + "fieldtype": "Link", + "fieldname": "asset_name", + "options": "Asset Maintenance", + "label": __("Asset Maintenance") + } + ], + get_events_method: "erpnext.assets.doctype.asset_maintenance_log.asset_maintenance_log.get_events" +}; diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js new file mode 100644 index 0000000000..b854413310 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js @@ -0,0 +1,14 @@ +frappe.listview_settings['Asset Maintenance Log'] = { + add_fields: ["maintenance_status"], + get_indicator: function(doc) { + if(doc.maintenance_status=="Pending") { + return [__("Pending"), "orange"]; + } else if(doc.maintenance_status=="Completed") { + return [__("Completed"), "green"]; + } else if(doc.maintenance_status=="Cancelled") { + return [__("Cancelled"), "red"]; + } else if(doc.maintenance_status=="Overdue") { + return [__("Overdue"), "red"]; + } + } +}; diff --git a/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.js b/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.js new file mode 100644 index 0000000000..4e80184ea7 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.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 Maintenance Log", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Maintenance Log + () => frappe.tests.make('Asset Maintenance Log', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py new file mode 100644 index 0000000000..a1ec8792b2 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestAssetMaintenanceLog(unittest.TestCase): + pass diff --git a/erpnext/assets/doctype/asset_maintenance_task/__init__.py b/erpnext/assets/doctype/asset_maintenance_task/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.json b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.json new file mode 100644 index 0000000000..7cf0fecbb7 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.json @@ -0,0 +1,643 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "field:maintenance_task", + "beta": 0, + "creation": "2017-10-20 07:10:55.903571", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "maintenance_task", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Maintenance Task", + "length": 0, + "no_copy": 0, + "options": "", + "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": 1 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "maintenance_type", + "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": "Maintenance Type", + "length": 0, + "no_copy": 0, + "options": "Preventive Maintenance\nCalibration", + "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_2", + "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, + "default": "", + "fieldname": "maintenance_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": 0, + "label": "Maintenance Status", + "length": 0, + "no_copy": 0, + "options": "Planned\nOverdue\nCancelled", + "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": "section_break_2", + "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, + "default": "Today", + "fieldname": "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": "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": 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": "periodicity", + "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": "Periodicity", + "length": 0, + "no_copy": 0, + "options": "\nDaily\nWeekly\nMonthly\nQuarterly\nYearly\n2 Yearly", + "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_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": "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": "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": "certificate_required", + "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": "Certificate Required", + "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": 1, + "set_only_once": 1, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_9", + "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": "assign_to", + "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": "Assign To", + "length": 0, + "no_copy": 0, + "options": "Maintenance Team Member", + "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": "assign_to_name", + "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": "Assign to Name", + "length": 0, + "no_copy": 0, + "options": "assign_to.full_name", + "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_10", + "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": "next_due_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": "Next Due 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_14", + "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": "last_completion_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": "Last Completion 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": "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": "description", + "fieldtype": "Text Editor", + "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": "Description", + "length": 0, + "no_copy": 0, + "options": "", + "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, + "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": "2017-10-25 21:51:38.931436", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Maintenance Task", + "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": 0, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py new file mode 100644 index 0000000000..2a5666d506 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, 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 AssetMaintenanceTask(Document): + pass diff --git a/erpnext/assets/doctype/asset_maintenance_team/__init__.py b/erpnext/assets/doctype/asset_maintenance_team/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.js b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.js new file mode 100644 index 0000000000..c94e3dbc3c --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.js @@ -0,0 +1,8 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Asset Maintenance Team', { + refresh: function() { + + } +}); diff --git a/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.json b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.json new file mode 100644 index 0000000000..28836b5062 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.json @@ -0,0 +1,275 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "field:maintenance_team_name", + "beta": 0, + "creation": "2017-10-20 11:43:47.712616", + "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": "maintenance_team_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": "Maintenance Team 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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "maintenance_manager", + "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": "Maintenance Manager", + "length": 0, + "no_copy": 0, + "options": "User", + "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": "maintenance_manager_name", + "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": "Maintenance Manager Name", + "length": 0, + "no_copy": 0, + "options": "maintenance_manager.full_name", + "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_2", + "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": "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": 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": "section_break_2", + "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": "maintenance_team_members", + "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": "Maintenance Team Members", + "length": 0, + "no_copy": 0, + "options": "Maintenance Team Member", + "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 + } + ], + "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": "2017-10-25 12:59:19.133235", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Maintenance Team", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 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 + } + ], + "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_maintenance_team/asset_maintenance_team.py b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py new file mode 100644 index 0000000000..f741a8fff3 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, 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 AssetMaintenanceTeam(Document): + pass diff --git a/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.js b/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.js new file mode 100644 index 0000000000..41bf69623e --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.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 Maintenance Team", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Maintenance Team + () => frappe.tests.make('Asset Maintenance Team', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py b/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py new file mode 100644 index 0000000000..a0c0b146f1 --- /dev/null +++ b/erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestAssetMaintenanceTeam(unittest.TestCase): + pass diff --git a/erpnext/assets/doctype/asset_movement/__init__.py b/erpnext/assets/doctype/asset_movement/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.js b/erpnext/assets/doctype/asset_movement/asset_movement.js new file mode 100644 index 0000000000..70c4080d1c --- /dev/null +++ b/erpnext/assets/doctype/asset_movement/asset_movement.js @@ -0,0 +1,18 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Asset Movement', { + onload: function(frm) { + frm.add_fetch("asset", "warehouse", "source_warehouse"); + + frm.set_query("target_warehouse", function() { + return { + filters: [ + ["Warehouse", "company", "in", ["", cstr(frm.doc.company)]], + ["Warehouse", "is_group", "=", 0] + ] + } + }) + + } +}); diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.json b/erpnext/assets/doctype/asset_movement/asset_movement.json new file mode 100644 index 0000000000..0c05552962 --- /dev/null +++ b/erpnext/assets/doctype/asset_movement/asset_movement.json @@ -0,0 +1,315 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 0, + "autoname": "AM-.#####", + "beta": 0, + "creation": "2016-04-25 18:00:23.559973", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 0, + "fields": [ + { + "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": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "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": "transaction_date", + "fieldtype": "Datetime", + "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": "Transaction 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": 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": "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, + "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_warehouse", + "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": 1, + "label": "Source Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "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_warehouse", + "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": "Target Warehouse", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "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": "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 Movement", + "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": "2017-10-19 16:08:17.389257", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Movement", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 1, + "apply_user_permissions": 0, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 1, + "apply_user_permissions": 0, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 1, + "apply_user_permissions": 0, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + } + ], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 0, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py new file mode 100644 index 0000000000..574c49992b --- /dev/null +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.model.document import Document + +class AssetMovement(Document): + def validate(self): + self.validate_asset() + self.validate_warehouses() + + def validate_asset(self): + status, company = frappe.db.get_value("Asset", self.asset, ["status", "company"]) + if status in ("Draft", "Scrapped", "Sold"): + frappe.throw(_("{0} asset cannot be transferred").format(status)) + + if company != self.company: + frappe.throw(_("Asset {0} does not belong to company {1}").format(self.asset, self.company)) + + def validate_warehouses(self): + if not self.source_warehouse: + self.source_warehouse = frappe.db.get_value("Asset", self.asset, "warehouse") + + if self.source_warehouse == self.target_warehouse: + frappe.throw(_("Source and Target Warehouse cannot be same")) + + def on_submit(self): + self.set_latest_warehouse_in_asset() + + def on_cancel(self): + self.set_latest_warehouse_in_asset() + + def set_latest_warehouse_in_asset(self): + latest_movement_entry = frappe.db.sql("""select target_warehouse from `tabAsset Movement` + where asset=%s and docstatus=1 and company=%s + order by transaction_date desc limit 1""", (self.asset, self.company)) + + if latest_movement_entry: + warehouse = latest_movement_entry[0][0] + else: + warehouse = frappe.db.sql("""select source_warehouse from `tabAsset Movement` + where asset=%s and docstatus=2 and company=%s + order by transaction_date asc limit 1""", (self.asset, self.company))[0][0] + + frappe.db.set_value("Asset", self.asset, "warehouse", warehouse) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.js b/erpnext/assets/doctype/asset_movement/test_asset_movement.js new file mode 100644 index 0000000000..b9515763c4 --- /dev/null +++ b/erpnext/assets/doctype/asset_movement/test_asset_movement.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 Movement", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Movement + () => frappe.tests.make('Asset Movement', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.py b/erpnext/assets/doctype/asset_movement/test_asset_movement.py new file mode 100644 index 0000000000..bf3e37b825 --- /dev/null +++ b/erpnext/assets/doctype/asset_movement/test_asset_movement.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +from frappe.utils import now +import unittest +from erpnext.assets.doctype.asset.test_asset import create_asset + + +class TestAssetMovement(unittest.TestCase): + def test_movement(self): + asset = create_asset() + + if asset.docstatus == 0: + asset.submit() + + movement1 = create_asset_movement(asset, target_warehouse="_Test Warehouse 1 - _TC") + self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 1 - _TC") + + movement2 = create_asset_movement(asset, target_warehouse="_Test Warehouse 2 - _TC") + self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 2 - _TC") + + movement1.cancel() + self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse 2 - _TC") + + movement2.cancel() + self.assertEqual(frappe.db.get_value("Asset", asset.name, "warehouse"), "_Test Warehouse - _TC") + + asset.load_from_db() + asset.cancel() + frappe.delete_doc("Asset", asset.name) + + +def create_asset_movement(asset, target_warehouse, transaction_date=None): + if not transaction_date: + transaction_date = now() + + movement = frappe.new_doc("Asset Movement") + movement.update({ + "asset": asset.name, + "transaction_date": transaction_date, + "target_warehouse": target_warehouse, + "company": asset.company + }) + + movement.insert() + movement.submit() + + return movement diff --git a/erpnext/assets/doctype/asset_repair/__init__.py b/erpnext/assets/doctype/asset_repair/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.js b/erpnext/assets/doctype/asset_repair/asset_repair.js new file mode 100644 index 0000000000..4ba2b4474a --- /dev/null +++ b/erpnext/assets/doctype/asset_repair/asset_repair.js @@ -0,0 +1,21 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Asset Repair', { + repair_status: (frm) => { + if (frm.doc.completion_date && frm.doc.repair_status == "Completed") { + frappe.call ({ + method: "erpnext.assets.doctype.asset_repair.asset_repair.get_downtime", + args: { + "failure_date":frm.doc.failure_date, + "completion_date":frm.doc.completion_date + }, + callback: function(r) { + if(r.message) { + frm.set_value("downtime", r.message + " Hrs"); + } + } + }); + } + } +}); diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.json b/erpnext/assets/doctype/asset_repair/asset_repair.json new file mode 100644 index 0000000000..ccba908bbc --- /dev/null +++ b/erpnext/assets/doctype/asset_repair/asset_repair.json @@ -0,0 +1,718 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "naming_series:", + "beta": 0, + "creation": "2017-10-23 11:38:54.004355", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "asset_name", + "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": "Asset Name", + "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": "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": "Series", + "length": 0, + "no_copy": 0, + "options": "ARLOG-", + "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_2", + "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": "item_code", + "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": "Item Code", + "length": 0, + "no_copy": 0, + "options": "asset_name.item_code", + "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": "item_name", + "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": "Item Name", + "length": 0, + "no_copy": 0, + "options": "asset_name.item_name", + "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_5", + "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": "failure_date", + "fieldtype": "Datetime", + "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": "Failure Date", + "length": 0, + "no_copy": 0, + "options": "", + "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "assign_to", + "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": "Assign To", + "length": 0, + "no_copy": 0, + "options": "User", + "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, + "fieldname": "assign_to_name", + "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": "Assign To Name", + "length": 0, + "no_copy": 0, + "options": "assign_to.full_name", + "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_6", + "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "completion_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": "Completion 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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Pending", + "fieldname": "repair_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": 0, + "label": "Repair Status", + "length": 0, + "no_copy": 1, + "options": "Pending\nCompleted\nCancelled", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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, + "width": "" + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_9", + "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": "description", + "fieldtype": "Long 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": "Error Description", + "length": 0, + "no_copy": 0, + "options": "", + "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_9", + "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "actions_performed", + "fieldtype": "Long 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": "Actions performed", + "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_17", + "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "downtime", + "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": "Downtime", + "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_19", + "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "repair_cost", + "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": "Repair Cost", + "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": "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 Repair", + "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": "2017-10-24 16:55:03.424503", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Repair", + "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": "Manufacturing 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": "Quality Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "", + "track_changes": 1, + "track_seen": 1 +} \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py new file mode 100644 index 0000000000..049b931b5e --- /dev/null +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, 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 time_diff_in_hours +from frappe.model.document import Document + +class AssetRepair(Document): + def validate(self): + if self.repair_status == "Completed" and not self.completion_date: + frappe.throw(_("Please select Completion Date for Completed Repair")) + + +@frappe.whitelist() +def get_downtime(failure_date, completion_date): + downtime = time_diff_in_hours(completion_date, failure_date) + return round(downtime, 2) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.js b/erpnext/assets/doctype/asset_repair/test_asset_repair.js new file mode 100644 index 0000000000..7424ffe2b8 --- /dev/null +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.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 Repair", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Asset Repair + () => frappe.tests.make('Asset Repair', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py new file mode 100644 index 0000000000..3d325a9683 --- /dev/null +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestAssetRepair(unittest.TestCase): + pass diff --git a/erpnext/assets/doctype/depreciation_schedule/__init__.py b/erpnext/assets/doctype/depreciation_schedule/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json new file mode 100644 index 0000000000..330347240d --- /dev/null +++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json @@ -0,0 +1,226 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 1, + "autoname": "", + "beta": 0, + "creation": "2016-03-02 15:11:01.278862", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "schedule_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": "Schedule Date", + "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": 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": "depreciation_amount", + "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": "Depreciation Amount", + "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": 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, + "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": "accumulated_depreciation_amount", + "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": "Accumulated Depreciation Amount", + "length": 0, + "no_copy": 1, + "options": "Company:company:default_currency", + "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, + "depends_on": "eval:doc.docstatus==1", + "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": 1, + "in_standard_filter": 0, + "label": "Journal Entry", + "length": 0, + "no_copy": 1, + "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.docstatus==1 && !doc.journal_entry && doc.schedule_date <= get_today())", + "fieldname": "make_depreciation_entry", + "fieldtype": "Button", + "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": "Make Depreciation Entry", + "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 + } + ], + "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": "2017-10-19 16:30:13.738170", + "modified_by": "Administrator", + "module": "Assets", + "name": "Depreciation Schedule", + "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": 0, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py new file mode 100644 index 0000000000..54fba3f68c --- /dev/null +++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, 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 DepreciationSchedule(Document): + pass diff --git a/erpnext/assets/doctype/maintenance_team_member/__init__.py b/erpnext/assets/doctype/maintenance_team_member/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.js b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.js new file mode 100644 index 0000000000..2db712546c --- /dev/null +++ b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.js @@ -0,0 +1,8 @@ +// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Maintenance Team Member', { + refresh: function() { + + } +}); diff --git a/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.json b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.json new file mode 100644 index 0000000000..195661a802 --- /dev/null +++ b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.json @@ -0,0 +1,136 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "field:team_member", + "beta": 0, + "creation": "2016-10-26 10:56:04.534717", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "team_member", + "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": "Team Member", + "length": 0, + "no_copy": 0, + "options": "User", + "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": "", + "fieldname": "full_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Full Name", + "length": 0, + "no_copy": 0, + "options": "team_member.full_name", + "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": "maintenance_role", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Maintenance Role", + "length": 0, + "no_copy": 0, + "options": "Role", + "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 + } + ], + "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": "2017-10-24 15:51:58.295745", + "modified_by": "Administrator", + "module": "Assets", + "name": "Maintenance Team Member", + "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": 0, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py new file mode 100644 index 0000000000..3d9e555db6 --- /dev/null +++ b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, 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 MaintenanceTeamMember(Document): + pass diff --git a/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.js b/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.js new file mode 100644 index 0000000000..d942e2a156 --- /dev/null +++ b/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.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: Maintenance Team Member", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Maintenance Team Member + () => frappe.tests.make('Maintenance Team Member', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py b/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py new file mode 100644 index 0000000000..c805e56e5c --- /dev/null +++ b/erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestMaintenanceTeamMember(unittest.TestCase): + pass diff --git a/erpnext/assets/report/__init__.py b/erpnext/assets/report/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/report/asset_maintenance/__init__.py b/erpnext/assets/report/asset_maintenance/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/report/asset_maintenance/asset_maintenance.json b/erpnext/assets/report/asset_maintenance/asset_maintenance.json new file mode 100644 index 0000000000..100c8d86ae --- /dev/null +++ b/erpnext/assets/report/asset_maintenance/asset_maintenance.json @@ -0,0 +1,24 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2017-10-24 13:12:39.946874", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "json": "{\"add_total_row\": 0, \"sort_by\": \"Asset Maintenance.modified\", \"add_totals_row\": 0, \"sort_order\": \"desc\", \"sort_by_next\": null, \"filters\": [], \"sort_order_next\": \"desc\", \"columns\": [[\"name\", \"Asset Maintenance\"], [\"asset_name\", \"Asset Maintenance\"], [\"item_code\", \"Asset Maintenance\"], [\"maintenance_type\", \"Asset Maintenance Task\"], [\"maintenance_task\", \"Asset Maintenance Task\"], [\"description\", \"Asset Maintenance Task\"], [\"assign_to_name\", \"Asset Maintenance Task\"], [\"maintenance_status\", \"Asset Maintenance Task\"], [\"next_due_date\", \"Asset Maintenance Task\"], [\"last_completion_date\", \"Asset Maintenance Task\"]]}", + "modified": "2017-10-27 22:49:56.286781", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Maintenance", + "owner": "Administrator", + "ref_doctype": "Asset Maintenance", + "report_name": "Asset Maintenance", + "report_type": "Report Builder", + "roles": [ + { + "role": "System Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index 6f4dd03883..cf35ef940a 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -98,14 +98,6 @@ def get_data(): { "type": "doctype", "name": "Item", - }, - { - "type": "doctype", - "name": "Asset", - }, - { - "type": "doctype", - "name": "Asset Category", } ] }, @@ -274,11 +266,6 @@ def get_data(): "name": "Period Closing Voucher", "description": _("Close Balance Sheet and book Profit or Loss.") }, - { - "type": "doctype", - "name": "Asset Movement", - "description": _("Transfer an asset from one warehouse to another") - }, { "type": "doctype", "name": "Cheque Print Template", diff --git a/erpnext/config/assets.py b/erpnext/config/assets.py new file mode 100644 index 0000000000..1001e948ec --- /dev/null +++ b/erpnext/config/assets.py @@ -0,0 +1,77 @@ +from __future__ import unicode_literals +from frappe import _ + +def get_data(): + return [ + { + "label": _("Assets"), + "items": [ + { + "type": "doctype", + "name": "Asset", + }, + { + "type": "doctype", + "name": "Asset Category", + } + ] + }, + { + "label": _("Maintenance"), + "items": [ + { + "type": "doctype", + "name": "Asset Maintenance Team", + }, + { + "type": "doctype", + "name": "Asset Maintenance", + }, + { + "type": "doctype", + "name": "Asset Maintenance Tasks", + }, + { + "type": "doctype", + "name": "Asset Maintenance Log", + }, + { + "type": "doctype", + "name": "Asset Repair", + }, + ] + }, + { + "label": _("Tools"), + "items": [ + { + "type": "doctype", + "name": "Asset Movement", + "description": _("Transfer an asset from one warehouse to another") + }, + ] + }, + { + "label": _("Reports"), + "icon": "fa fa-table", + "items": [ + { + "type": "report", + "name": "Asset Depreciation Ledger", + "doctype": "Asset", + "is_query_report": True, + }, + { + "type": "report", + "name": "Asset Depreciations and Balances", + "doctype": "Asset", + "is_query_report": True, + }, + { + "type": "report", + "name": "Asset Maintenance", + "doctype": "Asset Maintenance" + }, + ] + } + ] \ No newline at end of file diff --git a/erpnext/config/desktop.py b/erpnext/config/desktop.py index ce6c0c3f43..d204ed81d2 100644 --- a/erpnext/config/desktop.py +++ b/erpnext/config/desktop.py @@ -293,5 +293,11 @@ def get_data(): "_doctype": "Restaurant", "link": "List/Restaurant", "label": _("Restaurant") - } + }, + { + "module_name": "Assets", + "color": "#4286f4", + "icon": "octicon octicon-database", + "type": "module" + }, ] diff --git a/erpnext/demo/user/fixed_asset.py b/erpnext/demo/user/fixed_asset.py index b2db39c9f0..e6d1687202 100644 --- a/erpnext/demo/user/fixed_asset.py +++ b/erpnext/demo/user/fixed_asset.py @@ -6,8 +6,8 @@ from __future__ import unicode_literals import frappe from frappe.utils.make_random import get_random -from erpnext.accounts.doctype.asset.asset import make_purchase_invoice, make_sales_invoice -from erpnext.accounts.doctype.asset.depreciation import post_depreciation_entries, scrap_asset +from erpnext.assets.doctype.asset.asset import make_purchase_invoice, make_sales_invoice +from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset def work(): frappe.set_user(frappe.db.get_global('demo_accounts_user')) diff --git a/erpnext/docs/assets/img/accounts/asset-category.png b/erpnext/docs/assets/img/asset/asset-category.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset-category.png rename to erpnext/docs/assets/img/asset/asset-category.png diff --git a/erpnext/docs/assets/img/accounts/asset-graph.png b/erpnext/docs/assets/img/asset/asset-graph.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset-graph.png rename to erpnext/docs/assets/img/asset/asset-graph.png diff --git a/erpnext/docs/assets/img/accounts/asset-item.png b/erpnext/docs/assets/img/asset/asset-item.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset-item.png rename to erpnext/docs/assets/img/asset/asset-item.png diff --git a/erpnext/docs/assets/img/accounts/asset-movement-using-button.png b/erpnext/docs/assets/img/asset/asset-movement-using-button.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset-movement-using-button.png rename to erpnext/docs/assets/img/asset/asset-movement-using-button.png diff --git a/erpnext/docs/assets/img/accounts/asset-movement.png b/erpnext/docs/assets/img/asset/asset-movement.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset-movement.png rename to erpnext/docs/assets/img/asset/asset-movement.png diff --git a/erpnext/docs/assets/img/accounts/asset-purchase-invoice.png b/erpnext/docs/assets/img/asset/asset-purchase-invoice.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset-purchase-invoice.png rename to erpnext/docs/assets/img/asset/asset-purchase-invoice.png diff --git a/erpnext/docs/assets/img/accounts/asset-sales.png b/erpnext/docs/assets/img/asset/asset-sales.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset-sales.png rename to erpnext/docs/assets/img/asset/asset-sales.png diff --git a/erpnext/docs/assets/img/accounts/asset.png b/erpnext/docs/assets/img/asset/asset.png similarity index 100% rename from erpnext/docs/assets/img/accounts/asset.png rename to erpnext/docs/assets/img/asset/asset.png diff --git a/erpnext/docs/assets/img/asset/asset_maintenance.png b/erpnext/docs/assets/img/asset/asset_maintenance.png new file mode 100644 index 0000000000..725cf62809 Binary files /dev/null and b/erpnext/docs/assets/img/asset/asset_maintenance.png differ diff --git a/erpnext/docs/assets/img/asset/asset_maintenance_log.png b/erpnext/docs/assets/img/asset/asset_maintenance_log.png new file mode 100644 index 0000000000..8a51c2d514 Binary files /dev/null and b/erpnext/docs/assets/img/asset/asset_maintenance_log.png differ diff --git a/erpnext/docs/assets/img/asset/asset_maintenance_team.png b/erpnext/docs/assets/img/asset/asset_maintenance_team.png new file mode 100644 index 0000000000..c022249ff2 Binary files /dev/null and b/erpnext/docs/assets/img/asset/asset_maintenance_team.png differ diff --git a/erpnext/docs/assets/img/asset/asset_repair.png b/erpnext/docs/assets/img/asset/asset_repair.png new file mode 100644 index 0000000000..ff3cd5f4d3 Binary files /dev/null and b/erpnext/docs/assets/img/asset/asset_repair.png differ diff --git a/erpnext/docs/assets/img/accounts/depreciation-entry.png b/erpnext/docs/assets/img/asset/depreciation-entry.png similarity index 100% rename from erpnext/docs/assets/img/accounts/depreciation-entry.png rename to erpnext/docs/assets/img/asset/depreciation-entry.png diff --git a/erpnext/docs/assets/img/accounts/depreciation-schedule.png b/erpnext/docs/assets/img/asset/depreciation-schedule.png similarity index 100% rename from erpnext/docs/assets/img/accounts/depreciation-schedule.png rename to erpnext/docs/assets/img/asset/depreciation-schedule.png diff --git a/erpnext/docs/assets/img/asset/maintenance_required.png b/erpnext/docs/assets/img/asset/maintenance_required.png new file mode 100644 index 0000000000..a4c853ad90 Binary files /dev/null and b/erpnext/docs/assets/img/asset/maintenance_required.png differ diff --git a/erpnext/docs/assets/img/accounts/scrap-journal-entry.png b/erpnext/docs/assets/img/asset/scrap-journal-entry.png similarity index 100% rename from erpnext/docs/assets/img/accounts/scrap-journal-entry.png rename to erpnext/docs/assets/img/asset/scrap-journal-entry.png diff --git a/erpnext/docs/user/manual/en/asset/asset-maintenance.md b/erpnext/docs/user/manual/en/asset/asset-maintenance.md new file mode 100644 index 0000000000..7abb06b2de --- /dev/null +++ b/erpnext/docs/user/manual/en/asset/asset-maintenance.md @@ -0,0 +1,31 @@ +# Asset Maintenance Management +ERPNext provides features to track the details of individual maintenance/calibration tasks for an asset by date, the person responsible for the maintenance and future maintenance due date. + +To perform Asset Maintenance in ERPNext, + + 1. Enable Asset Maintenance. + 2. Create Asset Maintenance Team. + 3. Create Asset Maintenance. + 4. Create Asset Maintenance Log. + 5. Create Asset Repair Log. + +### Enable Asset Maintenance +Check Maintain Required in Asset to enable Asset Maintenance +Asset + +### Asset Maintenance Team +Create Asset Maintenance Team, select team members and their role. +Asset + + +### Asset Maintenance +For each asset create a Asset Maintenance record listing all the associated maintenance tasks, maintenance type (Preventive Maintenance or Calibration), periodicity, assign to and start and end date of maintenance. Based on start date and periodicity the next due date is auto-calculated and a ToDo is created for the Assignee. +Asset + +### Asset Maintenance Log +For each task in Asset Maintenance create a Asset Maintenance Log which will have status, completion date and actions performed. Based on completion date here, next due date is calculated automatically. +Asset + +### Asset Repair +You can also maintain the records of Repair/Failures of your asset which are not listed in Asset Maintenance. +Asset \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md b/erpnext/docs/user/manual/en/asset/assets.md similarity index 86% rename from erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md rename to erpnext/docs/user/manual/en/asset/assets.md index 45bd2278e5..6932c59dcc 100644 --- a/erpnext/docs/user/manual/en/accounts/managing-fixed-assets.md +++ b/erpnext/docs/user/manual/en/asset/assets.md @@ -6,7 +6,7 @@ In ERPNext, you can maintain fixed asset records like Computers, Furnitures, Car Based on the type of assets, create Asset Category. For example, all your desktops and laptops can be part of an Asset Category named "Computers". Here you can set default depreciation method, periodicity and depreciation related accounts, which will be applicable to all the assets under the category. -Asset Category +Asset Category > **Note:** You can also set default depreciation related Accounts and Cost Centers in Company master. @@ -14,13 +14,13 @@ Based on the type of assets, create Asset Category. For example, all your deskto Asset master is the heart of fixed asset management feature. All the transactions related to Asset like purchasing, sales, depreciation, scrapping will be managed from the Asset master. -Asset +Asset Explanation of the fields: 1. Item Code: An Item for the Asset must be a non-stock item, with "Is Asset" field checked. - Asset Item + Asset Item 2. Asset Category: The category of assets it belongs to. 3. Is Existing Asset: Check if the asset is being carried forward from the previous Fiscal Year. The existing assets which are partially / fully depreciated can also be created/maintained for the future reference. @@ -42,24 +42,24 @@ Explanation of the fields: The system automatically creates a schedule for depreciation based on depreciation method and other related inputs in the Asset record. -Asset +Asset On the scheduled date, system creates depreciation entry by creating a Journal Entry and the same Journal Entry is updated in the depreciation table for reference. Next Depreciation Date and Current Value are also updated on submission of depreciation entry. -Asset +Asset In the depreciation entry, the "Accumulated Depreciation Account" is credited and "Depreciation Expense Account" is debited. The related accounts can be set in the Asset Category or Company. For better visibility, net value of the asset on different depreciation dates are shown in a line graph. -Asset +Asset ## Purchase an Asset For purchasing a new asset, create and submit the asset record with all the depreciation settings. Then create a Purchase Invoice via "Make Purchase Invoice" button. On clicking the button, system will load a new Purchase Invoice form with pre-loaded items table. It will also set proper fixed asset account (defined in the Asset Category) in the Expense Account field. You need to select Supplier and other necessary details and submit the Purchase Invoice. -Asset +Asset On submission of the invoice, the "Fixed Asset Account" will be debited and payable account will be credited. It also updates purchase date, supplier and Purchase Invoice no. in the Asset master. @@ -73,23 +73,23 @@ To sell an asset, open the asset record and create a Sales Invoice by clicking o - "Accumulated Depreciation Account" will be debited by the total depreciated amount till now. - "Gain/Loss Account on Asset Disposal" will be credited/debited based on gain/loss amount. The Gain/Loss account can be set in Company record. -Asset +Asset ## Scrap an Asset You can scrap an asset anytime using the "Scrap Asset" button in the Asset record. The "Gain/Loss Account on Asset Disposal" mentioned in the Company is debited by the Current Value (After Depreciation) of the asset. After scrapping, you can also restore the asset using "Restore Asset" button. -Asset +Asset ## Asset Movement The movement of the assets (from one warehouse to another) is also tracked via Asset Movement form. -Asset +Asset There is also a dedicated button "Transfer Asset" inside the Asset form to track the Asset Movement. -Asset +Asset {next} diff --git a/erpnext/hooks.py b/erpnext/hooks.py index d929428377..b4afea77ec 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -214,7 +214,7 @@ scheduler_events = { "erpnext.accounts.doctype.fiscal_year.fiscal_year.auto_create_fiscal_year", "erpnext.hr.doctype.employee.employee.send_birthday_reminders", "erpnext.projects.doctype.task.task.set_tasks_as_overdue", - "erpnext.accounts.doctype.asset.depreciation.post_depreciation_entries", + "erpnext.assets.doctype.asset.depreciation.post_depreciation_entries", "erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings.send_summary", "erpnext.stock.doctype.serial_no.serial_no.update_maintenance_status", "erpnext.buying.doctype.supplier_scorecard.supplier_scorecard.refresh_scorecards", diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json index d1de7e335e..079ec68793 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json +++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json @@ -101,7 +101,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 1, "set_only_once": 0, "unique": 0 @@ -653,7 +653,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 @@ -685,7 +685,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 @@ -764,7 +764,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-06-13 14:29:01.615516", + "modified": "2017-10-17 07:57:01.723090", "modified_by": "Administrator", "module": "Maintenance", "name": "Maintenance Schedule", diff --git a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.js new file mode 100644 index 0000000000..e0f05b1abb --- /dev/null +++ b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.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: Maintenance Schedule", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Maintenance Schedule + () => frappe.tests.make('Maintenance Schedule', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json index c6aac14635..2f159e9a4d 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json +++ b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "autoname": "hash", @@ -13,6 +14,7 @@ "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -44,6 +46,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -62,6 +65,7 @@ "no_copy": 0, "oldfieldname": "item_name", "oldfieldtype": "Data", + "options": "item_code.item_name", "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, @@ -74,6 +78,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -85,13 +90,14 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 1, + "in_list_view": 0, "in_standard_filter": 0, "label": "Description", "length": 0, "no_copy": 0, "oldfieldname": "description", "oldfieldtype": "Data", + "options": "item_code.description", "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, @@ -106,6 +112,7 @@ "width": "300px" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -134,6 +141,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -164,6 +172,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -194,6 +203,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -225,6 +235,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -249,12 +260,13 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, "set_only_once": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -280,12 +292,13 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, "set_only_once": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -314,6 +327,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -344,6 +358,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -377,17 +392,17 @@ "width": "150px" } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-02-17 17:06:21.448695", + "modified": "2017-10-17 08:37:28.964789", "modified_by": "Administrator", "module": "Maintenance", "name": "Maintenance Schedule Item", diff --git a/erpnext/modules.txt b/erpnext/modules.txt index 79ded14573..beb1df56a9 100644 --- a/erpnext/modules.txt +++ b/erpnext/modules.txt @@ -17,4 +17,5 @@ Schools Regional Healthcare Restaurant -ERPNext Integrations \ No newline at end of file +ERPNext Integrations +Assets \ No newline at end of file diff --git a/erpnext/patches.txt b/erpnext/patches.txt index bc63f4a794..5d3c31f58d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -465,3 +465,4 @@ erpnext.patches.v9_2.delete_healthcare_domain_default_items erpnext.patches.v9_1.create_issue_opportunity_type erpnext.patches.v9_2.rename_translated_domains_in_en erpnext.patches.v9_0.set_shipping_type_for_existing_shipping_rules +erpnext.patches.v9_0.update_asset_module_doctypes diff --git a/erpnext/patches/v9_0/update_asset_module_doctypes.py b/erpnext/patches/v9_0/update_asset_module_doctypes.py new file mode 100644 index 0000000000..66eb287de3 --- /dev/null +++ b/erpnext/patches/v9_0/update_asset_module_doctypes.py @@ -0,0 +1,12 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('assets', 'doctype', 'asset_category') + frappe.db.set_value("DocType", "Asset Category", "module", "Assets") + frappe.db.set_value("DocType", "Asset", "module", "Assets") + frappe.db.set_value("DocType", "Asset Movement", "module", "Assets") + frappe.db.set_value("DocType", "Depreciation Schedule", "module", "Assets") \ No newline at end of file