From 3c9839f8324f5c7249736c05eb25d8db083c0ad9 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Tue, 17 Jul 2018 18:01:44 +0530 Subject: [PATCH] Defaults in Item Group (#14874) * Add Defaults table in Item Group * Fetch defaults from Item group if not found in Item * Add patch * Remove default fields from Item Group * Set query for defaults * Fix Codacy * Modify test records * Modify budget.py and sales_order.py * Remove join from query * Else condition to avoid error if no defaults found * refrain from making item test records before item_group * default cost center fetch correction * Remove tab item group from query --- erpnext/accounts/doctype/budget/budget.py | 16 +-- .../doctype/purchase_order/purchase_order.py | 4 +- erpnext/controllers/buying_controller.py | 6 + erpnext/patches.txt | 1 + .../patches/v11_0/add_item_group_defaults.py | 73 ++++++++++++ .../doctype/sales_order/sales_order.py | 8 +- .../setup/doctype/item_group/item_group.js | 34 ++++++ .../setup/doctype/item_group/item_group.json | 110 ++++++++++-------- .../setup/doctype/item_group/item_group.py | 16 +++ .../doctype/item_group/test_item_group.js | 23 ++++ .../doctype/item_group/test_records.json | 6 +- .../sales_partner/test_sales_partner.py | 4 +- .../doctype/sales_person/test_sales_person.py | 4 +- .../setup/doctype/territory/test_territory.py | 4 +- erpnext/stock/doctype/item/test_item.py | 2 +- .../stock/doctype/stock_entry/stock_entry.py | 6 +- erpnext/stock/get_item_details.py | 38 +++--- 17 files changed, 275 insertions(+), 80 deletions(-) create mode 100644 erpnext/patches/v11_0/add_item_group_defaults.py create mode 100644 erpnext/setup/doctype/item_group/test_item_group.js diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py index 421d756a1ed..771ec8d3694 100644 --- a/erpnext/accounts/doctype/budget/budget.py +++ b/erpnext/accounts/doctype/budget/budget.py @@ -298,8 +298,7 @@ def get_item_details(args): if not (cost_center and expense_account): for doctype in ['Item Group', 'Company']: - data = get_expense_cost_center(doctype, - args.get(frappe.scrub(doctype))) + data = get_expense_cost_center(doctype, args) if not cost_center and data: cost_center = data[0] @@ -312,8 +311,11 @@ def get_item_details(args): return cost_center, expense_account -def get_expense_cost_center(doctype, value): - fields = (['default_cost_center', 'default_expense_account'] - if doctype == 'Item Group' else ['cost_center', 'default_expense_account']) - - return frappe.db.get_value(doctype, value, fields) +def get_expense_cost_center(doctype, args): + if doctype == 'Item Group': + return frappe.db.get_value('Item Default', + {'parent': args.get(frappe.scrub(doctype)), 'company': args.get('company')}, + ['buying_cost_center', 'expense_account']) + else: + return frappe.db.get_value(doctype, args.get(frappe.scrub(doctype)),\ + ['cost_center', 'default_expense_account']) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 5af30788b7b..5b8204a8df5 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -15,6 +15,7 @@ from erpnext.buying.utils import validate_for_items, check_for_closed_status from erpnext.stock.utils import get_bin from six import string_types from erpnext.stock.doctype.item.item import get_item_defaults +from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -390,9 +391,10 @@ def make_purchase_invoice(source_name, target_doc=None): target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty) item = get_item_defaults(target.item_code, source_parent.company) + item_group = get_item_group_defaults(target.item_code, source_parent.company) target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \ or item.get("buying_cost_center") \ - or frappe.db.get_value("Item Group", item.item_group, "default_cost_center") + or item_group.get("buying_cost_center") doc = get_mapped_doc("Purchase Order", source_name, { "Purchase Order": { diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index a22a9ec960c..70a07733a7e 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -79,6 +79,12 @@ class BuyingController(StockController): {"parent": d.item_code, "company": self.company}, "default_supplier") if supplier: self.supplier = supplier + else: + item_group = frappe.db.get_value("Item", d.item_code, "item_group") + supplier = frappe.db.get_value("Item Default", + {"parent": item_group, "company": self.company}, "default_supplier") + if supplier: + self.supplier = supplier break def validate_stock_or_nonstock_items(self): diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 507f9f52127..f66f2a2e24d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -559,3 +559,4 @@ erpnext.patches.v11_0.skip_user_permission_check_for_department erpnext.patches.v11_0.set_department_for_doctypes erpnext.patches.v11_0.update_allow_transfer_for_manufacture erpnext.patches.v11_0.rename_healthcare_doctype_and_fields +erpnext.patches.v11_0.add_item_group_defaults diff --git a/erpnext/patches/v11_0/add_item_group_defaults.py b/erpnext/patches/v11_0/add_item_group_defaults.py new file mode 100644 index 00000000000..2a15ad1e2a3 --- /dev/null +++ b/erpnext/patches/v11_0/add_item_group_defaults.py @@ -0,0 +1,73 @@ +# Copyright (c) 2018, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + ''' + + Fields to move from item group to item defaults child table + [ default_cost_center, default_expense_account, default_income_account ] + + ''' + + frappe.reload_doc('stock', 'doctype', 'item_default') + frappe.reload_doc('setup', 'doctype', 'item_group') + + companies = frappe.get_all("Company") + item_groups = frappe.db.sql("""select name, default_income_account, default_expense_account,\ + default_cost_center from `tabItem Group`""", as_dict=True) + + if len(companies) == 1: + for item_group in item_groups: + doc = frappe.get_doc("Item Group", item_group.get("name")) + item_group_defaults = [] + item_group_defaults.append({ + "company": companies[0].name, + "income_account": item_group.get("default_income_account"), + "expense_account": item_group.get("default_expense_account"), + "buying_cost_center": item_group.get("default_cost_center"), + "selling_cost_center": item_group.get("default_cost_center") + }) + doc.extend("item_group_defaults", item_group_defaults) + for child_doc in doc.item_group_defaults: + child_doc.db_insert() + else: + item_group_dict = { + "default_expense_account": ["expense_account"], + "default_income_account": ["income_account"], + "default_cost_center": ["buying_cost_center", "selling_cost_center"] + } + for item_group in item_groups: + item_group_defaults = [] + def insert_into_item_defaults(doc_field_name, doc_field_value, company): + for d in item_group_defaults: + if d.get("company") == company: + d[doc_field_name[0]] = doc_field_value + if len(doc_field_name) > 1: + d[doc_field_name[1]] = doc_field_value + return + + item_group_defaults.append({ + "company": company, + doc_field_name[0]: doc_field_value + }) + + if(len(doc_field_name) > 1): + item_group_defaults[len(item_group_defaults)-1][doc_field_name[1]] = doc_field_value + + for d in [ + ["default_expense_account", "Account"], ["default_income_account", "Account"], + ["default_cost_center", "Cost Center"] + ]: + if item_group.get(d[0]): + company = frappe.get_value(d[1], item_group.get(d[0]), "company", cache=True) + doc_field_name = item_group_dict.get(d[0]) + + insert_into_item_defaults(doc_field_name, item_group.get(d[0]), company) + + doc = frappe.get_doc("Item Group", item_group.get("name")) + doc.extend("item_group_defaults", item_group_defaults) + for child_doc in doc.item_group_defaults: + child_doc.db_insert() diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 8d474164734..3ec4a233540 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -16,7 +16,7 @@ from erpnext.controllers.selling_controller import SellingController from frappe.desk.doctype.auto_repeat.auto_repeat import get_next_schedule_date from erpnext.selling.doctype.customer.customer import check_credit_limit from erpnext.stock.doctype.item.item import get_item_defaults - +from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -513,11 +513,12 @@ def make_delivery_note(source_name, target_doc=None): target.qty = flt(source.qty) - flt(source.delivered_qty) item = get_item_defaults(target.item_code, source_parent.company) + item_group = get_item_group_defaults(target.item_code, source_parent.company) if item: target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \ or item.get("selling_cost_center") \ - or frappe.db.get_value("Item Group", item.item_group, "default_cost_center") + or item_group.get("selling_cost_center") target_doc = get_mapped_doc("Sales Order", source_name, { "Sales Order": { @@ -581,8 +582,9 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") if not target.cost_center and target.item_code: item = get_item_defaults(target.item_code, target.company) + item_group = get_item_group_defaults(target.item_code, target.company) target.cost_center = item.get("selling_cost_center") \ - or frappe.db.get_value("Item Group", item.item_group, "default_cost_center") + or item_group.get("selling_cost_center") doclist = get_mapped_doc("Sales Order", source_name, { "Sales Order": { diff --git a/erpnext/setup/doctype/item_group/item_group.js b/erpnext/setup/doctype/item_group/item_group.js index c55c7cbf129..df2223192bd 100644 --- a/erpnext/setup/doctype/item_group/item_group.js +++ b/erpnext/setup/doctype/item_group/item_group.js @@ -14,6 +14,40 @@ frappe.ui.form.on("Item Group", { ] } } + frm.fields_dict["item_group_defaults"].grid.get_field("expense_account").get_query = function(doc, cdt, cdn) { + const row = locals[cdt][cdn]; + return { + query: "erpnext.controllers.queries.get_expense_account", + filters: { company: row.company } + } + } + frm.fields_dict["item_group_defaults"].grid.get_field("income_account").get_query = function(doc, cdt, cdn) { + const row = locals[cdt][cdn]; + return { + query: "erpnext.controllers.queries.get_income_account", + filters: { company: row.company } + } + } + + frm.fields_dict["item_group_defaults"].grid.get_field("buying_cost_center").get_query = function(doc, cdt, cdn) { + const row = locals[cdt][cdn]; + return { + filters: { + "is_group": 0, + "company": row.company + } + } + } + + frm.fields_dict["item_group_defaults"].grid.get_field("selling_cost_center").get_query = function(doc, cdt, cdn) { + const row = locals[cdt][cdn]; + return { + filters: { + "is_group": 0, + "company": row.company + } + } + } }, refresh: function(frm) { diff --git a/erpnext/setup/doctype/item_group/item_group.json b/erpnext/setup/doctype/item_group/item_group.json index 29486b2d1cb..0a16a297b2f 100644 --- a/erpnext/setup/doctype/item_group/item_group.json +++ b/erpnext/setup/doctype/item_group/item_group.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, "autoname": "field:item_group_name", @@ -13,6 +14,8 @@ "editable_grid": 0, "fields": [ { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -38,9 +41,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -68,9 +74,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "unique": 0 + "translatable": 0, + "unique": 1 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 1, "collapsible": 0, @@ -100,9 +109,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 1, "collapsible": 0, @@ -132,9 +144,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -159,15 +174,18 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "default_income_account", - "fieldtype": "Link", + "fieldname": "defaults", + "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -175,11 +193,11 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Default Income Account", + "label": "Defaults", "length": 0, "no_copy": 0, - "options": "Account", "permlevel": 0, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -188,15 +206,18 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "default_expense_account", - "fieldtype": "Link", + "fieldname": "item_group_defaults", + "fieldtype": "Table", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -204,40 +225,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Default Expense Account", + "label": "Item Group Defaults", "length": 0, "no_copy": 0, - "options": "Account", - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "default_cost_center", - "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": "Default Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", + "options": "Item Default", "permlevel": 0, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -246,9 +239,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -274,9 +270,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -303,9 +302,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -333,9 +335,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 1 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -364,9 +369,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -394,9 +402,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -424,9 +435,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -454,9 +468,12 @@ "reqd": 0, "search_index": 1, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -484,9 +501,12 @@ "reqd": 0, "search_index": 1, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -516,21 +536,22 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-sitemap", "idx": 1, "image_view": 0, "in_create": 0, - "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 3, - "modified": "2017-02-20 13:24:59.364873", + "modified": "2018-07-11 16:07:56.050363", "modified_by": "Administrator", "module": "Setup", "name": "Item Group", @@ -539,7 +560,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, @@ -559,7 +579,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, @@ -579,7 +598,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -599,7 +617,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, @@ -619,7 +636,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, @@ -639,7 +655,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, @@ -665,5 +680,6 @@ "show_name_in_global_search": 1, "sort_order": "DESC", "track_changes": 0, - "track_seen": 0 + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 230b740ef06..d4f16bed59e 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -173,3 +173,19 @@ def invalidate_cache_for(doc, item_group=None): item_group_name = frappe.db.get_value("Item Group", d.get('name')) if item_group_name: clear_cache(frappe.db.get_value('Item Group', item_group_name, 'route')) + +def get_item_group_defaults(item, company): + item_group = frappe.db.get_value("Item", item, "item_group") + item_group_defaults = frappe.db.sql(''' + select + expense_account, income_account, buying_cost_center, default_warehouse, + selling_cost_center, default_supplier + from + `tabItem Default` where company = %s and parent = %s and parenttype = 'Item Group' + ''', (company, item_group), as_dict=1) + + if item_group_defaults: + return item_group_defaults[0] + else: + return frappe.db.get_value("Item", item, ["name", "item_name", "description", "stock_uom", + "is_stock_item", "item_code", "item_group"], as_dict=1) \ No newline at end of file diff --git a/erpnext/setup/doctype/item_group/test_item_group.js b/erpnext/setup/doctype/item_group/test_item_group.js new file mode 100644 index 00000000000..ea322e23d65 --- /dev/null +++ b/erpnext/setup/doctype/item_group/test_item_group.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: Item Group", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Item Group + () => frappe.tests.make('Item Group', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/setup/doctype/item_group/test_records.json b/erpnext/setup/doctype/item_group/test_records.json index 74f464199b9..436535eef01 100644 --- a/erpnext/setup/doctype/item_group/test_records.json +++ b/erpnext/setup/doctype/item_group/test_records.json @@ -4,7 +4,11 @@ "is_group": 0, "item_group_name": "_Test Item Group", "parent_item_group": "All Item Groups", - "default_cost_center": "_Test Cost Center 2 - _TC" + "item_group_defaults": [{ + "company": "_Test Company", + "buying_cost_center": "_Test Cost Center 2 - _TC", + "selling_cost_center": "_Test Cost Center 2 - _TC" + }] }, { "doctype": "Item Group", diff --git a/erpnext/setup/doctype/sales_partner/test_sales_partner.py b/erpnext/setup/doctype/sales_partner/test_sales_partner.py index a4ae8074dbe..4548a4e19b5 100644 --- a/erpnext/setup/doctype/sales_partner/test_sales_partner.py +++ b/erpnext/setup/doctype/sales_partner/test_sales_partner.py @@ -4,4 +4,6 @@ from __future__ import unicode_literals import frappe -test_records = frappe.get_test_records('Sales Partner') \ No newline at end of file +test_records = frappe.get_test_records('Sales Partner') + +test_ignore = ["Item Group"] diff --git a/erpnext/setup/doctype/sales_person/test_sales_person.py b/erpnext/setup/doctype/sales_person/test_sales_person.py index 10b5f7c4870..8313cb45084 100644 --- a/erpnext/setup/doctype/sales_person/test_sales_person.py +++ b/erpnext/setup/doctype/sales_person/test_sales_person.py @@ -5,4 +5,6 @@ from __future__ import unicode_literals test_dependencies = ["Employee"] import frappe -test_records = frappe.get_test_records('Sales Person') \ No newline at end of file +test_records = frappe.get_test_records('Sales Person') + +test_ignore = ["Item Group"] diff --git a/erpnext/setup/doctype/territory/test_territory.py b/erpnext/setup/doctype/territory/test_territory.py index 5ec8e4a2bea..efe00c5a30b 100644 --- a/erpnext/setup/doctype/territory/test_territory.py +++ b/erpnext/setup/doctype/territory/test_territory.py @@ -4,4 +4,6 @@ from __future__ import unicode_literals import frappe -test_records = frappe.get_test_records('Territory') \ No newline at end of file +test_records = frappe.get_test_records('Territory') + +test_ignore = ["Item Group"] diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 5c35bec8dbc..7ef4f8cecc1 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -17,7 +17,7 @@ from erpnext.stock.get_item_details import get_item_details from six import iteritems test_ignore = ["BOM"] -test_dependencies = ["Warehouse"] +test_dependencies = ["Warehouse", "Item Group"] def make_item(item_code, properties=None): if frappe.db.exists("Item", item_code): diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 011df70bb5f..89f90bfdb76 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -9,6 +9,7 @@ from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate from erpnext.stock.utils import get_incoming_rate from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError, get_valuation_rate from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor +from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty from erpnext.stock.doctype.item.item import get_item_defaults from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, add_additional_cost @@ -579,7 +580,7 @@ class StockEntry(StockController): pro_doc.run_method("update_planned_qty") def get_item_details(self, args=None, for_update=False): - item = frappe.db.sql("""select i.stock_uom, i.description, i.image, i.item_name, i.item_group, + item = frappe.db.sql("""select i.name, i.stock_uom, i.description, i.image, i.item_name, i.item_group, i.has_batch_no, i.sample_quantity, i.has_serial_no, id.expense_account, id.buying_cost_center from `tabItem` i LEFT JOIN `tabItem Default` id ON i.name=id.parent and id.company=%s @@ -592,6 +593,7 @@ class StockEntry(StockController): frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get("item_code"))) item = item[0] + item_group_defaults = get_item_group_defaults(item.name, self.company) ret = frappe._dict({ 'uom' : item.stock_uom, @@ -600,7 +602,7 @@ class StockEntry(StockController): 'image' : item.image, 'item_name' : item.item_name, 'expense_account' : args.get("expense_account"), - 'cost_center' : get_default_cost_center(args, item), + 'cost_center' : get_default_cost_center(args, item, item_group_defaults), 'qty' : 0, 'transfer_qty' : 0, 'conversion_factor' : 1, diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 6d891872be1..f1afd1c2966 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -12,7 +12,7 @@ from frappe.model.meta import get_field_precision from erpnext.stock.doctype.batch.batch import get_batch_no from erpnext import get_company_currency from erpnext.stock.doctype.item.item import get_item_defaults - +from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults from six import string_types, iteritems @@ -208,7 +208,10 @@ def get_basic_details(args, item): if len(user_default_warehouse_list) == 1 else "" item_defaults = get_item_defaults(item.name, args.company) - warehouse = user_default_warehouse or item_defaults.get("default_warehouse") or args.warehouse + item_group_defaults = get_item_group_defaults(item.name, args.company) + + warehouse = user_default_warehouse or item_defaults.get("default_warehouse") or\ + item_group_defaults.get("default_warehouse") or args.warehouse material_request_type = '' if args.get('doctype') == "Material Request" and not args.get('material_request_type'): @@ -231,9 +234,9 @@ def get_basic_details(args, item): "description": cstr(item.description).strip(), "image": cstr(item.image).strip(), "warehouse": warehouse, - "income_account": get_default_income_account(args, item_defaults), - "expense_account": get_default_expense_account(args, item_defaults), - "cost_center": get_default_cost_center(args, item_defaults), + "income_account": get_default_income_account(args, item_defaults, item_group_defaults), + "expense_account": get_default_expense_account(args, item_defaults, item_group_defaults), + "cost_center": get_default_cost_center(args, item_defaults, item_group_defaults), 'has_serial_no': item.has_serial_no, 'has_batch_no': item.has_batch_no, "batch_no": None, @@ -252,7 +255,7 @@ def get_basic_details(args, item): "net_rate": 0.0, "net_amount": 0.0, "discount_percentage": 0.0, - "supplier": item_defaults.get("default_supplier"), + "supplier": get_default_supplier(args, item_defaults, item_group_defaults), "update_stock": args.get("update_stock") if args.get('doctype') in ['Sales Invoice', 'Purchase Invoice'] else 0, "delivered_by_supplier": item.delivered_by_supplier if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0, "is_fixed_asset": item.is_fixed_asset, @@ -299,15 +302,15 @@ def get_basic_details(args, item): return out -def get_default_income_account(args, item): +def get_default_income_account(args, item, item_group): return (item.get("income_account") - or args.income_account - or frappe.db.get_value("Item Group", item.item_group, "default_income_account")) + or item_group.get("income_account") + or args.income_account) -def get_default_expense_account(args, item): +def get_default_expense_account(args, item, item_group): return (item.get("expense_account") - or args.expense_account - or frappe.db.get_value("Item Group", item.item_group, "default_expense_account")) + or item_group.get("expense_account") + or args.expense_account) def get_default_deferred_revenue_account(args, item): if item.enable_deferred_revenue: @@ -317,12 +320,16 @@ def get_default_deferred_revenue_account(args, item): else: return None -def get_default_cost_center(args, item): +def get_default_cost_center(args, item, item_group): return (frappe.db.get_value("Project", args.get("project"), "cost_center") or (item.get("selling_cost_center") if args.get("customer") else item.get("buying_cost_center")) - or frappe.db.get_value("Item Group", item.item_group, "default_cost_center") + or (item_group.get("selling_cost_center") if args.get("customer") else item_group.get("buying_cost_center")) or args.get("cost_center")) +def get_default_supplier(args, item, item_group): + return (item.get("default_supplier") + or item_group.get("default_supplier")) + def get_price_list_rate(args, item_doc, out): meta = frappe.get_meta(args.parenttype or args.doctype) @@ -686,10 +693,11 @@ def get_default_bom(item_code=None): def get_valuation_rate(item_code, company, warehouse=None): item = get_item_defaults(item_code, company) + item_group = get_item_group_defaults(item_code, company) # item = frappe.get_doc("Item", item_code) if item.get("is_stock_item"): if not warehouse: - warehouse = item.get("default_warehouse") + warehouse = item.get("default_warehouse") or item_group.get("default_warehouse") return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, ["valuation_rate"], as_dict=True) or {"valuation_rate": 0}