From 6695830f3f325ae6a9d69fd4e9fa419ee3aad76a Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 16 Jan 2017 16:57:53 +0530 Subject: [PATCH] [fix] warehouse test cases --- erpnext/__init__.py | 15 ++++ erpnext/accounts/doctype/account/account.py | 44 +++++++--- .../journal_entry/test_journal_entry.py | 8 +- erpnext/controllers/accounts_controller.py | 16 ++-- .../purchase_receipt/test_purchase_receipt.py | 80 ++++++++--------- .../stock/doctype/warehouse/test_warehouse.py | 65 +++++++------- erpnext/stock/doctype/warehouse/warehouse.py | 87 +++++++++---------- 7 files changed, 170 insertions(+), 145 deletions(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 86d30e0aff..45602f1ea9 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -24,3 +24,18 @@ def get_default_currency(): company = get_default_company() if company: return frappe.db.get_value('Company', company, 'default_currency') + +def set_perpetual_inventory(enable=1): + accounts_settings = frappe.get_doc("Accounts Settings") + accounts_settings.auto_accounting_for_stock = enable + accounts_settings.save() + +def encode_company_abbr(name, company): + '''Returns name encoded with company abbreviation''' + company_abbr = frappe.db.get_value("Company", company, "abbr") + parts = name.rsplit(" - ", 1) + + if parts[-1].lower() != company_abbr.lower(): + parts.append(company_abbr) + + return " - ".join([parts[0], company_abbr]) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index cedaf60f9f..11f376d68c 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -3,11 +3,12 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cstr, cint +from frappe.utils import cint, fmt_money from frappe import throw, _ from frappe.model.document import Document class RootNotEditable(frappe.ValidationError): pass +class BalanceMismatchError(frappe.ValidationError): pass class Account(Document): nsm_parent_field = 'parent_account' @@ -162,23 +163,38 @@ class Account(Document): throw(_("Report Type is mandatory")) def validate_warehouse_account(self): + '''If perpetual inventory is set, and warehouse is linked, + the account balance and stock balance as of now must always match. + ''' + from erpnext.accounts.utils import get_balance_on + from erpnext.stock.utils import get_stock_value_on if not cint(frappe.defaults.get_global_default("auto_accounting_for_stock")): return - - if self.account_type == "Stock" and not cint(self.is_group): - if not self.warehouse: - throw(_("Warehouse is mandatory")) - - old_warehouse = cstr(frappe.db.get_value("Account", self.name, "warehouse")) - if old_warehouse != cstr(self.warehouse): - if old_warehouse and frappe.db.exists("Warehouse", old_warehouse): - self.validate_warehouse(old_warehouse) - if self.warehouse: - self.validate_warehouse(self.warehouse) - + + if self.account_type == "Stock": + if self.is_group == 0 and not self.warehouse: + frappe.throw(_("Warehouse is mandatory for non group Accounts of type Stock")) + + if self.warehouse: + # company must be same + if frappe.get_value('Warehouse', self.warehouse, 'company') != self.company: + frappe.throw(_("Warehouse company must be same as Account company")) + + # balance must be same + stock_balance = get_stock_value_on(self.warehouse) + if self.is_new(): + account_balance = 0.0 + else: + account_balance = get_balance_on(self.name) + + if account_balance != stock_balance: + frappe.throw(_('Account balance ({0}) and stock value ({1}) must be same')\ + .format(fmt_money(account_balance, self.account_currency), + fmt_money(stock_balance, self.account_currency))) + elif self.warehouse: self.warehouse = None - + def validate_warehouse(self, warehouse): lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py index b4bb542aa7..8756ca4413 100644 --- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py @@ -171,7 +171,7 @@ class TestJournalEntry(unittest.TestCase): }) jv.submit() - + def test_clear_blank_rows(self): je = make_journal_entry("_Test Bank - _TC", "_Test Account Stock Expenses - _TC", 100, save=False) je.append("accounts", { @@ -180,11 +180,11 @@ class TestJournalEntry(unittest.TestCase): "credit_in_account_currency": 0, "exchange_rate": 1 }) - + self.assertEqual(len(je.get("accounts")), 3) je.save() - self.assertEqual(len(je.get("accounts")), 2) - + self.assertEqual(len(je.get("accounts")), 2) + def make_journal_entry(account1, account2, amount, cost_center=None, posting_date=None, exchange_rate=1, save=True, submit=False, project=None): if not cost_center: diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index da0591134e..67d4822449 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -113,7 +113,7 @@ class AccountsController(TransactionBase): date_field = "transaction_date" if date_field and self.get(date_field): - validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company, + validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company, self.meta.get_label(date_field), self) def validate_due_date(self): @@ -131,7 +131,7 @@ class AccountsController(TransactionBase): transaction_date = self.posting_date else: transaction_date = self.transaction_date - + if self.meta.get_field("currency"): # price list part fieldname = "selling_price_list" if buying_or_selling.lower() == "selling" \ @@ -144,7 +144,7 @@ class AccountsController(TransactionBase): self.plc_conversion_rate = 1.0 elif not self.plc_conversion_rate: - self.plc_conversion_rate = get_exchange_rate(self.price_list_currency, + self.plc_conversion_rate = get_exchange_rate(self.price_list_currency, self.company_currency, transaction_date) # currency @@ -570,7 +570,7 @@ class AccountsController(TransactionBase): elif asset.status in ("Scrapped", "Cancelled", "Sold"): frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}") .format(d.idx, d.asset, asset.status)) - + def delink_advance_entries(self, linked_doc_name): total_allocated_amount = 0 for adv in self.advances: @@ -583,7 +583,7 @@ class AccountsController(TransactionBase): if consider_for_total_advance: total_allocated_amount += flt(adv.allocated_amount, adv.precision("allocated_amount")) - frappe.db.set_value(self.doctype, self.name, "total_advance", + frappe.db.set_value(self.doctype, self.name, "total_advance", total_allocated_amount, update_modified=False) def group_similar_items(self): @@ -711,7 +711,7 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field, .format(order_doctype, order_condition)) reference_condition = " and (" + " or ".join(conditions) + ")" if conditions else "" - + journal_entries = frappe.db.sql(""" select "Journal Entry" as reference_type, t1.name as reference_name, @@ -771,8 +771,8 @@ def get_advance_payment_entries(party_type, party, party_account, def update_invoice_status(): # Daily update the status of the invoices - frappe.db.sql(""" update `tabSales Invoice` set status = 'Overdue' + frappe.db.sql(""" update `tabSales Invoice` set status = 'Overdue' where due_date < CURDATE() and docstatus = 1 and outstanding_amount > 0""") - frappe.db.sql(""" update `tabPurchase Invoice` set status = 'Overdue' + frappe.db.sql(""" update `tabPurchase Invoice` set status = 'Overdue' where due_date < CURDATE() and docstatus = 1 and outstanding_amount > 0""") \ No newline at end of file diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index f961cdd1ef..7421e01947 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -8,6 +8,7 @@ import frappe import frappe.defaults from frappe.utils import cint, flt, cstr, today from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice +from erpnext import set_perpetual_inventory class TestPurchaseReceipt(unittest.TestCase): def test_make_purchase_invoice(self): @@ -26,10 +27,10 @@ class TestPurchaseReceipt(unittest.TestCase): def test_purchase_receipt_no_gl_entry(self): set_perpetual_inventory(0) - + existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, "stock_value") - + pr = make_purchase_receipt() stock_value_difference = frappe.db.get_value("Stock Ledger Entry", @@ -78,22 +79,22 @@ class TestPurchaseReceipt(unittest.TestCase): def test_subcontracting(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry - + make_stock_entry(item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100) - make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC", + make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100) - + pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes") self.assertEquals(len(pr.get("supplied_items")), 2) - + rm_supp_cost = sum([d.amount for d in pr.get("supplied_items")]) self.assertEquals(pr.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2)) def test_serial_no_supplier(self): pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1) - self.assertEquals(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "supplier"), + self.assertEquals(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "supplier"), pr.supplier) - + pr.cancel() self.assertFalse(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "warehouse")) @@ -118,21 +119,21 @@ class TestPurchaseReceipt(unittest.TestCase): for serial_no in rejected_serial_nos: self.assertEquals(frappe.db.get_value("Serial No", serial_no, "warehouse"), pr.get("items")[0].rejected_warehouse) - + def test_purchase_return(self): set_perpetual_inventory() - + pr = make_purchase_receipt() - + return_pr = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-2) # check sle - outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", + outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", "voucher_no": return_pr.name}, "outgoing_rate") - + self.assertEqual(outgoing_rate, 50) - - + + # check gl entries for return gl_entries = get_gl_entries("Purchase Receipt", return_pr.name) @@ -146,7 +147,7 @@ class TestPurchaseReceipt(unittest.TestCase): for gle in gl_entries: self.assertEquals(expected_values[gle.account][0], gle.debit) self.assertEquals(expected_values[gle.account][1], gle.credit) - + set_perpetual_inventory(0) def test_purchase_return_for_rejected_qty(self): @@ -158,7 +159,7 @@ class TestPurchaseReceipt(unittest.TestCase): actual_qty = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", "voucher_no": return_pr.name, 'warehouse': return_pr.items[0].rejected_warehouse}, "actual_qty") - + self.assertEqual(actual_qty, -2) set_perpetual_inventory(0) @@ -168,87 +169,82 @@ class TestPurchaseReceipt(unittest.TestCase): serial_no = frappe.get_doc("Serial No", serial_no) for field, value in field_values.items(): self.assertEquals(cstr(serial_no.get(field)), value) - + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos - + pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1) - + serial_no = get_serial_nos(pr.get("items")[0].serial_no)[0] - + _check_serial_no_values(serial_no, { "warehouse": "_Test Warehouse - _TC", "purchase_document_no": pr.name }) - - return_pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=-1, + + return_pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=-1, is_return=1, return_against=pr.name, serial_no=serial_no) - + _check_serial_no_values(serial_no, { "warehouse": "", "purchase_document_no": pr.name, "delivery_document_no": return_pr.name }) - + def test_closed_purchase_receipt(self): from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_purchase_receipt_status - + pr = make_purchase_receipt(do_not_submit=True) pr.submit() - + update_purchase_receipt_status(pr.name, "Closed") self.assertEquals(frappe.db.get_value("Purchase Receipt", pr.name, "status"), "Closed") - + def test_pr_billing_status(self): # PO -> PR1 -> PI and PO -> PI and PO -> PR2 from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order from erpnext.buying.doctype.purchase_order.purchase_order \ import make_purchase_receipt, make_purchase_invoice as make_purchase_invoice_from_po - + po = create_purchase_order() - + pr1 = make_purchase_receipt(po.name) pr1.posting_date = today() pr1.posting_time = "10:00" pr1.get("items")[0].received_qty = 2 pr1.get("items")[0].qty = 2 pr1.submit() - + pi1 = make_purchase_invoice(pr1.name) pi1.submit() - + pr1.load_from_db() self.assertEqual(pr1.per_billed, 100) - + pi2 = make_purchase_invoice_from_po(po.name) pi2.get("items")[0].qty = 4 pi2.submit() - + pr2 = make_purchase_receipt(po.name) pr2.posting_date = today() pr2.posting_time = "08:00" pr2.get("items")[0].received_qty = 5 pr2.get("items")[0].qty = 5 pr2.submit() - + pr1.load_from_db() self.assertEqual(pr1.get("items")[0].billed_amt, 1000) self.assertEqual(pr1.per_billed, 100) self.assertEqual(pr1.status, "Completed") - + self.assertEqual(pr2.get("items")[0].billed_amt, 2000) self.assertEqual(pr2.per_billed, 80) self.assertEqual(pr2.status, "To Bill") - + def get_gl_entries(voucher_type, voucher_no): return frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type=%s and voucher_no=%s order by account desc""", (voucher_type, voucher_no), as_dict=1) -def set_perpetual_inventory(enable=1): - accounts_settings = frappe.get_doc("Accounts Settings") - accounts_settings.auto_accounting_for_stock = enable - accounts_settings.save() - def make_purchase_receipt(**args): pr = frappe.new_doc("Purchase Receipt") args = frappe._dict(args) diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py index edc5400547..ec64bdd3bd 100644 --- a/erpnext/stock/doctype/warehouse/test_warehouse.py +++ b/erpnext/stock/doctype/warehouse/test_warehouse.py @@ -4,59 +4,64 @@ 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 -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory +from erpnext import set_perpetual_inventory +from frappe.test_runner import make_test_records import frappe import unittest test_records = frappe.get_test_records('Warehouse') class TestWarehouse(unittest.TestCase): + def setUp(self): + if not frappe.get_value('Item', '_Test Item'): + make_test_records('Item') + def test_parent_warehouse(self): parent_warehouse = frappe.get_doc("Warehouse", "_Test Warehouse Group - _TC") self.assertEquals(parent_warehouse.is_group, 1) - + def test_warehouse_hierarchy(self): p_warehouse = frappe.get_doc("Warehouse", "_Test Warehouse Group - _TC") - + child_warehouses = frappe.db.sql("""select name, is_group, parent_warehouse from `tabWarehouse` wh where wh.lft > %s and wh.rgt < %s""", (p_warehouse.lft, p_warehouse.rgt), as_dict=1) - + 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): set_perpetual_inventory(1) 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", + self.assertTrue(frappe.db.get_value("Account", filters={"warehouse": "Test Warehouse for Renaming 1 - _TC"})) - + # Rename with abbr if frappe.db.exists("Warehouse", "Test Warehouse for Renaming 2 - _TC"): frappe.delete_doc("Warehouse", "Test Warehouse for Renaming 2 - _TC") 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", + self.assertTrue(frappe.db.get_value("Account", filters={"warehouse": "Test Warehouse for Renaming 2 - _TC"})) - + self.assertFalse(frappe.db.get_value("Account", + filters={"warehouse": "Test Warehouse for Renaming 1 - _TC"})) + # Rename without abbr if frappe.db.exists("Warehouse", "Test Warehouse for Renaming 3 - _TC"): frappe.delete_doc("Warehouse", "Test Warehouse for Renaming 3 - _TC") - + 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", + self.assertTrue(frappe.db.get_value("Account", filters={"warehouse": "Test Warehouse for Renaming 3 - _TC"})) - - set_perpetual_inventory(0) - + def test_warehouse_merging(self): set_perpetual_inventory(1) - + create_warehouse("Test Warehouse for Merging 1") create_warehouse("Test Warehouse for Merging 2") @@ -64,31 +69,29 @@ class TestWarehouse(unittest.TestCase): 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", + 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", + + 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", + 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", + self.assertTrue(frappe.db.get_value("Account", filters={"warehouse": "Test Warehouse for Merging 2 - _TC"})) - - set_perpetual_inventory(0) - + def create_warehouse(warehouse_name): if not frappe.db.exists("Warehouse", warehouse_name + " - _TC"): w = frappe.new_doc("Warehouse") @@ -96,5 +99,7 @@ def create_warehouse(warehouse_name): w.parent_warehouse = "_Test Warehouse Group - _TC" w.company = "_Test Company" w.save() - - \ No newline at end of file + + if not frappe.get_value('Account', dict(warehouse=warehouse_name + ' - _TC')): + print 'Warehouse {0} not linked'.format(warehouse_name) + diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 4f5f66fdf2..d99cdf6ff7 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -2,7 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe, erpnext from frappe.utils import cint, validate_email_add from frappe import throw, msgprint, _ from frappe.utils.nestedset import NestedSet @@ -53,6 +53,8 @@ class Warehouse(NestedSet): self.update_nsm_model() def create_account_head(self): + '''Create new account head if there is no account linked to this Warehouse''' + from erpnext.accounts.doctype.account.account import BalanceMismatchError if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")): if not self.get_account(): if self.get("__islocal") or not frappe.db.get_value( @@ -76,10 +78,12 @@ class Warehouse(NestedSet): ac_doc.insert() msgprint(_("Account head {0} created").format(ac_doc.name), indicator='green', alert=True) - except frappe.DuplicateEntryError, e: - if not (e.args and e.args[0]=='Account'): - # if this is not due to creation of Account - raise + except frappe.DuplicateEntryError: + msgprint(_("Please create an Account for this Warehouse and link it. This cannot be done automatically as an account with name {0} already exists").format(frappe.bold(self.name)), + indicator='orange') + + except BalanceMismatchError: + msgprint(_("Cannot automatically create Account as there is already stock balance in the Account. You must create a matching account before you can make an entry on this warehouse")) def validate_parent_account(self): if not self.company: @@ -111,7 +115,7 @@ class Warehouse(NestedSet): else: frappe.db.sql("delete from `tabBin` where name = %s", d['name']) - warehouse_account = self.get_account(self.name) + warehouse_account = self.get_account() if warehouse_account: frappe.delete_doc("Account", warehouse_account) @@ -131,10 +135,9 @@ class Warehouse(NestedSet): return frappe.db.sql("""select name from `tabWarehouse` where parent_warehouse = %s""", self.name) - def before_rename(self, olddn, newdn, merge=False): + def before_rename(self, old_name, new_name, merge=False): # Add company abbr if not provided - from erpnext.setup.doctype.company.company import get_name_with_abbr - new_warehouse = get_name_with_abbr(newdn, self.company) + new_warehouse = erpnext.encode_company_abbr(new_name, self.company) if merge: if not frappe.db.exists("Warehouse", new_warehouse): @@ -143,64 +146,54 @@ class Warehouse(NestedSet): if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"): frappe.throw(_("Both Warehouse must belong to same Company")) - self.rename_account_for(olddn, new_warehouse, merge) + self.rename_account_for(old_name, new_warehouse, merge) return new_warehouse - def rename_account_for(self, olddn, newdn, merge): - if self.is_group: - old_account = self.get_account() - else: - old_account = self.get_account(olddn) + def rename_account_for(self, old_name, new_name, merge): + old_account_name = frappe.get_value('Account', dict(warehouse=old_name)) - if old_account: - new_account = None + if old_account_name: if not merge: - if old_account == self.add_abbr_if_missing(olddn): - new_account = frappe.rename_doc("Account", old_account, newdn) + # old account name is same as old name, so rename the account too + if old_account_name == erpnext.encode_company_abbr(old_name, self.company): + frappe.rename_doc("Account", old_account_name, new_name) else: - existing_new_account = self.get_account(newdn) - new_account = frappe.rename_doc("Account", old_account, - existing_new_account or newdn, merge=True if existing_new_account else False) + # merge + target_account = frappe.get_value('Account', dict(warehouse=new_name)) + if target_account: + # target warehouse has account, merge into target account + frappe.rename_doc("Account", old_account_name, + target_account, merge=True) + else: + # target warehouse does not have account, use this account + frappe.rename_doc("Account", old_account_name, + new_name, merge=False) - frappe.db.set_value("Account", new_account or old_account, "warehouse", newdn) + # rename link + frappe.db.set_value('Account', new_name, 'warehouse', new_name) - def add_abbr_if_missing(self, dn): - from erpnext.setup.doctype.company.company import get_name_with_abbr - return get_name_with_abbr(dn, self.company) + def get_account(self): + return frappe.get_value('Account', dict(warehouse=self.name)) - def get_account(self, warehouse=None): - filters = { - "account_type": "Stock", - "company": self.company, - "is_group": self.is_group - } - - if warehouse: - filters.update({"warehouse": warehouse}) - else: - filters.update({"account_name": self.warehouse_name}) - - return frappe.db.get_value("Account", filters) - - def after_rename(self, olddn, newdn, merge=False): + def after_rename(self, old_name, new_name, merge=False): if merge: - self.recalculate_bin_qty(newdn) + self.recalculate_bin_qty(new_name) - def recalculate_bin_qty(self, newdn): + def recalculate_bin_qty(self, new_name): from erpnext.stock.stock_balance import repost_stock frappe.db.auto_commit_on_many_writes = 1 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) repost_stock_for_items = frappe.db.sql_list("""select distinct item_code - from tabBin where warehouse=%s""", newdn) + from tabBin where warehouse=%s""", new_name) # Delete all existing bins to avoid duplicate bins for the same item and warehouse - frappe.db.sql("delete from `tabBin` where warehouse=%s", newdn) + frappe.db.sql("delete from `tabBin` where warehouse=%s", new_name) for item_code in repost_stock_for_items: - repost_stock(item_code, newdn) + repost_stock(item_code, new_name) frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock) frappe.db.auto_commit_on_many_writes = 0 @@ -231,7 +224,7 @@ class Warehouse(NestedSet): if self.check_if_sle_exists(): throw(_("Warehouses with existing transaction can not be converted to group.")) else: - account_name = self.get_account(self.name) + account_name = self.get_account() if account_name: doc = frappe.get_doc("Account", account_name) doc.flags.exclude_account_type_check = True