Merge pull request #7189 from nabinhait/fix_10111

Rename and merging of Item and Warehouse
This commit is contained in:
Nabin Hait 2016-12-12 17:27:38 +05:30 committed by GitHub
commit f67799197d
7 changed files with 187 additions and 17 deletions

View File

@ -32,6 +32,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@ -58,6 +59,7 @@
"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,
@ -86,6 +88,7 @@
"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,
@ -112,6 +115,7 @@
"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,
@ -138,6 +142,7 @@
"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,
@ -163,6 +168,7 @@
"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,
@ -190,6 +196,7 @@
"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,
@ -217,6 +224,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -245,6 +253,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -273,6 +282,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -300,6 +310,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -325,6 +336,7 @@
"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,
@ -351,6 +363,7 @@
"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,
@ -378,6 +391,7 @@
"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,
@ -404,6 +418,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
@ -416,7 +431,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "payment_url",
"fieldtype": "Data",
"fieldtype": "Small Text",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@ -430,6 +445,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -457,6 +473,7 @@
"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,
@ -484,6 +501,7 @@
"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,
@ -511,6 +529,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -537,6 +556,7 @@
"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,
@ -564,6 +584,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
@ -591,6 +612,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
@ -617,6 +639,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@ -634,7 +657,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-09-02 04:07:15.279949",
"modified": "2016-12-12 13:30:42.858205",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",
@ -651,6 +674,7 @@
"export": 1,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@ -671,6 +695,7 @@
"export": 1,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,

View File

@ -350,4 +350,5 @@ erpnext.patches.v7_1.update_invoice_status
erpnext.patches.v7_0.po_status_issue_for_pr_return
erpnext.patches.v7_1.update_missing_salary_component_type
erpnext.patches.v7_0.update_autoname_field
erpnext.patches.v7_0.update_status_of_po_so
erpnext.patches.v7_0.update_status_of_po_so
erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items

View File

