From c760222a6c104f2324573bd9232d014605c55687 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Fri, 4 May 2018 11:05:48 +0530 Subject: [PATCH 1/5] add the item defaults in the childtable for multicompany --- erpnext/patches.txt | 1 + ...efaults_to_child_table_for_multicompany.py | 64 +++ erpnext/stock/doctype/item/item.json | 63 +++ erpnext/stock/doctype/item/item.py | 18 +- .../stock/doctype/item_default/__init__.py | 0 .../doctype/item_default/item_default.json | 449 ++++++++++++++++++ .../doctype/item_default/item_default.py | 10 + .../doctype/stock_entry/stock_entry_utils.py | 1 + 8 files changed, 598 insertions(+), 8 deletions(-) create mode 100644 erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py create mode 100644 erpnext/stock/doctype/item_default/__init__.py create mode 100644 erpnext/stock/doctype/item_default/item_default.json create mode 100644 erpnext/stock/doctype/item_default/item_default.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index f1d3677946..97c6dd6014 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -541,3 +541,4 @@ erpnext.patches.v11_0.make_location_from_warehouse erpnext.patches.v11_0.make_asset_finance_book_against_old_entries erpnext.patches.v11_0.check_buying_selling_in_currency_exchange erpnext.patches.v11_0.refactor_erpnext_shopify +erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany diff --git a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py new file mode 100644 index 0000000000..a78d2d6f34 --- /dev/null +++ b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py @@ -0,0 +1,64 @@ +# 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 the item to item defaults child table + [ default_warehouse, buying_cost_center, expense_account, selling_cost_center, income_account ] + + ''' + + frappe.reload_doc('stock', 'doctype', 'item_default') + frappe.reload_doc('stock', 'doctype', 'item') + + item_details = frappe.get_all("Item", fields=["name", "default_warehouse", "buying_cost_center", + "expense_account", "selling_cost_center", "income_account"], limit=100) + + for item in item_details: + item_defaults = [] + + def insert_into_item_defaults(doc_field_name, doc_field_value, company): + for d in item_defaults: + if d.get("company") == company: + d[doc_field_name] = doc_field_value + return + item_defaults.append({ + "company": company, + doc_field_name: doc_field_value + }) + + if item.default_warehouse: + default_warehouse_company = frappe.get_value("Warehouse", item.default_warehouse, "company", cache=True) + insert_into_item_defaults("default_warehouse", item.default_warehouse, default_warehouse_company) + + if item.buying_cost_center: + buying_cost_center_company = get_cost_center_company(item.buying_cost_center) + insert_into_item_defaults("buying_cost_center", item.buying_cost_center, buying_cost_center_company) + + if item.selling_cost_center: + selling_cost_center_company = get_cost_center_company(item.buying_cost_center) + insert_into_item_defaults("selling_cost_center", item.selling_cost_center, selling_cost_center_company) + + if item.expense_account: + expense_account_company = get_account_company(item.expense_account) + insert_into_item_defaults("expense_account", item.expense_account, expense_account_company) + + if item.income_account: + income_account_company = get_account_company(item.income_account) + insert_into_item_defaults("income_account", item.income_account, income_account_company) + + doc = frappe.get_doc("Item", item.name) + doc.extend("item_defaults", item_defaults) + + for child_doc in doc.item_defaults: + child_doc.db_update() + +def get_account_company(account_name): + return frappe.get_value("Account", account_name, "company", cache=True) + +def get_cost_center_company(cost_center): + return frappe.get_value("Cost Center", cost_center, "company", cache=True) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 5013e23837..ce1bdc334e 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -1614,6 +1614,69 @@ "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "columns": 0, + "fieldname": "defaults", + "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": "Defaults", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_defaults", + "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": "Item Defaults", + "length": 0, + "no_copy": 0, + "options": "Item Default", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 945bde36fe..0289749adf 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -81,7 +81,8 @@ class Item(WebsiteGenerator): def after_insert(self): '''set opening stock and item price''' if self.standard_rate: - self.add_price() + for default in self.item_defaults: + self.add_price(default.default_price_list) if self.opening_stock: self.set_opening_stock() @@ -166,15 +167,16 @@ class Item(WebsiteGenerator): from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry # default warehouse, or Stores - default_warehouse = (self.default_warehouse - or frappe.db.get_single_value('Stock Settings', 'default_warehouse') - or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})) + for default in self.item_defaults: + default_warehouse = (default.default_warehouse + or frappe.db.get_single_value('Stock Settings', 'default_warehouse') + or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})) - if default_warehouse: - stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, - qty=self.opening_stock, rate=self.valuation_rate) + if default_warehouse: + stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock, + rate=self.valuation_rate, company=default.company) - stock_entry.add_comment("Comment", _("Opening Stock")) + stock_entry.add_comment("Comment", _("Opening Stock")) def make_route(self): if not self.route: diff --git a/erpnext/stock/doctype/item_default/__init__.py b/erpnext/stock/doctype/item_default/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/item_default/item_default.json b/erpnext/stock/doctype/item_default/item_default.json new file mode 100644 index 0000000000..72d7880287 --- /dev/null +++ b/erpnext/stock/doctype/item_default/item_default.json @@ -0,0 +1,449 @@ +{ + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2018-05-03 02:29:24.444341", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "company", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Company", + "length": 0, + "no_copy": 0, + "options": "Company", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "default_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": 0, + "label": "Default 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": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "default_price_list", + "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": "Default Price List", + "length": 0, + "no_copy": 0, + "options": "Price List", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "purchase_defaults", + "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": "Purchase Defaults", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "buying_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 Buying Cost Center", + "length": 0, + "no_copy": 0, + "options": "Cost Center", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "default_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": "Default 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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_8", + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "expense_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Expense Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "selling_defaults", + "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": "Sales Defaults", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "selling_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 Selling Cost Center", + "length": 0, + "no_copy": 0, + "options": "Cost Center", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_12", + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "income_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Income Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2018-05-03 02:44:24.097373", + "modified_by": "Administrator", + "module": "Stock", + "name": "Item Default", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 +} \ No newline at end of file diff --git a/erpnext/stock/doctype/item_default/item_default.py b/erpnext/stock/doctype/item_default/item_default.py new file mode 100644 index 0000000000..85e84db6f1 --- /dev/null +++ b/erpnext/stock/doctype/item_default/item_default.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document + +class ItemDefault(Document): + pass diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py index 8bf261060e..8647d0f14e 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py @@ -12,6 +12,7 @@ def make_stock_entry(**args): :item_code: Item to be moved :qty: Qty to be moved + :company: Company Name (optional) :from_warehouse: Optional :to_warehouse: Optional :rate: Optional From 087a2259d9593d218759e72afd5fe92a00160055 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Fri, 4 May 2018 16:02:38 +0530 Subject: [PATCH 2/5] update for default warehouse --- erpnext/accounts/doctype/sales_invoice/pos.py | 30 ++++--- erpnext/controllers/buying_controller.py | 5 +- erpnext/demo/data/item.json | 88 ++++++++++++++----- erpnext/demo/data/item_education.json | 66 +++++++++++--- erpnext/demo/setup/education.py | 3 +- erpnext/demo/setup/manufacture.py | 8 +- erpnext/manufacturing/doctype/bom/bom.py | 16 ++-- .../production_plan/production_plan.py | 19 ++-- erpnext/setup/doctype/company/company.py | 4 +- erpnext/stock/doctype/item/item.py | 11 +++ erpnext/stock/doctype/item/test_item.py | 17 +++- .../stock/doctype/packed_item/packed_item.py | 12 +-- .../stock/doctype/stock_entry/stock_entry.py | 8 +- .../stock_reconciliation.js | 3 +- .../stock_reconciliation.py | 8 +- erpnext/stock/get_item_details.py | 17 ++-- erpnext/utilities/user_progress_utils.py | 5 +- 17 files changed, 223 insertions(+), 97 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 47894647ee..4d2e7cc3d7 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -39,7 +39,7 @@ def get_pos_data(): update_multi_mode_option(doc, pos_profile) default_print_format = pos_profile.get('print_format') or "Point of Sale" print_template = frappe.db.get_value('Print Format', default_print_format, 'html') - items_list = get_items_list(pos_profile) + items_list = get_items_list(pos_profile, doc.company) customers = get_customers_list(pos_profile) return { @@ -151,25 +151,26 @@ def update_tax_table(doc): doc.append('taxes', tax) -def get_items_list(pos_profile): - cond = "1=1" - item_groups = [] +def get_items_list(pos_profile, company): + cond = "" + args_list = [company] if pos_profile.get('item_groups'): # Get items based on the item groups defined in the POS profile for d in pos_profile.get('item_groups'): - item_groups.extend([d.name for d in get_child_nodes('Item Group', d.item_group)]) - cond = "item_group in (%s)" % (', '.join(['%s'] * len(item_groups))) + args_list.extend([d.name for d in get_child_nodes('Item Group', d.item_group)]) + cond = "and i.item_group in (%s)" % (', '.join(['%s'] * len(args_list))) return frappe.db.sql(""" select - name, item_code, item_name, description, item_group, expense_account, has_batch_no, - has_serial_no, expense_account, selling_cost_center, stock_uom, image, - default_warehouse, is_stock_item, brand + i.name, i.item_code, i.item_name, i.description, i.item_group, i.has_batch_no, + i.has_serial_no, i.is_stock_item, i.brand, i.stock_uom, i.image, + id.expense_account, id.selling_cost_center, id.default_warehouse from - tabItem + `tabItem` i, `tabItem Default` id where - disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond} - """.format(cond=cond), tuple(item_groups), as_dict=1) + id.parent = i.name and i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1 + and id.company = %s {cond} + """.format(cond=cond), tuple(args_list), as_dict=1) def get_item_groups(pos_profile): @@ -531,9 +532,12 @@ def validate_item(doc): item_doc.item_code = item.get('item_code') item_doc.item_name = item.get('item_name') item_doc.description = item.get('description') - item_doc.default_warehouse = item.get('warehouse') item_doc.stock_uom = item.get('stock_uom') item_doc.item_group = item.get('item_group') + item_doc.append('item_defaults', { + "company": doc.get("company"), + "default_warehouse": item.get('warehouse') + }) item_doc.save(ignore_permissions=True) frappe.db.commit() diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index fa2436d647..13baf6ff78 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -216,8 +216,9 @@ class BuyingController(StockController): raw_materials_cost = 0 items = list(set([d.item_code for d in bom_items])) - item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse - from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items)) + item_wh = frappe._dict(frappe.db.sql("""select i.item_code, id.default_warehouse + from `tabItem` i, `tabItem Default` id where id.company=%s and i.name in ({0})""" + .format(", ".join(["%s"] * len(items))), [self.company] + items)) for bom_item in bom_items: if self.doctype == "Purchase Order": diff --git a/erpnext/demo/data/item.json b/erpnext/demo/data/item.json index 6974b943f6..461ed4235a 100644 --- a/erpnext/demo/data/item.json +++ b/erpnext/demo/data/item.json @@ -1,7 +1,9 @@ [ { "default_supplier": "Asiatic Solutions", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "For Upper Bearing", "image": "/assets/erpnext_demo/images/disc.png", "item_code": "Disc Collars", @@ -10,7 +12,9 @@ }, { "default_supplier": "Nan Duskin", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "CAST IRON, MCMASTER PART NO. 3710T13", "image": "/assets/erpnext_demo/images/bearing.jpg", "item_code": "Bearing Block", @@ -19,7 +23,9 @@ }, { "default_supplier": null, - "default_warehouse": "Finished Goods", + "item_defaults": [{ + "default_warehouse": "Finished Goods", + }], "description": "Wind Mill C Series for Commercial Use 18ft", "image": "/assets/erpnext_demo/images/wind-turbine-2.png", "item_code": "Wind MIll C Series", @@ -28,7 +34,9 @@ }, { "default_supplier": null, - "default_warehouse": "Finished Goods", + "item_defaults": [{ + "default_warehouse": "Finished Goods", + }], "description": "Wind Mill A Series for Home Use 9ft", "image": "/assets/erpnext_demo/images/wind-turbine.png", "item_code": "Wind Mill A Series", @@ -37,7 +45,9 @@ }, { "default_supplier": null, - "default_warehouse": "Finished Goods", + "item_defaults": [{ + "default_warehouse": "Finished Goods", + }], "description": "Small Wind Turbine for Home Use\n\n\n", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", "item_code": "Wind Turbine", @@ -51,7 +61,9 @@ }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "1.5 in. Diameter x 36 in. Mild Steel Tubing", "image": null, "item_code": "Bearing Pipe", @@ -60,7 +72,9 @@ }, { "default_supplier": "New World Realty", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "1/32 in. x 24 in. x 47 in. HDPE Opaque Sheet", "image": null, "item_code": "Wing Sheet", @@ -69,7 +83,9 @@ }, { "default_supplier": "Eagle Hardware", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "3/16 in. x 6 in. x 6 in. Low Carbon Steel Plate", "image": null, "item_code": "Upper Bearing Plate", @@ -78,7 +94,9 @@ }, { "default_supplier": "Asiatic Solutions", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "Bearing Assembly", "image": null, "item_code": "Bearing Assembly", @@ -87,7 +105,9 @@ }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood", "image": null, "item_code": "Base Plate", @@ -97,7 +117,9 @@ }, { "default_supplier": "Scott Ties", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "N/A", "image": null, "item_code": "Stand", @@ -106,7 +128,9 @@ }, { "default_supplier": "Eagle Hardware", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "1 in. x 3 in. x 1 ft. Multipurpose Al Alloy Bar", "image": null, "item_code": "Bearing Collar", @@ -115,7 +139,9 @@ }, { "default_supplier": "Eagle Hardware", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "1/4 in. x 6 in. x 6 in. Mild Steel Plate", "image": null, "item_code": "Base Bearing Plate", @@ -124,7 +150,9 @@ }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "15/32 in. x 4 ft. x 8 ft. 3-Ply Rtd Sheathing", "image": null, "item_code": "External Disc", @@ -133,7 +161,9 @@ }, { "default_supplier": "Eagle Hardware", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "1.25 in. Diameter x 6 ft. Mild Steel Tubing", "image": null, "item_code": "Shaft", @@ -142,7 +172,9 @@ }, { "default_supplier": "Ks Merchandise", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "1/2 in. x 2 ft. x 4 ft. Pine Plywood", "image": null, "item_code": "Blade Rib", @@ -151,7 +183,9 @@ }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "For Bearing Collar", "image": null, "item_code": "Internal Disc", @@ -160,7 +194,9 @@ }, { "default_supplier": null, - "default_warehouse": "Finished Goods", + "item_defaults": [{ + "default_warehouse": "Finished Goods", + }], "description": "Small Wind Turbine for Home Use\n\n\n\n

