From a11e7388017b0f5d939871949839add7fb0a360e Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Thu, 31 Oct 2019 15:55:03 +0530 Subject: [PATCH] feat: Stock value and account balance sync. (#19233) * feat: Allow user to sync stock_value and account_balance jv if perpetual inventory is checked * fix(test): Sales Invoice * fix(test): Purchase Invoice * fix(test): Delivery Note * fix: more test_case * fix(test): Stock Entry * fix(test): Purchase Receipt * fix(more-test): Stock Entries * fix(more-test): Sales Invoice and Delivery Note * fix: tests for delivery note * fix: tests for stock reconciliation * refactor: stock and account balance function * fix(more-test): Warehouse * fix(test): Landed Cost Voucher * fix: changes requested --- .../accounts/doctype/account/test_account.py | 2 +- .../loyalty_program/test_loyalty_program.py | 2 + .../purchase_invoice/test_purchase_invoice.py | 54 ++--- erpnext/accounts/doctype/sales_invoice/pos.py | 23 +- .../doctype/sales_invoice/sales_invoice.py | 1 - .../doctype/sales_invoice/test_records.json | 3 - .../sales_invoice/test_sales_invoice.py | 161 +++++++++----- .../shipping_rule/test_shipping_rule.py | 10 +- erpnext/accounts/general_ledger.py | 40 +++- erpnext/accounts/utils.py | 28 ++- erpnext/controllers/stock_controller.py | 35 --- .../production_plan/test_production_plan.py | 2 + .../doctype/work_order/test_work_order.py | 2 +- erpnext/setup/doctype/company/test_company.py | 18 +- .../setup/doctype/company/test_records.json | 11 + erpnext/stock/__init__.py | 2 +- erpnext/stock/doctype/batch/test_batch.py | 5 +- .../delivery_note/test_delivery_note.py | 208 ++++++++---------- .../item_alternative/test_item_alternative.py | 2 + .../test_landed_cost_voucher.py | 90 ++++---- .../purchase_receipt/test_purchase_receipt.py | 142 ++++++++---- .../purchase_receipt/test_records.json | 34 --- .../stock/doctype/serial_no/test_serial_no.py | 3 + .../doctype/stock_entry/test_stock_entry.py | 104 +++++---- .../test_stock_reconciliation.py | 39 ++-- .../stock/doctype/warehouse/test_records.json | 6 - .../stock/doctype/warehouse/test_warehouse.py | 46 +++- 27 files changed, 596 insertions(+), 477 deletions(-) diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py index 4ee55736fe..dc23b2b2d0 100644 --- a/erpnext/accounts/doctype/account/test_account.py +++ b/erpnext/accounts/doctype/account/test_account.py @@ -160,7 +160,7 @@ def _make_test_records(verbose): ["_Test Payable USD", "Current Liabilities", 0, "Payable", "USD"] ] - for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"]]: + for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"], ["_Test Company with perpetual inventory", "TCP1"]]: test_objects = make_test_objects("Account", [{ "doctype": "Account", "account_name": account_name, diff --git a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py index 4a7406e0cb..341884c190 100644 --- a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py +++ b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py @@ -8,10 +8,12 @@ import unittest from frappe.utils import today, cint, flt, getdate from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points from erpnext.accounts.party import get_dashboard_info +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory class TestLoyaltyProgram(unittest.TestCase): @classmethod def setUpClass(self): + set_perpetual_inventory(0) # create relevant item, customer, loyalty program, etc create_records() diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 6deee38148..b2ad4f4d51 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -10,7 +10,7 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_ent from frappe.utils import cint, flt, today, nowdate, add_days import frappe.defaults from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \ - test_records as pr_test_records + test_records as pr_test_records, make_purchase_receipt, get_taxes from erpnext.controllers.accounts_controller import get_payment_terms from erpnext.exceptions import InvalidCurrency from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction @@ -57,16 +57,11 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account)) def test_gl_entries_with_perpetual_inventory(self): - pi = frappe.copy_doc(test_records[1]) - set_perpetual_inventory(1, pi.company) + pi = make_purchase_invoice(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1", get_taxes_and_charges=True, qty=10) self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pi.company)), 1) - pi.insert() - pi.submit() self.check_gle_for_pi(pi.name) - set_perpetual_inventory(0, pi.company) - def test_terms_added_after_save(self): pi = frappe.copy_doc(test_records[1]) pi.insert() @@ -196,21 +191,21 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(pi.on_hold, 0) def test_gl_entries_with_perpetual_inventory_against_pr(self): - pr = frappe.copy_doc(pr_test_records[0]) - set_perpetual_inventory(1, pr.company) - self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1) - pr.submit() - pi = frappe.copy_doc(test_records[1]) - for d in pi.get("items"): + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", get_taxes_and_charges=True,) + + self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1) + + pi = make_purchase_invoice(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1", get_taxes_and_charges=True, qty=10,do_not_save= "True") + + for d in pi.items: d.purchase_receipt = pr.name + pi.insert() pi.submit() self.check_gle_for_pi(pi.name) - set_perpetual_inventory(0, pr.company) - def check_gle_for_pi(self, pi): gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s @@ -218,10 +213,10 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertTrue(gl_entries) expected_values = dict((d[0], d) for d in [ - ["_Test Payable - _TC", 0, 720], - ["Stock Received But Not Billed - _TC", 500.0, 0], - ["_Test Account Shipping Charges - _TC", 100.0, 0], - ["_Test Account VAT - _TC", 120.0, 0], + ["Creditors - TCP1", 0, 720], + ["Stock Received But Not Billed - TCP1", 500.0, 0], + ["_Test Account Shipping Charges - TCP1", 100.0, 0], + ["_Test Account VAT - TCP1", 120.0, 0], ]) for i, gle in enumerate(gl_entries): @@ -524,10 +519,9 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertFalse(gle) def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self): - set_perpetual_inventory() pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), - posting_time=frappe.utils.nowtime()) + posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1", company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1") gl_entries = frappe.db.sql("""select account, account_currency, debit, credit, debit_in_account_currency, credit_in_account_currency @@ -548,9 +542,9 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(expected_gl_entries[gle.account][2], gle.credit) def test_purchase_invoice_for_is_paid_and_update_stock_gl_entry_with_perpetual_inventory(self): - set_perpetual_inventory() + pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), - posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - _TC", is_paid=1) + posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1", is_paid=1, company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1") gl_entries = frappe.db.sql("""select account, account_currency, sum(debit) as debit, sum(credit) as credit, debit_in_account_currency, credit_in_account_currency @@ -563,7 +557,7 @@ class TestPurchaseInvoice(unittest.TestCase): expected_gl_entries = dict((d[0], d) for d in [ [pi.credit_to, 250.0, 250.0], [stock_in_hand_account, 250.0, 0.0], - ["Cash - _TC", 0.0, 250.0] + ["Cash - TCP1", 0.0, 250.0] ]) for i, gle in enumerate(gl_entries): @@ -630,6 +624,7 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(pi.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2)) def test_rejected_serial_no(self): + set_perpetual_inventory(0) pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1, rejected_qty=1, rate=500, update_stock=1, rejected_warehouse = "_Test Rejected Warehouse - _TC") @@ -881,7 +876,7 @@ def make_purchase_invoice(**args): pi.is_return = args.is_return pi.return_against = args.return_against pi.is_subcontracted = args.is_subcontracted or "No" - pi.supplier_warehouse = "_Test Warehouse 1 - _TC" + pi.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC" pi.append("items", { "item_code": args.item or args.item_code or "_Test Item", @@ -890,14 +885,21 @@ def make_purchase_invoice(**args): "received_qty": args.received_qty or 0, "rejected_qty": args.rejected_qty or 0, "rate": args.rate or 50, + 'expense_account': args.expense_account or '_Test Account Cost for Goods Sold - _TC', "conversion_factor": 1.0, "serial_no": args.serial_no, "stock_uom": "_Test UOM", - "cost_center": "_Test Cost Center - _TC", + "cost_center": args.cost_center or "_Test Cost Center - _TC", "project": args.project, "rejected_warehouse": args.rejected_warehouse or "", "rejected_serial_no": args.rejected_serial_no or "" }) + + if args.get_taxes_and_charges: + taxes = get_taxes() + for tax in taxes: + pi.append("taxes", tax) + if not args.do_not_save: pi.insert() if not args.do_not_submit: diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 7d4fc63955..ed45b2cc2c 100755 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -402,14 +402,21 @@ def make_invoice(doc_list={}, email_queue_list={}, customers_list={}): for docs in doc_list: for name, doc in iteritems(docs): if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}): - validate_records(doc) - si_doc = frappe.new_doc('Sales Invoice') - si_doc.offline_pos_name = name - si_doc.update(doc) - si_doc.set_posting_time = 1 - si_doc.customer = get_customer_id(doc) - si_doc.due_date = doc.get('posting_date') - name_list = submit_invoice(si_doc, name, doc, name_list) + if isinstance(doc, dict): + validate_records(doc) + si_doc = frappe.new_doc('Sales Invoice') + si_doc.offline_pos_name = name + si_doc.update(doc) + si_doc.set_posting_time = 1 + si_doc.customer = get_customer_id(doc) + si_doc.due_date = doc.get('posting_date') + name_list = submit_invoice(si_doc, name, doc, name_list) + else: + doc.due_date = doc.get('posting_date') + doc.customer = get_customer_id(doc) + doc.set_posting_time = 1 + doc.offline_pos_name = name + name_list = submit_invoice(doc, name, doc, name_list) else: name_list.append(name) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index e1256a78d9..5766c9a8d1 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -686,7 +686,6 @@ class SalesInvoice(SellingController): def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False): auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company) - if not gl_entries: gl_entries = self.get_gl_entries() diff --git a/erpnext/accounts/doctype/sales_invoice/test_records.json b/erpnext/accounts/doctype/sales_invoice/test_records.json index 9c8de7d5a2..ebe6e3da8d 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_records.json +++ b/erpnext/accounts/doctype/sales_invoice/test_records.json @@ -68,8 +68,6 @@ "selling_price_list": "_Test Price List", "territory": "_Test Territory" }, - - { "company": "_Test Company", "conversion_rate": 1.0, @@ -276,7 +274,6 @@ "uom": "_Test UOM 1", "conversion_factor": 1, "stock_uom": "_Test UOM 1" - }, { "cost_center": "_Test Cost Center - _TC", diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 4f253b69f7..530bd893c0 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -20,6 +20,9 @@ from erpnext.stock.doctype.item.test_item import create_item from six import iteritems from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction from erpnext.regional.india.utils import get_ewb_data +from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice class TestSalesInvoice(unittest.TestCase): def make(self): @@ -550,7 +553,6 @@ class TestSalesInvoice(unittest.TestCase): si.get("taxes")[6].tax_amount = 2 si.insert() - print(si.name) expected_values = [ { @@ -679,56 +681,67 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) def test_pos_gl_entry_with_perpetual_inventory(self): - set_perpetual_inventory() make_pos_profile() - self._insert_purchase_receipt() - pos = copy.deepcopy(test_records[1]) - pos["is_pos"] = 1 - pos["update_stock"] = 1 - pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, - {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300}] + pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1") + + pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True) + + pos.is_pos = 1 + pos.update_stock = 1 + + pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50}) + pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 50}) + + taxes = get_taxes_and_charges() + pos.taxes = [] + for tax in taxes: + pos.append("taxes", tax) si = frappe.copy_doc(pos) si.insert() si.submit() + self.assertEqual(si.paid_amount, 100.0) - self.assertEqual(si.paid_amount, 600.0) - - self.pos_gl_entry(si, pos, 300) + self.pos_gl_entry(si, pos, 50) def test_pos_change_amount(self): - set_perpetual_inventory() make_pos_profile() - self._insert_purchase_receipt() - pos = copy.deepcopy(test_records[1]) - pos["is_pos"] = 1 - pos["update_stock"] = 1 - pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, - {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 340}] + pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1") - si = frappe.copy_doc(pos) - si.change_amount = 5.0 - si.insert() - si.submit() + pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True) - self.assertEqual(si.grand_total, 630.0) - self.assertEqual(si.write_off_amount, -5) + pos.is_pos = 1 + pos.update_stock = 1 + + pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50}) + pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 60}) + + pos.change_amount = 5.0 + pos.insert() + pos.submit() + + self.assertEqual(pos.grand_total, 100.0) + self.assertEqual(pos.write_off_amount, -5) def test_make_pos_invoice(self): from erpnext.accounts.doctype.sales_invoice.pos import make_invoice - set_perpetual_inventory() - make_pos_profile() - self._insert_purchase_receipt() + pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1") + pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True) - pos = copy.deepcopy(test_records[1]) - pos["is_pos"] = 1 - pos["update_stock"] = 1 - pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, - {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}] + pos.is_pos = 1 + pos.update_stock = 1 + + pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50}) + pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 50}) + + taxes = get_taxes_and_charges() + pos.taxes = [] + for tax in taxes: + pos.append("taxes", tax) invoice_data = [{'09052016142': pos}] si = make_invoice(invoice_data).get('invoice') @@ -736,16 +749,15 @@ class TestSalesInvoice(unittest.TestCase): sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1}) si = frappe.get_doc('Sales Invoice', sales_invoice[0].name) - self.assertEqual(si.grand_total, 630.0) - self.pos_gl_entry(si, pos, 330) + self.assertEqual(si.grand_total, 100) + + self.pos_gl_entry(si, pos, 50) def test_make_pos_invoice_in_draft(self): from erpnext.accounts.doctype.sales_invoice.pos import make_invoice from erpnext.stock.doctype.item.test_item import make_item - set_perpetual_inventory() - allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock') if allow_negative_stock: frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0) @@ -789,7 +801,7 @@ class TestSalesInvoice(unittest.TestCase): si.name, as_dict=1)[0] self.assertTrue(sle) self.assertEqual([sle.item_code, sle.warehouse, sle.actual_qty], - ["_Test Item", "_Test Warehouse - _TC", -1.0]) + ['_Test FG Item', 'Stores - TCP1', -1.0]) # check gl entries gl_entries = frappe.db.sql("""select account, debit, credit @@ -797,19 +809,19 @@ class TestSalesInvoice(unittest.TestCase): order by account asc, debit asc, credit asc""", si.name, as_dict=1) self.assertTrue(gl_entries) - stock_in_hand = get_inventory_account('_Test Company') - + stock_in_hand = get_inventory_account('_Test Company with perpetual inventory') expected_gl_entries = sorted([ - [si.debit_to, 630.0, 0.0], - [pos["items"][0]["income_account"], 0.0, 500.0], - [pos["taxes"][0]["account_head"], 0.0, 80.0], - [pos["taxes"][1]["account_head"], 0.0, 50.0], + [si.debit_to, 100.0, 0.0], + [pos.items[0].income_account, 0.0, 89.09], + ['Round Off - TCP1', 0.0, 0.01], + [pos.taxes[0].account_head, 0.0, 10.69], + [pos.taxes[1].account_head, 0.0, 0.21], [stock_in_hand, 0.0, abs(sle.stock_value_difference)], - [pos["items"][0]["expense_account"], abs(sle.stock_value_difference), 0.0], - [si.debit_to, 0.0, 300.0], + [pos.items[0].expense_account, abs(sle.stock_value_difference), 0.0], + [si.debit_to, 0.0, 50.0], [si.debit_to, 0.0, cash_amount], - ["_Test Bank - _TC", 300.0, 0.0], - ["Cash - _TC", cash_amount, 0.0] + ["_Test Bank - TCP1", 50, 0.0], + ["Cash - TCP1", cash_amount, 0.0] ]) for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)): @@ -823,9 +835,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) - set_perpetual_inventory(0) frappe.db.sql("delete from `tabPOS Profile`") + si.delete() def test_pos_si_without_payment(self): set_perpetual_inventory() @@ -1008,7 +1020,6 @@ class TestSalesInvoice(unittest.TestCase): """ from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note - from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos se = make_serialized_item() @@ -1023,14 +1034,17 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(si.get("items")[0].serial_no, dn.get("items")[0].serial_no) def test_return_sales_invoice(self): - set_perpetual_inventory() - make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) + make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=50, basic_rate=100) - actual_qty_0 = get_qty_after_transaction() + actual_qty_0 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1") - si = create_sales_invoice(qty=5, rate=500, update_stock=1) + si = create_sales_invoice(qty = 5, rate=500, update_stock=1, company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1") + + + actual_qty_1 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1") + + frappe.db.commit() - actual_qty_1 = get_qty_after_transaction() self.assertEqual(actual_qty_0 - 5, actual_qty_1) # outgoing_rate @@ -1038,10 +1052,9 @@ class TestSalesInvoice(unittest.TestCase): "voucher_no": si.name}, "stock_value_difference") / 5 # return entry - si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1) - - actual_qty_2 = get_qty_after_transaction() + si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1, company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1") + actual_qty_2 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1") self.assertEqual(actual_qty_1 + 2, actual_qty_2) incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", @@ -1049,7 +1062,7 @@ class TestSalesInvoice(unittest.TestCase): ["incoming_rate", "stock_value_difference"]) self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) - stock_in_hand_account = get_inventory_account('_Test Company', si1.items[0].warehouse) + stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory', si1.items[0].warehouse) # Check gl entry gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice", @@ -1058,7 +1071,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(gle_warehouse_amount, stock_value_difference) party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice", - "voucher_no": si1.name, "account": "Debtors - _TC", "party": "_Test Customer"}, "credit") + "voucher_no": si1.name, "account": "Debtors - TCP1", "party": "_Test Customer"}, "credit") self.assertEqual(party_credited, 1000) @@ -1066,7 +1079,6 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(si1.outstanding_amount) self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500) - set_perpetual_inventory(0) def test_discount_on_net_total(self): si = frappe.copy_doc(test_records[2]) @@ -1524,6 +1536,8 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(si.total_taxes_and_charges, 577.05) self.assertEqual(si.grand_total, 1827.05) + + def test_create_invoice_without_terms(self): si = create_sales_invoice(do_not_save=1) self.assertFalse(si.get('payment_schedule')) @@ -1930,4 +1944,29 @@ def get_outstanding_amount(against_voucher_type, against_voucher, account, party if against_voucher_type == 'Purchase Invoice': bal = bal * -1 - return bal \ No newline at end of file + return bal + +def get_taxes_and_charges(): + return [{ + "account_head": "_Test Account Excise Duty - TCP1", + "charge_type": "On Net Total", + "cost_center": "Main - TCP1", + "description": "Excise Duty", + "doctype": "Sales Taxes and Charges", + "idx": 1, + "included_in_print_rate": 1, + "parentfield": "taxes", + "rate": 12 + }, + { + "account_head": "_Test Account Education Cess - TCP1", + "charge_type": "On Previous Row Amount", + "cost_center": "Main - TCP1", + "description": "Education Cess", + "doctype": "Sales Taxes and Charges", + "idx": 2, + "included_in_print_rate": 1, + "parentfield": "taxes", + "rate": 2, + "row_id": 1 + }] \ No newline at end of file diff --git a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py index 582ecb2e16..abc6ab82d3 100644 --- a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py @@ -14,13 +14,13 @@ class TestShippingRule(unittest.TestCase): shipping_rule.name = test_records[0].get('name') shipping_rule.get("conditions")[0].from_value = 101 self.assertRaises(FromGreaterThanToError, shipping_rule.insert) - + def test_many_zero_to_values(self): shipping_rule = frappe.copy_doc(test_records[0]) shipping_rule.name = test_records[0].get('name') shipping_rule.get("conditions")[0].to_value = 0 self.assertRaises(ManyBlankToValuesError, shipping_rule.insert) - + def test_overlapping_conditions(self): for range_a, range_b in [ ((50, 150), (0, 100)), @@ -38,6 +38,10 @@ class TestShippingRule(unittest.TestCase): self.assertRaises(OverlappingConditionError, shipping_rule.insert) def create_shipping_rule(shipping_rule_type, shipping_rule_name): + + if frappe.db.exists("Shipping Rule", shipping_rule_name): + return frappe.get_doc("Shipping Rule", shipping_rule_name) + sr = frappe.new_doc("Shipping Rule") sr.account = "_Test Account Shipping Charges - _TC" sr.calculate_based_on = "Net Total" @@ -70,4 +74,4 @@ def create_shipping_rule(shipping_rule_type, shipping_rule_name): }) sr.insert(ignore_permissions=True) sr.submit() - return sr + return sr diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 5c9e93d019..43d9ad6435 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -3,8 +3,9 @@ from __future__ import unicode_literals import frappe, erpnext -from frappe.utils import flt, cstr, cint +from frappe.utils import flt, cstr, cint, comma_and from frappe import _ +from erpnext.accounts.utils import get_stock_and_account_balance from frappe.model.meta import get_field_precision from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions @@ -12,6 +13,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import g class ClosedAccountingPeriod(frappe.ValidationError): pass class StockAccountInvalidTransaction(frappe.ValidationError): pass +class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False): if gl_map: @@ -115,11 +117,9 @@ def check_if_in_list(gle, gl_map, dimensions=None): def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False): if not from_repost: - validate_account_for_perpetual_inventory(gl_map) validate_cwip_accounts(gl_map) round_off_debit_credit(gl_map) - for entry in gl_map: make_entry(entry, adv_adj, update_outstanding, from_repost) @@ -127,6 +127,10 @@ def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False): if not from_repost: validate_expense_against_budget(entry) + if not from_repost: + validate_account_for_perpetual_inventory(gl_map) + + def make_entry(args, adv_adj, update_outstanding, from_repost=False): args.update({"doctype": "GL Entry"}) gle = frappe.get_doc(args) @@ -137,15 +141,31 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False): gle.submit() def validate_account_for_perpetual_inventory(gl_map): - if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)) \ - and gl_map[0].voucher_type=="Journal Entry": - aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount - where account_type = 'Stock' and is_group=0""")] + if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)): + account_list = [gl_entries.account for gl_entries in gl_map] - for entry in gl_map: - if entry.account in aii_accounts: + aii_accounts = [d.name for d in frappe.get_all("Account", + filters={'account_type': 'Stock', 'is_group': 0, 'company': gl_map[0].company})] + + for account in account_list: + if account not in aii_accounts: + continue + + account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(account, + gl_map[0].posting_date, gl_map[0].company) + + if gl_map[0].voucher_type=="Journal Entry": + # In case of Journal Entry, there are no corresponding SL entries, + # hence deducting currency amount + account_bal -= flt(gl_map[0].debit) - flt(gl_map[0].credit) + if account_bal == stock_bal: frappe.throw(_("Account: {0} can only be updated via Stock Transactions") - .format(entry.account), StockAccountInvalidTransaction) + .format(account), StockAccountInvalidTransaction) + + elif account_bal != stock_bal: + frappe.throw(_("Account Balance ({0}) and Stock Value ({1}) is out of sync for account {2} and linked warehouse ({3}). Please create adjustment Journal Entry for amount {4}.") + .format(account_bal, stock_bal, account, comma_and(warehouse_list), stock_bal - account_bal), + StockValueAndAccountBalanceOutOfSync) def validate_cwip_accounts(gl_map): if not cint(frappe.db.get_value("Asset Settings", None, "disable_cwip_accounting")) \ diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index ac69fd3c96..382a89b310 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -13,6 +13,10 @@ from six import iteritems # imported to enable erpnext.accounts.utils.get_account_currency from erpnext.accounts.doctype.account.account import get_account_currency +from erpnext.stock.utils import get_stock_value_on +from erpnext.stock import get_warehouse_account_map + + class FiscalYearError(frappe.ValidationError): pass @frappe.whitelist() @@ -560,23 +564,23 @@ def fix_total_debit_credit(): (dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr), (d.diff, d.voucher_type, d.voucher_no)) -def get_stock_and_account_difference(account_list=None, posting_date=None, company=None): - from erpnext.stock.utils import get_stock_value_on - from erpnext.stock import get_warehouse_account_map - +def get_stock_and_account_balance(account=None, posting_date=None, company=None): if not posting_date: posting_date = nowdate() - difference = {} warehouse_account = get_warehouse_account_map(company) - for warehouse, account_data in iteritems(warehouse_account): - if account_data.get('account') in account_list: - account_balance = get_balance_on(account_data.get('account'), posting_date, in_account_currency=False) - stock_value = get_stock_value_on(warehouse, posting_date) - if abs(flt(stock_value) - flt(account_balance)) > 0.005: - difference.setdefault(account_data.get('account'), flt(stock_value) - flt(account_balance)) + account_balance = get_balance_on(account, posting_date, in_account_currency=False) - return difference + related_warehouses = [wh for wh, wh_details in warehouse_account.items() + if wh_details.account == account and not wh_details.is_group] + + total_stock_value = 0.0 + for warehouse in related_warehouses: + value = get_stock_value_on(warehouse, posting_date) + total_stock_value += value + + precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency") + return flt(account_balance, precision), flt(total_stock_value, precision), related_warehouses def get_currency_precision(): precision = cint(frappe.db.get_default("currency_precision")) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 2d87a98f20..542073ebd7 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -207,41 +207,6 @@ class StockController(AccountsController): reference_doctype=self.doctype, reference_name=self.name)).insert().name - def make_adjustment_entry(self, expected_gle, voucher_obj): - from erpnext.accounts.utils import get_stock_and_account_difference - account_list = [d.account for d in expected_gle] - acc_diff = get_stock_and_account_difference(account_list, - expected_gle[0].posting_date, self.company) - - cost_center = self.get_company_default("cost_center") - stock_adjustment_account = self.get_company_default("stock_adjustment_account") - - gl_entries = [] - for account, diff in acc_diff.items(): - if diff: - gl_entries.append([ - # stock in hand account - voucher_obj.get_gl_dict({ - "account": account, - "against": stock_adjustment_account, - "debit": diff, - "remarks": "Adjustment Accounting Entry for Stock", - }), - - # account against stock in hand - voucher_obj.get_gl_dict({ - "account": stock_adjustment_account, - "against": account, - "credit": diff, - "cost_center": cost_center or None, - "remarks": "Adjustment Accounting Entry for Stock", - }), - ]) - - if gl_entries: - from erpnext.accounts.general_ledger import make_gl_entries - make_gl_entries(gl_entries) - def check_expense_account(self, item): if not item.get("expense_account"): frappe.throw(_("Expense or Difference account is mandatory for Item {0} as it impacts overall stock value").format(item.item_code)) diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index f70c9cc43f..44796417d4 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -11,9 +11,11 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import get_sa from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory class TestProductionPlan(unittest.TestCase): def setUp(self): + set_perpetual_inventory(0) for item in ['Test Production Item 1', 'Subassembly Item 1', 'Raw Material Item 1', 'Raw Material Item 2']: create_item(item, valuation_rate=100) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index d710e57056..ea2e7a96e1 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -17,11 +17,11 @@ from erpnext.manufacturing.doctype.production_plan.test_production_plan import m class TestWorkOrder(unittest.TestCase): def setUp(self): + set_perpetual_inventory(0) self.warehouse = '_Test Warehouse 2 - _TC' self.item = '_Test Item' def check_planned_qty(self): - set_perpetual_inventory(0) planned0 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item", "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") or 0 diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py index 8debef5ff6..8d9c23a37d 100644 --- a/erpnext/setup/doctype/company/test_company.py +++ b/erpnext/setup/doctype/company/test_company.py @@ -22,7 +22,7 @@ class TestCompany(unittest.TestCase): company.create_chart_of_accounts_based_on = "Existing Company" company.existing_company = "_Test Company" company.save() - + expected_results = { "Debtors - CFEC": { "account_type": "Receivable", @@ -37,7 +37,7 @@ class TestCompany(unittest.TestCase): "parent_account": "Cash In Hand - CFEC" } } - + for account, acc_property in expected_results.items(): acc = frappe.get_doc("Account", account) for prop, val in acc_property.items(): @@ -50,14 +50,14 @@ class TestCompany(unittest.TestCase): countries = ["India", "Brazil", "United Arab Emirates", "Canada", "Germany", "France", "Guatemala", "Indonesia", "Italy", "Mexico", "Nicaragua", "Netherlands", "Singapore", "Brazil", "Argentina", "Hungary", "Taiwan"] - + for country in countries: templates = get_charts_for_country(country) if len(templates) != 1 and "Standard" in templates: templates.remove("Standard") - + self.assertTrue(templates) - + for template in templates: try: company = frappe.new_doc("Company") @@ -67,11 +67,11 @@ class TestCompany(unittest.TestCase): company.create_chart_of_accounts_based_on = "Standard Template" company.chart_of_accounts = template company.save() - - account_types = ["Cost of Goods Sold", "Depreciation", - "Expenses Included In Valuation", "Fixed Asset", "Payable", "Receivable", + + account_types = ["Cost of Goods Sold", "Depreciation", + "Expenses Included In Valuation", "Fixed Asset", "Payable", "Receivable", "Stock Adjustment", "Stock Received But Not Billed", "Bank", "Cash", "Stock"] - + for account_type in account_types: filters = { "company": template, diff --git a/erpnext/setup/doctype/company/test_records.json b/erpnext/setup/doctype/company/test_records.json index 58d8b5c334..21302417d2 100644 --- a/erpnext/setup/doctype/company/test_records.json +++ b/erpnext/setup/doctype/company/test_records.json @@ -62,5 +62,16 @@ "domain": "Manufacturing", "chart_of_accounts": "Standard", "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "TCP1", + "company_name": "_Test Company with perpetual inventory", + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "enable_perpetual_inventory": 1, + "default_holiday_list": "_Test Holiday List" } ] diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py index 32a03e7373..a4d4cbd8ef 100644 --- a/erpnext/stock/__init__.py +++ b/erpnext/stock/__init__.py @@ -21,7 +21,7 @@ def get_warehouse_account_map(company=None): filters['company'] = company for d in frappe.get_all('Warehouse', - fields = ["name", "account", "parent_warehouse", "company"], + fields = ["name", "account", "parent_warehouse", "company", "is_group"], filters = filters, order_by="lft, rgt"): if not d.account: diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index 56b460781c..32445a618d 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -8,10 +8,13 @@ import unittest from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError, get_batch_no from frappe.utils import cint - +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory class TestBatch(unittest.TestCase): + def setUp(self): + set_perpetual_inventory(0) + def test_item_has_batch_enabled(self): self.assertRaises(ValidationError, frappe.get_doc({ "doctype": "Batch", diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 91b6f4c606..dc92c5c9ff 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -20,18 +20,11 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation \ import create_stock_reconciliation, set_valuation_method from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order, create_dn_against_so from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account +from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse class TestDeliveryNote(unittest.TestCase): - def tearDown(self): - target_warehouse = "_Test Warehouse 1 - _TC" - company = "_Test Company" - if not frappe.db.exists("Account", target_warehouse): - parent_account = frappe.db.get_value('Account', - {'company': company, 'is_group':1, 'account_type': 'Stock'},'name') - - account = create_account(account_name="_Test Warehouse 1", \ - account_type="Stock", parent_account= parent_account, company=company) - frappe.db.set_value('Warehouse', target_warehouse, 'account', account) + def setUp(self): + set_perpetual_inventory(0) def test_over_billing_against_dn(self): frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) @@ -68,17 +61,16 @@ class TestDeliveryNote(unittest.TestCase): self.assertFalse(get_gl_entries("Delivery Note", dn.name)) def test_delivery_note_gl_entry(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') set_valuation_method("_Test Item", "FIFO") - make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100) + make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100) - stock_in_hand_account = get_inventory_account('_Test Company') + stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory') prev_bal = get_balance_on(stock_in_hand_account) - dn = create_delivery_note() + dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1") gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) @@ -88,7 +80,7 @@ class TestDeliveryNote(unittest.TestCase): expected_values = { stock_in_hand_account: [0.0, stock_value_difference], - "Cost of Goods Sold - _TC": [stock_value_difference, 0.0] + "Cost of Goods Sold - TCP1": [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) @@ -98,7 +90,7 @@ class TestDeliveryNote(unittest.TestCase): self.assertEqual(bal, prev_bal - stock_value_difference) # back dated incoming entry - make_stock_entry(posting_date=add_days(nowdate(), -2), target="_Test Warehouse - _TC", + make_stock_entry(posting_date=add_days(nowdate(), -2), target="Stores - TCP1", qty=5, basic_rate=100) gl_entries = get_gl_entries("Delivery Note", dn.name) @@ -109,27 +101,25 @@ class TestDeliveryNote(unittest.TestCase): expected_values = { stock_in_hand_account: [0.0, stock_value_difference], - "Cost of Goods Sold - _TC": [stock_value_difference, 0.0] + "Cost of Goods Sold - TCP1": [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) dn.cancel() self.assertFalse(get_gl_entries("Delivery Note", dn.name)) - set_perpetual_inventory(0, company) def test_delivery_note_gl_entry_packing_item(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') - make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=10, basic_rate=100) + make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=10, basic_rate=100) make_stock_entry(item_code="_Test Item Home Desktop 100", - target="_Test Warehouse - _TC", qty=10, basic_rate=100) + target="Stores - TCP1", qty=10, basic_rate=100) - stock_in_hand_account = get_inventory_account('_Test Company') + stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory') prev_bal = get_balance_on(stock_in_hand_account) - dn = create_delivery_note(item_code="_Test Product Bundle Item") + dn = create_delivery_note(item_code="_Test Product Bundle Item", company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1") stock_value_diff_rm1 = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"}, @@ -146,7 +136,7 @@ class TestDeliveryNote(unittest.TestCase): expected_values = { stock_in_hand_account: [0.0, stock_value_diff], - "Cost of Goods Sold - _TC": [stock_value_diff, 0.0] + "Cost of Goods Sold - TCP1": [stock_value_diff, 0.0] } for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) @@ -158,8 +148,6 @@ class TestDeliveryNote(unittest.TestCase): dn.cancel() self.assertFalse(get_gl_entries("Delivery Note", dn.name)) - set_perpetual_inventory(0, company) - def test_serialized(self): se = make_serialized_item() serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] @@ -218,16 +206,16 @@ class TestDeliveryNote(unittest.TestCase): self.assertEqual(cstr(serial_no.get(field)), value) def test_sales_return_for_non_bundled_items(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') - make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) + make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=50, basic_rate=100) - actual_qty_0 = get_qty_after_transaction() + actual_qty_0 = get_qty_after_transaction(warehouse="Stores - TCP1") - dn = create_delivery_note(qty=5, rate=500) + dn = create_delivery_note(qty=5, rate=500, warehouse="Stores - TCP1", company=company, + expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") - actual_qty_1 = get_qty_after_transaction() + actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty_0 - 5, actual_qty_1) # outgoing_rate @@ -235,9 +223,10 @@ class TestDeliveryNote(unittest.TestCase): "voucher_no": dn.name}, "stock_value_difference") / 5 # return entry - dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, rate=500) + dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, rate=500, + company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") - actual_qty_2 = get_qty_after_transaction() + actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty_1 + 2, actual_qty_2) @@ -246,27 +235,29 @@ class TestDeliveryNote(unittest.TestCase): ["incoming_rate", "stock_value_difference"]) self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) - stock_in_hand_account = get_inventory_account('_Test Company', dn1.items[0].warehouse) + stock_in_hand_account = get_inventory_account(company, dn1.items[0].warehouse) gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name, "account": stock_in_hand_account}, "debit") self.assertEqual(gle_warehouse_amount, stock_value_difference) - set_perpetual_inventory(0, company) - def test_return_single_item_from_bundled_items(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') - create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100) - create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", - qty=50, rate=100) + create_stock_reconciliation(item_code="_Test Item", + warehouse="Stores - TCP1", qty=50, rate=100, + company=company, expense_account = "Stock Adjustment - TCP1") + create_stock_reconciliation(item_code="_Test Item Home Desktop 100", + warehouse="Stores - TCP1", qty=50, rate=100, + company=company, expense_account = "Stock Adjustment - TCP1") - dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500) + dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500, + company=company, warehouse="Stores - TCP1", + expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # Qty after delivery - actual_qty_1 = get_qty_after_transaction() + actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty_1, 25) # outgoing_rate @@ -274,10 +265,12 @@ class TestDeliveryNote(unittest.TestCase): "voucher_no": dn.name, "item_code": "_Test Item"}, "stock_value_difference") / 25 # return 'test item' from packed items - dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500) + dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500, + company=company, warehouse="Stores - TCP1", + expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # qty after return - actual_qty_2 = get_qty_after_transaction() + actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty_2, 35) # Check incoming rate for return entry @@ -286,7 +279,7 @@ class TestDeliveryNote(unittest.TestCase): ["incoming_rate", "stock_value_difference"]) self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) - stock_in_hand_account = get_inventory_account('_Test Company', dn1.items[0].warehouse) + stock_in_hand_account = get_inventory_account(company, dn1.items[0].warehouse) # Check gl entry for warehouse gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", @@ -294,33 +287,33 @@ class TestDeliveryNote(unittest.TestCase): self.assertEqual(gle_warehouse_amount, stock_value_difference) - set_perpetual_inventory(0, company) def test_return_entire_bundled_items(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') create_stock_reconciliation(item_code="_Test Item", - target="_Test Warehouse - _TC", qty=50, rate=100) + warehouse="Stores - TCP1", qty=50, rate=100, + company=company, expense_account = "Stock Adjustment - TCP1") create_stock_reconciliation(item_code="_Test Item Home Desktop 100", - target="_Test Warehouse - _TC", qty=50, rate=100) + warehouse="Stores - TCP1", qty=50, rate=100, + company=company, expense_account = "Stock Adjustment - TCP1") - actual_qty = get_qty_after_transaction() + actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty, 50) dn = create_delivery_note(item_code="_Test Product Bundle Item", - qty=5, rate=500) + qty=5, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # qty after return - actual_qty = get_qty_after_transaction() + actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty, 25) # return bundled item dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1, - return_against=dn.name, qty=-2, rate=500) + return_against=dn.name, qty=-2, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # qty after return - actual_qty = get_qty_after_transaction() + actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty, 35) # Check incoming rate for return entry @@ -337,8 +330,6 @@ class TestDeliveryNote(unittest.TestCase): self.assertEqual(gle_warehouse_amount, 1400) - set_perpetual_inventory(0, company) - def test_return_for_serialized_items(self): se = make_serialized_item() serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] @@ -375,56 +366,44 @@ class TestDeliveryNote(unittest.TestCase): }) def test_delivery_of_bundled_items_to_target_warehouse(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO") - for warehouse in ("_Test Warehouse - _TC", "_Test Warehouse 1 - _TC"): - create_stock_reconciliation(item_code="_Test Item", target=warehouse, - qty=100, rate=100) - create_stock_reconciliation(item_code="_Test Item Home Desktop 100", - target=warehouse, qty=100, rate=100) + target_warehouse=get_warehouse(company=company, abbr="TCP1", + warehouse_name="_Test Customer Warehouse").name + + for warehouse in ("Stores - TCP1", target_warehouse): + create_stock_reconciliation(item_code="_Test Item", warehouse=warehouse, company = company, + expense_account = "Stock Adjustment - TCP1", qty=500, rate=100) + create_stock_reconciliation(item_code="_Test Item Home Desktop 100", company = company, + expense_account = "Stock Adjustment - TCP1", warehouse=warehouse, qty=500, rate=100) - opening_qty_test_warehouse_1 = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC") dn = create_delivery_note(item_code="_Test Product Bundle Item", - qty=5, rate=500, target_warehouse="_Test Warehouse 1 - _TC", do_not_submit=True) + company='_Test Company with perpetual inventory', cost_center = 'Main - TCP1', + expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True, qty=5, rate=500, + warehouse="Stores - TCP1", target_warehouse=target_warehouse) dn.submit() # qty after delivery - actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse - _TC") - self.assertEqual(actual_qty, 75) + actual_qty_at_source = get_qty_after_transaction(warehouse="Stores - TCP1") + self.assertEqual(actual_qty_at_source, 475) - actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC") - self.assertEqual(actual_qty, opening_qty_test_warehouse_1 + 25) + actual_qty_at_target = get_qty_after_transaction(warehouse=target_warehouse) + self.assertEqual(actual_qty_at_target, 525) - # stock value diff for source warehouse - # for "_Test Item" + # stock value diff for source warehouse for "_Test Item" stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, - "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, + "item_code": "_Test Item", "warehouse": "Stores - TCP1"}, "stock_value_difference") # stock value diff for target warehouse stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, - "item_code": "_Test Item", "warehouse": "_Test Warehouse 1 - _TC"}, - "stock_value_difference") - - self.assertEqual(abs(stock_value_difference), stock_value_difference1) - - # for "_Test Item Home Desktop 100" - stock_value_difference = frappe.db.get_value("Stock Ledger Entry", - {"voucher_type": "Delivery Note", "voucher_no": dn.name, - "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse - _TC"}, - "stock_value_difference") - - # stock value diff for target warehouse - stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", - {"voucher_type": "Delivery Note", "voucher_no": dn.name, - "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse 1 - _TC"}, + "item_code": "_Test Item", "warehouse": target_warehouse}, "stock_value_difference") self.assertEqual(abs(stock_value_difference), stock_value_difference1) @@ -435,21 +414,20 @@ class TestDeliveryNote(unittest.TestCase): stock_value_difference = abs(frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s - and warehouse='_Test Warehouse - _TC'""", dn.name)[0][0]) + and warehouse='Stores - TCP1'""", dn.name)[0][0]) expected_values = { - "Stock In Hand - _TC": [0.0, stock_value_difference], - "_Test Warehouse 1 - _TC": [stock_value_difference, 0.0] + "Stock In Hand - TCP1": [0.0, stock_value_difference], + target_warehouse: [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) - set_perpetual_inventory(0, company) - def test_closed_delivery_note(self): from erpnext.stock.doctype.delivery_note.delivery_note import update_delivery_note_status - dn = create_delivery_note(do_not_submit=True) + dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True) + dn.submit() update_delivery_note_status(dn.name, "Closed") @@ -574,24 +552,23 @@ class TestDeliveryNote(unittest.TestCase): accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings') accounts_settings.allow_cost_center_in_entry_of_bs_account = 1 accounts_settings.save() - cost_center = "_Test Cost Center for BS Account - _TC" - create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company") + cost_center = "_Test Cost Center for BS Account - TCP1" + create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory") - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') set_valuation_method("_Test Item", "FIFO") - make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100) + make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100) - stock_in_hand_account = get_inventory_account('_Test Company') - dn = create_delivery_note(cost_center=cost_center) + stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory') + dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', expense_account = "Cost of Goods Sold - TCP1", cost_center=cost_center) gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) expected_values = { - "Cost of Goods Sold - _TC": { + "Cost of Goods Sold - TCP1": { "cost_center": cost_center }, stock_in_hand_account: { @@ -600,8 +577,6 @@ class TestDeliveryNote(unittest.TestCase): } for i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) - - set_perpetual_inventory(0, company) accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.save() @@ -609,23 +584,22 @@ class TestDeliveryNote(unittest.TestCase): accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings') accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.save() - cost_center = "_Test Cost Center - _TC" + cost_center = "Main - TCP1" - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') set_valuation_method("_Test Item", "FIFO") - make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100) + make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100) - stock_in_hand_account = get_inventory_account('_Test Company') - dn = create_delivery_note() + stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory') + dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1") gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) expected_values = { - "Cost of Goods Sold - _TC": { + "Cost of Goods Sold - TCP1": { "cost_center": cost_center }, stock_in_hand_account: { @@ -635,8 +609,6 @@ class TestDeliveryNote(unittest.TestCase): for i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) - set_perpetual_inventory(0, company) - def test_make_sales_invoice_from_dn_for_returned_qty(self): from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice @@ -702,7 +674,7 @@ def create_delivery_note(**args): "rate": args.rate or 100, "conversion_factor": 1.0, "allow_zero_valuation_rate": args.allow_zero_valuation_rate or 1, - "expense_account": "Cost of Goods Sold - _TC", + "expense_account": args.expense_account or "Cost of Goods Sold - _TC", "cost_center": args.cost_center or "_Test Cost Center - _TC", "serial_no": args.serial_no, "target_warehouse": args.target_warehouse diff --git a/erpnext/stock/doctype/item_alternative/test_item_alternative.py b/erpnext/stock/doctype/item_alternative/test_item_alternative.py index d5700fe514..f045e4f911 100644 --- a/erpnext/stock/doctype/item_alternative/test_item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/test_item_alternative.py @@ -12,9 +12,11 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt, make_rm_stock_entry import unittest +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory class TestItemAlternative(unittest.TestCase): def setUp(self): + set_perpetual_inventory(0) make_items() def test_alternative_item_for_subcontract_rm(self): diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py index c32f028b08..4dc0b7b059 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py @@ -14,15 +14,15 @@ from erpnext.accounts.doctype.account.test_account import get_inventory_account class TestLandedCostVoucher(unittest.TestCase): def test_landed_cost_voucher(self): frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) - set_perpetual_inventory(1) - pr = frappe.copy_doc(pr_test_records[0]) - pr.submit() + + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True) + last_sle = frappe.db.get_value("Stock Ledger Entry", { "voucher_type": pr.doctype, "voucher_no": pr.name, "item_code": "_Test Item", - "warehouse": "_Test Warehouse - _TC" + "warehouse": "Stores - TCP1" }, fieldname=["qty_after_transaction", "stock_value"], as_dict=1) @@ -35,7 +35,7 @@ class TestLandedCostVoucher(unittest.TestCase): "voucher_type": pr.doctype, "voucher_no": pr.name, "item_code": "_Test Item", - "warehouse": "_Test Warehouse - _TC" + "warehouse": "Stores - TCP1" }, fieldname=["qty_after_transaction", "stock_value"], as_dict=1) @@ -48,55 +48,56 @@ class TestLandedCostVoucher(unittest.TestCase): self.assertTrue(gl_entries) stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) - fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse) + fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse) if stock_in_hand_account == fixed_asset_account: expected_values = { stock_in_hand_account: [800.0, 0.0], - "Stock Received But Not Billed - _TC": [0.0, 500.0], - "Expenses Included In Valuation - _TC": [0.0, 300.0] + "Stock Received But Not Billed - TCP1": [0.0, 500.0], + "Expenses Included In Valuation - TCP1": [0.0, 300.0] } - + else: expected_values = { stock_in_hand_account: [400.0, 0.0], fixed_asset_account: [400.0, 0.0], - "Stock Received But Not Billed - _TC": [0.0, 500.0], - "Expenses Included In Valuation - _TC": [0.0, 300.0] + "Stock Received But Not Billed - TCP1": [0.0, 500.0], + "Expenses Included In Valuation - TCP1": [0.0, 300.0] } for gle in gl_entries: self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][1], gle.credit) - set_perpetual_inventory(0) - + def test_landed_cost_voucher_against_purchase_invoice(self): - set_perpetual_inventory(1) - + pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), - posting_time=frappe.utils.nowtime()) + posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1", + company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", + warehouse= "Stores - TCP1", cost_center = "Main - TCP1", + expense_account ="_Test Account Cost for Goods Sold - TCP1") last_sle = frappe.db.get_value("Stock Ledger Entry", { "voucher_type": pi.doctype, "voucher_no": pi.name, "item_code": "_Test Item", - "warehouse": "_Test Warehouse - _TC" + "warehouse": "Stores - TCP1" }, fieldname=["qty_after_transaction", "stock_value"], as_dict=1) submit_landed_cost_voucher("Purchase Invoice", pi.name) - - pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name}, + + pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name}, "landed_cost_voucher_amount") - + self.assertEqual(pi_lc_value, 50.0) last_sle_after_landed_cost = frappe.db.get_value("Stock Ledger Entry", { "voucher_type": pi.doctype, "voucher_no": pi.name, "item_code": "_Test Item", - "warehouse": "_Test Warehouse - _TC" + "warehouse": "Stores - TCP1" }, fieldname=["qty_after_transaction", "stock_value"], as_dict=1) @@ -111,21 +112,21 @@ class TestLandedCostVoucher(unittest.TestCase): expected_values = { stock_in_hand_account: [300.0, 0.0], - "Creditors - _TC": [0.0, 250.0], - "Expenses Included In Valuation - _TC": [0.0, 50.0] + "Creditors - TCP1": [0.0, 250.0], + "Expenses Included In Valuation - TCP1": [0.0, 50.0] } for gle in gl_entries: self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][1], gle.credit) - set_perpetual_inventory(0) - - def test_landed_cost_voucher_for_serialized_item(self): - set_perpetual_inventory(1) - frappe.db.sql("delete from `tabSerial No` where name in ('SN001', 'SN002', 'SN003', 'SN004', 'SN005')") - pr = frappe.copy_doc(pr_test_records[0]) + def test_landed_cost_voucher_for_serialized_item(self): + frappe.db.sql("delete from `tabSerial No` where name in ('SN001', 'SN002', 'SN003', 'SN004', 'SN005')") + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", + supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, + get_taxes_and_charges = True, do_not_submit = True) + pr.items[0].item_code = "_Test Serialized Item" pr.items[0].serial_no = "SN001\nSN002\nSN003\nSN004\nSN005" pr.submit() @@ -138,39 +139,36 @@ class TestLandedCostVoucher(unittest.TestCase): ["warehouse", "purchase_rate"], as_dict=1) self.assertEqual(serial_no.purchase_rate - serial_no_rate, 5.0) - self.assertEqual(serial_no.warehouse, "_Test Warehouse - _TC") + self.assertEqual(serial_no.warehouse, "Stores - TCP1") - set_perpetual_inventory(0) def test_landed_cost_voucher_for_odd_numbers (self): - set_perpetual_inventory(1) - pr = make_purchase_receipt(do_not_save=True) - pr.items[0].cost_center = "_Test Company - _TC" + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", do_not_save=True) + pr.items[0].cost_center = "Main - TCP1" for x in range(2): pr.append("items", { "item_code": "_Test Item", - "warehouse": "_Test Warehouse - _TC", - "cost_center": "_Test Company - _TC", + "warehouse": "Stores - TCP1", + "cost_center": "Main - TCP1", "qty": 5, "rate": 50 }) pr.submit() lcv = submit_landed_cost_voucher("Purchase Receipt", pr.name, 123.22) - + self.assertEqual(lcv.items[0].applicable_charges, 41.07) - self.assertEqual(lcv.items[2].applicable_charges, 41.08) - - set_perpetual_inventory(0) + self.assertEqual(lcv.items[2].applicable_charges, 41.08) + def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=50): ref_doc = frappe.get_doc(receipt_document_type, receipt_document) - + lcv = frappe.new_doc("Landed Cost Voucher") lcv.company = "_Test Company" lcv.distribute_charges_based_on = 'Amount' - + lcv.set("purchase_receipts", [{ "receipt_document_type": receipt_document_type, "receipt_document": receipt_document, @@ -178,7 +176,7 @@ def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges= "posting_date": ref_doc.posting_date, "grand_total": ref_doc.base_grand_total }]) - + lcv.set("taxes", [{ "description": "Insurance Charges", "account": "_Test Account Insurance Charges - _TC", @@ -186,13 +184,13 @@ def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges= }]) lcv.insert() - + distribute_landed_cost_on_items(lcv) - + lcv.submit() return lcv - + def distribute_landed_cost_on_items(lcv): based_on = lcv.distribute_charges_based_on.lower() total = sum([flt(d.get(based_on)) for d in lcv.get("items")]) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index ab9311b480..e9ddf9d976 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -14,6 +14,7 @@ from erpnext.stock.doctype.item.test_item import make_item from six import iteritems class TestPurchaseReceipt(unittest.TestCase): def setUp(self): + set_perpetual_inventory(0) frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) def test_make_purchase_invoice(self): @@ -32,7 +33,6 @@ class TestPurchaseReceipt(unittest.TestCase): def test_purchase_receipt_no_gl_entry(self): company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(0, company) existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, "stock_value") @@ -52,33 +52,29 @@ class TestPurchaseReceipt(unittest.TestCase): self.assertFalse(get_gl_entries("Purchase Receipt", pr.name)) def test_purchase_receipt_gl_entry(self): - pr = frappe.copy_doc(test_records[0]) - set_perpetual_inventory(1, pr.company) + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True) self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1) - pr.insert() - pr.submit() gl_entries = get_gl_entries("Purchase Receipt", pr.name) self.assertTrue(gl_entries) - stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) - fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse) + stock_in_hand_account = get_inventory_account(pr.company, pr.items[0].warehouse) + fixed_asset_account = get_inventory_account(pr.company, pr.items[1].warehouse) if stock_in_hand_account == fixed_asset_account: expected_values = { stock_in_hand_account: [750.0, 0.0], - "Stock Received But Not Billed - _TC": [0.0, 500.0], - "Expenses Included In Valuation - _TC": [0.0, 250.0] + "Stock Received But Not Billed - TCP1": [0.0, 500.0], + "Expenses Included In Valuation - TCP1": [0.0, 250.0] } else: expected_values = { stock_in_hand_account: [375.0, 0.0], fixed_asset_account: [375.0, 0.0], - "Stock Received But Not Billed - _TC": [0.0, 500.0], - "Expenses Included In Valuation - _TC": [0.0, 250.0] + "Stock Received But Not Billed - TCP1": [0.0, 500.0], + "Expenses Included In Valuation - TCP1": [0.0, 250.0] } - for gle in gl_entries: self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][1], gle.credit) @@ -86,8 +82,6 @@ class TestPurchaseReceipt(unittest.TestCase): pr.cancel() self.assertFalse(get_gl_entries("Purchase Receipt", pr.name)) - set_perpetual_inventory(0, pr.company) - def test_subcontracting(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry @@ -132,11 +126,10 @@ class TestPurchaseReceipt(unittest.TestCase): pr.get("items")[0].rejected_warehouse) def test_purchase_return(self): - set_perpetual_inventory() - pr = make_purchase_receipt() + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1") - return_pr = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-2) + return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, qty=-2) # check sle outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", @@ -153,28 +146,28 @@ class TestPurchaseReceipt(unittest.TestCase): expected_values = { stock_in_hand_account: [0.0, 100.0], - "Stock Received But Not Billed - _TC": [100.0, 0.0], + "Stock Received But Not Billed - TCP1": [100.0, 0.0], } for gle in gl_entries: self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][1], gle.credit) - set_perpetual_inventory(0) def test_purchase_return_for_rejected_qty(self): - set_perpetual_inventory() + from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse - pr = make_purchase_receipt(received_qty=4, qty=2) + rejected_warehouse=get_warehouse(company = "_Test Company with perpetual inventory", abbr = " - TCP1", warehouse_name = "_Test Rejected Warehouse").name + print(rejected_warehouse) + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", received_qty=4, qty=2, rejected_warehouse=rejected_warehouse) - return_pr = make_purchase_receipt(is_return=1, return_against=pr.name, received_qty = -4, qty=-2) + return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, received_qty = -4, qty=-2, rejected_warehouse=rejected_warehouse) 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) def test_purchase_return_for_serialized_items(self): def _check_serial_no_values(serial_no, field_values): @@ -337,7 +330,6 @@ class TestPurchaseReceipt(unittest.TestCase): pr.cancel() serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or [] self.assertEquals(len(serial_nos), 0) - #frappe.db.sql("delete from `tabLocation") frappe.db.sql("delete from `tabAsset`") def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self): @@ -345,8 +337,8 @@ class TestPurchaseReceipt(unittest.TestCase): accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings') accounts_settings.allow_cost_center_in_entry_of_bs_account = 1 accounts_settings.save() - cost_center = "_Test Cost Center for BS Account - _TC" - create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company") + cost_center = "_Test Cost Center for BS Account - TCP1" + create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory") if not frappe.db.exists('Location', 'Test Location'): frappe.get_doc({ @@ -354,8 +346,7 @@ class TestPurchaseReceipt(unittest.TestCase): 'location_name': 'Test Location' }).insert() - set_perpetual_inventory(1, "_Test Company") - pr = make_purchase_receipt(cost_center=cost_center) + pr = make_purchase_receipt(cost_center=cost_center, company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1") stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) gl_entries = get_gl_entries("Purchase Receipt", pr.name) @@ -363,7 +354,7 @@ class TestPurchaseReceipt(unittest.TestCase): self.assertTrue(gl_entries) expected_values = { - "Stock Received But Not Billed - _TC": { + "Stock Received But Not Billed - TCP1": { "cost_center": cost_center }, stock_in_hand_account: { @@ -373,7 +364,6 @@ class TestPurchaseReceipt(unittest.TestCase): for i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) - set_perpetual_inventory(0, pr.company) accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.save() @@ -387,9 +377,7 @@ class TestPurchaseReceipt(unittest.TestCase): 'doctype': 'Location', 'location_name': 'Test Location' }).insert() - - set_perpetual_inventory(1, "_Test Company") - pr = make_purchase_receipt() + pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1") stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) gl_entries = get_gl_entries("Purchase Receipt", pr.name) @@ -397,7 +385,7 @@ class TestPurchaseReceipt(unittest.TestCase): self.assertTrue(gl_entries) expected_values = { - "Stock Received But Not Billed - _TC": { + "Stock Received But Not Billed - TCP1": { "cost_center": None }, stock_in_hand_account: { @@ -407,8 +395,6 @@ class TestPurchaseReceipt(unittest.TestCase): for i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) - set_perpetual_inventory(0, pr.company) - def test_make_purchase_invoice_from_pr_for_returned_qty(self): from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po @@ -452,6 +438,78 @@ def get_gl_entries(voucher_type, voucher_no): from `tabGL Entry` where voucher_type=%s and voucher_no=%s order by account desc""", (voucher_type, voucher_no), as_dict=1) +def get_taxes(**args): + + args = frappe._dict(args) + + return [{'account_head': '_Test Account Shipping Charges - TCP1', + 'add_deduct_tax': 'Add', + 'category': 'Valuation and Total', + 'charge_type': 'Actual', + 'cost_center': args.cost_center or 'Main - TCP1', + 'description': 'Shipping Charges', + 'doctype': 'Purchase Taxes and Charges', + 'parentfield': 'taxes', + 'rate': 100.0, + 'tax_amount': 100.0}, + {'account_head': '_Test Account VAT - TCP1', + 'add_deduct_tax': 'Add', + 'category': 'Total', + 'charge_type': 'Actual', + 'cost_center': args.cost_center or 'Main - TCP1', + 'description': 'VAT', + 'doctype': 'Purchase Taxes and Charges', + 'parentfield': 'taxes', + 'rate': 120.0, + 'tax_amount': 120.0}, + {'account_head': '_Test Account Customs Duty - TCP1', + 'add_deduct_tax': 'Add', + 'category': 'Valuation', + 'charge_type': 'Actual', + 'cost_center': args.cost_center or 'Main - TCP1', + 'description': 'Customs Duty', + 'doctype': 'Purchase Taxes and Charges', + 'parentfield': 'taxes', + 'rate': 150.0, + 'tax_amount': 150.0}] + +def get_items(**args): + args = frappe._dict(args) + return [{ + "base_amount": 250.0, + "conversion_factor": 1.0, + "description": "_Test Item", + "doctype": "Purchase Receipt Item", + "item_code": "_Test Item", + "item_name": "_Test Item", + "parentfield": "items", + "qty": 5.0, + "rate": 50.0, + "received_qty": 5.0, + "rejected_qty": 0.0, + "stock_uom": "_Test UOM", + "uom": "_Test UOM", + "warehouse": args.warehouse or "_Test Warehouse - _TC", + "cost_center": args.cost_center or "Main - _TC" + }, + { + "base_amount": 250.0, + "conversion_factor": 1.0, + "description": "_Test Item Home Desktop 100", + "doctype": "Purchase Receipt Item", + "item_code": "_Test Item Home Desktop 100", + "item_name": "_Test Item Home Desktop 100", + "parentfield": "items", + "qty": 5.0, + "rate": 50.0, + "received_qty": 5.0, + "rejected_qty": 0.0, + "stock_uom": "_Test UOM", + "uom": "_Test UOM", + "warehouse": args.warehouse or "_Test Warehouse 1 - _TC", + "cost_center": args.cost_center or "Main - _TC" + }] + def make_purchase_receipt(**args): if not frappe.db.exists('Location', 'Test Location'): frappe.get_doc({ @@ -468,7 +526,7 @@ def make_purchase_receipt(**args): pr.company = args.company or "_Test Company" pr.supplier = args.supplier or "_Test Supplier" pr.is_subcontracted = args.is_subcontracted or "No" - pr.supplier_warehouse = "_Test Warehouse 1 - _TC" + pr.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC" pr.currency = args.currency or "INR" pr.is_return = args.is_return pr.return_against = args.return_against @@ -492,6 +550,16 @@ def make_purchase_receipt(**args): "asset_location": args.location or "Test Location" }) + if args.get_multiple_items: + pr.items = [] + for item in get_items(warehouse= args.warehouse, cost_center = args.cost_center or frappe.get_cached_value('Company', pr.company, 'cost_center')): + pr.append("items", item) + + + if args.get_taxes_and_charges: + for tax in get_taxes(): + pr.append("taxes", tax) + if not args.do_not_save: pr.insert() if not args.do_not_submit: diff --git a/erpnext/stock/doctype/purchase_receipt/test_records.json b/erpnext/stock/doctype/purchase_receipt/test_records.json index 7c20991a1b..e7ea9af6b9 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_records.json +++ b/erpnext/stock/doctype/purchase_receipt/test_records.json @@ -83,39 +83,5 @@ } ], "supplier": "_Test Supplier" - }, - - - { - "buying_price_list": "_Test Price List", - "company": "_Test Company", - "conversion_rate": 1.0, - "currency": "INR", - "doctype": "Purchase Receipt", - "base_grand_total": 5000.0, - "is_subcontracted": "Yes", - "base_net_total": 5000.0, - "posting_date": "2013-02-12", - "items": [ - { - "base_amount": 5000.0, - "conversion_factor": 1.0, - "description": "_Test FG Item", - "doctype": "Purchase Receipt Item", - "item_code": "_Test FG Item", - "item_name": "_Test FG Item", - "parentfield": "items", - "qty": 10.0, - "rate": 500.0, - "received_qty": 10.0, - "rejected_qty": 0.0, - "stock_uom": "_Test UOM", - "uom": "_Test UOM", - "warehouse": "_Test Warehouse - _TC", - "cost_center": "Main - _TC" - } - ], - "supplier": "_Test Supplier", - "supplier_warehouse": "_Test Warehouse - _TC" } ] \ No newline at end of file diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.py b/erpnext/stock/doctype/serial_no/test_serial_no.py index ed70790b2c..ab061076e5 100644 --- a/erpnext/stock/doctype/serial_no/test_serial_no.py +++ b/erpnext/stock/doctype/serial_no/test_serial_no.py @@ -12,6 +12,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory test_dependencies = ["Item"] test_records = frappe.get_test_records('Serial No') @@ -37,6 +38,8 @@ class TestSerialNo(unittest.TestCase): self.assertTrue(SerialNoCannotCannotChangeError, sr.save) def test_inter_company_transfer(self): + set_perpetual_inventory(0, "_Test Company 1") + set_perpetual_inventory(0) se = make_serialized_item(target_warehouse="_Test Warehouse - _TC") serial_nos = get_serial_nos(se.get("items")[0].serial_no) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 3fa815dc82..941472bbf9 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -16,7 +16,6 @@ from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse, make_stock_in_entry from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError - from six import iteritems def get_sle(**args): @@ -132,20 +131,19 @@ class TestStockEntry(unittest.TestCase): self.assertTrue(item_code in items) def test_material_receipt_gl_entry(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') - mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", - qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") + mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company, + qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1") stock_in_hand_account = get_inventory_account(mr.company, mr.get("items")[0].t_warehouse) self.check_stock_ledger_entries("Stock Entry", mr.name, - [["_Test Item", "_Test Warehouse - _TC", 50.0]]) + [["_Test Item", "Stores - TCP1", 50.0]]) self.check_gl_entries("Stock Entry", mr.name, sorted([ [stock_in_hand_account, 5000.0, 0.0], - ["Stock Adjustment - _TC", 0.0, 5000.0] + ["Stock Adjustment - TCP1", 0.0, 5000.0] ]) ) @@ -158,29 +156,26 @@ class TestStockEntry(unittest.TestCase): where voucher_type='Stock Entry' and voucher_no=%s""", mr.name)) def test_material_issue_gl_entry(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') + make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company, + qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1") - make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", - qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") - - mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", - qty=40, expense_account="Stock Adjustment - _TC") + mi = make_stock_entry(item_code="_Test Item", source="Stores - TCP1", company=company, + qty=40, expense_account="Stock Adjustment - TCP1") self.check_stock_ledger_entries("Stock Entry", mi.name, - [["_Test Item", "_Test Warehouse - _TC", -40.0]]) + [["_Test Item", "Stores - TCP1", -40.0]]) - stock_in_hand_account = get_inventory_account(mi.company, "_Test Warehouse - _TC") + stock_in_hand_account = get_inventory_account(mi.company, "Stores - TCP1") stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", "voucher_no": mi.name}, "stock_value_difference")) self.check_gl_entries("Stock Entry", mi.name, sorted([ [stock_in_hand_account, 0.0, stock_value_diff], - ["Stock Adjustment - _TC", stock_value_diff, 0.0] + ["Stock Adjustment - TCP1", stock_value_diff, 0.0] ]) ) - mi.cancel() self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry` @@ -190,16 +185,15 @@ class TestStockEntry(unittest.TestCase): where voucher_type='Stock Entry' and voucher_no=%s""", mi.name)) def test_material_transfer_gl_entry(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') create_stock_reconciliation(qty=100, rate=100) - mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", - target="_Test Warehouse 1 - _TC", qty=45) + mtn = make_stock_entry(item_code="_Test Item", source="Stores - TCP1", + target="Finished Goods - TCP1", qty=45) self.check_stock_ledger_entries("Stock Entry", mtn.name, - [["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]]) + [["_Test Item", "Stores - TCP1", -45.0], ["_Test Item", "Finished Goods - TCP1", 45.0]]) stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse) @@ -212,7 +206,7 @@ class TestStockEntry(unittest.TestCase): else: stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", - "voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference")) + "voucher_no": mtn.name, "warehouse": "Stores - TCP1"}, "stock_value_difference")) self.check_gl_entries("Stock Entry", mtn.name, sorted([ @@ -255,14 +249,21 @@ class TestStockEntry(unittest.TestCase): set_perpetual_inventory(0, repack.company) def test_repack_with_additional_costs(self): - company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') - set_perpetual_inventory(1, company) + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') - make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) - repack = frappe.copy_doc(test_records[3]) + make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company, + qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1") + + + repack = make_stock_entry(company = company, purpose="Repack", do_not_save=True) repack.posting_date = nowdate() repack.posting_time = nowtime() + items = get_multiple_items() + repack.items = [] + for item in items: + repack.append("items", item) + repack.set("additional_costs", [ { "description": "Actual Oerating Cost", @@ -292,13 +293,12 @@ class TestStockEntry(unittest.TestCase): self.check_gl_entries("Stock Entry", repack.name, sorted([ [stock_in_hand_account, 1200, 0.0], - ["Expenses Included In Valuation - _TC", 0.0, 1200.0] + ["Expenses Included In Valuation - TCP1", 0.0, 1200.0] ]) ) - set_perpetual_inventory(0, repack.company) def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle): - expected_sle.sort(key=lambda x: x[0]) + expected_sle.sort(key=lambda x: x[1]) # check stock ledger entries sle = frappe.db.sql("""select item_code, warehouse, actual_qty @@ -306,7 +306,7 @@ class TestStockEntry(unittest.TestCase): and voucher_no = %s order by item_code, warehouse, actual_qty""", (voucher_type, voucher_no), as_list=1) self.assertTrue(sle) - sle.sort(key=lambda x: x[0]) + sle.sort(key=lambda x: x[1]) for i, sle in enumerate(sle): self.assertEqual(expected_sle[i][0], sle[0]) @@ -773,14 +773,12 @@ class TestStockEntry(unittest.TestCase): self.assertEqual(doc.per_transferred, 100) def test_gle_for_opening_stock_entry(self): - set_perpetual_inventory(1) - - mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", - qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC", is_opening="Yes", do_not_save=True) + mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True) self.assertRaises(OpeningEntryAccountError, mr.save) - mr.items[0].expense_account = "Temporary Opening - _TC" + mr.items[0].expense_account = "Temporary Opening - TCP1" + mr.save() mr.submit() @@ -805,14 +803,42 @@ def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None): def get_qty_after_transaction(**args): args = frappe._dict(args) - last_sle = get_previous_sle({ "item_code": args.item_code or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", "posting_date": args.posting_date or nowdate(), "posting_time": args.posting_time or nowtime() }) - return flt(last_sle.get("qty_after_transaction")) +def get_multiple_items(): + return [ + { + "conversion_factor": 1.0, + "cost_center": "Main - TCP1", + "doctype": "Stock Entry Detail", + "expense_account": "Stock Adjustment - TCP1", + "basic_rate": 100, + "item_code": "_Test Item", + "qty": 50.0, + "s_warehouse": "Stores - TCP1", + "stock_uom": "_Test UOM", + "transfer_qty": 50.0, + "uom": "_Test UOM" + }, + { + "conversion_factor": 1.0, + "cost_center": "Main - TCP1", + "doctype": "Stock Entry Detail", + "expense_account": "Stock Adjustment - TCP1", + "basic_rate": 5000, + "item_code": "_Test Item Home Desktop 100", + "qty": 1, + "stock_uom": "_Test UOM", + "t_warehouse": "Stores - TCP1", + "transfer_qty": 1, + "uom": "_Test UOM" + } + ] + test_records = frappe.get_test_records('Stock Entry') diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index cd05929743..e6d7e3fea7 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals import frappe, unittest from frappe.utils import flt, nowdate, nowtime -from erpnext.accounts.utils import get_stock_and_account_difference +from erpnext.accounts.utils import get_stock_and_account_balance from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items @@ -21,7 +21,6 @@ class TestStockReconciliation(unittest.TestCase): def setUpClass(self): create_batch_or_serial_no_items() frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - insert_existing_sle() def test_reco_for_fifo(self): self._test_reco_sle_gle("FIFO") @@ -30,7 +29,8 @@ class TestStockReconciliation(unittest.TestCase): self._test_reco_sle_gle("Moving Average") def _test_reco_sle_gle(self, valuation_method): - set_perpetual_inventory() + insert_existing_sle(warehouse='Stores - TCP1') + company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') # [[qty, valuation_rate, posting_date, # posting_time, expected_stock_value, bin_qty, bin_valuation]] input_data = [ @@ -46,14 +46,15 @@ class TestStockReconciliation(unittest.TestCase): last_sle = get_previous_sle({ "item_code": "_Test Item", - "warehouse": "_Test Warehouse - _TC", + "warehouse": "Stores - TCP1", "posting_date": d[2], "posting_time": d[3] }) # submit stock reconciliation stock_reco = create_stock_reconciliation(qty=d[0], rate=d[1], - posting_date=d[2], posting_time=d[3]) + posting_date=d[2], posting_time=d[3], warehouse="Stores - TCP1", + company=company, expense_account = "Stock Adjustment - TCP1") # check stock value sle = frappe.db.sql("""select * from `tabStock Ledger Entry` @@ -73,17 +74,18 @@ class TestStockReconciliation(unittest.TestCase): # no gl entries self.assertTrue(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) - self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"])) - stock_reco.cancel() + acc_bal, stock_bal, wh_list = get_stock_and_account_balance("Stock In Hand - TCP1", + stock_reco.posting_date, stock_reco.company) + self.assertEqual(acc_bal, stock_bal) - self.assertFalse(frappe.db.get_value("Stock Ledger Entry", - {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) + stock_reco.cancel() - self.assertFalse(frappe.db.get_value("GL Entry", - {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) + self.assertFalse(frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) - set_perpetual_inventory(0) + self.assertFalse(frappe.db.get_value("GL Entry", + {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) def test_get_items(self): create_warehouse("_Test Warehouse Group 1", {"is_group": 1}) @@ -203,17 +205,17 @@ class TestStockReconciliation(unittest.TestCase): stock_doc.cancel() -def insert_existing_sle(): +def insert_existing_sle(warehouse): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item", - target="_Test Warehouse - _TC", qty=10, basic_rate=700) + target=warehouse, qty=10, basic_rate=700) make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item", - source="_Test Warehouse - _TC", qty=15) + source=warehouse, qty=15) make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item", - target="_Test Warehouse - _TC", qty=15, basic_rate=1200) + target=warehouse, qty=15, basic_rate=1200) def create_batch_or_serial_no_items(): create_warehouse("_Test Warehouse for Stock Reco1", @@ -244,7 +246,10 @@ def create_stock_reconciliation(**args): sr.company = args.company or "_Test Company" sr.expense_account = args.expense_account or \ ("Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC") - sr.cost_center = args.cost_center or "_Test Cost Center - _TC" + sr.cost_center = args.cost_center \ + or frappe.get_cached_value("Company", sr.company, "cost_center") \ + or "_Test Cost Center - _TC" + sr.append("items", { "item_code": args.item_code or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", diff --git a/erpnext/stock/doctype/warehouse/test_records.json b/erpnext/stock/doctype/warehouse/test_records.json index 014cf3e501..e128558ed3 100644 --- a/erpnext/stock/doctype/warehouse/test_records.json +++ b/erpnext/stock/doctype/warehouse/test_records.json @@ -1,42 +1,36 @@ [ { "company": "_Test Company", - "create_account_under": "Stock Assets - _TC", "doctype": "Warehouse", "warehouse_name": "_Test Warehouse", "is_group": 0 }, { "company": "_Test Company", - "create_account_under": "Stock Assets - _TC", "doctype": "Warehouse", "warehouse_name": "_Test Scrap Warehouse", "is_group": 0 }, { "company": "_Test Company", - "create_account_under": "Fixed Assets - _TC", "doctype": "Warehouse", "warehouse_name": "_Test Warehouse 1", "is_group": 0 }, { "company": "_Test Company", - "create_account_under": "Fixed Assets - _TC", "doctype": "Warehouse", "warehouse_name": "_Test Warehouse 2", "is_group": 0 }, { "company": "_Test Company", - "create_account_under": "Stock Assets - _TC", "doctype": "Warehouse", "warehouse_name": "_Test Rejected Warehouse", "is_group": 0 }, { "company": "_Test Company 1", - "create_account_under": "Stock Assets - _TC1", "doctype": "Warehouse", "warehouse_name": "_Test Warehouse 2", "is_group": 0 diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py index dc39e101ce..121222d7bc 100644 --- a/erpnext/stock/doctype/warehouse/test_warehouse.py +++ b/erpnext/stock/doctype/warehouse/test_warehouse.py @@ -101,8 +101,7 @@ def create_warehouse(warehouse_name, properties=None, company=None): w.warehouse_name = warehouse_name w.parent_warehouse = "_Test Warehouse Group - _TC" w.company = company - make_account_for_warehouse(warehouse_name, w) - w.account = warehouse_id + w.account = get_warehouse_account(warehouse_name, company) if properties: w.update(properties) w.save() @@ -110,9 +109,40 @@ def create_warehouse(warehouse_name, properties=None, company=None): else: return warehouse_id -def make_account_for_warehouse(warehouse_name, warehouse_obj): - if not frappe.db.exists("Account", warehouse_name + " - _TC"): - parent_account = frappe.db.get_value('Account', - {'company': warehouse_obj.company, 'is_group':1, 'account_type': 'Stock'},'name') - account = create_account(account_name=warehouse_name, \ - account_type="Stock", parent_account= parent_account, company=warehouse_obj.company) \ No newline at end of file +def get_warehouse(**args): + args = frappe._dict(args) + if(frappe.db.exists("Warehouse", args.warehouse_name + " - " + args.abbr)): + return frappe.get_doc("Warehouse", args.warehouse_name + " - " + args.abbr) + else: + w = frappe.get_doc({ + "company": args.company or "_Test Company", + "doctype": "Warehouse", + "warehouse_name": args.warehouse_name, + "is_group": 0, + "account": get_warehouse_account(args.warehouse_name, args.company, args.abbr) + }) + w.insert() + return w + +def get_warehouse_account(warehouse_name, company, company_abbr=None): + if not company_abbr: + company_abbr = frappe.get_cached_value("Company", company, 'abbr') + + if not frappe.db.exists("Account", warehouse_name + " - " + company_abbr): + return create_account( + account_name=warehouse_name, + parent_account=get_group_stock_account(company, company_abbr), + account_type='Stock', + company=company) + else: + return warehouse_name + " - " + company_abbr + + +def get_group_stock_account(company, company_abbr=None): + group_stock_account = frappe.db.get_value("Account", + filters={'account_type': 'Stock', 'is_group': 1, 'company': company}, fieldname='name') + if not group_stock_account: + if not company_abbr: + company_abbr = frappe.get_cached_value("Company", company, 'abbr') + group_stock_account = "Current Assets - " + company_abbr + return group_stock_account \ No newline at end of file