@ -0,0 +1,41 @@
from __future__ import unicode_literals
import frappe
from erpnext.stock.stock_balance import repost_stock
def execute():
modified_items = frappe.db.sql_list("""
select name from `tabItem`
where is_stock_item=1 and modified >= '2016-10-31'
""")
if not modified_items:
return
item_warehouses_with_transactions = []
transactions = ("Sales Order Item", "Material Request Item", "Purchase Order Item",
"Stock Ledger Entry", "Packed Item")
for doctype in transactions:
item_warehouses_with_transactions += list(frappe.db.sql("""
select distinct item_code, warehouse
from `tab{0}` where docstatus=1 and item_code in ({1})"""
.format(doctype, ', '.join(['%s']*len(modified_items))), tuple(modified_items)))
item_warehouses_with_transactions += list(frappe.db.sql("""
select distinct production_item, fg_warehouse
from `tabProduction Order` where docstatus=1 and production_item in ({0})"""
.format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
item_warehouses_with_transactions += list(frappe.db.sql("""
select distinct pr_item.item_code, pr.source_warehouse
from `tabProduction Order` pr, `tabProduction Order Item` pr_item
where pr_item.parent and pr.name and pr.docstatus=1 and pr_item.item_code in ({0})"""
.format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
item_warehouses_with_bin = list(frappe.db.sql("select distinct item_code, warehouse from `tabBin`"))
item_warehouses_with_missing_bin = list(
set(item_warehouses_with_transactions) - set(item_warehouses_with_bin))
for item_code, warehouse in item_warehouses_with_missing_bin:
repost_stock(item_code, warehouse)

View File

@ -532,8 +532,6 @@ class Item(WebsiteGenerator):
frappe.throw(_("To merge, following properties must be same for both items")
+ ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]))
frappe.db.sql("delete from `tabBin` where item_code=%s", old_name)
def after_rename(self, old_name, new_name, merge):
if self.route:
invalidate_cache_for_item(self)
@ -567,8 +565,14 @@ class Item(WebsiteGenerator):
existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
for warehouse in frappe.db.sql("select warehouse from `tabBin` where item_code=%s", new_name):
repost_stock(new_name, warehouse[0])
repost_stock_for_warehouses = frappe.db.sql_list("""select distinct warehouse
from tabBin where item_code=%s""", new_name)
# Delete all existing bins to avoid duplicate bins for the same item and warehouse
frappe.db.sql("delete from `tabBin` where item_code=%s", new_name)
for warehouse in repost_stock_for_warehouses:
repost_stock(new_name, warehouse)
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
frappe.db.auto_commit_on_many_writes = 0

View File

@ -9,6 +9,9 @@ from frappe.test_runner import make_test_records
from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError,
InvalidItemAttributeValueError)
from frappe.model.rename_doc import rename_doc
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
test_ignore = ["BOM"]
test_dependencies = ["Warehouse"]
@ -164,11 +167,32 @@ class TestItem(unittest.TestCase):
variant.item_name = "_Test Numeric Variant Large 1.1m"
self.assertRaises(InvalidItemAttributeValueError, variant.save)
variant = create_variant("_Test Numeric Template Item", {"Test Size": "Large", "Test Item Length": 1.5})
variant = create_variant("_Test Numeric Template Item",
{"Test Size": "Large", "Test Item Length": 1.5})
self.assertEquals(variant.item_code, None)
variant.item_code = "_Test Numeric Variant-L-1.5"
variant.item_name = "_Test Numeric Variant Large 1.5m"
variant.save()
def test_item_merging(self):
create_item("Test Item for Merging 1")
create_item("Test Item for Merging 2")
make_stock_entry(item_code="Test Item for Merging 1", target="_Test Warehouse - _TC",
qty=1, rate=100)
make_stock_entry(item_code="Test Item for Merging 2", target="_Test Warehouse 1 - _TC",
qty=1, rate=100)
rename_doc("Item", "Test Item for Merging 1", "Test Item for Merging 2", merge=True)
self.assertFalse(frappe.db.exists("Item", "Test Item for Merging 1"))
self.assertTrue(frappe.db.get_value("Bin",
{"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse - _TC"}))
self.assertTrue(frappe.db.get_value("Bin",
{"item_code": "Test Item for Merging - 2", "warehouse": "_Test Warehouse 1 - _TC"}))
def make_item_variant():
if not frappe.db.exists("Item", "_Test Variant Item-S"):
@ -184,3 +208,14 @@ def get_total_projected_qty(item):
return total_qty[0].projected_qty if total_qty else 0.0
test_records = frappe.get_test_records('Item')
def create_item(item_code, is_stock_item=None):
if not frappe.db.exists("Item", item_code):
item = frappe.new_doc("Item")
item.item_code = item_code
item.item_name = item_code
item.description = item_code
item.item_group = "All Item Groups"
item.is_stock_item = is_stock_item or 1
item.save()

View File

@ -1,7 +1,9 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
from frappe.model.rename_doc import rename_doc
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from frappe.utils import cint
import frappe
import unittest
@ -21,5 +23,66 @@ class TestWarehouse(unittest.TestCase):
for child_warehouse in child_warehouses:
self.assertEquals(p_warehouse.name, child_warehouse.parent_warehouse)
self.assertEquals(child_warehouse.is_group, 0)
def test_warehouse_renaming(self):
create_warehouse("Test Warehouse for Renaming 1")
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Renaming 1 - _TC"))
self.assertTrue(frappe.db.get_value("Account",
filters={"warehouse": "Test Warehouse for Renaming 1 - _TC"}))
# Rename with abbr
rename_doc("Warehouse", "Test Warehouse for Renaming 1 - _TC", "Test Warehouse for Renaming 2 - _TC")
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Renaming 2 - _TC"))
self.assertTrue(frappe.db.get_value("Account",
filters={"warehouse": "Test Warehouse for Renaming 2 - _TC"}))
# Rename without abbr
rename_doc("Warehouse", "Test Warehouse for Renaming 2 - _TC", "Test Warehouse for Renaming 3")
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Renaming 3 - _TC"))
self.assertTrue(frappe.db.get_value("Account",
filters={"warehouse": "Test Warehouse for Renaming 3 - _TC"}))
def test_warehouse_merging(self):
create_warehouse("Test Warehouse for Merging 1")
create_warehouse("Test Warehouse for Merging 2")
make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 1 - _TC",
qty=1, rate=100)
make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 2 - _TC",
qty=1, rate=100)
existing_bin_qty = (
cint(frappe.db.get_value("Bin",
{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 1 - _TC"}, "actual_qty"))
+ cint(frappe.db.get_value("Bin",
{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty"))
)
rename_doc("Warehouse", "Test Warehouse for Merging 1 - _TC",
"Test Warehouse for Merging 2 - _TC", merge=True)
self.assertFalse(frappe.db.exists("Warehouse", "Test Warehouse for Merging 1 - _TC"))
bin_qty = frappe.db.get_value("Bin",
{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty")
self.assertEqual(bin_qty, existing_bin_qty)
self.assertFalse(frappe.db.exists("Account", "Test Warehouse for Merging 1 - _TC"))
self.assertTrue(frappe.db.exists("Account", "Test Warehouse for Merging 2 - _TC"))
self.assertTrue(frappe.db.get_value("Account",
filters={"warehouse": "Test Warehouse for Merging 2 - _TC"}))
def create_warehouse(warehouse_name):
if not frappe.db.exists("Warehouse", warehouse_name + " - _TC"):
w = frappe.new_doc("Warehouse")
w.warehouse_name = warehouse_name
w.parent_warehouse = "_Test Warehouse Group - _TC"
w.company = "_Test Company"
w.save()

View File

@ -143,9 +143,7 @@ class Warehouse(NestedSet):
if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"):
frappe.throw(_("Both Warehouse must belong to same Company"))
frappe.db.sql("delete from `tabBin` where warehouse=%s", olddn)
self.rename_account_for(olddn, newdn, merge)
self.rename_account_for(olddn, new_warehouse, merge)
return new_warehouse
@ -195,11 +193,14 @@ class Warehouse(NestedSet):
existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
for item in frappe.db.sql("""select distinct item_code from (
select name as item_code from `tabItem` where is_stock_item=1
union
select distinct item_code from tabBin) a"""):
repost_stock(item[0], newdn)
repost_stock_for_items = frappe.db.sql_list("""select distinct item_code
from tabBin where warehouse=%s""", newdn)
# Delete all existing bins to avoid duplicate bins for the same item and warehouse
frappe.db.sql("delete from `tabBin` where warehouse=%s", newdn)
for item_code in repost_stock_for_items:
repost_stock(item_code, newdn)
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
frappe.db.auto_commit_on_many_writes = 0