Size: Small

", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", "item_code": "Wind Turbine-S", @@ -177,7 +213,9 @@ }, { "default_supplier": null, - "default_warehouse": "Finished Goods", + "item_defaults": [{ + "default_warehouse": "Finished Goods", + }], "description": "Small Wind Turbine for Home Use\n\n\n\n

Size: Medium

", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", "item_code": "Wind Turbine-M", @@ -194,7 +232,9 @@ }, { "default_supplier": null, - "default_warehouse": "Finished Goods", + "item_defaults": [{ + "default_warehouse": "Finished Goods", + }], "description": "Small Wind Turbine for Home Use\n\n\n\n

Size: Large

", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", "item_code": "Wind Turbine-L", @@ -218,7 +258,9 @@ }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood", "image": null, "item_code": "Base Plate Un Painted", @@ -284,7 +326,9 @@ "has_batch_no": 1, "create_new_batch": 1, "valuation_rate": 200, - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + }], "description": "Corrugated Box", "item_code": "Corrugated Box", "item_name": "Corrugated Box", diff --git a/erpnext/demo/data/item_education.json b/erpnext/demo/data/item_education.json index 077fcaacda..40e4701596 100644 --- a/erpnext/demo/data/item_education.json +++ b/erpnext/demo/data/item_education.json @@ -1,63 +1,90 @@ [ { "default_supplier": "Asiatic Solutions", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Books", "item_group": "Raw Material", "item_name": "Books" }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Pencil", "item_group": "Raw Material", "item_name": "Pencil" }, { "default_supplier": "New World Realty", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Tables", "item_group": "Raw Material", "item_name": "Tables" }, { "default_supplier": "Eagle Hardware", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Chair", "item_group": "Raw Material", "item_name": "Chair" }, { "default_supplier": "Asiatic Solutions", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Black Board", "item_group": "Sub Assemblies", "item_name": "Black Board" }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Chalk", "item_group": "Raw Material", "item_name": "Chalk" }, { "default_supplier": "HomeBase", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Notepad", "item_group": "Raw Material", "item_name": "Notepad" }, { "default_supplier": "Ks Merchandise", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Uniform", "item_group": "Raw Material", "item_name": "Uniform" }, { "is_stock_item": 0, - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "description": "Computer", "item_code": "Computer", "item_name": "Computer", @@ -65,7 +92,10 @@ }, { "is_stock_item": 0, - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "description": "Mobile", "item_code": "Mobile", "item_name": "Mobile", @@ -73,7 +103,10 @@ }, { "is_stock_item": 0, - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "description": "ERP", "item_code": "ERP", "item_name": "ERP", @@ -81,15 +114,20 @@ }, { "is_stock_item": 0, - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "description": "Autocad", "item_code": "Autocad", "item_name": "Autocad", "item_group": "All Item Groups" }, { - "default_warehouse": "Stores", - "default_warehouse": "Stores", + "item_defaults": [{ + "default_warehouse": "Stores", + "company": "Whitmore College" + }], "item_code": "Service", "item_group": "Services", "item_name": "Service", diff --git a/erpnext/demo/setup/education.py b/erpnext/demo/setup/education.py index 2a894f79d1..0403c06411 100644 --- a/erpnext/demo/setup/education.py +++ b/erpnext/demo/setup/education.py @@ -36,7 +36,8 @@ def setup_item(): item = frappe.new_doc('Item') item.update(i) item.min_order_qty = random.randint(10, 30) - item.default_warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.default_warehouse}, limit=1)[0].name + item.item_defaults[0].default_warehouse = frappe.get_all('Warehouse', + filters={'warehouse_name': item.item_defaults[0].default_warehouse}, limit=1)[0].name item.insert() def make_student_applicants(): diff --git a/erpnext/demo/setup/manufacture.py b/erpnext/demo/setup/manufacture.py index 4d8c450d4b..4db510a18d 100644 --- a/erpnext/demo/setup/manufacture.py +++ b/erpnext/demo/setup/manufacture.py @@ -4,6 +4,7 @@ import random, json import frappe from frappe.utils import nowdate, add_days from erpnext.demo.setup.setup_data import import_json +from erpnext.demo.domains import data from six import iteritems @@ -65,10 +66,11 @@ def setup_item(): for i in items: item = frappe.new_doc('Item') item.update(i) - if item.default_warehouse: - warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.default_warehouse}, limit=1) + if item.item_defaults[0].default_warehouse: + item.item_defaults[0].company = data.get("Manufacturing").get('company_name') + warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.item_defaults[0].default_warehouse}, limit=1) if warehouse: - item.default_warehouse = warehouse[0].name + item.item_defaults[0].default_warehouse = warehouse[0].name item.insert() def setup_product_bundle(): diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 559bbdf5cd..c09ea1153b 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -544,14 +544,16 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite item.image, item.stock_uom, item.allow_alternative_item, - item.default_warehouse, - item.expense_account as expense_account, - item.buying_cost_center as cost_center + item_default.default_warehouse, + item_default.expense_account as expense_account, + item_default.buying_cost_center as cost_center {select_columns} from - `tab{table}` bom_item, `tabBOM` bom, `tabItem` item + `tab{table}` bom_item, `tabBOM` bom, `tabItem` item, `tabItem Default` item_default where bom_item.docstatus < 2 + and item_default.parent = item.name + and item_default.company = %(company)s and bom.name = %(bom)s and bom_item.parent = bom.name and item.name = bom_item.item_code @@ -564,14 +566,14 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite query = query.format(table="BOM Explosion Item", where_conditions="", select_columns = ", bom_item.source_warehouse, (Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s ) as idx") - items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom }, as_dict=True) + items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True) elif fetch_scrap_items: query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx") - items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True) + items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) else: query = query.format(table="BOM Item", where_conditions="", select_columns = ", bom_item.source_warehouse, bom_item.idx") - items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True) + items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) for item in items: if item.item_code in item_dict: diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index ee64a1670c..006e542e4d 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -293,14 +293,15 @@ class ProductionPlan(Document): for d in frappe.db.sql("""select bei.item_code, item.default_bom as bom, ifnull(sum(bei.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, item.item_name, bei.description, bei.stock_uom, item.min_order_qty, bei.source_warehouse, - item.default_material_request_type, item.min_order_qty, item.default_warehouse + item.default_material_request_type, item.min_order_qty, item_default.default_warehouse from - `tabBOM Explosion Item` bei, `tabBOM` bom, `tabItem` item + `tabBOM Explosion Item` bei, `tabBOM` bom, `tabItem` item, `tabItem Default` item_default where - bom.name = bei.parent and item.name = bei.item_code - and bei.docstatus < 2 and bom.name=%s and item.is_stock_item in (1, {0}) + bom.name = bei.parent and item.name = bei.item_code and bei.docstatus < 2 + and item_default.parent = item.name and item_default.company=%s + and bom.name=%s and item.is_stock_item in (1, {0}) group by bei.item_code, bei.stock_uom""".format(self.include_non_stock_items), - data.bom_no, as_dict=1): + (self.company, data.bom_no), as_dict=1): bom_wise_item_details.setdefault(d.item_code, d) else: bom_wise_item_details = self.get_subitems(data, bom_wise_item_details, data.bom_no, 1) @@ -317,16 +318,18 @@ class ProductionPlan(Document): item.is_sub_contracted_item as is_sub_contracted, bom_item.source_warehouse, item.default_bom as default_bom, bom_item.description as description, bom_item.stock_uom as stock_uom, item.min_order_qty as min_order_qty, - item.default_warehouse + item_default.default_warehouse FROM - `tabBOM Item` bom_item, `tabBOM` bom, tabItem item + `tabBOM Item` bom_item, `tabBOM` bom, tabItem item, `tabItem Default` item_default where bom.name = bom_item.parent and bom.name = %(bom)s and bom_item.docstatus < 2 and bom_item.item_code = item.name + and item.name = item_default.parent and item_default.company = %(company)s and item.is_stock_item in (1, {0}) group by bom_item.item_code""".format(self.include_non_stock_items),{ 'bom': bom_no, - 'parent_qty': parent_qty + 'parent_qty': parent_qty, + 'company': self.company }, as_dict=1) for d in items: diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index a2feddc529..2f177eed41 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -313,8 +313,8 @@ class Company(NestedSet): # clear default accounts, warehouses from item if warehouses: for f in ["default_warehouse", "website_warehouse"]: - frappe.db.sql("""update tabItem set %s=NULL where %s in (%s)""" - % (f, f, ', '.join(['%s']*len(warehouses))), tuple(warehouses)) + frappe.db.sql("""update `tabItem Default` set %s=NULL where company=%s and %s in (%s)""" + % (f, self.name, f, ', '.join(['%s']*len(warehouses))), tuple(warehouses)) frappe.db.sql("""delete from `tabItem Reorder` where warehouse in (%s)""" % ', '.join(['%s']*len(warehouses)), tuple(warehouses)) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 0289749adf..7dc9a89ce3 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -882,3 +882,14 @@ def check_stock_uom_with_bin(item, stock_uom): if not matched: frappe.throw( _("Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.").format(item)) + +def get_item_details(item, company): + return frappe.db.sql(''' + select + i.item_name, i.description, i.stock_uom, i.name, i.is_stock_item, i.item_code + id.expense_account, id.buying_cost_center, id.warehouse + from + `tabItem` i, `tabItem Default` id + where + i.name = id.parent and i.name = %s and id.company = %s + ''', (item, company), as_dict=1) \ No newline at end of file diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 3f0d7fac5e..ee2ca988e1 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -35,8 +35,9 @@ def make_item(item_code, properties=None): item.update(properties) - if item.is_stock_item and not item.default_warehouse: - item.default_warehouse = "_Test Warehouse - _TC" + if item.is_stock_item: + for item_default in [doc for doc in item.item_defaults if not doc.default_warehouse] + item_default.default_warehouse = "_Test Warehouse - _TC" item.insert() @@ -199,7 +200,12 @@ class TestItem(unittest.TestCase): "increment": 0.5 } ], - "default_warehouse": "_Test Warehouse - _TC", + "item_defaults": [ + { + "default_warehouse": "_Test Warehouse - _TC", + "company": "_Test Company" + } + ] "has_variants": 1 }) @@ -305,5 +311,8 @@ def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None) item.item_group = "All Item Groups" item.is_stock_item = is_stock_item or 1 item.valuation_rate = valuation_rate or 0.0 - item.default_warehouse = warehouse or '_Test Warehouse - _TC' + item.append("item_defaults", { + "default_warehouse": warehouse or '_Test Warehouse - _TC', + "company": "_Test Company" + }) item.save() diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 74dfa057aa..7ca5ead20e 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -18,9 +18,10 @@ def get_product_bundle_items(item_code): from `tabProduct Bundle Item` t1, `tabProduct Bundle` t2 where t2.new_item_code=%s and t1.parent = t2.name order by t1.idx""", item_code, as_dict=1) -def get_packing_item_details(item): - return frappe.db.sql("""select item_name, description, stock_uom, default_warehouse from `tabItem` - where name = %s""", item, as_dict = 1)[0] +def get_packing_item_details(item, company): + return frappe.db.sql("""select i.item_name, i.description, i.stock_uom, id.default_warehouse + from `tabItem` i, `tabItem Default` id where id.parent=i.name and i.name = %s and id.company""", + (item, company), as_dict = 1)[0] def get_bin_qty(item, warehouse): det = frappe.db.sql("""select actual_qty, projected_qty from `tabBin` @@ -28,12 +29,13 @@ def get_bin_qty(item, warehouse): return det and det[0] or frappe._dict() def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description): - item = get_packing_item_details(packing_item_code) + item = get_packing_item_details(packing_item_code, doc.company) # check if exists exists = 0 for d in doc.get("packed_items"): - if d.parent_item == main_item_row.item_code and d.item_code == packing_item_code and d.parent_detail_docname == main_item_row.name and d.description == description: + if d.parent_item == main_item_row.item_code and d.item_code == packing_item_code and\ + d.parent_detail_docname == main_item_row.name and d.description == description: pi, exists = d, 1 break diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 233138f0c7..49a278ca8a 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -10,6 +10,7 @@ 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.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty +from erpnext.stock.doctype.item.item import get_item_details from erpnext.manufacturing.doctype.bom.bom import validate_bom_no from erpnext.stock.utils import get_bin import json @@ -716,8 +717,7 @@ class StockEntry(StockController): item_code = frappe.db.get_value("BOM", self.bom_no, "item") to_warehouse = self.to_warehouse - item = frappe.db.get_value("Item", item_code, ["item_name", - "description", "stock_uom", "expense_account", "buying_cost_center", "name", "default_warehouse"], as_dict=1) + item = get_item_details(item_code, self.company) if not self.work_order and not to_warehouse: # in case of BOM @@ -782,8 +782,8 @@ class StockEntry(StockController): for item in wo_items: qty = item.required_qty - item_account_details = frappe.db.get_value("Item", item.item_code, ["item_name", - "description", "stock_uom", "expense_account", "buying_cost_center", "name", "default_warehouse"], as_dict=1) + + item_account_details = get_item_details(item.item_code, self.company) # Take into account consumption if there are any. if self.purpose == 'Manufacture': req_qty_each = flt(item.required_qty / wo.qty) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js index 3342768261..ce32e01d33 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js @@ -49,7 +49,8 @@ frappe.ui.form.on("Stock Reconciliation", { args: { warehouse: data.warehouse, posting_date: frm.doc.posting_date, - posting_time: frm.doc.posting_time + posting_time: frm.doc.posting_time, + company:frm.doc.company }, callback: function(r) { var items = []; diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 938173deb8..e4342339e0 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -268,12 +268,12 @@ class StockReconciliation(StockController): self._cancel() @frappe.whitelist() -def get_items(warehouse, posting_date, posting_time): +def get_items(warehouse, posting_date, posting_time, company): items = frappe.get_list("Bin", fields=["item_code"], filters={"warehouse": warehouse}, as_list=1) - items += frappe.get_list("Item", fields=["name"], filters= {"is_stock_item": 1, "has_serial_no": 0, - "has_batch_no": 0, "has_variants": 0, "disabled": 0, "default_warehouse": warehouse}, - as_list=1) + items += frappe.db.sql_list('''select i.name from `tabItem` i, `tabItem Default` id where i.name = id.parent + and i.is_stock_item=1 and i.has_serial_no=0 and i.has_batch_no=0 and i.has_variants=0 and i.disabled=0 + and id.default_warehouse=%s and id.company=%s''', (warehouse, company)) res = [] for item in set(items): diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index b33656570d..0351364d83 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -11,6 +11,8 @@ from erpnext.setup.utils import get_exchange_rate 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_details + from six import string_types, iteritems @@ -52,7 +54,7 @@ def get_item_details(args): for bundle_item in bundled_items.items: valuation_rate += \ - flt(get_valuation_rate(bundle_item.item_code, out.get("warehouse")).get("valuation_rate") \ + flt(get_valuation_rate(bundle_item.item_code, args.company, out.get("warehouse")).get("valuation_rate") \ * bundle_item.qty) out.update({ @@ -60,7 +62,7 @@ def get_item_details(args): }) else: - out.update(get_valuation_rate(args.item_code, out.get("warehouse"))) + out.update(get_valuation_rate(args.item_code, args.company, out.get("warehouse"))) get_price_list_rate(args, item_doc, out) @@ -203,8 +205,10 @@ def get_basic_details(args, item): user_default_warehouse_list = get_user_default_as_list('Warehouse') user_default_warehouse = user_default_warehouse_list[0] \ if len(user_default_warehouse_list) == 1 else "" - - warehouse = user_default_warehouse or item.default_warehouse or args.warehouse + + item_default_warehouse = [default.default_warehouse for default in item.item_defaults if default.company == args.company] + item_default_warehouse = item_default_warehouse[0] if item_default_warehouse else None + warehouse = user_default_warehouse or item_default_warehouse or args.warehouse material_request_type = '' if args.get('doctype') == "Material Request": @@ -677,8 +681,9 @@ def get_default_bom(item_code=None): if bom: return bom -def get_valuation_rate(item_code, warehouse=None): - item = frappe.get_doc("Item", item_code) +def get_valuation_rate(item_code, company, warehouse=None): + item = get_item_details(item_code, company) + # item = frappe.get_doc("Item", item_code) if item.is_stock_item: if not warehouse: warehouse = item.default_warehouse diff --git a/erpnext/utilities/user_progress_utils.py b/erpnext/utilities/user_progress_utils.py index 20e533e91a..0377a0a1f1 100644 --- a/erpnext/utilities/user_progress_utils.py +++ b/erpnext/utilities/user_progress_utils.py @@ -110,7 +110,10 @@ def create_items(args_data): "is_stock_item": 1, "item_group": _("Products"), "stock_uom": _(args.get("item_uom_" + str(i))), - "default_warehouse": default_warehouse + "item_defaults": [{ + "default_warehouse": default_warehouse, + "company": defaults.get("company_name") + }] }).insert() except frappe.NameError: From b16a4ec79e45c693aa704989bfb4e05758ca9dd1 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Fri, 4 May 2018 16:49:33 +0530 Subject: [PATCH 3/5] changes for the default cost center --- .../doctype/purchase_order/purchase_order.py | 3 ++- .../doctype/sales_order/sales_order.py | 6 +++-- erpnext/setup/doctype/company/company.py | 23 +++---------------- erpnext/stock/doctype/item/item.py | 8 +++---- erpnext/stock/doctype/item/test_item.py | 4 ++-- .../stock/doctype/stock_entry/stock_entry.py | 22 +++++++++--------- erpnext/stock/get_item_details.py | 15 ++++++------ 7 files changed, 33 insertions(+), 48 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 5a7573bc93..846c5b491b 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -14,6 +14,7 @@ from frappe.desk.notifications import clear_doctype_notifications 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 form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -374,7 +375,7 @@ def make_purchase_invoice(source_name, target_doc=None): target.base_amount = target.amount * flt(source_parent.conversion_rate) target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty) - item = frappe.db.get_value("Item", target.item_code, ["item_group", "buying_cost_center"], as_dict=1) + item = get_item_defaults(target.item_code, target.company) target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \ or item.buying_cost_center \ or frappe.db.get_value("Item Group", item.item_group, "default_cost_center") diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 7e6c3dcbae..5116725439 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -15,6 +15,8 @@ from frappe.contacts.doctype.address.address import get_company_address 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 + form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -493,7 +495,7 @@ def make_delivery_note(source_name, target_doc=None): target.amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.rate) target.qty = flt(source.qty) - flt(source.delivered_qty) - item = frappe.db.get_value("Item", target.item_code, ["item_group", "selling_cost_center"], as_dict=1) + item = get_item_defaults(target.item_code, target.company) if item: target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \ @@ -557,7 +559,7 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): if source_parent.project: target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") if not target.cost_center and target.item_code: - item = frappe.db.get_value("Item", target.item_code, ["item_group", "selling_cost_center"], as_dict=1) + item = get_item_defaults(target.item_code, target.company) target.cost_center = item.selling_cost_center \ or frappe.db.get_value("Item Group", item.item_group, "default_cost_center") diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 2f177eed41..9e9ac5594f 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -291,9 +291,6 @@ class Company(NestedSet): Trash accounts and cost centers for this company if no gl entry exists """ self.update_nsm_model() - accounts = frappe.db.sql_list("select name from tabAccount where company=%s", self.name) - cost_centers = frappe.db.sql_list("select name from `tabCost Center` where company=%s", self.name) - warehouses = frappe.db.sql_list("select name from tabWarehouse where company=%s", self.name) rec = frappe.db.sql("SELECT name from `tabGL Entry` where company = %s", self.name) if not rec: @@ -308,33 +305,19 @@ class Company(NestedSet): frappe.db.sql("""delete from `tabWarehouse` where company=%s""", self.name) frappe.defaults.clear_default("company", value=self.name) - frappe.db.sql("delete from `tabMode of Payment Account` where company=%s", self.name) + for doctype in ["Mode of Payment Account", "Item Default"]: + frappe.db.sql("delete from `tab{0}` where company = %s".format(doctype), self.name) # clear default accounts, warehouses from item + warehouses = frappe.db.sql_list("select name from tabWarehouse where company=%s", self.name) if warehouses: - for f in ["default_warehouse", "website_warehouse"]: - frappe.db.sql("""update `tabItem Default` set %s=NULL where company=%s and %s in (%s)""" - % (f, self.name, f, ', '.join(['%s']*len(warehouses))), tuple(warehouses)) - frappe.db.sql("""delete from `tabItem Reorder` where warehouse in (%s)""" % ', '.join(['%s']*len(warehouses)), tuple(warehouses)) - if accounts: - for f in ["income_account", "expense_account"]: - frappe.db.sql("""update tabItem set %s=NULL where %s in (%s)""" - % (f, f, ', '.join(['%s']*len(accounts))), tuple(accounts)) - - if cost_centers: - for f in ["selling_cost_center", "buying_cost_center"]: - frappe.db.sql("""update tabItem set %s=NULL where %s in (%s)""" - % (f, f, ', '.join(['%s']*len(cost_centers))), tuple(cost_centers)) - # reset default company frappe.db.sql("""update `tabSingles` set value="" where doctype='Global Defaults' and field='default_company' and value=%s""", self.name) - # delete mode of payment account - frappe.db.sql("delete from `tabMode of Payment Account` where company=%s", self.name) # delete BOMs boms = frappe.db.sql_list("select name from tabBOM where company=%s", self.name) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 7dc9a89ce3..9487963394 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -883,13 +883,13 @@ def check_stock_uom_with_bin(item, stock_uom): frappe.throw( _("Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.").format(item)) -def get_item_details(item, company): +def get_item_defaults(item, company): return frappe.db.sql(''' select - i.item_name, i.description, i.stock_uom, i.name, i.is_stock_item, i.item_code - id.expense_account, id.buying_cost_center, id.warehouse + i.item_name, i.description, i.stock_uom, i.name, i.is_stock_item, i.item_code, i.item_group, + id.expense_account, id.buying_cost_center, id.default_warehouse, id.selling_cost_center from `tabItem` i, `tabItem Default` id where i.name = id.parent and i.name = %s and id.company = %s - ''', (item, company), as_dict=1) \ No newline at end of file + ''', (item, company), as_dict=1)[0] \ No newline at end of file diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index ee2ca988e1..1c915ee8f2 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -36,7 +36,7 @@ def make_item(item_code, properties=None): if item.is_stock_item: - for item_default in [doc for doc in item.item_defaults if not doc.default_warehouse] + for item_default in [doc for doc in item.item_defaults if not doc.default_warehouse]: item_default.default_warehouse = "_Test Warehouse - _TC" item.insert() @@ -205,7 +205,7 @@ class TestItem(unittest.TestCase): "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" } - ] + ], "has_variants": 1 }) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 49a278ca8a..5a6384aa73 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -10,7 +10,7 @@ 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.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty -from erpnext.stock.doctype.item.item import get_item_details +from erpnext.stock.doctype.item.item import get_item_defaults from erpnext.manufacturing.doctype.bom.bom import validate_bom_no from erpnext.stock.utils import get_bin import json @@ -563,14 +563,14 @@ 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 stock_uom, description, image, item_name, - expense_account, buying_cost_center, item_group, has_serial_no, - has_batch_no, sample_quantity - from `tabItem` - where name = %s - and disabled=0 - and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""", - (args.get('item_code'), nowdate()), as_dict = 1) + item = frappe.db.sql("""select 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`, `tabItem Default` id + where i.name=%s and i.name=id.parent and id.company=%s + and i.disabled=0 + and (i.end_of_life is null or i.end_of_life='0000-00-00' or i.end_of_life > %s)""", + (args.get('item_code'), self.company, nowdate()), as_dict = 1) if not item: frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get("item_code"))) @@ -717,7 +717,7 @@ class StockEntry(StockController): item_code = frappe.db.get_value("BOM", self.bom_no, "item") to_warehouse = self.to_warehouse - item = get_item_details(item_code, self.company) + item = get_item_defaults(item_code, self.company) if not self.work_order and not to_warehouse: # in case of BOM @@ -783,7 +783,7 @@ class StockEntry(StockController): for item in wo_items: qty = item.required_qty - item_account_details = get_item_details(item.item_code, self.company) + item_account_details = get_item_defaults(item.item_code, self.company) # Take into account consumption if there are any. if self.purpose == 'Manufacture': req_qty_each = flt(item.required_qty / wo.qty) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 0351364d83..bbbe860396 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -11,7 +11,7 @@ from erpnext.setup.utils import get_exchange_rate 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_details +from erpnext.stock.doctype.item.item import get_item_defaults from six import string_types, iteritems @@ -206,9 +206,8 @@ def get_basic_details(args, item): user_default_warehouse = user_default_warehouse_list[0] \ if len(user_default_warehouse_list) == 1 else "" - item_default_warehouse = [default.default_warehouse for default in item.item_defaults if default.company == args.company] - item_default_warehouse = item_default_warehouse[0] if item_default_warehouse else None - warehouse = user_default_warehouse or item_default_warehouse or args.warehouse + item_defaults = get_item_defaults(item.name, args.company) + warehouse = user_default_warehouse or item_defaults.default_warehouse or args.warehouse material_request_type = '' if args.get('doctype') == "Material Request": @@ -231,9 +230,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), - "expense_account": get_default_expense_account(args, item), - "cost_center": get_default_cost_center(args, item), + "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), 'has_serial_no': item.has_serial_no, 'has_batch_no': item.has_batch_no, "batch_no": None, @@ -682,7 +681,7 @@ def get_default_bom(item_code=None): return bom def get_valuation_rate(item_code, company, warehouse=None): - item = get_item_details(item_code, company) + item = get_item_defaults(item_code, company) # item = frappe.get_doc("Item", item_code) if item.is_stock_item: if not warehouse: From bbd8508783a7264d3b8b5a5e31d685343f7aaa8e Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Mon, 7 May 2018 13:37:34 +0530 Subject: [PATCH 4/5] optimize the patch --- erpnext/controllers/selling_controller.py | 22 ++++-- ...efaults_to_child_table_for_multicompany.py | 79 +++++++++---------- .../doctype/quotation/test_quotation.py | 6 +- .../doctype/sales_order/test_sales_order.py | 9 +-- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 2a22b32637..feee067496 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -340,10 +340,22 @@ class SellingController(StockController): def check_active_sales_items(obj): for d in obj.get("items"): if d.item_code: - item = frappe.db.sql("""select docstatus, - income_account from tabItem where name = %s""", - d.item_code, as_dict=True)[0] + item = frappe.db.sql("""select i.docstatus, id.income_account + from `tabItem` i, `tabItem Default` id + where i.name=%s and id.parent=i.name and id.company=%s""", + (d.item_code,obj.company), as_dict=True)[0] + income_account_set = False if getattr(d, "income_account", None) and not item.income_account: - frappe.db.set_value("Item", d.item_code, "income_account", - d.income_account) + doc = frappe.get_doc("Item", d.item_code) + for default in doc.item_defaults: + if default.company == obj.company: + default.income_account = d.income_account + income_account_set = True + else: + if not income_account_set: + doc.append("item_defaults", { + "company": obj.company, + "income_account": d.income_account + }) + doc.save() \ No newline at end of file diff --git a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py index a78d2d6f34..8e17ea61dd 100644 --- a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py +++ b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py @@ -15,50 +15,45 @@ def execute(): frappe.reload_doc('stock', 'doctype', 'item_default') frappe.reload_doc('stock', 'doctype', 'item') - item_details = frappe.get_all("Item", fields=["name", "default_warehouse", "buying_cost_center", - "expense_account", "selling_cost_center", "income_account"], limit=100) + companies = frappe.get_all("Company") + if len(companies) == 1: + frappe.db.sql(''' + INSERT INTO `tabItem Default` + (name, parent, parenttype, parentfield, idx, company, default_warehouse, + buying_cost_center, selling_cost_center, expense_account, income_account, default_supplier) + SELECT + SUBSTRING(SHA2(name,224), 1, 10) as name, name as parent, 'Item' as parenttype, + 'item_defaults' as parentfield, 1 as idx, %s as company, default_warehouse, + buying_cost_center, selling_cost_center, expense_account, income_account, default_supplier + FROM `tabItem`; + ''', companies[0].name) + else: + item_details = frappe.get_all("Item", fields=["name", "default_warehouse", "buying_cost_center", + "expense_account", "selling_cost_center", "income_account"], limit=100) - for item in item_details: - item_defaults = [] + for item in item_details: + item_defaults = [] - def insert_into_item_defaults(doc_field_name, doc_field_value, company): - for d in item_defaults: - if d.get("company") == company: - d[doc_field_name] = doc_field_value - return - item_defaults.append({ - "company": company, - doc_field_name: doc_field_value - }) + def insert_into_item_defaults(doc_field_name, doc_field_value, company): + for d in item_defaults: + if d.get("company") == company: + d[doc_field_name] = doc_field_value + return + item_defaults.append({ + "company": company, + doc_field_name: doc_field_value + }) - if item.default_warehouse: - default_warehouse_company = frappe.get_value("Warehouse", item.default_warehouse, "company", cache=True) - insert_into_item_defaults("default_warehouse", item.default_warehouse, default_warehouse_company) + for d in [ + ["default_warehouse", "Warehouse"], ["expense_account", "Account"], ["expense_account", "Account"], + ["buying_cost_center", "Cost Center"], ["selling_cost_center", "Cost Center"] + ]: + if item.get(d[0]): + company = frappe.get_value(d[1], item.get(d[0]), "company", cache=True) + insert_into_item_defaults(d[0], item.get(d[0]), company) - if item.buying_cost_center: - buying_cost_center_company = get_cost_center_company(item.buying_cost_center) - insert_into_item_defaults("buying_cost_center", item.buying_cost_center, buying_cost_center_company) + doc = frappe.get_doc("Item", item.name) + doc.extend("item_defaults", item_defaults) - if item.selling_cost_center: - selling_cost_center_company = get_cost_center_company(item.buying_cost_center) - insert_into_item_defaults("selling_cost_center", item.selling_cost_center, selling_cost_center_company) - - if item.expense_account: - expense_account_company = get_account_company(item.expense_account) - insert_into_item_defaults("expense_account", item.expense_account, expense_account_company) - - if item.income_account: - income_account_company = get_account_company(item.income_account) - insert_into_item_defaults("income_account", item.income_account, income_account_company) - - doc = frappe.get_doc("Item", item.name) - doc.extend("item_defaults", item_defaults) - - for child_doc in doc.item_defaults: - child_doc.db_update() - -def get_account_company(account_name): - return frappe.get_value("Account", account_name, "company", cache=True) - -def get_cost_center_company(cost_center): - return frappe.get_value("Cost Center", cost_center, "company", cache=True) + for child_doc in doc.item_defaults: + child_doc.db_insert() \ No newline at end of file diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index ced5ebf4fb..3b36a2dca5 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -150,12 +150,10 @@ class TestQuotation(unittest.TestCase): from erpnext.stock.doctype.item.test_item import make_item first_item = make_item("_Test Laptop", - {"is_stock_item": 1, "expense_account": "_Test Account Cost for Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC"}) + {"is_stock_item": 1}) second_item = make_item("_Test CPU", - {"is_stock_item": 1, "expense_account": "_Test Account Cost for Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC"}) + {"is_stock_item": 1}) qo_item1 = [ { diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index c5f7ef22ec..83889412f4 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -359,14 +359,9 @@ class TestSalesOrder(unittest.TestCase): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) - po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1, - 'default_supplier': '_Test Supplier', - "expense_account": "_Test Account Cost for Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC" - }) + po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1}) - dn_item = make_item("_Test Regular Item", {"is_stock_item": 1, "expense_account": "_Test Account Cost for Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC"}) + dn_item = make_item("_Test Regular Item", {"is_stock_item": 1}) so_items = [ { From 64614374d86694fe0ade61446e2af81cf8c49e88 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Mon, 7 May 2018 16:55:32 +0530 Subject: [PATCH 5/5] fix codacy --- erpnext/controllers/selling_controller.py | 12 ++--- erpnext/demo/data/item.json | 44 +++++++++---------- .../doctype/item_default/item_default.py | 1 - erpnext/stock/get_item_details.py | 2 +- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index feee067496..83e7916e84 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -352,10 +352,10 @@ def check_active_sales_items(obj): if default.company == obj.company: default.income_account = d.income_account income_account_set = True - else: - if not income_account_set: - doc.append("item_defaults", { - "company": obj.company, - "income_account": d.income_account - }) + break + if not income_account_set: + doc.append("item_defaults", { + "company": obj.company, + "income_account": d.income_account + }) doc.save() \ No newline at end of file diff --git a/erpnext/demo/data/item.json b/erpnext/demo/data/item.json index 461ed4235a..908de15d0b 100644 --- a/erpnext/demo/data/item.json +++ b/erpnext/demo/data/item.json @@ -2,7 +2,7 @@ { "default_supplier": "Asiatic Solutions", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "For Upper Bearing", "image": "/assets/erpnext_demo/images/disc.png", @@ -13,7 +13,7 @@ { "default_supplier": "Nan Duskin", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "CAST IRON, MCMASTER PART NO. 3710T13", "image": "/assets/erpnext_demo/images/bearing.jpg", @@ -24,7 +24,7 @@ { "default_supplier": null, "item_defaults": [{ - "default_warehouse": "Finished Goods", + "default_warehouse": "Finished Goods" }], "description": "Wind Mill C Series for Commercial Use 18ft", "image": "/assets/erpnext_demo/images/wind-turbine-2.png", @@ -35,7 +35,7 @@ { "default_supplier": null, "item_defaults": [{ - "default_warehouse": "Finished Goods", + "default_warehouse": "Finished Goods" }], "description": "Wind Mill A Series for Home Use 9ft", "image": "/assets/erpnext_demo/images/wind-turbine.png", @@ -46,7 +46,7 @@ { "default_supplier": null, "item_defaults": [{ - "default_warehouse": "Finished Goods", + "default_warehouse": "Finished Goods" }], "description": "Small Wind Turbine for Home Use\n\n\n", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", @@ -62,7 +62,7 @@ { "default_supplier": "HomeBase", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "1.5 in. Diameter x 36 in. Mild Steel Tubing", "image": null, @@ -73,7 +73,7 @@ { "default_supplier": "New World Realty", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "1/32 in. x 24 in. x 47 in. HDPE Opaque Sheet", "image": null, @@ -84,7 +84,7 @@ { "default_supplier": "Eagle Hardware", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "3/16 in. x 6 in. x 6 in. Low Carbon Steel Plate", "image": null, @@ -95,7 +95,7 @@ { "default_supplier": "Asiatic Solutions", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "Bearing Assembly", "image": null, @@ -106,7 +106,7 @@ { "default_supplier": "HomeBase", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood", "image": null, @@ -118,7 +118,7 @@ { "default_supplier": "Scott Ties", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "N/A", "image": null, @@ -129,7 +129,7 @@ { "default_supplier": "Eagle Hardware", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "1 in. x 3 in. x 1 ft. Multipurpose Al Alloy Bar", "image": null, @@ -140,7 +140,7 @@ { "default_supplier": "Eagle Hardware", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "1/4 in. x 6 in. x 6 in. Mild Steel Plate", "image": null, @@ -151,7 +151,7 @@ { "default_supplier": "HomeBase", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "15/32 in. x 4 ft. x 8 ft. 3-Ply Rtd Sheathing", "image": null, @@ -162,7 +162,7 @@ { "default_supplier": "Eagle Hardware", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "1.25 in. Diameter x 6 ft. Mild Steel Tubing", "image": null, @@ -173,7 +173,7 @@ { "default_supplier": "Ks Merchandise", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "1/2 in. x 2 ft. x 4 ft. Pine Plywood", "image": null, @@ -184,7 +184,7 @@ { "default_supplier": "HomeBase", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "For Bearing Collar", "image": null, @@ -195,7 +195,7 @@ { "default_supplier": null, "item_defaults": [{ - "default_warehouse": "Finished Goods", + "default_warehouse": "Finished Goods" }], "description": "Small Wind Turbine for Home Use\n\n\n\n

Size: Small

", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", @@ -214,7 +214,7 @@ { "default_supplier": null, "item_defaults": [{ - "default_warehouse": "Finished Goods", + "default_warehouse": "Finished Goods" }], "description": "Small Wind Turbine for Home Use\n\n\n\n

Size: Medium

", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", @@ -233,7 +233,7 @@ { "default_supplier": null, "item_defaults": [{ - "default_warehouse": "Finished Goods", + "default_warehouse": "Finished Goods" }], "description": "Small Wind Turbine for Home Use\n\n\n\n

Size: Large

", "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg", @@ -259,7 +259,7 @@ { "default_supplier": "HomeBase", "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood", "image": null, @@ -327,7 +327,7 @@ "create_new_batch": 1, "valuation_rate": 200, "item_defaults": [{ - "default_warehouse": "Stores", + "default_warehouse": "Stores" }], "description": "Corrugated Box", "item_code": "Corrugated Box", diff --git a/erpnext/stock/doctype/item_default/item_default.py b/erpnext/stock/doctype/item_default/item_default.py index 85e84db6f1..935f0ffb0f 100644 --- a/erpnext/stock/doctype/item_default/item_default.py +++ b/erpnext/stock/doctype/item_default/item_default.py @@ -3,7 +3,6 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document class ItemDefault(Document): diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index bbbe860396..fd145d2ac8 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -205,7 +205,7 @@ def get_basic_details(args, item): user_default_warehouse_list = get_user_default_as_list('Warehouse') user_default_warehouse = user_default_warehouse_list[0] \ if len(user_default_warehouse_list) == 1 else "" - + item_defaults = get_item_defaults(item.name, args.company) warehouse = user_default_warehouse or item_defaults.default_warehouse or args.warehouse