From 142aab79bf4271d0a1b22fee7b5412a5e21914e9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 12 Dec 2016 15:36:42 +0530 Subject: [PATCH 1/3] Fieldtype of payment url should be Small Text --- .../payment_request/payment_request.json | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 50946c3742..3619ccb713 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -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, From 3ef63bef02f35451264bcab1e7364548750ad07d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 12 Dec 2016 15:37:35 +0530 Subject: [PATCH 2/3] Rename and merging of Item and Warehouse and patch to fix deleted bins --- erpnext/patches.txt | 3 +- ...tock_for_deleted_bins_for_merging_items.py | 41 +++++++++++++++++++ erpnext/stock/doctype/item/item.py | 12 ++++-- erpnext/stock/doctype/warehouse/warehouse.py | 17 ++++---- 4 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b578ac2cca..b9f8efb303 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -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 \ No newline at end of file +erpnext.patches.v7_0.update_status_of_po_so +erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items \ No newline at end of file diff --git a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py new file mode 100644 index 0000000000..5c63c007ad --- /dev/null +++ b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py @@ -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) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 3d248d1c28..98d0ebcfac 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -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 diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 8e7941cdea..e01cc0b6fe 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -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 From fb1fb83b8c048afa2b1ac8a378ff8f371b7503a0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 12 Dec 2016 17:01:24 +0530 Subject: [PATCH 3/3] [tests] Test cases for Item and Warehouse renaming and merging --- erpnext/stock/doctype/item/test_item.py | 37 ++++++++++- .../stock/doctype/warehouse/test_warehouse.py | 65 ++++++++++++++++++- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index aceefc0ce5..52cf10dfce 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -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() + \ No newline at end of file diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py index 223258430f..c9c4b5f9d2 100644 --- a/erpnext/stock/doctype/warehouse/test_warehouse.py +++ b/erpnext/stock/doctype/warehouse/test_warehouse.py @@ -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() + + \ No newline at end of file