From 7c9d00391741d3d56f8dcdff1f1cf1768bc088c5 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 13 Mar 2015 08:14:31 +0530 Subject: [PATCH] Test case cleanup and fixes --- .../journal_entry/test_journal_entry.py | 133 ++--- .../doctype/journal_entry/test_records.json | 6 +- .../doctype/payment_tool/test_payment_tool.py | 33 +- .../test_period_closing_voucher.py | 67 +-- .../period_closing_voucher/test_records.json | 8 - .../doctype/sales_invoice/test_records.json | 11 +- .../sales_invoice/test_sales_invoice.py | 65 ++- .../purchase_order/test_purchase_order.py | 131 +++-- .../production_order/test_records.json | 2 +- .../doctype/sales_order/test_sales_order.py | 425 ++++++---------- .../setup/page/setup_wizard/setup_wizard.py | 2 - .../page/setup_wizard/test_setup_data.py | 2 +- erpnext/setup/utils.py | 3 +- erpnext/shopping_cart/test_shopping_cart.py | 16 +- .../delivery_note/test_delivery_note.py | 247 +++++---- .../doctype/delivery_note/test_records.json | 10 +- erpnext/stock/doctype/item/test_item.py | 14 +- erpnext/stock/doctype/item/test_records.json | 9 + .../purchase_receipt/test_purchase_receipt.py | 108 ++-- .../purchase_receipt/test_records.json | 11 +- .../stock/doctype/stock_entry/stock_entry.py | 22 +- .../doctype/stock_entry/test_records.json | 11 +- .../doctype/stock_entry/test_stock_entry.py | 468 +++++++----------- .../test_stock_reconciliation.py | 330 ++++-------- 24 files changed, 864 insertions(+), 1270 deletions(-) delete mode 100644 erpnext/accounts/doctype/period_closing_voucher/test_records.json diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py index bd35d18f38..d4525a1ad9 100644 --- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py @@ -4,27 +4,26 @@ from __future__ import unicode_literals import unittest, frappe from frappe.utils import flt +from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year + class TestJournalEntry(unittest.TestCase): def test_journal_entry_with_against_jv(self): - jv_invoice = frappe.copy_doc(test_records[2]) base_jv = frappe.copy_doc(test_records[0]) self.jv_against_voucher_testcase(base_jv, jv_invoice) def test_jv_against_sales_order(self): - from erpnext.selling.doctype.sales_order.test_sales_order \ - import test_records as so_test_records + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order - sales_order = frappe.copy_doc(so_test_records[0]) + sales_order = make_sales_order(do_not_save=True) base_jv = frappe.copy_doc(test_records[0]) self.jv_against_voucher_testcase(base_jv, sales_order) def test_jv_against_purchase_order(self): - from erpnext.buying.doctype.purchase_order.test_purchase_order \ - import test_records as po_test_records + from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order - purchase_order = frappe.copy_doc(po_test_records[0]) + purchase_order = create_purchase_order(do_not_save=True) base_jv = frappe.copy_doc(test_records[1]) self.jv_against_voucher_testcase(base_jv, purchase_order) @@ -35,7 +34,6 @@ class TestJournalEntry(unittest.TestCase): 'Purchase Order': "against_purchase_order" } - self.clear_account_balance() test_voucher.insert() test_voucher.submit() @@ -104,88 +102,101 @@ class TestJournalEntry(unittest.TestCase): def test_monthly_budget_crossed_ignore(self): frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore") - self.clear_account_balance() - - jv = frappe.copy_doc(test_records[0]) - jv.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" - jv.get("accounts")[1].cost_center = "_Test Cost Center - _TC" - jv.get("accounts")[1].debit = 20000.0 - jv.get("accounts")[0].credit = 20000.0 - jv.insert() - jv.submit() + + existing_expense = self.get_actual_expense("2013-02-28") + current_expense = - existing_expense + 20000 if existing_expense < 0 else 20000 + + jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC", + "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC", submit=True) + self.assertTrue(frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})) def test_monthly_budget_crossed_stop(self): - from erpnext.accounts.utils import BudgetError frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop") - self.clear_account_balance() - - jv = frappe.copy_doc(test_records[0]) - jv.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" - jv.get("accounts")[1].cost_center = "_Test Cost Center - _TC" - jv.get("accounts")[1].debit = 20000.0 - jv.get("accounts")[0].credit = 20000.0 - jv.insert() - + + existing_expense = self.get_actual_expense("2013-02-28") + current_expense = - existing_expense + 20000 if existing_expense < 0 else 20000 + + jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC", + "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC") + self.assertRaises(BudgetError, jv.submit) frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore") def test_yearly_budget_crossed_stop(self): - from erpnext.accounts.utils import BudgetError - self.clear_account_balance() self.test_monthly_budget_crossed_ignore() frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Stop") + + existing_expense = self.get_actual_expense("2013-02-28") + current_expense = - existing_expense + 150000 if existing_expense < 0 else 150000 - jv = frappe.copy_doc(test_records[0]) - jv.posting_date = "2013-08-12" - jv.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" - jv.get("accounts")[1].cost_center = "_Test Cost Center - _TC" - jv.get("accounts")[1].debit = 150000.0 - jv.get("accounts")[0].credit = 150000.0 - jv.insert() - + jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC", + "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC") + self.assertRaises(BudgetError, jv.submit) frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Ignore") def test_monthly_budget_on_cancellation(self): - from erpnext.accounts.utils import BudgetError frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop") - self.clear_account_balance() - - jv = frappe.copy_doc(test_records[0]) - jv.get("accounts")[0].update({ - "account": "_Test Account Cost for Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC", - "party_type": None, - "party": None, - "credit": 30000.0 - }) - jv.get("accounts")[1].debit = 30000.0 - jv.submit() + existing_expense = self.get_actual_expense("2013-02-28") + current_expense = - existing_expense - 30000 if existing_expense < 0 else 30000 + + jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC", + "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC", submit=True) + self.assertTrue(frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})) - jv1 = frappe.copy_doc(test_records[0]) - jv1.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" - jv1.get("accounts")[1].cost_center = "_Test Cost Center - _TC" - jv1.get("accounts")[1].debit = 40000.0 - jv1.get("accounts")[0].credit = 40000.0 - jv1.submit() - + jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC", + "_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC", submit=True) + self.assertTrue(frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv1.name})) self.assertRaises(BudgetError, jv.cancel) frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore") - - def clear_account_balance(self): - frappe.db.sql("""delete from `tabGL Entry`""") - + + def get_actual_expense(self, monthly_end_date): + return get_actual_expense({ + "account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", + "monthly_end_date": monthly_end_date, + "company": "_Test Company", + "fiscal_year": get_fiscal_year(monthly_end_date)[0] + }) + +def make_journal_entry(account1, account2, amount, cost_center=None, submit=False): + jv = frappe.new_doc("Journal Entry") + jv.posting_date = "2013-02-14" + jv.company = "_Test Company" + jv.fiscal_year = "_Test Fiscal Year 2013" + jv.user_remark = "test" + + jv.set("accounts", [ + { + "account": account1, + "cost_center": cost_center, + "debit": amount if amount > 0 else 0, + "credit": abs(amount) if amount < 0 else 0, + }, { + "account": account2, + "cost_center": cost_center, + "credit": amount if amount > 0 else 0, + "debit": abs(amount) if amount < 0 else 0, + } + ]) + jv.insert() + + if submit: + jv.submit() + + return jv + test_records = frappe.get_test_records('Journal Entry') diff --git a/erpnext/accounts/doctype/journal_entry/test_records.json b/erpnext/accounts/doctype/journal_entry/test_records.json index 01745c54e6..f6608638e0 100644 --- a/erpnext/accounts/doctype/journal_entry/test_records.json +++ b/erpnext/accounts/doctype/journal_entry/test_records.json @@ -1,6 +1,6 @@ [ { - "cheque_date": "2013-02-14", + "cheque_date": "2013-03-14", "cheque_no": "33", "company": "_Test Company", "doctype": "Journal Entry", @@ -28,6 +28,8 @@ "user_remark": "test", "voucher_type": "Bank Entry" }, + + { "cheque_date": "2013-02-14", "cheque_no": "33", @@ -57,6 +59,8 @@ "user_remark": "test", "voucher_type": "Bank Entry" }, + + { "cheque_date": "2013-02-14", "cheque_no": "33", diff --git a/erpnext/accounts/doctype/payment_tool/test_payment_tool.py b/erpnext/accounts/doctype/payment_tool/test_payment_tool.py index da8508c15e..a4ff33331a 100644 --- a/erpnext/accounts/doctype/payment_tool/test_payment_tool.py +++ b/erpnext/accounts/doctype/payment_tool/test_payment_tool.py @@ -4,33 +4,26 @@ from __future__ import unicode_literals import unittest, frappe, json from frappe.utils import flt +from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order +from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import test_records as si_test_records +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import test_records as pi_test_records +from erpnext.accounts.doctype.journal_entry.test_journal_entry import test_records as jv_test_records test_dependencies = ["Item"] class TestPaymentTool(unittest.TestCase): def test_make_journal_entry(self): - from erpnext.accounts.doctype.journal_entry.test_journal_entry \ - import test_records as jv_test_records - from erpnext.selling.doctype.sales_order.test_sales_order \ - import test_records as so_test_records - from erpnext.buying.doctype.purchase_order.test_purchase_order \ - import test_records as po_test_records - from erpnext.accounts.doctype.sales_invoice.test_sales_invoice \ - import test_records as si_test_records - from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice \ - import test_records as pi_test_records - self.clear_table_entries() + frappe.db.set_default("currency", "INR") base_customer_jv = self.create_against_jv(jv_test_records[2], { "party": "_Test Customer 3"}) base_supplier_jv = self.create_against_jv(jv_test_records[1], { "party": "_Test Supplier 1"}) # Create SO with partial outstanding - so1 = self.create_voucher(so_test_records[0], { - "customer": "_Test Customer 3" - }) - + so1 = make_sales_order(customer="_Test Customer 3", qty=10, rate=100) + self.create_against_jv(jv_test_records[0], { "party": "_Test Customer 3", "against_sales_order": so1.name, @@ -39,9 +32,7 @@ class TestPaymentTool(unittest.TestCase): #Create SO with no outstanding - so2 = self.create_voucher(so_test_records[0], { - "customer": "_Test Customer 3" - }) + so2 = make_sales_order(customer="_Test Customer 3") self.create_against_jv(jv_test_records[0], { "party": "_Test Customer 3", @@ -51,9 +42,7 @@ class TestPaymentTool(unittest.TestCase): }) # Purchase order - po = self.create_voucher(po_test_records[1], { - "supplier": "_Test Supplier 1" - }) + po = create_purchase_order(supplier="_Test Supplier 1") #Create SI with partial outstanding si1 = self.create_voucher(si_test_records[0], { @@ -136,7 +125,7 @@ class TestPaymentTool(unittest.TestCase): def make_voucher_for_party(self, args, expected_outstanding): #Make Journal Entry for Party payment_tool_doc = frappe.new_doc("Payment Tool") - + for k, v in args.items(): payment_tool_doc.set(k, v) diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index 2477b10245..afff47fd40 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -5,43 +5,48 @@ from __future__ import unicode_literals import unittest import frappe -from erpnext.accounts.doctype.journal_entry.test_journal_entry import test_records as jv_records +from frappe.utils import flt +from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry class TestPeriodClosingVoucher(unittest.TestCase): def test_closing_entry(self): - # clear GL Entries - frappe.db.sql("""delete from `tabGL Entry`""") - jv = frappe.copy_doc(jv_records[2]) - jv.insert() - jv.submit() + make_journal_entry("_Test Account Bank Account - _TC", "Sales - _TC", 400, + "_Test Cost Center - _TC", submit=True) + + make_journal_entry("_Test Account Cost for Goods Sold - _TC", + "_Test Account Bank Account - _TC", 600, "_Test Cost Center - _TC", submit=True) + + profit_or_loss = frappe.db.sql("""select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance + from `tabGL Entry` t1, `tabAccount` t2 + where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss' + and t2.docstatus < 2 and t2.company = '_Test Company' + and t1.posting_date between '2013-01-01' and '2013-12-31'""") + + profit_or_loss = flt(profit_or_loss[0][0]) if profit_or_loss else 0 + + pcv = self.make_period_closing_voucher() + + gle_value = frappe.db.sql("""select ifnull(debit, 0) - ifnull(credit, 0) + from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s + and account = '_Test Account Reserves and Surplus - _TC'""", pcv.name) + + gle_value = flt(gle_value[0][0]) if gle_value else 0 - jv1 = frappe.copy_doc(jv_records[0]) - jv1.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" - jv1.get("accounts")[1].cost_center = "_Test Cost Center - _TC" - jv1.get("accounts")[1].debit = 600.0 - jv1.get("accounts")[0].credit = 600.0 - jv1.insert() - jv1.submit() - - pcv = frappe.copy_doc(test_records[0]) + self.assertEqual(gle_value, profit_or_loss) + + def make_period_closing_voucher(self): + pcv = frappe.get_doc({ + "doctype": "Period Closing Voucher", + "closing_account_head": "_Test Account Reserves and Surplus - _TC", + "company": "_Test Company", + "fiscal_year": "_Test Fiscal Year 2013", + "posting_date": "2013-12-31", + "remarks": "test" + }) pcv.insert() pcv.submit() - - gl_entries = frappe.db.sql("""select account, debit, credit - from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s - order by account asc, debit asc""", pcv.name, as_dict=1) - - self.assertTrue(gl_entries) - - expected_gl_entries = sorted([ - ["_Test Account Reserves and Surplus - _TC", 200.0, 0.0], - ["_Test Account Cost for Goods Sold - _TC", 0.0, 600.0], - ["Sales - _TC", 400.0, 0.0] - ]) - for i, gle in enumerate(gl_entries): - self.assertEquals(expected_gl_entries[i][0], gle.account) - self.assertEquals(expected_gl_entries[i][1], gle.debit) - self.assertEquals(expected_gl_entries[i][2], gle.credit) + + return pcv test_dependencies = ["Customer", "Cost Center"] diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_records.json b/erpnext/accounts/doctype/period_closing_voucher/test_records.json deleted file mode 100644 index d21948f674..0000000000 --- a/erpnext/accounts/doctype/period_closing_voucher/test_records.json +++ /dev/null @@ -1,8 +0,0 @@ -[{ - "doctype": "Period Closing Voucher", - "closing_account_head": "_Test Account Reserves and Surplus - _TC", - "company": "_Test Company", - "fiscal_year": "_Test Fiscal Year 2013", - "posting_date": "2013-03-31", - "remarks": "test" -}] diff --git a/erpnext/accounts/doctype/sales_invoice/test_records.json b/erpnext/accounts/doctype/sales_invoice/test_records.json index 7726835967..f0164b5fc8 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_records.json +++ b/erpnext/accounts/doctype/sales_invoice/test_records.json @@ -7,7 +7,6 @@ "customer_name": "_Test Customer", "debit_to": "_Test Receivable - _TC", "doctype": "Sales Invoice", - "due_date": "2013-01-23", "items": [ { "amount": 500.0, @@ -49,7 +48,6 @@ } ], "plc_conversion_rate": 1.0, - "posting_date": "2013-01-23", "price_list_currency": "INR", "sales_team": [ { @@ -68,6 +66,8 @@ "selling_price_list": "_Test Price List", "territory": "_Test Territory" }, + + { "company": "_Test Company", "conversion_rate": 1.0, @@ -76,7 +76,6 @@ "customer_name": "_Test Customer", "debit_to": "_Test Receivable - _TC", "doctype": "Sales Invoice", - "due_date": "2013-03-07", "items": [ { "amount": 500.0, @@ -94,7 +93,6 @@ "qty": 1.0 } ], - "fiscal_year": "_Test Fiscal Year 2013", "base_grand_total": 630.0, "grand_total": 630.0, "is_pos": 0, @@ -119,7 +117,6 @@ } ], "plc_conversion_rate": 1.0, - "posting_date": "2013-03-07", "price_list_currency": "INR", "selling_price_list": "_Test Price List", "territory": "_Test Territory" @@ -132,7 +129,6 @@ "customer_name": "_Test Customer", "debit_to": "_Test Receivable - _TC", "doctype": "Sales Invoice", - "due_date": "2013-01-23", "items": [ { "cost_center": "_Test Cost Center - _TC", @@ -245,7 +241,6 @@ } ], "plc_conversion_rate": 1.0, - "posting_date": "2013-01-23", "price_list_currency": "INR", "selling_price_list": "_Test Price List", "territory": "_Test Territory" @@ -258,7 +253,6 @@ "customer_name": "_Test Customer", "debit_to": "_Test Receivable - _TC", "doctype": "Sales Invoice", - "due_date": "2013-01-23", "items": [ { "cost_center": "_Test Cost Center - _TC", @@ -382,7 +376,6 @@ } ], "plc_conversion_rate": 1.0, - "posting_date": "2013-01-23", "price_list_currency": "INR", "selling_price_list": "_Test Price List", "territory": "_Test Territory" diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 5c6f75de1e..fc4ca214a8 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3,8 +3,7 @@ from __future__ import unicode_literals import frappe -import unittest, json, copy -from frappe.utils import flt +import unittest, copy from erpnext.accounts.utils import get_stock_and_account_difference from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.projects.doctype.time_log_batch.test_time_log_batch import * @@ -93,8 +92,8 @@ class TestSalesInvoice(unittest.TestCase): expected_values = { "keys": ["price_list_rate", "discount_percentage", "rate", "amount", "base_price_list_rate", "base_rate", "base_amount"], - "_Test Item Home Desktop 100": [50, 0, 50, 500, 2500, 2500, 25000], - "_Test Item Home Desktop 200": [150, 0, 150, 750, 7500, 7500, 37500], + "_Test Item Home Desktop 100": [1, 0, 1, 10, 50, 50, 500], + "_Test Item Home Desktop 200": [3, 0, 3, 15, 150, 150, 750], } # check if children are saved @@ -106,8 +105,10 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(d.get(k), expected_values[d.item_code][i]) # check net total - self.assertEquals(si.net_total, 1250) - self.assertEquals(si.base_net_total, 62500) + self.assertEquals(si.total, 25) + self.assertEquals(si.base_total, 1250) + self.assertEquals(si.net_total, 25) + self.assertEquals(si.base_net_total, 1250) # check tax calculation expected_values = { @@ -385,7 +386,6 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(w.outstanding_amount, w.base_grand_total) def test_payment(self): - frappe.db.sql("""delete from `tabGL Entry`""") w = self.make() from erpnext.accounts.doctype.journal_entry.test_journal_entry \ @@ -396,12 +396,10 @@ class TestSalesInvoice(unittest.TestCase): jv.insert() jv.submit() - self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), - 161.8) + self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 161.8) jv.cancel() - self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), - 561.8) + self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8) def test_time_log_batch(self): delete_time_log_and_batch() @@ -430,7 +428,6 @@ class TestSalesInvoice(unittest.TestCase): delete_time_log_and_batch() def test_sales_invoice_gl_entry_without_aii(self): - self.clear_stock_account_balance() set_perpetual_inventory(0) si = frappe.copy_doc(test_records[1]) si.insert() @@ -463,7 +460,6 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) def test_pos_gl_entry_with_aii(self): - self.clear_stock_account_balance() set_perpetual_inventory() self.make_pos_setting() @@ -501,8 +497,8 @@ class TestSalesInvoice(unittest.TestCase): [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], - [stock_in_hand, 0.0, 75.0], - [pos["items"][0]["expense_account"], 75.0, 0.0], + [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, 600.0], ["_Test Account Bank Account - _TC", 600.0, 0.0] ]) @@ -545,7 +541,6 @@ class TestSalesInvoice(unittest.TestCase): pos_setting.insert() def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): - self.clear_stock_account_balance() set_perpetual_inventory() frappe.delete_doc("Account", "_Test Warehouse No Account - _TC") @@ -600,7 +595,6 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) def test_sales_invoice_gl_entry_with_aii_no_item_code(self): - self.clear_stock_account_balance() set_perpetual_inventory() si = frappe.get_doc(test_records[1]) @@ -627,7 +621,6 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): - self.clear_stock_account_balance() set_perpetual_inventory() si = frappe.get_doc(test_records[1]) si.get("items")[0].item_code = "_Test Non Stock Item" @@ -705,14 +698,8 @@ class TestSalesInvoice(unittest.TestCase): def test_recurring_invoice(self): from erpnext.controllers.tests.test_recurring_document import test_recurring_document - test_recurring_document(self, test_records) - def clear_stock_account_balance(self): - frappe.db.sql("delete from `tabStock Ledger Entry`") - frappe.db.sql("delete from tabBin") - frappe.db.sql("delete from `tabGL Entry`") - def test_serialized(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos @@ -766,6 +753,36 @@ class TestSalesInvoice(unittest.TestCase): si.insert() self.assertRaises(SerialNoStatusError, si.submit) + +def create_sales_invoice(**args): + si = frappe.new_doc("Sales Invoice") + args = frappe._dict(args) + if args.posting_date: + si.posting_date = args.posting_date + if args.posting_time: + si.posting_time = args.posting_time + + si.company = args.company or "_Test Company" + si.customer = args.customer or "_Test Customer" + si.debit_to = args.debit_to or "Debtors - _TC" + si.update_stock = args.update_stock + si.is_pos = args.is_pos + + si.append("items", { + "item_code": args.item or args.item_code or "_Test Item", + "warehouse": args.warehouse or "_Test Warehouse - _TC", + "qty": args.qty or 1, + "rate": args.rate or 100, + "expense_account": "Cost of Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", + "serial_no": args.serial_no + }) + + if not args.do_not_save: + si.insert() + if not args.do_not_submit: + si.submit() + return si test_dependencies = ["Journal Entry", "Contact", "Address"] test_records = frappe.get_test_records('Sales Invoice') diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index e78a01f844..f68f814ce3 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -5,119 +5,106 @@ from __future__ import unicode_literals import unittest import frappe import frappe.defaults -from frappe.utils import flt +from frappe.utils import flt, add_days, nowdate +from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt, make_purchase_invoice class TestPurchaseOrder(unittest.TestCase): def test_make_purchase_receipt(self): - from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt - - po = frappe.copy_doc(test_records[0]).insert() - - self.assertRaises(frappe.ValidationError, make_purchase_receipt, - po.name) - - po = frappe.get_doc("Purchase Order", po.name) + po = create_purchase_order(do_not_submit=True) + self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name) po.submit() - pr = make_purchase_receipt(po.name) - pr.supplier_warehouse = "_Test Warehouse 1 - _TC" - pr.posting_date = "2013-05-12" - self.assertEquals(pr.doctype, "Purchase Receipt") - self.assertEquals(len(pr.get("items")), len(test_records[0]["items"])) - - pr.naming_series = "_T-Purchase Receipt-" - frappe.get_doc(pr).insert() + pr = create_pr_against_po(po.name) + self.assertEquals(len(pr.get("items")), 1) def test_ordered_qty(self): - existing_ordered_qty = self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC") - from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt - - po = frappe.copy_doc(test_records[0]).insert() - + existing_ordered_qty = get_ordered_qty() + + po = create_purchase_order(do_not_submit=True) self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name) - - po = frappe.get_doc("Purchase Order", po.name) - po.is_subcontracted = "No" - po.get("items")[0].item_code = "_Test Item" + po.submit() + self.assertEqual(get_ordered_qty(), existing_ordered_qty + 10) - self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 10) - - pr = make_purchase_receipt(po.name) - - self.assertEquals(pr.doctype, "Purchase Receipt") - self.assertEquals(len(pr.get("items", [])), len(test_records[0]["items"])) - pr.posting_date = "2013-05-12" - pr.naming_series = "_T-Purchase Receipt-" - pr.items[0].qty = 4.0 - pr.insert() - pr.submit() - + create_pr_against_po(po.name) + self.assertEqual(get_ordered_qty(), existing_ordered_qty + 6) + po.load_from_db() self.assertEquals(po.get("items")[0].received_qty, 4) - self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 6) frappe.db.set_value('Item', '_Test Item', 'tolerance', 50) - pr1 = make_purchase_receipt(po.name) - pr1.naming_series = "_T-Purchase Receipt-" - pr1.posting_date = "2013-05-12" - pr1.get("items")[0].qty = 8 - pr1.insert() - pr1.submit() - + pr = create_pr_against_po(po.name, received_qty=8) + self.assertEqual(get_ordered_qty(), existing_ordered_qty) + po.load_from_db() self.assertEquals(po.get("items")[0].received_qty, 12) - self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty) - - pr1.load_from_db() - pr1.cancel() + pr.cancel() + self.assertEqual(get_ordered_qty(), existing_ordered_qty + 6) + po.load_from_db() self.assertEquals(po.get("items")[0].received_qty, 4) - self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 6) def test_make_purchase_invoice(self): - from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_invoice + po = create_purchase_order(do_not_submit=True) - po = frappe.copy_doc(test_records[0]).insert() + self.assertRaises(frappe.ValidationError, make_purchase_invoice, po.name) - self.assertRaises(frappe.ValidationError, make_purchase_invoice, - po.name) - - po = frappe.get_doc("Purchase Order", po.name) po.submit() pi = make_purchase_invoice(po.name) self.assertEquals(pi.doctype, "Purchase Invoice") - self.assertEquals(len(pi.get("items", [])), len(test_records[0]["items"])) - - pi.credit_to = "_Test Payable - _TC" - pi.posting_date = "2013-05-12" - pi.bill_no = "NA" - frappe.get_doc(pi).insert() + self.assertEquals(len(pi.get("items", [])), 1) def test_subcontracting(self): - po = frappe.copy_doc(test_records[0]) - po.insert() + po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes") self.assertEquals(len(po.get("supplied_items")), 2) def test_warehouse_company_validation(self): from erpnext.stock.utils import InvalidWarehouseCompany - po = frappe.copy_doc(test_records[0]) - po.company = "_Test Company 1" - po.conversion_rate = 0.0167 + po = create_purchase_order(company="_Test Company 1", do_not_save=True) self.assertRaises(InvalidWarehouseCompany, po.insert) def test_uom_integer_validation(self): from erpnext.utilities.transaction_base import UOMMustBeIntegerError - po = frappe.copy_doc(test_records[0]) - po.get("items")[0].qty = 3.4 + po = create_purchase_order(qty=3.4, do_not_save=True) self.assertRaises(UOMMustBeIntegerError, po.insert) - def _get_ordered_qty(self, item_code, warehouse): - return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "ordered_qty")) +def create_purchase_order(**args): + po = frappe.new_doc("Purchase Order") + args = frappe._dict(args) + if args.transaction_date: + po.transaction_date = args.transaction_date + po.company = args.company or "_Test Company" + po.supplier = args.customer or "_Test Supplier" + po.is_subcontracted = args.is_subcontracted or "No" + + po.append("items", { + "item_code": args.item or args.item_code or "_Test Item", + "warehouse": args.warehouse or "_Test Warehouse - _TC", + "qty": args.qty or 10, + "rate": args.rate or 500, + "schedule_date": add_days(nowdate(), 1) + }) + if not args.do_not_save: + po.insert() + if not args.do_not_submit: + po.submit() + + return po + +def create_pr_against_po(po, received_qty=4): + pr = make_purchase_receipt(po) + pr.get("items")[0].qty = received_qty + pr.insert() + pr.submit() + return pr + +def get_ordered_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"): + return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, + "ordered_qty")) test_dependencies = ["BOM", "Item Price"] diff --git a/erpnext/manufacturing/doctype/production_order/test_records.json b/erpnext/manufacturing/doctype/production_order/test_records.json index d6afc065f1..e744e3b000 100644 --- a/erpnext/manufacturing/doctype/production_order/test_records.json +++ b/erpnext/manufacturing/doctype/production_order/test_records.json @@ -6,7 +6,7 @@ "fg_warehouse": "_Test Warehouse 1 - _TC", "production_item": "_Test FG Item", "qty": 10.0, - "stock_uom": "Nos", + "stock_uom": "_Test UOM", "wip_warehouse": "_Test Warehouse - _TC" } ] \ No newline at end of file diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 696aafe98d..4e78555635 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -1,342 +1,190 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals - import frappe -from frappe.utils import flt +from frappe.utils import flt, add_days import frappe.permissions import unittest -import copy +from erpnext.selling.doctype.sales_order.sales_order \ + import make_material_request, make_delivery_note, make_sales_invoice class TestSalesOrder(unittest.TestCase): def tearDown(self): frappe.set_user("Administrator") def test_make_material_request(self): - from erpnext.selling.doctype.sales_order.sales_order import make_material_request + so = make_sales_order(do_not_submit=True) - so = frappe.copy_doc(test_records[0]).insert() + self.assertRaises(frappe.ValidationError, make_material_request, so.name) - self.assertRaises(frappe.ValidationError, make_material_request, - so.name) - - sales_order = frappe.get_doc("Sales Order", so.name) - sales_order.submit() + so.submit() mr = make_material_request(so.name) self.assertEquals(mr.material_request_type, "Purchase") - self.assertEquals(len(mr.get("items")), len(sales_order.get("items"))) + self.assertEquals(len(mr.get("items")), len(so.get("items"))) def test_make_delivery_note(self): - from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note + so = make_sales_order(do_not_submit=True) - so = frappe.copy_doc(test_records[0]).insert() + self.assertRaises(frappe.ValidationError, make_delivery_note, so.name) - self.assertRaises(frappe.ValidationError, make_delivery_note, - so.name) - - dn = self.make_next_doc_testcase(so, "Delivery Note") + so.submit() + dn = make_delivery_note(so.name) self.assertEquals(dn.doctype, "Delivery Note") self.assertEquals(len(dn.get("items")), len(so.get("items"))) def test_make_sales_invoice(self): - from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice + so = make_sales_order(do_not_submit=True) - so = frappe.copy_doc(test_records[0]).insert() + self.assertRaises(frappe.ValidationError, make_sales_invoice, so.name) - self.assertRaises(frappe.ValidationError, make_sales_invoice, - so.name) + so.submit() + si = make_sales_invoice(so.name) - si = self.make_next_doc_testcase(so, "Sales Invoice") - - self.assertEquals(si.doctype, "Sales Invoice") self.assertEquals(len(si.get("items")), len(so.get("items"))) self.assertEquals(len(si.get("items")), 1) - si.set("debit_to", "_Test Receivable - _TC") - si.set("posting_date", "2013-10-10") si.insert() si.submit() - si1 = self.make_next_doc_testcase(so, "Sales Invoice") + si1 = make_sales_invoice(so.name) self.assertEquals(len(si1.get("items")), 0) def test_update_qty(self): - so = frappe.copy_doc(test_records[0]).insert() + so = make_sales_order() - dn = self.make_next_doc_testcase(so, "Delivery Note") + create_dn_against_so(so.name, 6) - dn.get("items")[0].qty = 6 - dn.posting_date = "2013-10-10" - dn.insert() + so.load_from_db() + self.assertEquals(so.get("items")[0].delivered_qty, 6) - delivery_note = frappe.get_doc("Delivery Note", dn.name) - delivery_note.submit() - - sales_order = frappe.get_doc("Sales Order", so.name) - - self.assertEquals(sales_order.get("items")[0].delivered_qty, 6) - - #Check delivered_qty after make_sales_invoice without update_stock checked - si1 = self.make_next_doc_testcase(sales_order, "Sales Invoice") - - si1.set("debit_to", "_Test Receivable - _TC") - si1.set("posting_date", "2013-10-10") - si1.get("items")[0].qty = 1 + # Check delivered_qty after make_sales_invoice without update_stock checked + si1 = make_sales_invoice(so.name) + si1.get("items")[0].qty = 6 si1.insert() si1.submit() - sales_order = frappe.get_doc("Sales Order", sales_order.name) + so.load_from_db() + self.assertEquals(so.get("items")[0].delivered_qty, 6) - self.assertEquals(sales_order.get("items")[0].delivered_qty, 6) - - #Check delivered_qty after make_sales_invoice with update_stock checked - si2 = self.make_next_doc_testcase(sales_order, "Sales Invoice") - - si2.set("debit_to", "_Test Receivable - _TC") - si2.set("posting_date", "2013-10-10") + # Check delivered_qty after make_sales_invoice with update_stock checked + si2 = make_sales_invoice(so.name) si2.set("update_stock", 1) si2.get("items")[0].qty = 3 si2.insert() si2.submit() - sales_order = frappe.get_doc("Sales Order", sales_order.name) - - self.assertEquals(sales_order.get("items")[0].delivered_qty, 9) - - def make_next_doc_testcase(self, so, next_doc = None): - - if so.docstatus < 1: - so.submit() - - if next_doc == "Delivery Note": - from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note - next_doc = make_delivery_note(so.name) - - if next_doc == "Sales Invoice": - from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice - next_doc = make_sales_invoice(so.name) - - return next_doc - - def create_so(self, so_doc = None): - if not so_doc: - so_doc = test_records[0] - - w = frappe.copy_doc(so_doc) - w.insert() - w.submit() - - return w - - def create_dn_against_so(self, so, delivered_qty=0): - from erpnext.stock.doctype.delivery_note.test_delivery_note import test_records as dn_test_records - from erpnext.stock.doctype.delivery_note.test_delivery_note import _insert_purchase_receipt - - _insert_purchase_receipt(so.get("items")[0].item_code) - - dn = frappe.get_doc(frappe.copy_doc(dn_test_records[0])) - dn.get("items")[0].item_code = so.get("items")[0].item_code - dn.get("items")[0].against_sales_order = so.name - dn.get("items")[0].so_detail = so.get("items")[0].name - if delivered_qty: - dn.get("items")[0].qty = delivered_qty - dn.insert() - dn.submit() - return dn - - def get_bin_reserved_qty(self, item_code, warehouse): - return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, - "reserved_qty")) - - def delete_bin(self, item_code, warehouse): - bin = frappe.db.exists({"doctype": "Bin", "item_code": item_code, - "warehouse": warehouse}) - if bin: - frappe.delete_doc("Bin", bin[0][0]) - - def check_reserved_qty(self, item_code, warehouse, qty): - bin_reserved_qty = self.get_bin_reserved_qty(item_code, warehouse) - self.assertEqual(bin_reserved_qty, qty) - - def test_reserved_qty_for_so(self): - # reset bin - so_item = test_records[0]["items"][0].copy() - self.delete_bin(so_item["item_code"], so_item["warehouse"]) - - # submit - so = self.create_so() - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 10.0) - - # cancel - so.cancel() - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 0.0) - + so.load_from_db() + self.assertEquals(so.get("items")[0].delivered_qty, 9) def test_reserved_qty_for_partial_delivery(self): - # reset bin - so_item = test_records[0]["items"][0].copy() - self.delete_bin(so_item["item_code"], so_item["warehouse"]) + existing_reserved_qty = get_reserved_qty() + + so = make_sales_order() + self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) - # submit so - so = self.create_so() - - # allow negative stock - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - - # submit dn - dn = self.create_dn_against_so(so) - - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 5.0) + dn = create_dn_against_so(so.name) + self.assertEqual(get_reserved_qty(), existing_reserved_qty + 5) # stop so so.load_from_db() so.stop_sales_order() - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 0.0) - + self.assertEqual(get_reserved_qty(), existing_reserved_qty) + # unstop so so.load_from_db() so.unstop_sales_order() - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 5.0) + self.assertEqual(get_reserved_qty(), existing_reserved_qty + 5) - # cancel dn dn.cancel() - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 10.0) + self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) + + # cancel + so.load_from_db() + so.cancel() + self.assertEqual(get_reserved_qty(), existing_reserved_qty) def test_reserved_qty_for_over_delivery(self): - # reset bin - so_item = test_records[0]["items"][0].copy() - self.delete_bin(so_item["item_code"], so_item["warehouse"]) - - # submit so - so = self.create_so() - - # allow negative stock - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - # set over-delivery tolerance - frappe.db.set_value('Item', so.get("items")[0].item_code, 'tolerance', 50) + frappe.db.set_value('Item', "_Test Item", 'tolerance', 50) + + existing_reserved_qty = get_reserved_qty() + + so = make_sales_order() + self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) - # submit dn - dn = self.create_dn_against_so(so, 15) - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 0.0) - # cancel dn + dn = create_dn_against_so(so.name, 15) + self.assertEqual(get_reserved_qty(), existing_reserved_qty) + dn.cancel() - self.check_reserved_qty(so.get("items")[0].item_code, so.get("items")[0].warehouse, 10.0) - - def test_reserved_qty_for_so_with_packing_list(self): - from erpnext.selling.doctype.sales_bom.test_sales_bom import test_records as sbom_test_records - - # change item in test so record - test_record = copy.deepcopy(test_records[0]) - test_record["items"][0]["item_code"] = "_Test Sales BOM Item" - - # reset bin - self.delete_bin(sbom_test_records[0]["items"][0]["item_code"], test_record.get("items")[0]["warehouse"]) - self.delete_bin(sbom_test_records[0]["items"][1]["item_code"], test_record.get("items")[0]["warehouse"]) - - # submit - so = self.create_so(test_record) - - - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 50.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 20.0) - - # cancel - so.cancel() - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 0.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 0.0) + self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) def test_reserved_qty_for_partial_delivery_with_packing_list(self): - from erpnext.selling.doctype.sales_bom.test_sales_bom import test_records as sbom_test_records - - # change item in test so record - - test_record = frappe.copy_doc(test_records[0]) - test_record.get("items")[0].item_code = "_Test Sales BOM Item" - - # reset bin - self.delete_bin(sbom_test_records[0]["items"][0]["item_code"], test_record.get("items")[0].warehouse) - self.delete_bin(sbom_test_records[0]["items"][1]["item_code"], test_record.get("items")[0].warehouse) - - # submit - so = self.create_so(test_record) - - # allow negative stock - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - - # submit dn - dn = self.create_dn_against_so(so) - - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 25.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 10.0) + existing_reserved_qty_item1 = get_reserved_qty("_Test Item") + existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") + + so = make_sales_order(item_code="_Test Sales BOM Item") + + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), + existing_reserved_qty_item2 + 20) + + dn = create_dn_against_so(so.name) + + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), + existing_reserved_qty_item2 + 10) # stop so so.load_from_db() so.stop_sales_order() - - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 0.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 0.0) + + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2) # unstop so so.load_from_db() so.unstop_sales_order() - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 25.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 10.0) + + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), + existing_reserved_qty_item2 + 10) - # cancel dn dn.cancel() - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 50.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 20.0) + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), + existing_reserved_qty_item2 + 20) + + so.load_from_db() + so.cancel() + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2) def test_reserved_qty_for_over_delivery_with_packing_list(self): - from erpnext.selling.doctype.sales_bom.test_sales_bom import test_records as sbom_test_records - - # change item in test so record - test_record = frappe.copy_doc(test_records[0]) - test_record.get("items")[0].item_code = "_Test Sales BOM Item" - - # reset bin - self.delete_bin(sbom_test_records[0]["items"][0]["item_code"], test_record.get("items")[0].warehouse) - self.delete_bin(sbom_test_records[0]["items"][1]["item_code"], test_record.get("items")[0].warehouse) - - # submit - so = self.create_so(test_record) - - # allow negative stock - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) - # set over-delivery tolerance - frappe.db.set_value('Item', so.get("items")[0].item_code, 'tolerance', 50) - - # submit dn - dn = self.create_dn_against_so(so, 15) - - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 0.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 0.0) - - # cancel dn + frappe.db.set_value('Item', "_Test Sales BOM Item", 'tolerance', 50) + + existing_reserved_qty_item1 = get_reserved_qty("_Test Item") + existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") + + so = make_sales_order(item_code="_Test Sales BOM Item") + + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), + existing_reserved_qty_item2 + 20) + + dn = create_dn_against_so(so.name, 15) + + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), + existing_reserved_qty_item2) + dn.cancel() - self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], - so.get("items")[0].warehouse, 50.0) - self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], - so.get("items")[0].warehouse, 20.0) + self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), + existing_reserved_qty_item2 + 20) def test_warehouse_user(self): frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com") @@ -353,11 +201,10 @@ class TestSalesOrder(unittest.TestCase): frappe.set_user("test@example.com") - so = frappe.copy_doc(test_records[0]) - so.company = "_Test Company 1" + so = make_sales_order(company="_Test Company 1", + warehouse="_Test Warehouse 2 - _TC1", do_not_save=True) so.conversion_rate = 0.02 so.plc_conversion_rate = 0.02 - so.get("items")[0].warehouse = "_Test Warehouse 2 - _TC1" self.assertRaises(frappe.PermissionError, so.insert) frappe.set_user("test2@example.com") @@ -368,24 +215,50 @@ class TestSalesOrder(unittest.TestCase): frappe.permissions.remove_user_permission("Company", "_Test Company 1", "test2@example.com") def test_block_delivery_note_against_cancelled_sales_order(self): - from erpnext.stock.doctype.delivery_note.test_delivery_note import _insert_purchase_receipt - from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note + so = make_sales_order() + + dn = make_delivery_note(so.name) + dn.insert() + + so.cancel() + + self.assertRaises(frappe.CancelledLinkError, dn.submit) + +def make_sales_order(**args): + so = frappe.new_doc("Sales Order") + args = frappe._dict(args) + if args.transaction_date: + so.transaction_date = args.transaction_date - sales_order = frappe.copy_doc(test_records[0]) - sales_order.items[0].qty = 5 - sales_order.insert() - sales_order.submit() + so.company = args.company or "_Test Company" + so.customer = args.customer or "_Test Customer" + so.delivery_date = add_days(so.transaction_date, 10) - _insert_purchase_receipt(sales_order.get("items")[0].item_code) + so.append("items", { + "item_code": args.item or args.item_code or "_Test Item", + "warehouse": args.warehouse or "_Test Warehouse - _TC", + "qty": args.qty or 10, + "rate": args.rate or 100, + "conversion_factor": 1.0, + }) + if not args.do_not_save: + so.insert() + if not args.do_not_submit: + so.submit() + + return so + +def create_dn_against_so(so, delivered_qty=0): + frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) + + dn = make_delivery_note(so) + dn.get("items")[0].qty = delivered_qty or 5 + dn.insert() + dn.submit() + return dn - delivery_note = make_delivery_note(sales_order.name) - delivery_note.posting_date = sales_order.transaction_date - delivery_note.insert() - - sales_order.cancel() - - self.assertRaises(frappe.CancelledLinkError, delivery_note.submit) - -test_dependencies = ["Sales BOM", "Currency Exchange"] - -test_records = frappe.get_test_records('Sales Order') +def get_reserved_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"): + return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, + "reserved_qty")) + +test_dependencies = ["Currency Exchange"] \ No newline at end of file diff --git a/erpnext/setup/page/setup_wizard/setup_wizard.py b/erpnext/setup/page/setup_wizard/setup_wizard.py index 234eeba565..b07e372e93 100644 --- a/erpnext/setup/page/setup_wizard/setup_wizard.py +++ b/erpnext/setup/page/setup_wizard/setup_wizard.py @@ -17,8 +17,6 @@ import install_fixtures @frappe.whitelist() def setup_account(args=None): try: - frappe.clear_cache() - if frappe.db.sql("select name from tabCompany"): frappe.throw(_("Setup Already Complete!!")) diff --git a/erpnext/setup/page/setup_wizard/test_setup_data.py b/erpnext/setup/page/setup_wizard/test_setup_data.py index 9c7a996df2..43fc2cf782 100644 --- a/erpnext/setup/page/setup_wizard/test_setup_data.py +++ b/erpnext/setup/page/setup_wizard/test_setup_data.py @@ -48,7 +48,7 @@ args = { "supplier_3": "Digital Ocean", "tax_1": "Service Tax", "tax_rate_1": "12.5", -"timezone": "Asia/Calcutta", +"timezone": "America/New_York", "password": "password", "email": "test@erpnext.com", } diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index 69f6752463..b4ae5ef6cf 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -30,9 +30,10 @@ def get_ancestors_of(doctype, name): return result or [] def before_tests(): + frappe.clear_cache() # complete setup if missing from erpnext.setup.page.setup_wizard.setup_wizard import setup_account - if not frappe.get_list("Item Group"): + if not frappe.get_list("Company"): setup_account({ "currency" :"USD", "first_name" :"Test", diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py index 207d34c349..b44bd0a7d7 100644 --- a/erpnext/shopping_cart/test_shopping_cart.py +++ b/erpnext/shopping_cart/test_shopping_cart.py @@ -58,6 +58,9 @@ class TestShoppingCart(unittest.TestCase): def test_add_to_cart(self): self.login_as_lead() + # remove from cart + self.remove_all_items_from_cart() + # add first item set_item_in_cart("_Test Item", 1) quotation = self.test_get_cart_lead() @@ -84,7 +87,7 @@ class TestShoppingCart(unittest.TestCase): self.assertEquals(quotation.get("items")[0].item_code, "_Test Item") self.assertEquals(quotation.get("items")[0].qty, 5) self.assertEquals(quotation.get("items")[0].amount, 50) - self.assertEquals(quotation.base_net_total, 70) + self.assertEquals(quotation.net_total, 70) self.assertEquals(len(quotation.get("items")), 2) def test_remove_from_cart(self): @@ -97,13 +100,13 @@ class TestShoppingCart(unittest.TestCase): self.assertEquals(quotation.get("items")[0].item_code, "_Test Item 2") self.assertEquals(quotation.get("items")[0].qty, 1) self.assertEquals(quotation.get("items")[0].amount, 20) - self.assertEquals(quotation.base_net_total, 20) + self.assertEquals(quotation.net_total, 20) self.assertEquals(len(quotation.get("items")), 1) # remove second item set_item_in_cart("_Test Item 2", 0) quotation = self.test_get_cart_lead() - self.assertEquals(quotation.base_net_total, 0) + self.assertEquals(quotation.net_total, 0) self.assertEquals(len(quotation.get("items")), 0) def test_set_billing_address(self): @@ -141,7 +144,7 @@ class TestShoppingCart(unittest.TestCase): def enable_shopping_cart(self): settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings") - if settings.default_territory == "_Test Territory Rest Of The World": + if settings.get("price_lists"): settings.enabled = 1 else: settings.update({ @@ -224,6 +227,11 @@ class TestShoppingCart(unittest.TestCase): "lead_name": "_Test Website Lead", "phone": "+91 0000000000" }).insert(ignore_permissions=True) + + def remove_all_items_from_cart(self): + quotation = get_quotation() + quotation.set("items", []) + quotation.save(ignore_permissions=True) test_dependencies = ["Sales Taxes and Charges Master", "Price List", "Item Price", "Shipping Rule", "Currency Exchange", diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index d39f1e26e2..8556c928b4 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -5,109 +5,95 @@ from __future__ import unicode_literals import unittest import frappe +import json import frappe.defaults -from frappe.utils import cint -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, set_perpetual_inventory, test_records as pr_test_records - -def _insert_purchase_receipt(item_code=None): - if not item_code: - item_code = pr_test_records[0]["items"][0]["item_code"] - - pr = frappe.copy_doc(pr_test_records[0]) - pr.get("items")[0].item_code = item_code - pr.insert() - pr.submit() +from frappe.utils import cint, nowdate, nowtime, cstr, add_days +from erpnext.stock.stock_ledger import get_previous_sle +from erpnext.accounts.utils import get_balance_on +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ + import get_gl_entries, set_perpetual_inventory +from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice +from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, make_serialized_item +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, SerialNoStatusError class TestDeliveryNote(unittest.TestCase): def test_over_billing_against_dn(self): - self.clear_stock_account_balance() - _insert_purchase_receipt() + frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) + + dn = create_delivery_note(do_not_submit=True) + self.assertRaises(frappe.ValidationError, make_sales_invoice, dn.name) - from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice - _insert_purchase_receipt() - dn = frappe.copy_doc(test_records[0]).insert() - - self.assertRaises(frappe.ValidationError, make_sales_invoice, - dn.name) - - dn = frappe.get_doc("Delivery Note", dn.name) dn.submit() si = make_sales_invoice(dn.name) - self.assertEquals(len(si.get("items")), len(dn.get("items"))) # modify amount si.get("items")[0].rate = 200 self.assertRaises(frappe.ValidationError, frappe.get_doc(si).insert) - def test_delivery_note_no_gl_entry(self): - self.clear_stock_account_balance() set_perpetual_inventory(0) self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 0) - _insert_purchase_receipt() - - dn = frappe.copy_doc(test_records[0]) - dn.insert() - dn.submit() - - stock_value, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", - {"voucher_type": "Delivery Note", "voucher_no": dn.name, - "item_code": "_Test Item"}, ["stock_value", "stock_value_difference"]) - self.assertEqual(stock_value, 0) - self.assertEqual(stock_value_difference, -375) + make_stock_entry(target="_Test Warehouse - _TC", qty=5, incoming_rate=100) + + stock_queue = json.loads(get_previous_sle({ + "item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC", + "posting_date": nowdate(), + "posting_time": nowtime() + }).stock_queue or "[]") + + dn = create_delivery_note() + + sle = frappe.get_doc("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name}) + + self.assertEqual(sle.stock_value_difference, -1*stock_queue[0][1]) self.assertFalse(get_gl_entries("Delivery Note", dn.name)) def test_delivery_note_gl_entry(self): - self.clear_stock_account_balance() set_perpetual_inventory() self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) frappe.db.set_value("Item", "_Test Item", "valuation_method", "FIFO") - _insert_purchase_receipt() + make_stock_entry(target="_Test Warehouse - _TC", qty=5, incoming_rate=100) - dn = frappe.copy_doc(test_records[0]) - dn.get("items")[0].expense_account = "Cost of Goods Sold - _TC" - dn.get("items")[0].cost_center = "Main - _TC" - - stock_in_hand_account = frappe.db.get_value("Account", - {"warehouse": dn.get("items")[0].warehouse}) - - from erpnext.accounts.utils import get_balance_on - prev_bal = get_balance_on(stock_in_hand_account, dn.posting_date) - - dn.insert() - dn.submit() + stock_in_hand_account = frappe.db.get_value("Account", {"warehouse": "_Test Warehouse - _TC"}) + prev_bal = get_balance_on(stock_in_hand_account) + + dn = create_delivery_note() gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) + + stock_value_difference = abs(frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name}, "stock_value_difference")) + expected_values = { - stock_in_hand_account: [0.0, 375.0], - "Cost of Goods Sold - _TC": [375.0, 0.0] + stock_in_hand_account: [0.0, stock_value_difference], + "Cost of Goods Sold - _TC": [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) # check stock in hand balance - bal = get_balance_on(stock_in_hand_account, dn.posting_date) - self.assertEquals(bal, prev_bal - 375.0) + bal = get_balance_on(stock_in_hand_account) + self.assertEquals(bal, prev_bal - stock_value_difference) - # back dated purchase receipt - pr = frappe.copy_doc(pr_test_records[0]) - pr.posting_date = "2013-01-01" - pr.get("items")[0].rate = 100 - pr.get("items")[0].base_amount = 100 - - pr.insert() - pr.submit() + # back dated incoming entry + make_stock_entry(posting_date=add_days(nowdate(), -2), target="_Test Warehouse - _TC", + qty=5, incoming_rate=100) gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) + + stock_value_difference = abs(frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name}, "stock_value_difference")) + expected_values = { - stock_in_hand_account: [0.0, 666.67], - "Cost of Goods Sold - _TC": [666.67, 0.0] + stock_in_hand_account: [0.0, stock_value_difference], + "Cost of Goods Sold - _TC": [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) @@ -117,38 +103,40 @@ class TestDeliveryNote(unittest.TestCase): set_perpetual_inventory(0) def test_delivery_note_gl_entry_packing_item(self): - self.clear_stock_account_balance() set_perpetual_inventory() - _insert_purchase_receipt() - _insert_purchase_receipt("_Test Item Home Desktop 100") + make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=10, incoming_rate=100) + make_stock_entry(item_code="_Test Item Home Desktop 100", + target="_Test Warehouse - _TC", qty=10, incoming_rate=100) - dn = frappe.copy_doc(test_records[0]) - dn.get("items")[0].item_code = "_Test Sales BOM Item" - dn.get("items")[0].qty = 1 + stock_in_hand_account = frappe.db.get_value("Account", {"warehouse": "_Test Warehouse - _TC"}) + prev_bal = get_balance_on(stock_in_hand_account) - stock_in_hand_account = frappe.db.get_value("Account", - {"warehouse": dn.get("items")[0].warehouse}) - - from erpnext.accounts.utils import get_balance_on - prev_bal = get_balance_on(stock_in_hand_account, dn.posting_date) - - dn.insert() - dn.submit() + dn = create_delivery_note(item_code="_Test Sales BOM Item") + + stock_value_diff_rm1 = abs(frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"}, + "stock_value_difference")) + + stock_value_diff_rm2 = abs(frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Delivery Note", "voucher_no": dn.name, + "item_code": "_Test Item Home Desktop 100"}, "stock_value_difference")) + + stock_value_diff = stock_value_diff_rm1 + stock_value_diff_rm2 gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) expected_values = { - stock_in_hand_account: [0.0, 525], - "Cost of Goods Sold - _TC": [525.0, 0.0] + stock_in_hand_account: [0.0, stock_value_diff], + "Cost of Goods Sold - _TC": [stock_value_diff, 0.0] } for i, gle in enumerate(gl_entries): self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) # check stock in hand balance - bal = get_balance_on(stock_in_hand_account, dn.posting_date) - self.assertEquals(bal, prev_bal - 525.0) + bal = get_balance_on(stock_in_hand_account) + self.assertEquals(bal, prev_bal - stock_value_diff) dn.cancel() self.assertFalse(get_gl_entries("Delivery Note", dn.name)) @@ -156,62 +144,67 @@ class TestDeliveryNote(unittest.TestCase): set_perpetual_inventory(0) def test_serialized(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item - from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos - se = make_serialized_item() - serial_nos = get_serial_nos(se.get("items")[0].serial_no) + serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] - dn = frappe.copy_doc(test_records[0]) - dn.get("items")[0].item_code = "_Test Serialized Item With Series" - dn.get("items")[0].qty = 1 - dn.get("items")[0].serial_no = serial_nos[0] - dn.insert() - dn.submit() + dn = create_delivery_note(item_code="_Test Serialized Item With Series", serial_no=serial_no) - self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Delivered") - self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse")) - self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], - "delivery_document_no"), dn.name) + self.check_serial_no_values(serial_no, { + "status": "Delivered", + "warehouse": "", + "delivery_document_no": dn.name + }) - return dn - - def test_serialized_cancel(self): - from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos - dn = self.test_serialized() dn.cancel() - - serial_nos = get_serial_nos(dn.get("items")[0].serial_no) - - self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Available") - self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC") - self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], - "delivery_document_no")) + + self.check_serial_no_values(serial_no, { + "status": "Available", + "warehouse": "_Test Warehouse - _TC", + "delivery_document_no": "" + }) def test_serialize_status(self): - from erpnext.stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item - se = make_serialized_item() - serial_nos = get_serial_nos(se.get("items")[0].serial_no) + serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] + + frappe.db.set_value("Serial No", serial_no, "status", "Not Available") - sr = frappe.get_doc("Serial No", serial_nos[0]) - sr.status = "Not Available" - sr.save() - - dn = frappe.copy_doc(test_records[0]) - dn.get("items")[0].item_code = "_Test Serialized Item With Series" - dn.get("items")[0].qty = 1 - dn.get("items")[0].serial_no = serial_nos[0] - dn.insert() + dn = create_delivery_note(item_code="_Test Serialized Item With Series", + serial_no=serial_no, do_not_submit=True) self.assertRaises(SerialNoStatusError, dn.submit) + + def check_serial_no_values(self, serial_no, field_values): + for field, value in field_values.items(): + self.assertEquals(cstr(frappe.db.get_value("Serial No", serial_no, field)), value) - def clear_stock_account_balance(self): - frappe.db.sql("""delete from `tabBin`""") - frappe.db.sql("delete from `tabStock Ledger Entry`") - frappe.db.sql("delete from `tabGL Entry`") -test_dependencies = ["Sales BOM"] - -test_records = frappe.get_test_records('Delivery Note') +def create_delivery_note(**args): + dn = frappe.new_doc("Delivery Note") + args = frappe._dict(args) + if args.posting_date: + dn.posting_date = args.posting_date + if args.posting_time: + dn.posting_time = args.posting_time + + dn.company = args.company or "_Test Company" + dn.customer = args.customer or "_Test Customer" + + dn.append("items", { + "item_code": args.item or args.item_code or "_Test Item", + "warehouse": args.warehouse or "_Test Warehouse - _TC", + "qty": args.qty or 1, + "rate": args.rate or 100, + "conversion_factor": 1.0, + "expense_account": "Cost of Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", + "serial_no": args.serial_no + }) + + if not args.do_not_save: + dn.insert() + if not args.do_not_submit: + dn.submit() + return dn + +test_dependencies = ["Sales BOM"] \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_note/test_records.json b/erpnext/stock/doctype/delivery_note/test_records.json index ff06637d3f..7163432c1c 100644 --- a/erpnext/stock/doctype/delivery_note/test_records.json +++ b/erpnext/stock/doctype/delivery_note/test_records.json @@ -7,7 +7,7 @@ "customer_name": "_Test Customer", "items": [ { - "base_amount": 500.0, + "base_amount": 100.0, "base_rate": 100.0, "cost_center": "Main - _TC", "description": "CPU", @@ -16,7 +16,7 @@ "item_code": "_Test Item", "item_name": "_Test Item", "parentfield": "items", - "qty": 5.0, + "qty": 1.0, "rate": 100.0, "stock_uom": "_Test UOM", "warehouse": "_Test Warehouse - _TC" @@ -24,10 +24,10 @@ ], "doctype": "Delivery Note", "fiscal_year": "_Test Fiscal Year 2013", - "base_grand_total": 500.0, - "grand_total": 500.0, + "base_grand_total": 100.0, + "grand_total": 100.0, "naming_series": "_T-Delivery Note-", - "base_net_total": 500.0, + "base_net_total": 100.0, "plc_conversion_rate": 1.0, "posting_date": "2013-02-21", "posting_time": "9:00:00", diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 3d7d951886..a8f3583f98 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -7,6 +7,7 @@ import frappe from frappe.test_runner import make_test_records from erpnext.stock.doctype.item.item import WarehouseNotSet, DuplicateVariant, ItemTemplateCannotHaveStock +from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry test_ignore = ["BOM"] test_dependencies = ["Warehouse"] @@ -29,17 +30,8 @@ class TestItem(unittest.TestCase): def test_template_cannot_have_stock(self): item = self.get_item(10) - - se = frappe.new_doc("Stock Entry") - se.purpose = "Material Receipt" - se.append("items", { - "item_code": item.name, - "t_warehouse": "Stores - _TC", - "qty": 1, - "incoming_rate": 1 - }) - se.insert() - se.submit() + + se = make_stock_entry(item_code=item.name, target="Stores - _TC", qty=1, incoming_rate=1) item.has_variants = 1 self.assertRaises(ItemTemplateCannotHaveStock, item.save) diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json index 51dd9fb7bf..dc095c6b14 100644 --- a/erpnext/stock/doctype/item/test_records.json +++ b/erpnext/stock/doctype/item/test_records.json @@ -4,6 +4,7 @@ "description": "_Test Item 1", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -36,6 +37,7 @@ "description": "_Test Item 2", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -59,6 +61,7 @@ "description": "_Test Item Home Desktop 100 3", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -88,6 +91,7 @@ "description": "_Test Item Home Desktop 200 4", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -108,6 +112,7 @@ "description": "_Test Sales BOM Item 5", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -129,6 +134,7 @@ "description": "_Test FG Item 6", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -207,6 +213,7 @@ "description": "_Test Item Home Desktop Manufactured 10", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -227,6 +234,7 @@ "description": "_Test FG Item 2 11", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", @@ -248,6 +256,7 @@ "description": "_Test Variant Item 12", "doctype": "Item", "expense_account": "_Test Account Cost for Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", "has_batch_no": "No", "has_serial_no": "No", "income_account": "Sales - _TC", diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 5af43cafed..8b256c4298 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -6,21 +6,16 @@ from __future__ import unicode_literals import unittest import frappe import frappe.defaults -from frappe.utils import cint +from frappe.utils import cint, flt class TestPurchaseReceipt(unittest.TestCase): def test_make_purchase_invoice(self): - self._clear_stock_account_balance() - set_perpetual_inventory(0) from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice - pr = frappe.copy_doc(test_records[0]).insert() - - self.assertRaises(frappe.ValidationError, make_purchase_invoice, - pr.name) - - pr = frappe.get_doc("Purchase Receipt", pr.name) + pr = make_purchase_receipt(do_not_save=True) + self.assertRaises(frappe.ValidationError, make_purchase_invoice, pr.name) pr.submit() + pi = make_purchase_invoice(pr.name) self.assertEquals(pi.doctype, "Purchase Invoice") @@ -31,28 +26,26 @@ class TestPurchaseReceipt(unittest.TestCase): self.assertRaises(frappe.ValidationError, frappe.get_doc(pi).submit) def test_purchase_receipt_no_gl_entry(self): - self._clear_stock_account_balance() set_perpetual_inventory(0) - pr = frappe.copy_doc(test_records[0]) - pr.insert() - pr.submit() - - stock_value, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", - {"voucher_type": "Purchase Receipt", "voucher_no": pr.name, - "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, - ["stock_value", "stock_value_difference"]) - self.assertEqual(stock_value, 375) - self.assertEqual(stock_value_difference, 375) - - bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", + + existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, "stock_value") - self.assertEqual(bin_stock_value, 375) + + pr = make_purchase_receipt() + + stock_value_difference = frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name, + "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference") + + self.assertEqual(stock_value_difference, 250) + + current_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC"}, "stock_value") + self.assertEqual(current_bin_stock_value, existing_bin_stock_value + 250) self.assertFalse(get_gl_entries("Purchase Receipt", pr.name)) def test_purchase_receipt_gl_entry(self): - self._clear_stock_account_balance() - set_perpetual_inventory() self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) pr = frappe.copy_doc(test_records[0]) @@ -84,39 +77,20 @@ class TestPurchaseReceipt(unittest.TestCase): set_perpetual_inventory(0) - def _clear_stock_account_balance(self): - frappe.db.sql("delete from `tabStock Ledger Entry`") - frappe.db.sql("""delete from `tabBin`""") - frappe.db.sql("""delete from `tabGL Entry`""") - def test_subcontracting(self): - pr = frappe.copy_doc(test_records[1]) - pr.run_method("calculate_taxes_and_totals") - pr.insert() - + pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes") self.assertEquals(len(pr.get("supplied_items")), 2) - self.assertEquals(pr.get("items")[0].rm_supp_cost, 20750.0) - + + rm_supp_cost = sum([d.amount for d in pr.get("supplied_items")]) + self.assertEquals(pr.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2)) def test_serial_no_supplier(self): - pr = frappe.copy_doc(test_records[0]) - pr.get("items")[0].item_code = "_Test Serialized Item With Series" - pr.get("items")[0].qty = 1 - pr.get("items")[0].received_qty = 1 - pr.insert() - pr.submit() - - self.assertEquals(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, - "supplier"), pr.supplier) - - return pr - - def test_serial_no_cancel(self): - pr = self.test_serial_no_supplier() + pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1) + self.assertEquals(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "supplier"), + pr.supplier) + pr.cancel() - - self.assertFalse(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, - "warehouse")) + self.assertFalse(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "warehouse")) def test_rejected_serial_no(self): pr = frappe.copy_doc(test_records[0]) @@ -149,8 +123,34 @@ def set_perpetual_inventory(enable=1): accounts_settings = frappe.get_doc("Accounts Settings") accounts_settings.auto_accounting_for_stock = enable accounts_settings.save() + +def make_purchase_receipt(**args): + pr = frappe.new_doc("Purchase Receipt") + args = frappe._dict(args) + if args.posting_date: + pr.posting_date = args.posting_date + if args.posting_time: + pr.posting_time = args.posting_time + 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.append("items", { + "item_code": args.item or args.item_code or "_Test Item", + "warehouse": args.warehouse or "_Test Warehouse - _TC", + "qty": args.qty or 5, + "received_qty": args.qty or 5, + "rate": args.rate or 50, + "conversion_factor": 1.0, + "serial_no": args.serial_no + }) + if not args.do_not_save: + pr.insert() + if not args.do_not_submit: + pr.submit() + return pr test_dependencies = ["BOM", "Item Price"] - test_records = frappe.get_test_records('Purchase Receipt') diff --git a/erpnext/stock/doctype/purchase_receipt/test_records.json b/erpnext/stock/doctype/purchase_receipt/test_records.json index 481bb170bd..72fcabfc42 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_records.json +++ b/erpnext/stock/doctype/purchase_receipt/test_records.json @@ -5,7 +5,6 @@ "conversion_rate": 1.0, "currency": "INR", "doctype": "Purchase Receipt", - "fiscal_year": "_Test Fiscal Year 2013", "base_grand_total": 720.0, "naming_series": "_T-Purchase Receipt-", "base_net_total": 500.0, @@ -47,8 +46,6 @@ "cost_center": "Main - _TC" } ], - "posting_date": "2013-02-12", - "posting_time": "15:33:30", "items": [ { "base_amount": 250.0, @@ -62,7 +59,7 @@ "rate": 50.0, "received_qty": 5.0, "rejected_qty": 0.0, - "stock_uom": "Nos", + "stock_uom": "_Test UOM", "uom": "_Test UOM", "warehouse": "_Test Warehouse - _TC", "cost_center": "Main - _TC" @@ -79,7 +76,7 @@ "rate": 50.0, "received_qty": 5.0, "rejected_qty": 0.0, - "stock_uom": "Nos", + "stock_uom": "_Test UOM", "uom": "_Test UOM", "warehouse": "_Test Warehouse 1 - _TC", "cost_center": "Main - _TC" @@ -87,6 +84,8 @@ ], "supplier": "_Test Supplier" }, + + { "buying_price_list": "_Test Price List", "company": "_Test Company", @@ -112,7 +111,7 @@ "rate": 500.0, "received_qty": 10.0, "rejected_qty": 0.0, - "stock_uom": "Nos", + "stock_uom": "_Test UOM", "uom": "_Test UOM", "warehouse": "_Test Warehouse - _TC", "cost_center": "Main - _TC" diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 619d6c26a2..05e5a8a838 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe import frappe.defaults -from frappe.utils import cstr, cint, flt, comma_or, nowdate +from frappe.utils import cstr, cint, flt, comma_or, nowdate, get_datetime from frappe import _ from erpnext.stock.utils import get_incoming_rate @@ -283,7 +283,7 @@ class StockEntry(StockController): incoming_rate = flt(self.get_incoming_rate(args), self.precision("incoming_rate", d)) if incoming_rate > 0: d.incoming_rate = incoming_rate - + d.amount = flt(d.transfer_qty) * flt(d.incoming_rate) if not d.t_warehouse: raw_material_cost += flt(d.amount) @@ -298,9 +298,7 @@ class StockEntry(StockController): number_of_fg_items = len([t.t_warehouse for t in self.get("items") if t.t_warehouse]) for d in self.get("items"): if d.bom_no or (d.t_warehouse and number_of_fg_items == 1): - operation_cost_per_unit = 0.0 - if self.production_order: - operation_cost_per_unit = self.get_operation_cost_per_unit(d.bom_no, d.qty) + operation_cost_per_unit = self.get_operation_cost_per_unit(d.bom_no, d.qty) d.incoming_rate = operation_cost_per_unit + (raw_material_cost / flt(d.transfer_qty)) d.amount = flt(flt(d.transfer_qty) * flt(d.incoming_rate), self.precision("transfer_qty", d)) @@ -382,7 +380,7 @@ class StockEntry(StockController): def validate_return_reference_doc(self): """validate item with reference doc""" ref = get_return_doc_and_details(self) - + if ref.doc: # validate docstatus if ref.doc.docstatus != 1: @@ -394,13 +392,13 @@ class StockEntry(StockController): frappe.throw(_("'Update Stock' for Sales Invoice {0} must be set").format(ref.doc.name), NotUpdateStockError) # posting date check - ref_posting_datetime = "%s %s" % (cstr(ref.doc.posting_date), - cstr(ref.doc.posting_time) or "00:00:00") - this_posting_datetime = "%s %s" % (cstr(self.posting_date), - cstr(self.posting_time)) - if this_posting_datetime < ref_posting_datetime: + ref_posting_datetime = "%s %s" % (ref.doc.posting_date, ref.doc.posting_time or "00:00:00") + this_posting_datetime = "%s %s" % (self.posting_date, self.posting_time) + + if get_datetime(ref_posting_datetime) < get_datetime(ref_posting_datetime): from frappe.utils.dateutils import datetime_in_user_format - frappe.throw(_("Posting timestamp must be after {0}").format(datetime_in_user_format(ref_posting_datetime))) + frappe.throw(_("Posting timestamp must be after {0}") + .format(datetime_in_user_format(ref_posting_datetime))) stock_items = get_stock_items_for_return(ref.doc, ref.parentfields) already_returned_item_qty = self.get_already_returned_item_qty(ref.fieldname) diff --git a/erpnext/stock/doctype/stock_entry/test_records.json b/erpnext/stock/doctype/stock_entry/test_records.json index 10df737b4a..b9060fcc8b 100644 --- a/erpnext/stock/doctype/stock_entry/test_records.json +++ b/erpnext/stock/doctype/stock_entry/test_records.json @@ -2,7 +2,6 @@ { "company": "_Test Company", "doctype": "Stock Entry", - "fiscal_year": "_Test Fiscal Year 2013", "items": [ { "conversion_factor": 1.0, @@ -19,10 +18,10 @@ "uom": "_Test UOM" } ], - "posting_date": "2013-01-01", - "posting_time": "17:14:24", "purpose": "Material Receipt" }, + + { "company": "_Test Company", "doctype": "Stock Entry", @@ -47,6 +46,8 @@ "posting_time": "17:15", "purpose": "Material Issue" }, + + { "company": "_Test Company", "doctype": "Stock Entry", @@ -72,6 +73,8 @@ "posting_time": "17:14:24", "purpose": "Material Transfer" }, + + { "company": "_Test Company", "doctype": "Stock Entry", @@ -106,8 +109,6 @@ "uom": "_Test UOM" } ], - "posting_date": "2013-01-25", - "posting_time": "17:14:24", "purpose": "Repack" } ] \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 21b38dc97d..a5e82b9bcf 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -4,10 +4,16 @@ from __future__ import unicode_literals import frappe, unittest import frappe.defaults -from frappe.utils import flt, getdate +from frappe.utils import flt, nowdate, nowtime from erpnext.stock.doctype.serial_no.serial_no import * -from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ + import set_perpetual_inventory, make_purchase_receipt from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError +from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice +from erpnext.stock.stock_ledger import get_previous_sle +from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order, create_dn_against_so +from erpnext.stock.doctype.stock_entry.stock_entry import make_return_jv, NotUpdateStockError +from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation def get_sle(**args): condition, values = "", [] @@ -20,35 +26,25 @@ def get_sle(**args): order by timestamp(posting_date, posting_time) desc, name desc limit 1"""% condition, values, as_dict=1) -def make_zero(item_code, warehouse): - sle = get_sle(item_code = item_code, warehouse = warehouse) - qty = sle[0].qty_after_transaction if sle else 0 - if qty < 0: - make_stock_entry(item_code=item_code, target=warehouse, qty=abs(qty), incoming_rate=10) - elif qty > 0: - make_stock_entry(item_code=item_code, source=warehouse, qty=qty, incoming_rate=10) - class TestStockEntry(unittest.TestCase): def tearDown(self): frappe.set_user("Administrator") set_perpetual_inventory(0) - if hasattr(self, "old_default_company"): - frappe.db.set_default("company", self.old_default_company) def test_fifo(self): frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) item_code = "_Test Item 2" warehouse = "_Test Warehouse - _TC" - make_zero(item_code, warehouse) + + create_stock_reconciliation(item_code="_Test Item 2", warehouse="_Test Warehouse - _TC", + qty=0, rate=100) make_stock_entry(item_code=item_code, target=warehouse, qty=1, incoming_rate=10) sle = get_sle(item_code = item_code, warehouse = warehouse)[0] - self.assertEqual([[1, 10]], eval(sle.stock_queue)) # negative qty - make_zero(item_code, warehouse) - make_stock_entry(item_code=item_code, source=warehouse, qty=1, incoming_rate=10) + make_stock_entry(item_code=item_code, source=warehouse, qty=2, incoming_rate=10) sle = get_sle(item_code = item_code, warehouse = warehouse)[0] self.assertEqual([[-1, 10]], eval(sle.stock_queue)) @@ -60,12 +56,17 @@ class TestStockEntry(unittest.TestCase): self.assertEqual([[-2, 10]], eval(sle.stock_queue)) # move stock to positive - make_stock_entry(item_code=item_code, target=warehouse, qty=3, incoming_rate=10) + make_stock_entry(item_code=item_code, target=warehouse, qty=3, incoming_rate=20) + sle = get_sle(item_code = item_code, warehouse = warehouse)[0] + self.assertEqual([[1, 20]], eval(sle.stock_queue)) + + # incoming entry with diff rate + make_stock_entry(item_code=item_code, target=warehouse, qty=1, incoming_rate=30) sle = get_sle(item_code = item_code, warehouse = warehouse)[0] - self.assertEqual([[1, 10]], eval(sle.stock_queue)) + self.assertEqual([[1, 20],[1, 30]], eval(sle.stock_queue)) - frappe.db.set_default("allow_negative_stock", 0) + frappe.db.set_default("allow_negative_stock", 0) def test_auto_material_request(self): self._test_auto_material_request("_Test Item") @@ -92,7 +93,7 @@ class TestStockEntry(unittest.TestCase): # update re-level qty so that it is more than projected_qty if projected_qty > template.reorder_levels[0].warehouse_reorder_level: - template.reorder_levels[0].warehouse_reorder_level += projected_qty + template.reorder_levels[0].warehouse_reorder_level = projected_qty template.save() from erpnext.stock.reorder_item import reorder_item @@ -108,12 +109,10 @@ class TestStockEntry(unittest.TestCase): self.assertTrue(item_code in items) def test_material_receipt_gl_entry(self): - self._clear_stock_account_balance() set_perpetual_inventory() - - mr = frappe.copy_doc(test_records[0]) - mr.insert() - mr.submit() + + mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + qty=50, incoming_rate=100) stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": mr.get("items")[0].t_warehouse}) @@ -136,53 +135,46 @@ class TestStockEntry(unittest.TestCase): self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mr.name)) - def test_material_issue_gl_entry(self): - self._clear_stock_account_balance() set_perpetual_inventory() - self._insert_material_receipt() - - mi = frappe.copy_doc(test_records[1]) - mi.insert() - mi.submit() + make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + qty=50, incoming_rate=100) + + mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", qty=40) self.check_stock_ledger_entries("Stock Entry", mi.name, [["_Test Item", "_Test Warehouse - _TC", -40.0]]) stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", - "warehouse": mi.get("items")[0].s_warehouse}) + "warehouse": "_Test Warehouse - _TC"}) + + 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, 4000.0], - ["Stock Adjustment - _TC", 4000.0, 0.0] + [stock_in_hand_account, 0.0, stock_value_diff], + ["Stock Adjustment - _TC", stock_value_diff, 0.0] ]) ) mi.cancel() - self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry` + + self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mi.name)) - self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` + self.assertFalse(frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mi.name)) - self.assertEquals(frappe.db.get_value("Bin", {"warehouse": mi.get("items")[0].s_warehouse, - "item_code": mi.get("items")[0].item_code}, "actual_qty"), 50) - - self.assertEquals(frappe.db.get_value("Bin", {"warehouse": mi.get("items")[0].s_warehouse, - "item_code": mi.get("items")[0].item_code}, "stock_value"), 5000) - def test_material_transfer_gl_entry(self): - self._clear_stock_account_balance() set_perpetual_inventory() - - self._insert_material_receipt() - - mtn = frappe.copy_doc(test_records[2]) - mtn.insert() - mtn.submit() - + + 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) + self.check_stock_ledger_entries("Stock Entry", mtn.name, [["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]]) @@ -192,15 +184,16 @@ class TestStockEntry(unittest.TestCase): fixed_asset_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": mtn.get("items")[0].t_warehouse}) + 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")) self.check_gl_entries("Stock Entry", mtn.name, sorted([ - [stock_in_hand_account, 0.0, 4500.0], - [fixed_asset_account, 4500.0, 0.0], + [stock_in_hand_account, 0.0, stock_value_diff], + [fixed_asset_account, stock_value_diff, 0.0], ]) ) - - + mtn.cancel() self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) @@ -208,14 +201,16 @@ class TestStockEntry(unittest.TestCase): self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) - def test_repack_no_change_in_valuation(self): - self._clear_stock_account_balance() - set_perpetual_inventory() + set_perpetual_inventory(0) - self._insert_material_receipt() + make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100) + make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", + qty=50, incoming_rate=100) repack = frappe.copy_doc(test_records[3]) + repack.posting_date = nowdate() + repack.posting_time = nowtime() repack.insert() repack.submit() @@ -231,23 +226,32 @@ class TestStockEntry(unittest.TestCase): set_perpetual_inventory(0) def test_repack_with_change_in_valuation(self): - self._clear_stock_account_balance() set_perpetual_inventory() - self._insert_material_receipt() - + make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100) + repack = frappe.copy_doc(test_records[3]) - repack.get("items")[1].incoming_rate = 6000 + repack.posting_date = nowdate() + repack.posting_time = nowtime() + repack.additional_operating_cost = 1000.0 repack.insert() repack.submit() stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": repack.get("items")[1].t_warehouse}) + + rm_stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", + "voucher_no": repack.name, "item_code": "_Test Item"}, "stock_value_difference")) + + fg_stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", + "voucher_no": repack.name, "item_code": "_Test Item Home Desktop 100"}, "stock_value_difference")) + + stock_value_diff = flt(fg_stock_value_diff - rm_stock_value_diff, 2) self.check_gl_entries("Stock Entry", repack.name, sorted([ - [stock_in_hand_account, 1000.0, 0.0], - ["Stock Adjustment - _TC", 0.0, 1000.0], + [stock_in_hand_account, stock_value_diff, 0.0], + ["Stock Adjustment - _TC", 0.0, stock_value_diff], ]) ) set_perpetual_inventory(0) @@ -274,6 +278,7 @@ class TestStockEntry(unittest.TestCase): gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type=%s and voucher_no=%s order by account asc, debit asc""", (voucher_type, voucher_no), as_list=1) + self.assertTrue(gl_entries) gl_entries.sort(key=lambda x: x[0]) @@ -282,180 +287,107 @@ class TestStockEntry(unittest.TestCase): self.assertEquals(expected_gl_entries[i][1], gle[1]) self.assertEquals(expected_gl_entries[i][2], gle[2]) - def _insert_material_receipt(self): - self._clear_stock_account_balance() - se1 = frappe.copy_doc(test_records[0]) - se1.insert() - se1.submit() - - se2 = frappe.copy_doc(test_records[0]) - se2.get("items")[0].item_code = "_Test Item Home Desktop 100" - se2.insert() - se2.submit() - - frappe.db.set_default("company", self.old_default_company) - - def _get_actual_qty(self): - return flt(frappe.db.get_value("Bin", {"item_code": "_Test Item", - "warehouse": "_Test Warehouse - _TC"}, "actual_qty")) - def _test_sales_invoice_return(self, item_code, delivered_qty, returned_qty): - from erpnext.stock.doctype.stock_entry.stock_entry import NotUpdateStockError + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice - from erpnext.accounts.doctype.sales_invoice.test_sales_invoice \ - import test_records as sales_invoice_test_records + si = create_sales_invoice(item_code=item_code, qty=delivered_qty) - # invalid sales invoice as update stock not checked - si = frappe.copy_doc(sales_invoice_test_records[1]) - si.insert() - si.submit() - - se = frappe.copy_doc(test_records[0]) - se.purpose = "Sales Return" - se.sales_invoice_no = si.name - se.get("items")[0].qty = returned_qty - se.get("items")[0].transfer_qty = returned_qty + se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=returned_qty, + purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True) self.assertRaises(NotUpdateStockError, se.insert) - self._insert_material_receipt() + make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=200, incoming_rate=100) # check currency available qty in bin - actual_qty_0 = self._get_actual_qty() + actual_qty_0 = get_qty_after_transaction() # insert a pos invoice with update stock - si = frappe.copy_doc(sales_invoice_test_records[1]) - si.update_stock = 1 - si.get("items")[0].warehouse = "_Test Warehouse - _TC" - si.get("items")[0].item_code = item_code - si.get("items")[0].qty = 5.0 - si.insert() - si.submit() + si = create_sales_invoice(update_stock=1, item_code=item_code, qty=5) # check available bin qty after invoice submission - actual_qty_1 = self._get_actual_qty() + actual_qty_1 = get_qty_after_transaction() self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) # check if item is validated - se = frappe.copy_doc(test_records[0]) - se.purpose = "Sales Return" - se.sales_invoice_no = si.name - se.posting_date = "2013-03-10" - se.fiscal_year = "_Test Fiscal Year 2013" - se.get("items")[0].item_code = "_Test Item Home Desktop 200" - se.get("items")[0].qty = returned_qty - se.get("items")[0].transfer_qty = returned_qty + se = make_stock_entry(item_code="_Test Item Home Desktop 200", target="_Test Warehouse - _TC", + qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True) - # check if stock entry gets submitted self.assertRaises(frappe.DoesNotExistError, se.insert) # try again - se = frappe.copy_doc(test_records[0]) - se.purpose = "Sales Return" - se.posting_date = "2013-03-10" - se.fiscal_year = "_Test Fiscal Year 2013" - se.sales_invoice_no = si.name - se.get("items")[0].qty = returned_qty - se.get("items")[0].transfer_qty = returned_qty - # in both cases item code remains _Test Item when returning - se.insert() - - se.submit() + se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name) # check if available qty is increased - actual_qty_2 = self._get_actual_qty() + actual_qty_2 = get_qty_after_transaction() self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) return se def test_sales_invoice_return_of_non_packing_item(self): - self._clear_stock_account_balance() self._test_sales_invoice_return("_Test Item", 5, 2) def test_sales_invoice_return_of_packing_item(self): - self._clear_stock_account_balance() self._test_sales_invoice_return("_Test Sales BOM Item", 25, 20) def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty): - self._insert_material_receipt() - - from erpnext.stock.doctype.delivery_note.test_delivery_note \ - import test_records as delivery_note_test_records - + 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 + + make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100) - actual_qty_0 = self._get_actual_qty() + actual_qty_0 = get_qty_after_transaction() # make a delivery note based on this invoice - dn = frappe.copy_doc(delivery_note_test_records[0]) - dn.get("items")[0].item_code = item_code - dn.insert() - dn.submit() + dn = create_delivery_note(item_code="_Test Item", + warehouse="_Test Warehouse - _TC", qty=delivered_qty) - actual_qty_1 = self._get_actual_qty() + actual_qty_1 = get_qty_after_transaction() self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) - si_doc = make_sales_invoice(dn.name) - - si = frappe.get_doc(si_doc) - si.posting_date = dn.posting_date - si.debit_to = "_Test Receivable - _TC" - for d in si.get("items"): - d.income_account = "Sales - _TC" - d.cost_center = "_Test Cost Center - _TC" + si = make_sales_invoice(dn.name) si.insert() si.submit() # insert and submit stock entry for sales return - se = frappe.copy_doc(test_records[0]) - se.purpose = "Sales Return" - se.delivery_note_no = dn.name - se.posting_date = "2013-03-10" - se.fiscal_year = "_Test Fiscal Year 2013" - se.get("items")[0].qty = se.get("items")[0].transfer_qty = returned_qty + se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name) - se.insert() - se.submit() - - actual_qty_2 = self._get_actual_qty() + actual_qty_2 = get_qty_after_transaction() self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) return se def test_delivery_note_return_of_non_packing_item(self): - self._clear_stock_account_balance() self._test_delivery_note_return("_Test Item", 5, 2) def test_delivery_note_return_of_packing_item(self): - self._clear_stock_account_balance() self._test_delivery_note_return("_Test Sales BOM Item", 25, 20) def _test_sales_return_jv(self, se): - from erpnext.stock.doctype.stock_entry.stock_entry import make_return_jv jv = make_return_jv(se.name) self.assertEqual(len(jv.get("accounts")), 2) self.assertEqual(jv.get("voucher_type"), "Credit Note") self.assertEqual(jv.get("posting_date"), se.posting_date) - self.assertEqual(jv.get("accounts")[0].get("account"), "_Test Receivable - _TC") + self.assertEqual(jv.get("accounts")[0].get("account"), "Debtors - _TC") self.assertEqual(jv.get("accounts")[0].get("party_type"), "Customer") self.assertEqual(jv.get("accounts")[0].get("party"), "_Test Customer") self.assertTrue(jv.get("accounts")[0].get("against_invoice")) self.assertEqual(jv.get("accounts")[1].get("account"), "Sales - _TC") def test_make_return_jv_for_sales_invoice_non_packing_item(self): - self._clear_stock_account_balance() se = self._test_sales_invoice_return("_Test Item", 5, 2) self._test_sales_return_jv(se) def test_make_return_jv_for_sales_invoice_packing_item(self): - self._clear_stock_account_balance() se = self._test_sales_invoice_return("_Test Sales BOM Item", 25, 20) self._test_sales_return_jv(se) def test_make_return_jv_for_delivery_note_non_packing_item(self): - self._clear_stock_account_balance() se = self._test_delivery_note_return("_Test Item", 5, 2) self._test_sales_return_jv(se) @@ -463,7 +395,6 @@ class TestStockEntry(unittest.TestCase): self._test_sales_return_jv(se) def test_make_return_jv_for_delivery_note_packing_item(self): - self._clear_stock_account_balance() se = self._test_delivery_note_return("_Test Sales BOM Item", 25, 20) self._test_sales_return_jv(se) @@ -471,69 +402,37 @@ class TestStockEntry(unittest.TestCase): self._test_sales_return_jv(se) def _test_delivery_note_return_against_sales_order(self, item_code, delivered_qty, returned_qty): - self._insert_material_receipt() + from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice + + actual_qty_0 = get_qty_after_transaction() + + so = make_sales_order(qty=50) - from erpnext.selling.doctype.sales_order.test_sales_order import test_records as sales_order_test_records - from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice, make_delivery_note - - actual_qty_0 = self._get_actual_qty() - - so = frappe.copy_doc(sales_order_test_records[0]) - so.get("items")[0].item_code = item_code - so.get("items")[0].qty = 5.0 - so.insert() - so.submit() - - dn = make_delivery_note(so.name) - dn.status = "Draft" - dn.posting_date = so.delivery_date - dn.insert() - dn.submit() - - actual_qty_1 = self._get_actual_qty() + dn = create_dn_against_so(so.name, delivered_qty) + + actual_qty_1 = get_qty_after_transaction() self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) si = make_sales_invoice(so.name) - si.posting_date = dn.posting_date - si.debit_to = "_Test Receivable - _TC" - for d in si.get("items"): - d.income_account = "Sales - _TC" - d.cost_center = "_Test Cost Center - _TC" si.insert() si.submit() # insert and submit stock entry for sales return - se = frappe.copy_doc(test_records[0]) - se.purpose = "Sales Return" - se.delivery_note_no = dn.name - se.posting_date = "2013-03-10" - se.fiscal_year = "_Test Fiscal Year 2013" - se.get("items")[0].qty = se.get("items")[0].transfer_qty = returned_qty + se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", + qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name) - se.insert() - se.submit() - - actual_qty_2 = self._get_actual_qty() + actual_qty_2 = get_qty_after_transaction() self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) return se def test_purchase_receipt_return(self): - self._clear_stock_account_balance() - - actual_qty_0 = self._get_actual_qty() - - from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ - import test_records as purchase_receipt_test_records - - from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice + actual_qty_0 = get_qty_after_transaction() # submit purchase receipt - pr = frappe.copy_doc(purchase_receipt_test_records[0]) - pr.insert() - pr.submit() + pr = make_purchase_receipt(item_code="_Test Item", warehouse="_Test Warehouse - _TC", qty=5) - actual_qty_1 = self._get_actual_qty() + actual_qty_1 = get_qty_after_transaction() self.assertEquals(actual_qty_0 + 5, actual_qty_1) @@ -549,52 +448,31 @@ class TestStockEntry(unittest.TestCase): for d in pi.get("taxes"): d.cost_center = "_Test Cost Center - _TC" - pi.run_method("calculate_taxes_and_totals") - pi.bill_no = "NA" pi.insert() pi.submit() # submit purchase return - se = frappe.copy_doc(test_records[0]) - se.purpose = "Purchase Return" - se.purchase_receipt_no = pr.name - se.posting_date = "2013-03-01" - se.fiscal_year = "_Test Fiscal Year 2013" - se.difference_account = "_Test Account Stock Adjustment - _TC" - se.get("items")[0].qty = se.get("items")[0].transfer_qty = 5 - se.get("items")[0].s_warehouse = "_Test Warehouse - _TC" - se.insert() - se.submit() + se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", + qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name) - actual_qty_2 = self._get_actual_qty() + actual_qty_2 = get_qty_after_transaction() self.assertEquals(actual_qty_1 - 5, actual_qty_2) - frappe.db.set_default("company", self.old_default_company) - return se, pr.name def test_over_stock_return(self): from erpnext.stock.doctype.stock_entry.stock_entry import StockOverReturnError - self._clear_stock_account_balance() # out of 10, 5 gets returned prev_se, pr_docname = self.test_purchase_receipt_return() - # submit purchase return - return another 6 qtys so that exception is raised - se = frappe.copy_doc(test_records[0]) - se.purpose = "Purchase Return" - se.purchase_receipt_no = pr_docname - se.difference_account = "_Test Account Stock Adjustment - _TC" - se.posting_date = "2013-03-01" - se.fiscal_year = "_Test Fiscal Year 2013" - se.get("items")[0].qty = se.get("items")[0].transfer_qty = 6 - se.get("items")[0].s_warehouse = "_Test Warehouse - _TC" - + se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", + qty=6, purpose="Purchase Return", purchase_receipt_no=pr_docname, do_not_save=True) + self.assertRaises(StockOverReturnError, se.insert) def _test_purchase_return_jv(self, se): - from erpnext.stock.doctype.stock_entry.stock_entry import make_return_jv jv = make_return_jv(se.name) self.assertEqual(len(jv.get("accounts")), 2) @@ -606,7 +484,6 @@ class TestStockEntry(unittest.TestCase): self.assertTrue(jv.get("accounts")[0].get("against_voucher")) def test_make_return_jv_for_purchase_receipt(self): - self._clear_stock_account_balance() se, pr_name = self.test_purchase_receipt_return() self._test_purchase_return_jv(se) @@ -614,9 +491,8 @@ class TestStockEntry(unittest.TestCase): self._test_purchase_return_jv(se) def _test_purchase_return_return_against_purchase_order(self): - self._clear_stock_account_balance() - actual_qty_0 = self._get_actual_qty() + actual_qty_0 = get_qty_after_transaction() from erpnext.buying.doctype.purchase_order.test_purchase_order \ import test_records as purchase_order_test_records @@ -626,6 +502,7 @@ class TestStockEntry(unittest.TestCase): # submit purchase receipt po = frappe.copy_doc(purchase_order_test_records[0]) + po.transaction_date = nowdate() po.is_subcontracted = None po.get("items")[0].item_code = "_Test Item" po.get("items")[0].rate = 50 @@ -639,7 +516,7 @@ class TestStockEntry(unittest.TestCase): pr.insert() pr.submit() - actual_qty_1 = self._get_actual_qty() + actual_qty_1 = get_qty_after_transaction() self.assertEquals(actual_qty_0 + 10, actual_qty_1) @@ -660,33 +537,15 @@ class TestStockEntry(unittest.TestCase): pi.submit() # submit purchase return - se = frappe.copy_doc(test_records[0]) - se.purpose = "Purchase Return" - se.purchase_receipt_no = pr.name - se.difference_account = "_Test Account Stock Adjustment - _TC" - se.posting_date = "2013-03-01" - se.fiscal_year = "_Test Fiscal Year 2013" - se.get("items")[0].qty = se.get("items")[0].transfer_qty = 5 - se.get("items")[0].s_warehouse = "_Test Warehouse - _TC" - se.insert() - se.submit() + se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", + qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name) - actual_qty_2 = self._get_actual_qty() + actual_qty_2 = get_qty_after_transaction() self.assertEquals(actual_qty_1 - 5, actual_qty_2) - frappe.db.set_default("company", self.old_default_company) - return se, pr.name - def _clear_stock_account_balance(self): - frappe.db.sql("delete from `tabStock Ledger Entry`") - frappe.db.sql("""delete from `tabBin`""") - frappe.db.sql("""delete from `tabGL Entry`""") - - self.old_default_company = frappe.db.get_default("company") - frappe.db.set_default("company", "_Test Company") - def test_serial_no_not_reqd(self): se = frappe.copy_doc(test_records[0]) se.get("items")[0].serial_no = "ABCD" @@ -720,7 +579,6 @@ class TestStockEntry(unittest.TestCase): self.assertRaises(SerialNoQtyError, se.submit) def test_serial_no_transfer_in(self): - self._clear_stock_account_balance() se = frappe.copy_doc(test_records[0]) se.get("items")[0].item_code = "_Test Serialized Item" se.get("items")[0].qty = 2 @@ -736,7 +594,6 @@ class TestStockEntry(unittest.TestCase): self.assertFalse(frappe.db.get_value("Serial No", "ABCD", "warehouse")) def test_serial_no_not_exists(self): - self._clear_stock_account_balance() frappe.db.sql("delete from `tabSerial No` where name in ('ABCD', 'EFGH')") make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC") se = frappe.copy_doc(test_records[0]) @@ -752,7 +609,6 @@ class TestStockEntry(unittest.TestCase): self.assertRaises(SerialNoNotExistsError, se.submit) def test_serial_duplicate(self): - self._clear_stock_account_balance() se, serial_nos = self.test_serial_by_series() se = frappe.copy_doc(test_records[0]) @@ -764,7 +620,6 @@ class TestStockEntry(unittest.TestCase): self.assertRaises(SerialNoDuplicateError, se.submit) def test_serial_by_series(self): - self._clear_stock_account_balance() se = make_serialized_item() serial_nos = get_serial_nos(se.get("items")[0].serial_no) @@ -790,7 +645,6 @@ class TestStockEntry(unittest.TestCase): self.assertRaises(SerialNoItemError, se.submit) def test_serial_move(self): - self._clear_stock_account_balance() se = make_serialized_item() serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] @@ -810,7 +664,6 @@ class TestStockEntry(unittest.TestCase): self.assertTrue(frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse - _TC") def test_serial_warehouse_error(self): - self._clear_stock_account_balance() make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC") t = make_serialized_item() @@ -828,7 +681,6 @@ class TestStockEntry(unittest.TestCase): self.assertRaises(SerialNoWarehouseError, se.submit) def test_serial_cancel(self): - self._clear_stock_account_balance() se, serial_nos = self.test_serial_by_series() se.cancel() @@ -837,7 +689,6 @@ class TestStockEntry(unittest.TestCase): def test_warehouse_company_validation(self): set_perpetual_inventory(0) - self._clear_stock_account_balance() frappe.get_doc("User", "test2@example.com")\ .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") frappe.set_user("test2@example.com") @@ -880,25 +731,26 @@ class TestStockEntry(unittest.TestCase): "test2@example.com", parenttype="User Permission") def test_freeze_stocks(self): - self._clear_stock_account_balance() frappe.db.set_value('Stock Settings', None,'stock_auth_role', '') # test freeze_stocks_upto - date_newer_than_test_records = add_days(getdate(test_records[0]['posting_date']), 5) - frappe.db.set_value("Stock Settings", None, "stock_frozen_upto", date_newer_than_test_records) + frappe.db.set_value("Stock Settings", None, "stock_frozen_upto", add_days(nowdate(), 5)) se = frappe.copy_doc(test_records[0]).insert() - self.assertRaises (StockFreezeError, se.submit) + self.assertRaises(StockFreezeError, se.submit) + frappe.db.set_value("Stock Settings", None, "stock_frozen_upto", '') # test freeze_stocks_upto_days frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 7) - se = frappe.copy_doc(test_records[0]).insert() - self.assertRaises (StockFreezeError, se.submit) + se = frappe.copy_doc(test_records[0]) + se.posting_date = add_days(nowdate(), -15) + se.insert() + self.assertRaises(StockFreezeError, se.submit) frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0) def test_production_order(self): - bom_no = frappe.db.get_value("BOM", {"item": "_Test FG Item 2", - "is_default": 1, "docstatus": 1}) + bom_no, bom_operation_cost = frappe.db.get_value("BOM", {"item": "_Test FG Item 2", + "is_default": 1, "docstatus": 1}, ["name", "operating_cost"]) production_order = frappe.new_doc("Production Order") production_order.update({ @@ -907,13 +759,13 @@ class TestStockEntry(unittest.TestCase): "production_item": "_Test FG Item 2", "bom_no": bom_no, "qty": 1.0, - "stock_uom": "Nos", + "stock_uom": "_Test UOM", "wip_warehouse": "_Test Warehouse - _TC" }) production_order.insert() production_order.submit() - self._insert_material_receipt() + make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100) stock_entry = frappe.new_doc("Stock Entry") stock_entry.update({ @@ -925,10 +777,15 @@ class TestStockEntry(unittest.TestCase): }) stock_entry.get_items() - fg_rate = [d.amount for d in stock_entry.get("items") if d.item_code=="_Test FG Item 2"][0] - self.assertEqual(fg_rate, 1200.00) - fg_rate = [d.amount for d in stock_entry.get("items") if d.item_code=="_Test Item"][0] - self.assertEqual(fg_rate, 100.00) + rm_cost = 0 + for d in stock_entry.get("items"): + if d.s_warehouse: + rm_cost += flt(d.amount) + + fg_cost = filter(lambda x: x.item_code=="_Test FG Item 2", stock_entry.get("items"))[0].amount + + self.assertEqual(fg_cost, rm_cost + bom_operation_cost + stock_entry.additional_operating_cost) + def test_variant_production_order(self): bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item", @@ -941,7 +798,7 @@ class TestStockEntry(unittest.TestCase): "production_item": "_Test Variant Item-S", "bom_no": bom_no, "qty": 1.0, - "stock_uom": "Nos", + "stock_uom": "_Test UOM", "wip_warehouse": "_Test Warehouse - _TC" }) production_order.insert() @@ -968,12 +825,15 @@ def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None): return se def make_stock_entry(**args): + from erpnext.accounts.utils import get_fiscal_year + s = frappe.new_doc("Stock Entry") args = frappe._dict(args) if args.posting_date: s.posting_date = args.posting_date if args.posting_time: s.posting_time = args.posting_time + if not args.purpose: if args.source and args.target: s.purpose = "Material Transfer" @@ -981,19 +841,43 @@ def make_stock_entry(**args): s.purpose = "Material Issue" else: s.purpose = "Material Receipt" + else: + s.purpose = args.purpose + s.company = args.company or "_Test Company" + s.fiscal_year = get_fiscal_year(s.posting_date)[0] + s.purchase_receipt_no = args.purchase_receipt_no + s.delivery_note_no = args.delivery_note_no + s.sales_invoice_no = args.sales_invoice_no + s.difference_account = args.difference_account or "Stock Adjustment - _TC" + s.append("items", { - "item_code": args.item or args.item_code, + "item_code": args.item or args.item_code or "_Test Item", "s_warehouse": args.from_warehouse or args.source, "t_warehouse": args.to_warehouse or args.target, "qty": args.qty, "incoming_rate": args.incoming_rate, - "conversion_factor": 1.0 + "expense_account": args.expense_account or "Stock Adjustment - _TC", + "conversion_factor": 1.0, + "cost_center": "_Test Cost Center - _TC" }) - s.posting_date= "2013-01-01" - s.fiscal_year= "_Test Fiscal Year 2013" - s.insert() - s.submit() + + if not args.do_not_save: + s.insert() + if not args.do_not_submit: + s.submit() return s + +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")) 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 7b0d801f89..c006a07d6b 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -6,274 +6,114 @@ from __future__ import unicode_literals import frappe, unittest -from frappe.utils import flt -import json +from frappe.utils import flt, nowdate, nowtime from erpnext.accounts.utils import get_fiscal_year, get_stock_and_account_difference - +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 class TestStockReconciliation(unittest.TestCase): def setUp(self): frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) + self.insert_existing_sle() def test_reco_for_fifo(self): - frappe.defaults.set_global_default("auto_accounting_for_stock", 0) - # [[qty, valuation_rate, posting_date, - # posting_time, expected_stock_value, bin_qty, bin_valuation]] - input_data = [ - [50, 1000, "2012-12-26", "12:00", 50000, 45, 48000], - [5, 1000, "2012-12-26", "12:00", 5000, 0, 0], - [15, 1000, "2012-12-26", "12:00", 15000, 10, 12000], - [25, 900, "2012-12-26", "12:00", 22500, 20, 22500], - [20, 500, "2012-12-26", "12:00", 10000, 15, 18000], - [50, 1000, "2013-01-01", "12:00", 50000, 65, 68000], - [5, 1000, "2013-01-01", "12:00", 5000, 20, 23000], - ["", 1000, "2012-12-26", "12:05", 15000, 10, 12000], - [20, "", "2012-12-26", "12:05", 16000, 15, 18000], - [10, 2000, "2012-12-26", "12:10", 20000, 5, 6000], - [1, 1000, "2012-12-01", "00:00", 1000, 11, 13200], - [0, "", "2012-12-26", "12:10", 0, -5, -6000] - ] - - for d in input_data: - self.cleanup_data() - self.insert_existing_sle("FIFO") - stock_reco = self.submit_stock_reconciliation(d[0], d[1], d[2], d[3]) - - # check stock value - res = frappe.db.sql("""select stock_value from `tabStock Ledger Entry` - where item_code = '_Test Item' and warehouse = '_Test Warehouse - _TC' - and posting_date = %s and posting_time = %s order by name desc limit 1""", - (d[2], d[3])) - self.assertEqual(res and flt(res[0][0]) or 0, d[4]) - - # check bin qty and stock value - bin = frappe.db.sql("""select actual_qty, stock_value from `tabBin` - where item_code = '_Test Item' and warehouse = '_Test Warehouse - _TC'""") - - self.assertEqual(bin and [flt(bin[0][0]), flt(bin[0][1])] or [], [d[5], d[6]]) - - # no gl entries - gl_entries = frappe.db.sql("""select name from `tabGL Entry` - where voucher_type = 'Stock Reconciliation' and voucher_no = %s""", - stock_reco.name) - self.assertFalse(gl_entries) - - + self._test_reco_sle_gle("FIFO") + def test_reco_for_moving_average(self): - frappe.defaults.set_global_default("auto_accounting_for_stock", 0) + self._test_reco_sle_gle("Moving Average") + + def _test_reco_sle_gle(self, valuation_method): + set_perpetual_inventory() # [[qty, valuation_rate, posting_date, # posting_time, expected_stock_value, bin_qty, bin_valuation]] - input_data = [ - [50, 1000, "2012-12-26", "12:00", 50000, 45, 48000], - [5, 1000, "2012-12-26", "12:00", 5000, 0, 0], - [15, 1000, "2012-12-26", "12:00", 15000, 10, 11500], - [25, 900, "2012-12-26", "12:00", 22500, 20, 22500], - [20, 500, "2012-12-26", "12:00", 10000, 15, 18000], - [50, 1000, "2013-01-01", "12:00", 50000, 65, 68000], - [5, 1000, "2013-01-01", "12:00", 5000, 20, 23000], - ["", 1000, "2012-12-26", "12:05", 15000, 10, 11500], - [20, "", "2012-12-26", "12:05", 18000, 15, 18000], - [10, 2000, "2012-12-26", "12:10", 20000, 5, 7600], - [1, 1000, "2012-12-01", "00:00", 1000, 11, 12512.73], - [0, "", "2012-12-26", "12:10", 0, -5, -5142.86] - - ] - - for d in input_data: - self.cleanup_data() - self.insert_existing_sle("Moving Average") - stock_reco = self.submit_stock_reconciliation(d[0], d[1], d[2], d[3]) - - # check stock value in sle - res = frappe.db.sql("""select stock_value from `tabStock Ledger Entry` - where item_code = '_Test Item' and warehouse = '_Test Warehouse - _TC' - and posting_date = %s and posting_time = %s order by name desc limit 1""", - (d[2], d[3])) - - self.assertEqual(res and flt(res[0][0], 4) or 0, d[4]) - - # bin qty and stock value - bin = frappe.db.sql("""select actual_qty, stock_value from `tabBin` - where item_code = '_Test Item' and warehouse = '_Test Warehouse - _TC'""") - - self.assertEqual(bin and [flt(bin[0][0]), flt(bin[0][1], 4)] or [], - [flt(d[5]), flt(d[6])]) - - # no gl entries - gl_entries = frappe.db.sql("""select name from `tabGL Entry` - where voucher_type = 'Stock Reconciliation' and voucher_no = %s""", - stock_reco.name) - self.assertFalse(gl_entries) - - def test_reco_fifo_gl_entries(self): - frappe.defaults.set_global_default("auto_accounting_for_stock", 1) - - # [[qty, valuation_rate, posting_date, posting_time, stock_in_hand_debit]] input_data = [ [50, 1000, "2012-12-26", "12:00"], - [5, 1000, "2012-12-26", "12:00"], - [15, 1000, "2012-12-26", "12:00"], [25, 900, "2012-12-26", "12:00"], - [20, 500, "2012-12-26", "12:00"], - ["", 1000, "2012-12-26", "12:05"], + ["", 1000, "2012-12-20", "12:05"], [20, "", "2012-12-26", "12:05"], - [10, 2000, "2012-12-26", "12:10"], - [0, "", "2012-12-26", "12:10"], - [50, 1000, "2013-01-01", "12:00"], - [5, 1000, "2013-01-01", "12:00"], - [1, 1000, "2012-12-01", "00:00"], + [0, "", "2012-12-31", "12:10"] ] for d in input_data: - self.cleanup_data() - self.insert_existing_sle("FIFO") - self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"])) - stock_reco = self.submit_stock_reconciliation(d[0], d[1], d[2], d[3]) - - - self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"])) - - stock_reco.cancel() - self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"])) - - frappe.defaults.set_global_default("auto_accounting_for_stock", 0) - - def test_reco_moving_average_gl_entries(self): - frappe.defaults.set_global_default("auto_accounting_for_stock", 1) - - # [[qty, valuation_rate, posting_date, - # posting_time, stock_in_hand_debit]] - input_data = [ - [50, 1000, "2012-12-26", "12:00", 36500], - [5, 1000, "2012-12-26", "12:00", -8500], - [15, 1000, "2012-12-26", "12:00", 1500], - [25, 900, "2012-12-26", "12:00", 9000], - [20, 500, "2012-12-26", "12:00", -3500], - ["", 1000, "2012-12-26", "12:05", 1500], - [20, "", "2012-12-26", "12:05", 4500], - [10, 2000, "2012-12-26", "12:10", 6500], - [0, "", "2012-12-26", "12:10", -13500], - [50, 1000, "2013-01-01", "12:00", 50000], - [5, 1000, "2013-01-01", "12:00", 5000], - [1, 1000, "2012-12-01", "00:00", 1000], - - ] - - for d in input_data: - self.cleanup_data() - self.insert_existing_sle("Moving Average") - stock_reco = self.submit_stock_reconciliation(d[0], d[1], d[2], d[3]) - self.assertFalse(get_stock_and_account_difference(["_Test Warehouse - _TC"])) - - # cancel - stock_reco.cancel() - self.assertFalse(get_stock_and_account_difference(["_Test Warehouse - _TC"])) - - frappe.defaults.set_global_default("auto_accounting_for_stock", 0) - - - def cleanup_data(self): - frappe.db.sql("delete from `tabStock Ledger Entry`") - frappe.db.sql("delete from tabBin") - frappe.db.sql("delete from `tabGL Entry`") - - def submit_stock_reconciliation(self, qty, rate, posting_date, posting_time): - stock_reco = frappe.get_doc({ - "doctype": "Stock Reconciliation", - "posting_date": posting_date, - "posting_time": posting_time, - "fiscal_year": get_fiscal_year(posting_date)[0], - "company": "_Test Company", - "expense_account": "Stock Adjustment - _TC", - "cost_center": "_Test Cost Center - _TC", - "items": [{ + repost_stock_as_per_valuation_method(valuation_method) + + last_sle = get_previous_sle({ "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC", - "qty": qty, - "valuation_rate": rate - }] - }) - stock_reco.insert() - stock_reco.submit() - frappe.db.commit() - return stock_reco + "posting_date": d[2], + "posting_time": d[3] + }) - def insert_existing_sle(self, valuation_method): - frappe.db.set_value("Item", "_Test Item", "valuation_method", valuation_method) - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) + # submit stock reconciliation + stock_reco = create_stock_reconciliation(qty=d[0], rate=d[1], + posting_date=d[2], posting_time=d[3]) + + # check stock value + sle = frappe.db.sql("""select * from `tabStock Ledger Entry` + where voucher_type='Stock Reconciliation' and voucher_no=%s""", stock_reco.name, as_dict=1) + + qty_after_transaction = flt(d[0]) if d[0] != "" else flt(last_sle.get("qty_after_transaction")) + + valuation_rate = flt(d[1]) if d[1] != "" else flt(last_sle.get("valuation_rate")) + + if qty_after_transaction == last_sle.get("qty_after_transaction") \ + and valuation_rate == last_sle.get("valuation_rate"): + self.assertFalse(sle) + else: + self.assertEqual(sle[0].qty_after_transaction, qty_after_transaction) + self.assertEqual(sle[0].stock_value, qty_after_transaction * valuation_rate) + + # 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() + + self.assertFalse(frappe.db.get_value("Stock Ledger Entry", + {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) + + self.assertFalse(frappe.db.get_value("GL Entry", + {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) + + set_perpetual_inventory(0) - stock_entry = { - "company": "_Test Company", - "doctype": "Stock Entry", - "posting_date": "2012-12-12", - "posting_time": "01:00", - "purpose": "Material Receipt", - "fiscal_year": "_Test Fiscal Year 2012", - "items": [ - { - "conversion_factor": 1.0, - "doctype": "Stock Entry Detail", - "item_code": "_Test Item", - "parentfield": "items", - "incoming_rate": 1000, - "qty": 20.0, - "stock_uom": "_Test UOM", - "transfer_qty": 20.0, - "uom": "_Test UOM", - "t_warehouse": "_Test Warehouse - _TC", - "expense_account": "Stock Adjustment - _TC", - "cost_center": "_Test Cost Center - _TC" - } - ] - } + def insert_existing_sle(self): + 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, incoming_rate=700) - pr = frappe.copy_doc(stock_entry) - pr.insert() - pr.submit() + make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item", + source="_Test Warehouse - _TC", qty=15) - pr1 = frappe.copy_doc(stock_entry) - pr1.posting_date = "2012-12-15" - pr1.posting_time = "02:00" - pr1.get("items")[0].qty = 10 - pr1.get("items")[0].transfer_qty = 10 - pr1.get("items")[0].incoming_rate = 700 - pr1.insert() - pr1.submit() - - pr2 = frappe.copy_doc(stock_entry) - pr2.posting_date = "2012-12-25" - pr2.posting_time = "03:00" - pr2.purpose = "Material Issue" - pr2.get("items")[0].s_warehouse = "_Test Warehouse - _TC" - pr2.get("items")[0].t_warehouse = None - pr2.get("items")[0].qty = 15 - pr2.get("items")[0].transfer_qty = 15 - pr2.get("items")[0].incoming_rate = 0 - pr2.insert() - pr2.submit() - - pr3 = frappe.copy_doc(stock_entry) - pr3.posting_date = "2012-12-31" - pr3.posting_time = "08:00" - pr3.purpose = "Material Issue" - pr3.get("items")[0].s_warehouse = "_Test Warehouse - _TC" - pr3.get("items")[0].t_warehouse = None - pr3.get("items")[0].qty = 20 - pr3.get("items")[0].transfer_qty = 20 - pr3.get("items")[0].incoming_rate = 0 - pr3.insert() - pr3.submit() - - - pr4 = frappe.copy_doc(stock_entry) - pr4.posting_date = "2013-01-05" - pr4.fiscal_year = "_Test Fiscal Year 2013" - pr4.posting_time = "07:00" - pr4.get("items")[0].qty = 15 - pr4.get("items")[0].transfer_qty = 15 - pr4.get("items")[0].incoming_rate = 1200 - pr4.insert() - pr4.submit() + make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item", + target="_Test Warehouse - _TC", qty=15, incoming_rate=1200) + +def create_stock_reconciliation(**args): + args = frappe._dict(args) + sr = frappe.new_doc("Stock Reconciliation") + sr.posting_date = args.posting_date or nowdate() + sr.posting_time = args.posting_time or nowtime() + sr.company = args.company or "_Test Company" + sr.fiscal_year = get_fiscal_year(sr.posting_date)[0] + sr.expense_account = args.expense_account or "Stock Adjustment - _TC" + sr.cost_center = args.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", + "qty": args.qty, + "valuation_rate": args.rate + }) + sr.insert() + sr.submit() + return sr +def repost_stock_as_per_valuation_method(valuation_method): + frappe.db.set_value("Item", "_Test Item", "valuation_method", valuation_method) + update_entries_after({ + "item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC", + }, allow_negative_stock=1) test_dependencies = ["Item", "Warehouse"]