Test case cleanup and fixes

This commit is contained in:
Nabin Hait 2015-03-13 08:14:31 +05:30
parent c8c1d1c693
commit 7c9d003917
24 changed files with 864 additions and 1270 deletions

View File

@ -4,27 +4,26 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest, frappe import unittest, frappe
from frappe.utils import flt from frappe.utils import flt
from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year
class TestJournalEntry(unittest.TestCase): class TestJournalEntry(unittest.TestCase):
def test_journal_entry_with_against_jv(self): def test_journal_entry_with_against_jv(self):
jv_invoice = frappe.copy_doc(test_records[2]) jv_invoice = frappe.copy_doc(test_records[2])
base_jv = frappe.copy_doc(test_records[0]) base_jv = frappe.copy_doc(test_records[0])
self.jv_against_voucher_testcase(base_jv, jv_invoice) self.jv_against_voucher_testcase(base_jv, jv_invoice)
def test_jv_against_sales_order(self): def test_jv_against_sales_order(self):
from erpnext.selling.doctype.sales_order.test_sales_order \ from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
import test_records as so_test_records
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]) base_jv = frappe.copy_doc(test_records[0])
self.jv_against_voucher_testcase(base_jv, sales_order) self.jv_against_voucher_testcase(base_jv, sales_order)
def test_jv_against_purchase_order(self): def test_jv_against_purchase_order(self):
from erpnext.buying.doctype.purchase_order.test_purchase_order \ from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
import test_records as po_test_records
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]) base_jv = frappe.copy_doc(test_records[1])
self.jv_against_voucher_testcase(base_jv, purchase_order) self.jv_against_voucher_testcase(base_jv, purchase_order)
@ -35,7 +34,6 @@ class TestJournalEntry(unittest.TestCase):
'Purchase Order': "against_purchase_order" 'Purchase Order': "against_purchase_order"
} }
self.clear_account_balance()
test_voucher.insert() test_voucher.insert()
test_voucher.submit() test_voucher.submit()
@ -104,78 +102,58 @@ class TestJournalEntry(unittest.TestCase):
def test_monthly_budget_crossed_ignore(self): def test_monthly_budget_crossed_ignore(self):
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore") frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
self.clear_account_balance()
jv = frappe.copy_doc(test_records[0]) existing_expense = self.get_actual_expense("2013-02-28")
jv.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" current_expense = - existing_expense + 20000 if existing_expense < 0 else 20000
jv.get("accounts")[1].cost_center = "_Test Cost Center - _TC"
jv.get("accounts")[1].debit = 20000.0 jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv.get("accounts")[0].credit = 20000.0 "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC", submit=True)
jv.insert()
jv.submit()
self.assertTrue(frappe.db.get_value("GL Entry", self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv.name})) {"voucher_type": "Journal Entry", "voucher_no": jv.name}))
def test_monthly_budget_crossed_stop(self): def test_monthly_budget_crossed_stop(self):
from erpnext.accounts.utils import BudgetError
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop") frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop")
self.clear_account_balance()
jv = frappe.copy_doc(test_records[0]) existing_expense = self.get_actual_expense("2013-02-28")
jv.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" current_expense = - existing_expense + 20000 if existing_expense < 0 else 20000
jv.get("accounts")[1].cost_center = "_Test Cost Center - _TC"
jv.get("accounts")[1].debit = 20000.0 jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv.get("accounts")[0].credit = 20000.0 "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC")
jv.insert()
self.assertRaises(BudgetError, jv.submit) self.assertRaises(BudgetError, jv.submit)
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore") frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
def test_yearly_budget_crossed_stop(self): def test_yearly_budget_crossed_stop(self):
from erpnext.accounts.utils import BudgetError
self.clear_account_balance()
self.test_monthly_budget_crossed_ignore() self.test_monthly_budget_crossed_ignore()
frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Stop") frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Stop")
jv = frappe.copy_doc(test_records[0]) existing_expense = self.get_actual_expense("2013-02-28")
jv.posting_date = "2013-08-12" current_expense = - existing_expense + 150000 if existing_expense < 0 else 150000
jv.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC"
jv.get("accounts")[1].cost_center = "_Test Cost Center - _TC" jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv.get("accounts")[1].debit = 150000.0 "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC")
jv.get("accounts")[0].credit = 150000.0
jv.insert()
self.assertRaises(BudgetError, jv.submit) self.assertRaises(BudgetError, jv.submit)
frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Ignore") frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Ignore")
def test_monthly_budget_on_cancellation(self): def test_monthly_budget_on_cancellation(self):
from erpnext.accounts.utils import BudgetError
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop") frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop")
self.clear_account_balance()
jv = frappe.copy_doc(test_records[0]) existing_expense = self.get_actual_expense("2013-02-28")
jv.get("accounts")[0].update({ current_expense = - existing_expense - 30000 if existing_expense < 0 else 30000
"account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC", jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"party_type": None, "_Test Account Bank Account - _TC", current_expense, "_Test Cost Center - _TC", submit=True)
"party": None,
"credit": 30000.0
})
jv.get("accounts")[1].debit = 30000.0
jv.submit()
self.assertTrue(frappe.db.get_value("GL Entry", self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv.name})) {"voucher_type": "Journal Entry", "voucher_no": jv.name}))
jv1 = frappe.copy_doc(test_records[0]) jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv1.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" "_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC", submit=True)
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()
self.assertTrue(frappe.db.get_value("GL Entry", self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv1.name})) {"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
@ -184,8 +162,41 @@ class TestJournalEntry(unittest.TestCase):
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore") frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
def clear_account_balance(self): def get_actual_expense(self, monthly_end_date):
frappe.db.sql("""delete from `tabGL Entry`""") 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') test_records = frappe.get_test_records('Journal Entry')

View File

@ -1,6 +1,6 @@
[ [
{ {
"cheque_date": "2013-02-14", "cheque_date": "2013-03-14",
"cheque_no": "33", "cheque_no": "33",
"company": "_Test Company", "company": "_Test Company",
"doctype": "Journal Entry", "doctype": "Journal Entry",
@ -28,6 +28,8 @@
"user_remark": "test", "user_remark": "test",
"voucher_type": "Bank Entry" "voucher_type": "Bank Entry"
}, },
{ {
"cheque_date": "2013-02-14", "cheque_date": "2013-02-14",
"cheque_no": "33", "cheque_no": "33",
@ -57,6 +59,8 @@
"user_remark": "test", "user_remark": "test",
"voucher_type": "Bank Entry" "voucher_type": "Bank Entry"
}, },
{ {
"cheque_date": "2013-02-14", "cheque_date": "2013-02-14",
"cheque_no": "33", "cheque_no": "33",

View File

@ -4,32 +4,25 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest, frappe, json import unittest, frappe, json
from frappe.utils import flt 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"] test_dependencies = ["Item"]
class TestPaymentTool(unittest.TestCase): class TestPaymentTool(unittest.TestCase):
def test_make_journal_entry(self): 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() 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_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"}) base_supplier_jv = self.create_against_jv(jv_test_records[1], { "party": "_Test Supplier 1"})
# Create SO with partial outstanding # Create SO with partial outstanding
so1 = self.create_voucher(so_test_records[0], { so1 = make_sales_order(customer="_Test Customer 3", qty=10, rate=100)
"customer": "_Test Customer 3"
})
self.create_against_jv(jv_test_records[0], { self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3", "party": "_Test Customer 3",
@ -39,9 +32,7 @@ class TestPaymentTool(unittest.TestCase):
#Create SO with no outstanding #Create SO with no outstanding
so2 = self.create_voucher(so_test_records[0], { so2 = make_sales_order(customer="_Test Customer 3")
"customer": "_Test Customer 3"
})
self.create_against_jv(jv_test_records[0], { self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3", "party": "_Test Customer 3",
@ -51,9 +42,7 @@ class TestPaymentTool(unittest.TestCase):
}) })
# Purchase order # Purchase order
po = self.create_voucher(po_test_records[1], { po = create_purchase_order(supplier="_Test Supplier 1")
"supplier": "_Test Supplier 1"
})
#Create SI with partial outstanding #Create SI with partial outstanding
si1 = self.create_voucher(si_test_records[0], { si1 = self.create_voucher(si_test_records[0], {

View File

@ -5,43 +5,48 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest import unittest
import frappe 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): class TestPeriodClosingVoucher(unittest.TestCase):
def test_closing_entry(self): def test_closing_entry(self):
# clear GL Entries make_journal_entry("_Test Account Bank Account - _TC", "Sales - _TC", 400,
frappe.db.sql("""delete from `tabGL Entry`""") "_Test Cost Center - _TC", submit=True)
jv = frappe.copy_doc(jv_records[2])
jv.insert()
jv.submit()
jv1 = frappe.copy_doc(jv_records[0]) make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv1.get("accounts")[1].account = "_Test Account Cost for Goods Sold - _TC" "_Test Account Bank Account - _TC", 600, "_Test Cost Center - _TC", submit=True)
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]) 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
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.insert()
pcv.submit() pcv.submit()
gl_entries = frappe.db.sql("""select account, debit, credit return pcv
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)
test_dependencies = ["Customer", "Cost Center"] test_dependencies = ["Customer", "Cost Center"]

View File

@ -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"
}]

View File

@ -7,7 +7,6 @@
"customer_name": "_Test Customer", "customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC", "debit_to": "_Test Receivable - _TC",
"doctype": "Sales Invoice", "doctype": "Sales Invoice",
"due_date": "2013-01-23",
"items": [ "items": [
{ {
"amount": 500.0, "amount": 500.0,
@ -49,7 +48,6 @@
} }
], ],
"plc_conversion_rate": 1.0, "plc_conversion_rate": 1.0,
"posting_date": "2013-01-23",
"price_list_currency": "INR", "price_list_currency": "INR",
"sales_team": [ "sales_team": [
{ {
@ -68,6 +66,8 @@
"selling_price_list": "_Test Price List", "selling_price_list": "_Test Price List",
"territory": "_Test Territory" "territory": "_Test Territory"
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"conversion_rate": 1.0, "conversion_rate": 1.0,
@ -76,7 +76,6 @@
"customer_name": "_Test Customer", "customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC", "debit_to": "_Test Receivable - _TC",
"doctype": "Sales Invoice", "doctype": "Sales Invoice",
"due_date": "2013-03-07",
"items": [ "items": [
{ {
"amount": 500.0, "amount": 500.0,
@ -94,7 +93,6 @@
"qty": 1.0 "qty": 1.0
} }
], ],
"fiscal_year": "_Test Fiscal Year 2013",
"base_grand_total": 630.0, "base_grand_total": 630.0,
"grand_total": 630.0, "grand_total": 630.0,
"is_pos": 0, "is_pos": 0,
@ -119,7 +117,6 @@
} }
], ],
"plc_conversion_rate": 1.0, "plc_conversion_rate": 1.0,
"posting_date": "2013-03-07",
"price_list_currency": "INR", "price_list_currency": "INR",
"selling_price_list": "_Test Price List", "selling_price_list": "_Test Price List",
"territory": "_Test Territory" "territory": "_Test Territory"
@ -132,7 +129,6 @@
"customer_name": "_Test Customer", "customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC", "debit_to": "_Test Receivable - _TC",
"doctype": "Sales Invoice", "doctype": "Sales Invoice",
"due_date": "2013-01-23",
"items": [ "items": [
{ {
"cost_center": "_Test Cost Center - _TC", "cost_center": "_Test Cost Center - _TC",
@ -245,7 +241,6 @@
} }
], ],
"plc_conversion_rate": 1.0, "plc_conversion_rate": 1.0,
"posting_date": "2013-01-23",
"price_list_currency": "INR", "price_list_currency": "INR",
"selling_price_list": "_Test Price List", "selling_price_list": "_Test Price List",
"territory": "_Test Territory" "territory": "_Test Territory"
@ -258,7 +253,6 @@
"customer_name": "_Test Customer", "customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC", "debit_to": "_Test Receivable - _TC",
"doctype": "Sales Invoice", "doctype": "Sales Invoice",
"due_date": "2013-01-23",
"items": [ "items": [
{ {
"cost_center": "_Test Cost Center - _TC", "cost_center": "_Test Cost Center - _TC",
@ -382,7 +376,6 @@
} }
], ],
"plc_conversion_rate": 1.0, "plc_conversion_rate": 1.0,
"posting_date": "2013-01-23",
"price_list_currency": "INR", "price_list_currency": "INR",
"selling_price_list": "_Test Price List", "selling_price_list": "_Test Price List",
"territory": "_Test Territory" "territory": "_Test Territory"

View File

@ -3,8 +3,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
import unittest, json, copy import unittest, copy
from frappe.utils import flt
from erpnext.accounts.utils import get_stock_and_account_difference 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.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.projects.doctype.time_log_batch.test_time_log_batch import * from erpnext.projects.doctype.time_log_batch.test_time_log_batch import *
@ -93,8 +92,8 @@ class TestSalesInvoice(unittest.TestCase):
expected_values = { expected_values = {
"keys": ["price_list_rate", "discount_percentage", "rate", "amount", "keys": ["price_list_rate", "discount_percentage", "rate", "amount",
"base_price_list_rate", "base_rate", "base_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 100": [1, 0, 1, 10, 50, 50, 500],
"_Test Item Home Desktop 200": [150, 0, 150, 750, 7500, 7500, 37500], "_Test Item Home Desktop 200": [3, 0, 3, 15, 150, 150, 750],
} }
# check if children are saved # check if children are saved
@ -106,8 +105,10 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(d.get(k), expected_values[d.item_code][i]) self.assertEquals(d.get(k), expected_values[d.item_code][i])
# check net total # check net total
self.assertEquals(si.net_total, 1250) self.assertEquals(si.total, 25)
self.assertEquals(si.base_net_total, 62500) self.assertEquals(si.base_total, 1250)
self.assertEquals(si.net_total, 25)
self.assertEquals(si.base_net_total, 1250)
# check tax calculation # check tax calculation
expected_values = { expected_values = {
@ -385,7 +386,6 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(w.outstanding_amount, w.base_grand_total) self.assertEquals(w.outstanding_amount, w.base_grand_total)
def test_payment(self): def test_payment(self):
frappe.db.sql("""delete from `tabGL Entry`""")
w = self.make() w = self.make()
from erpnext.accounts.doctype.journal_entry.test_journal_entry \ from erpnext.accounts.doctype.journal_entry.test_journal_entry \
@ -396,12 +396,10 @@ class TestSalesInvoice(unittest.TestCase):
jv.insert() jv.insert()
jv.submit() jv.submit()
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 161.8)
161.8)
jv.cancel() jv.cancel()
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8)
561.8)
def test_time_log_batch(self): def test_time_log_batch(self):
delete_time_log_and_batch() delete_time_log_and_batch()
@ -430,7 +428,6 @@ class TestSalesInvoice(unittest.TestCase):
delete_time_log_and_batch() delete_time_log_and_batch()
def test_sales_invoice_gl_entry_without_aii(self): def test_sales_invoice_gl_entry_without_aii(self):
self.clear_stock_account_balance()
set_perpetual_inventory(0) set_perpetual_inventory(0)
si = frappe.copy_doc(test_records[1]) si = frappe.copy_doc(test_records[1])
si.insert() si.insert()
@ -463,7 +460,6 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle) self.assertFalse(gle)
def test_pos_gl_entry_with_aii(self): def test_pos_gl_entry_with_aii(self):
self.clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
self.make_pos_setting() self.make_pos_setting()
@ -501,8 +497,8 @@ class TestSalesInvoice(unittest.TestCase):
[pos["items"][0]["income_account"], 0.0, 500.0], [pos["items"][0]["income_account"], 0.0, 500.0],
[pos["taxes"][0]["account_head"], 0.0, 80.0], [pos["taxes"][0]["account_head"], 0.0, 80.0],
[pos["taxes"][1]["account_head"], 0.0, 50.0], [pos["taxes"][1]["account_head"], 0.0, 50.0],
[stock_in_hand, 0.0, 75.0], [stock_in_hand, 0.0, abs(sle.stock_value_difference)],
[pos["items"][0]["expense_account"], 75.0, 0.0], [pos["items"][0]["expense_account"], abs(sle.stock_value_difference), 0.0],
[si.debit_to, 0.0, 600.0], [si.debit_to, 0.0, 600.0],
["_Test Account Bank Account - _TC", 600.0, 0.0] ["_Test Account Bank Account - _TC", 600.0, 0.0]
]) ])
@ -545,7 +541,6 @@ class TestSalesInvoice(unittest.TestCase):
pos_setting.insert() pos_setting.insert()
def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self):
self.clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
frappe.delete_doc("Account", "_Test Warehouse No Account - _TC") frappe.delete_doc("Account", "_Test Warehouse No Account - _TC")
@ -600,7 +595,6 @@ class TestSalesInvoice(unittest.TestCase):
set_perpetual_inventory(0) set_perpetual_inventory(0)
def test_sales_invoice_gl_entry_with_aii_no_item_code(self): def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
self.clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
si = frappe.get_doc(test_records[1]) si = frappe.get_doc(test_records[1])
@ -627,7 +621,6 @@ class TestSalesInvoice(unittest.TestCase):
set_perpetual_inventory(0) set_perpetual_inventory(0)
def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): def test_sales_invoice_gl_entry_with_aii_non_stock_item(self):
self.clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
si = frappe.get_doc(test_records[1]) si = frappe.get_doc(test_records[1])
si.get("items")[0].item_code = "_Test Non Stock Item" si.get("items")[0].item_code = "_Test Non Stock Item"
@ -705,14 +698,8 @@ class TestSalesInvoice(unittest.TestCase):
def test_recurring_invoice(self): def test_recurring_invoice(self):
from erpnext.controllers.tests.test_recurring_document import test_recurring_document from erpnext.controllers.tests.test_recurring_document import test_recurring_document
test_recurring_document(self, test_records) 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): def test_serialized(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item 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 from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@ -767,5 +754,35 @@ class TestSalesInvoice(unittest.TestCase):
self.assertRaises(SerialNoStatusError, si.submit) 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_dependencies = ["Journal Entry", "Contact", "Address"]
test_records = frappe.get_test_records('Sales Invoice') test_records = frappe.get_test_records('Sales Invoice')

View File

@ -5,119 +5,106 @@ from __future__ import unicode_literals
import unittest import unittest
import frappe import frappe
import frappe.defaults 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): class TestPurchaseOrder(unittest.TestCase):
def test_make_purchase_receipt(self): def test_make_purchase_receipt(self):
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt po = create_purchase_order(do_not_submit=True)
self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name)
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.submit() po.submit()
pr = make_purchase_receipt(po.name) pr = create_pr_against_po(po.name)
pr.supplier_warehouse = "_Test Warehouse 1 - _TC" self.assertEquals(len(pr.get("items")), 1)
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()
def test_ordered_qty(self): def test_ordered_qty(self):
existing_ordered_qty = self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC") existing_ordered_qty = get_ordered_qty()
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
po = frappe.copy_doc(test_records[0]).insert()
po = create_purchase_order(do_not_submit=True)
self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name) 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() 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) create_pr_against_po(po.name)
self.assertEqual(get_ordered_qty(), existing_ordered_qty + 6)
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()
po.load_from_db() po.load_from_db()
self.assertEquals(po.get("items")[0].received_qty, 4) 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) frappe.db.set_value('Item', '_Test Item', 'tolerance', 50)
pr1 = make_purchase_receipt(po.name) pr = create_pr_against_po(po.name, received_qty=8)
pr1.naming_series = "_T-Purchase Receipt-" self.assertEqual(get_ordered_qty(), existing_ordered_qty)
pr1.posting_date = "2013-05-12"
pr1.get("items")[0].qty = 8
pr1.insert()
pr1.submit()
po.load_from_db() po.load_from_db()
self.assertEquals(po.get("items")[0].received_qty, 12) 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() pr.cancel()
pr1.cancel() self.assertEqual(get_ordered_qty(), existing_ordered_qty + 6)
po.load_from_db() po.load_from_db()
self.assertEquals(po.get("items")[0].received_qty, 4) 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): 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() po.submit()
pi = make_purchase_invoice(po.name) pi = make_purchase_invoice(po.name)
self.assertEquals(pi.doctype, "Purchase Invoice") self.assertEquals(pi.doctype, "Purchase Invoice")
self.assertEquals(len(pi.get("items", [])), len(test_records[0]["items"])) self.assertEquals(len(pi.get("items", [])), 1)
pi.credit_to = "_Test Payable - _TC"
pi.posting_date = "2013-05-12"
pi.bill_no = "NA"
frappe.get_doc(pi).insert()
def test_subcontracting(self): def test_subcontracting(self):
po = frappe.copy_doc(test_records[0]) po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
po.insert()
self.assertEquals(len(po.get("supplied_items")), 2) self.assertEquals(len(po.get("supplied_items")), 2)
def test_warehouse_company_validation(self): def test_warehouse_company_validation(self):
from erpnext.stock.utils import InvalidWarehouseCompany from erpnext.stock.utils import InvalidWarehouseCompany
po = frappe.copy_doc(test_records[0]) po = create_purchase_order(company="_Test Company 1", do_not_save=True)
po.company = "_Test Company 1"
po.conversion_rate = 0.0167
self.assertRaises(InvalidWarehouseCompany, po.insert) self.assertRaises(InvalidWarehouseCompany, po.insert)
def test_uom_integer_validation(self): def test_uom_integer_validation(self):
from erpnext.utilities.transaction_base import UOMMustBeIntegerError from erpnext.utilities.transaction_base import UOMMustBeIntegerError
po = frappe.copy_doc(test_records[0]) po = create_purchase_order(qty=3.4, do_not_save=True)
po.get("items")[0].qty = 3.4
self.assertRaises(UOMMustBeIntegerError, po.insert) self.assertRaises(UOMMustBeIntegerError, po.insert)
def _get_ordered_qty(self, item_code, warehouse): def create_purchase_order(**args):
return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "ordered_qty")) 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"] test_dependencies = ["BOM", "Item Price"]

View File

@ -6,7 +6,7 @@
"fg_warehouse": "_Test Warehouse 1 - _TC", "fg_warehouse": "_Test Warehouse 1 - _TC",
"production_item": "_Test FG Item", "production_item": "_Test FG Item",
"qty": 10.0, "qty": 10.0,
"stock_uom": "Nos", "stock_uom": "_Test UOM",
"wip_warehouse": "_Test Warehouse - _TC" "wip_warehouse": "_Test Warehouse - _TC"
} }
] ]

View File

@ -1,342 +1,190 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt # License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import flt from frappe.utils import flt, add_days
import frappe.permissions import frappe.permissions
import unittest 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): class TestSalesOrder(unittest.TestCase):
def tearDown(self): def tearDown(self):
frappe.set_user("Administrator") frappe.set_user("Administrator")
def test_make_material_request(self): 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.submit()
so.name)
sales_order = frappe.get_doc("Sales Order", so.name)
sales_order.submit()
mr = make_material_request(so.name) mr = make_material_request(so.name)
self.assertEquals(mr.material_request_type, "Purchase") 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): 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.submit()
so.name) dn = make_delivery_note(so.name)
dn = self.make_next_doc_testcase(so, "Delivery Note")
self.assertEquals(dn.doctype, "Delivery Note") self.assertEquals(dn.doctype, "Delivery Note")
self.assertEquals(len(dn.get("items")), len(so.get("items"))) self.assertEquals(len(dn.get("items")), len(so.get("items")))
def test_make_sales_invoice(self): 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.submit()
so.name) 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")), len(so.get("items")))
self.assertEquals(len(si.get("items")), 1) self.assertEquals(len(si.get("items")), 1)
si.set("debit_to", "_Test Receivable - _TC")
si.set("posting_date", "2013-10-10")
si.insert() si.insert()
si.submit() si.submit()
si1 = self.make_next_doc_testcase(so, "Sales Invoice") si1 = make_sales_invoice(so.name)
self.assertEquals(len(si1.get("items")), 0) self.assertEquals(len(si1.get("items")), 0)
def test_update_qty(self): 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 so.load_from_db()
dn.posting_date = "2013-10-10" self.assertEquals(so.get("items")[0].delivered_qty, 6)
dn.insert()
delivery_note = frappe.get_doc("Delivery Note", dn.name) # Check delivered_qty after make_sales_invoice without update_stock checked
delivery_note.submit() si1 = make_sales_invoice(so.name)
si1.get("items")[0].qty = 6
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
si1.insert() si1.insert()
si1.submit() 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 = make_sales_invoice(so.name)
#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")
si2.set("update_stock", 1) si2.set("update_stock", 1)
si2.get("items")[0].qty = 3 si2.get("items")[0].qty = 3
si2.insert() si2.insert()
si2.submit() si2.submit()
sales_order = frappe.get_doc("Sales Order", sales_order.name) so.load_from_db()
self.assertEquals(so.get("items")[0].delivered_qty, 9)
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)
def test_reserved_qty_for_partial_delivery(self): def test_reserved_qty_for_partial_delivery(self):
# reset bin existing_reserved_qty = get_reserved_qty()
so_item = test_records[0]["items"][0].copy()
self.delete_bin(so_item["item_code"], so_item["warehouse"])
# submit so so = make_sales_order()
so = self.create_so() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
# allow negative stock dn = create_dn_against_so(so.name)
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) self.assertEqual(get_reserved_qty(), existing_reserved_qty + 5)
# 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)
# stop so # stop so
so.load_from_db() so.load_from_db()
so.stop_sales_order() 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 # unstop so
so.load_from_db() so.load_from_db()
so.unstop_sales_order() 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() 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)
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)
# 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.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 # cancel
so.load_from_db()
so.cancel() so.cancel()
self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], self.assertEqual(get_reserved_qty(), existing_reserved_qty)
so.get("items")[0].warehouse, 0.0)
self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], def test_reserved_qty_for_over_delivery(self):
so.get("items")[0].warehouse, 0.0) # set over-delivery tolerance
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)
dn = create_dn_against_so(so.name, 15)
self.assertEqual(get_reserved_qty(), existing_reserved_qty)
dn.cancel()
self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
def test_reserved_qty_for_partial_delivery_with_packing_list(self): 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 existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100")
# change item in test so record so = make_sales_order(item_code="_Test Sales BOM Item")
test_record = frappe.copy_doc(test_records[0]) self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
test_record.get("items")[0].item_code = "_Test Sales BOM Item" self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
existing_reserved_qty_item2 + 20)
# reset bin dn = create_dn_against_so(so.name)
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 self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25)
so = self.create_so(test_record) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
existing_reserved_qty_item2 + 10)
# 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)
# stop so # stop so
so.load_from_db() so.load_from_db()
so.stop_sales_order() so.stop_sales_order()
self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
so.get("items")[0].warehouse, 0.0) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"],
so.get("items")[0].warehouse, 0.0)
# unstop so # unstop so
so.load_from_db() so.load_from_db()
so.unstop_sales_order() 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)
# cancel dn 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)
dn.cancel() dn.cancel()
self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
so.get("items")[0].warehouse, 50.0) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], existing_reserved_qty_item2 + 20)
so.get("items")[0].warehouse, 20.0)
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): 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 # set over-delivery tolerance
frappe.db.set_value('Item', so.get("items")[0].item_code, 'tolerance', 50) frappe.db.set_value('Item', "_Test Sales BOM Item", 'tolerance', 50)
# submit dn existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
dn = self.create_dn_against_so(so, 15) existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100")
self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], so = make_sales_order(item_code="_Test Sales BOM Item")
so.get("items")[0].warehouse, 0.0)
self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
so.get("items")[0].warehouse, 0.0) 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)
# cancel dn
dn.cancel() dn.cancel()
self.check_reserved_qty(sbom_test_records[0]["items"][0]["item_code"], self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
so.get("items")[0].warehouse, 50.0) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
self.check_reserved_qty(sbom_test_records[0]["items"][1]["item_code"], existing_reserved_qty_item2 + 20)
so.get("items")[0].warehouse, 20.0)
def test_warehouse_user(self): def test_warehouse_user(self):
frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com") 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") frappe.set_user("test@example.com")
so = frappe.copy_doc(test_records[0]) so = make_sales_order(company="_Test Company 1",
so.company = "_Test Company 1" warehouse="_Test Warehouse 2 - _TC1", do_not_save=True)
so.conversion_rate = 0.02 so.conversion_rate = 0.02
so.plc_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) self.assertRaises(frappe.PermissionError, so.insert)
frappe.set_user("test2@example.com") 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") frappe.permissions.remove_user_permission("Company", "_Test Company 1", "test2@example.com")
def test_block_delivery_note_against_cancelled_sales_order(self): def test_block_delivery_note_against_cancelled_sales_order(self):
from erpnext.stock.doctype.delivery_note.test_delivery_note import _insert_purchase_receipt so = make_sales_order()
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
sales_order = frappe.copy_doc(test_records[0]) dn = make_delivery_note(so.name)
sales_order.items[0].qty = 5 dn.insert()
sales_order.insert()
sales_order.submit()
_insert_purchase_receipt(sales_order.get("items")[0].item_code) so.cancel()
delivery_note = make_delivery_note(sales_order.name) self.assertRaises(frappe.CancelledLinkError, dn.submit)
delivery_note.posting_date = sales_order.transaction_date
delivery_note.insert()
sales_order.cancel() 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
self.assertRaises(frappe.CancelledLinkError, delivery_note.submit) so.company = args.company or "_Test Company"
so.customer = args.customer or "_Test Customer"
so.delivery_date = add_days(so.transaction_date, 10)
test_dependencies = ["Sales BOM", "Currency Exchange"] 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()
test_records = frappe.get_test_records('Sales Order') 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
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"]

View File

@ -17,8 +17,6 @@ import install_fixtures
@frappe.whitelist() @frappe.whitelist()
def setup_account(args=None): def setup_account(args=None):
try: try:
frappe.clear_cache()
if frappe.db.sql("select name from tabCompany"): if frappe.db.sql("select name from tabCompany"):
frappe.throw(_("Setup Already Complete!!")) frappe.throw(_("Setup Already Complete!!"))

View File

@ -48,7 +48,7 @@ args = {
"supplier_3": "Digital Ocean", "supplier_3": "Digital Ocean",
"tax_1": "Service Tax", "tax_1": "Service Tax",
"tax_rate_1": "12.5", "tax_rate_1": "12.5",
"timezone": "Asia/Calcutta", "timezone": "America/New_York",
"password": "password", "password": "password",
"email": "test@erpnext.com", "email": "test@erpnext.com",
} }

View File

@ -30,9 +30,10 @@ def get_ancestors_of(doctype, name):
return result or [] return result or []
def before_tests(): def before_tests():
frappe.clear_cache()
# complete setup if missing # complete setup if missing
from erpnext.setup.page.setup_wizard.setup_wizard import setup_account 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({ setup_account({
"currency" :"USD", "currency" :"USD",
"first_name" :"Test", "first_name" :"Test",

View File

@ -58,6 +58,9 @@ class TestShoppingCart(unittest.TestCase):
def test_add_to_cart(self): def test_add_to_cart(self):
self.login_as_lead() self.login_as_lead()
# remove from cart
self.remove_all_items_from_cart()
# add first item # add first item
set_item_in_cart("_Test Item", 1) set_item_in_cart("_Test Item", 1)
quotation = self.test_get_cart_lead() 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].item_code, "_Test Item")
self.assertEquals(quotation.get("items")[0].qty, 5) self.assertEquals(quotation.get("items")[0].qty, 5)
self.assertEquals(quotation.get("items")[0].amount, 50) 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) self.assertEquals(len(quotation.get("items")), 2)
def test_remove_from_cart(self): 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].item_code, "_Test Item 2")
self.assertEquals(quotation.get("items")[0].qty, 1) self.assertEquals(quotation.get("items")[0].qty, 1)
self.assertEquals(quotation.get("items")[0].amount, 20) 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) self.assertEquals(len(quotation.get("items")), 1)
# remove second item # remove second item
set_item_in_cart("_Test Item 2", 0) set_item_in_cart("_Test Item 2", 0)
quotation = self.test_get_cart_lead() 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) self.assertEquals(len(quotation.get("items")), 0)
def test_set_billing_address(self): def test_set_billing_address(self):
@ -141,7 +144,7 @@ class TestShoppingCart(unittest.TestCase):
def enable_shopping_cart(self): def enable_shopping_cart(self):
settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings") 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 settings.enabled = 1
else: else:
settings.update({ settings.update({
@ -225,6 +228,11 @@ class TestShoppingCart(unittest.TestCase):
"phone": "+91 0000000000" "phone": "+91 0000000000"
}).insert(ignore_permissions=True) }).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", test_dependencies = ["Sales Taxes and Charges Master", "Price List", "Item Price", "Shipping Rule", "Currency Exchange",
"Customer Group", "Lead", "Customer", "Contact", "Address", "Item"] "Customer Group", "Lead", "Customer", "Contact", "Address", "Item"]

View File

@ -5,109 +5,95 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest import unittest
import frappe import frappe
import json
import frappe.defaults import frappe.defaults
from frappe.utils import cint from frappe.utils import cint, nowdate, nowtime, cstr, add_days
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, set_perpetual_inventory, test_records as pr_test_records from erpnext.stock.stock_ledger import get_previous_sle
from erpnext.accounts.utils import get_balance_on
def _insert_purchase_receipt(item_code=None): from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \
if not item_code: import get_gl_entries, set_perpetual_inventory
item_code = pr_test_records[0]["items"][0]["item_code"] 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
pr = frappe.copy_doc(pr_test_records[0]) from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, SerialNoStatusError
pr.get("items")[0].item_code = item_code
pr.insert()
pr.submit()
class TestDeliveryNote(unittest.TestCase): class TestDeliveryNote(unittest.TestCase):
def test_over_billing_against_dn(self): def test_over_billing_against_dn(self):
self.clear_stock_account_balance() frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
_insert_purchase_receipt()
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice dn = create_delivery_note(do_not_submit=True)
_insert_purchase_receipt() self.assertRaises(frappe.ValidationError, make_sales_invoice, dn.name)
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() dn.submit()
si = make_sales_invoice(dn.name) si = make_sales_invoice(dn.name)
self.assertEquals(len(si.get("items")), len(dn.get("items"))) self.assertEquals(len(si.get("items")), len(dn.get("items")))
# modify amount # modify amount
si.get("items")[0].rate = 200 si.get("items")[0].rate = 200
self.assertRaises(frappe.ValidationError, frappe.get_doc(si).insert) self.assertRaises(frappe.ValidationError, frappe.get_doc(si).insert)
def test_delivery_note_no_gl_entry(self): def test_delivery_note_no_gl_entry(self):
self.clear_stock_account_balance()
set_perpetual_inventory(0) set_perpetual_inventory(0)
self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 0) self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 0)
_insert_purchase_receipt() make_stock_entry(target="_Test Warehouse - _TC", qty=5, incoming_rate=100)
dn = frappe.copy_doc(test_records[0]) stock_queue = json.loads(get_previous_sle({
dn.insert() "item_code": "_Test Item",
dn.submit() "warehouse": "_Test Warehouse - _TC",
"posting_date": nowdate(),
"posting_time": nowtime()
}).stock_queue or "[]")
stock_value, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", dn = create_delivery_note()
{"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item"}, ["stock_value", "stock_value_difference"]) sle = frappe.get_doc("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name})
self.assertEqual(stock_value, 0)
self.assertEqual(stock_value_difference, -375) self.assertEqual(sle.stock_value_difference, -1*stock_queue[0][1])
self.assertFalse(get_gl_entries("Delivery Note", dn.name)) self.assertFalse(get_gl_entries("Delivery Note", dn.name))
def test_delivery_note_gl_entry(self): def test_delivery_note_gl_entry(self):
self.clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1)
frappe.db.set_value("Item", "_Test Item", "valuation_method", "FIFO") 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]) stock_in_hand_account = frappe.db.get_value("Account", {"warehouse": "_Test Warehouse - _TC"})
dn.get("items")[0].expense_account = "Cost of Goods Sold - _TC" prev_bal = get_balance_on(stock_in_hand_account)
dn.get("items")[0].cost_center = "Main - _TC"
stock_in_hand_account = frappe.db.get_value("Account", dn = create_delivery_note()
{"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()
gl_entries = get_gl_entries("Delivery Note", dn.name) gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries) 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 = { expected_values = {
stock_in_hand_account: [0.0, 375.0], stock_in_hand_account: [0.0, stock_value_difference],
"Cost of Goods Sold - _TC": [375.0, 0.0] "Cost of Goods Sold - _TC": [stock_value_difference, 0.0]
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))
# check stock in hand balance # check stock in hand balance
bal = get_balance_on(stock_in_hand_account, dn.posting_date) bal = get_balance_on(stock_in_hand_account)
self.assertEquals(bal, prev_bal - 375.0) self.assertEquals(bal, prev_bal - stock_value_difference)
# back dated purchase receipt # back dated incoming entry
pr = frappe.copy_doc(pr_test_records[0]) make_stock_entry(posting_date=add_days(nowdate(), -2), target="_Test Warehouse - _TC",
pr.posting_date = "2013-01-01" qty=5, incoming_rate=100)
pr.get("items")[0].rate = 100
pr.get("items")[0].base_amount = 100
pr.insert()
pr.submit()
gl_entries = get_gl_entries("Delivery Note", dn.name) gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries) 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 = { expected_values = {
stock_in_hand_account: [0.0, 666.67], stock_in_hand_account: [0.0, stock_value_difference],
"Cost of Goods Sold - _TC": [666.67, 0.0] "Cost of Goods Sold - _TC": [stock_value_difference, 0.0]
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))
@ -117,38 +103,40 @@ class TestDeliveryNote(unittest.TestCase):
set_perpetual_inventory(0) set_perpetual_inventory(0)
def test_delivery_note_gl_entry_packing_item(self): def test_delivery_note_gl_entry_packing_item(self):
self.clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
_insert_purchase_receipt() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=10, incoming_rate=100)
_insert_purchase_receipt("_Test Item Home Desktop 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]) stock_in_hand_account = frappe.db.get_value("Account", {"warehouse": "_Test Warehouse - _TC"})
dn.get("items")[0].item_code = "_Test Sales BOM Item" prev_bal = get_balance_on(stock_in_hand_account)
dn.get("items")[0].qty = 1
stock_in_hand_account = frappe.db.get_value("Account", dn = create_delivery_note(item_code="_Test Sales BOM Item")
{"warehouse": dn.get("items")[0].warehouse})
from erpnext.accounts.utils import get_balance_on stock_value_diff_rm1 = abs(frappe.db.get_value("Stock Ledger Entry",
prev_bal = get_balance_on(stock_in_hand_account, dn.posting_date) {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"},
"stock_value_difference"))
dn.insert() stock_value_diff_rm2 = abs(frappe.db.get_value("Stock Ledger Entry",
dn.submit() {"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) gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
expected_values = { expected_values = {
stock_in_hand_account: [0.0, 525], stock_in_hand_account: [0.0, stock_value_diff],
"Cost of Goods Sold - _TC": [525.0, 0.0] "Cost of Goods Sold - _TC": [stock_value_diff, 0.0]
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))
# check stock in hand balance # check stock in hand balance
bal = get_balance_on(stock_in_hand_account, dn.posting_date) bal = get_balance_on(stock_in_hand_account)
self.assertEquals(bal, prev_bal - 525.0) self.assertEquals(bal, prev_bal - stock_value_diff)
dn.cancel() dn.cancel()
self.assertFalse(get_gl_entries("Delivery Note", dn.name)) self.assertFalse(get_gl_entries("Delivery Note", dn.name))
@ -156,62 +144,67 @@ class TestDeliveryNote(unittest.TestCase):
set_perpetual_inventory(0) set_perpetual_inventory(0)
def test_serialized(self): 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() 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 = create_delivery_note(item_code="_Test Serialized Item With Series", serial_no=serial_no)
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()
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Delivered") self.check_serial_no_values(serial_no, {
self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse")) "status": "Delivered",
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse": "",
"delivery_document_no"), dn.name) "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() dn.cancel()
serial_nos = get_serial_nos(dn.get("items")[0].serial_no) self.check_serial_no_values(serial_no, {
"status": "Available",
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Available") "warehouse": "_Test Warehouse - _TC",
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC") "delivery_document_no": ""
self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], })
"delivery_document_no"))
def test_serialize_status(self): 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() 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]
sr = frappe.get_doc("Serial No", serial_nos[0]) frappe.db.set_value("Serial No", serial_no, "status", "Not Available")
sr.status = "Not Available"
sr.save()
dn = frappe.copy_doc(test_records[0]) dn = create_delivery_note(item_code="_Test Serialized Item With Series",
dn.get("items")[0].item_code = "_Test Serialized Item With Series" serial_no=serial_no, do_not_submit=True)
dn.get("items")[0].qty = 1
dn.get("items")[0].serial_no = serial_nos[0]
dn.insert()
self.assertRaises(SerialNoStatusError, dn.submit) self.assertRaises(SerialNoStatusError, dn.submit)
def clear_stock_account_balance(self): def check_serial_no_values(self, serial_no, field_values):
frappe.db.sql("""delete from `tabBin`""") for field, value in field_values.items():
frappe.db.sql("delete from `tabStock Ledger Entry`") self.assertEquals(cstr(frappe.db.get_value("Serial No", serial_no, field)), value)
frappe.db.sql("delete from `tabGL Entry`")
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"] test_dependencies = ["Sales BOM"]
test_records = frappe.get_test_records('Delivery Note')

View File

@ -7,7 +7,7 @@
"customer_name": "_Test Customer", "customer_name": "_Test Customer",
"items": [ "items": [
{ {
"base_amount": 500.0, "base_amount": 100.0,
"base_rate": 100.0, "base_rate": 100.0,
"cost_center": "Main - _TC", "cost_center": "Main - _TC",
"description": "CPU", "description": "CPU",
@ -16,7 +16,7 @@
"item_code": "_Test Item", "item_code": "_Test Item",
"item_name": "_Test Item", "item_name": "_Test Item",
"parentfield": "items", "parentfield": "items",
"qty": 5.0, "qty": 1.0,
"rate": 100.0, "rate": 100.0,
"stock_uom": "_Test UOM", "stock_uom": "_Test UOM",
"warehouse": "_Test Warehouse - _TC" "warehouse": "_Test Warehouse - _TC"
@ -24,10 +24,10 @@
], ],
"doctype": "Delivery Note", "doctype": "Delivery Note",
"fiscal_year": "_Test Fiscal Year 2013", "fiscal_year": "_Test Fiscal Year 2013",
"base_grand_total": 500.0, "base_grand_total": 100.0,
"grand_total": 500.0, "grand_total": 100.0,
"naming_series": "_T-Delivery Note-", "naming_series": "_T-Delivery Note-",
"base_net_total": 500.0, "base_net_total": 100.0,
"plc_conversion_rate": 1.0, "plc_conversion_rate": 1.0,
"posting_date": "2013-02-21", "posting_date": "2013-02-21",
"posting_time": "9:00:00", "posting_time": "9:00:00",

View File

@ -7,6 +7,7 @@ import frappe
from frappe.test_runner import make_test_records from frappe.test_runner import make_test_records
from erpnext.stock.doctype.item.item import WarehouseNotSet, DuplicateVariant, ItemTemplateCannotHaveStock 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_ignore = ["BOM"]
test_dependencies = ["Warehouse"] test_dependencies = ["Warehouse"]
@ -30,16 +31,7 @@ class TestItem(unittest.TestCase):
def test_template_cannot_have_stock(self): def test_template_cannot_have_stock(self):
item = self.get_item(10) item = self.get_item(10)
se = frappe.new_doc("Stock Entry") se = make_stock_entry(item_code=item.name, target="Stores - _TC", qty=1, incoming_rate=1)
se.purpose = "Material Receipt"
se.append("items", {
"item_code": item.name,
"t_warehouse": "Stores - _TC",
"qty": 1,
"incoming_rate": 1
})
se.insert()
se.submit()
item.has_variants = 1 item.has_variants = 1
self.assertRaises(ItemTemplateCannotHaveStock, item.save) self.assertRaises(ItemTemplateCannotHaveStock, item.save)

View File

@ -4,6 +4,7 @@
"description": "_Test Item 1", "description": "_Test Item 1",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -36,6 +37,7 @@
"description": "_Test Item 2", "description": "_Test Item 2",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -59,6 +61,7 @@
"description": "_Test Item Home Desktop 100 3", "description": "_Test Item Home Desktop 100 3",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -88,6 +91,7 @@
"description": "_Test Item Home Desktop 200 4", "description": "_Test Item Home Desktop 200 4",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -108,6 +112,7 @@
"description": "_Test Sales BOM Item 5", "description": "_Test Sales BOM Item 5",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -129,6 +134,7 @@
"description": "_Test FG Item 6", "description": "_Test FG Item 6",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -207,6 +213,7 @@
"description": "_Test Item Home Desktop Manufactured 10", "description": "_Test Item Home Desktop Manufactured 10",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -227,6 +234,7 @@
"description": "_Test FG Item 2 11", "description": "_Test FG Item 2 11",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",
@ -248,6 +256,7 @@
"description": "_Test Variant Item 12", "description": "_Test Variant Item 12",
"doctype": "Item", "doctype": "Item",
"expense_account": "_Test Account Cost for Goods Sold - _TC", "expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"has_batch_no": "No", "has_batch_no": "No",
"has_serial_no": "No", "has_serial_no": "No",
"income_account": "Sales - _TC", "income_account": "Sales - _TC",

View File

@ -6,21 +6,16 @@ from __future__ import unicode_literals
import unittest import unittest
import frappe import frappe
import frappe.defaults import frappe.defaults
from frappe.utils import cint from frappe.utils import cint, flt
class TestPurchaseReceipt(unittest.TestCase): class TestPurchaseReceipt(unittest.TestCase):
def test_make_purchase_invoice(self): 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 from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice
pr = frappe.copy_doc(test_records[0]).insert() pr = make_purchase_receipt(do_not_save=True)
self.assertRaises(frappe.ValidationError, make_purchase_invoice, pr.name)
self.assertRaises(frappe.ValidationError, make_purchase_invoice,
pr.name)
pr = frappe.get_doc("Purchase Receipt", pr.name)
pr.submit() pr.submit()
pi = make_purchase_invoice(pr.name) pi = make_purchase_invoice(pr.name)
self.assertEquals(pi.doctype, "Purchase Invoice") self.assertEquals(pi.doctype, "Purchase Invoice")
@ -31,28 +26,26 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertRaises(frappe.ValidationError, frappe.get_doc(pi).submit) self.assertRaises(frappe.ValidationError, frappe.get_doc(pi).submit)
def test_purchase_receipt_no_gl_entry(self): def test_purchase_receipt_no_gl_entry(self):
self._clear_stock_account_balance()
set_perpetual_inventory(0) 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", existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item",
{"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",
"warehouse": "_Test Warehouse - _TC"}, "stock_value") "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)) self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
def test_purchase_receipt_gl_entry(self): def test_purchase_receipt_gl_entry(self):
self._clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1) self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1)
pr = frappe.copy_doc(test_records[0]) pr = frappe.copy_doc(test_records[0])
@ -84,39 +77,20 @@ class TestPurchaseReceipt(unittest.TestCase):
set_perpetual_inventory(0) 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): def test_subcontracting(self):
pr = frappe.copy_doc(test_records[1]) pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes")
pr.run_method("calculate_taxes_and_totals")
pr.insert()
self.assertEquals(len(pr.get("supplied_items")), 2) 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): def test_serial_no_supplier(self):
pr = frappe.copy_doc(test_records[0]) pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1)
pr.get("items")[0].item_code = "_Test Serialized Item With Series" self.assertEquals(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "supplier"),
pr.get("items")[0].qty = 1 pr.supplier)
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.cancel() 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): def test_rejected_serial_no(self):
pr = frappe.copy_doc(test_records[0]) pr = frappe.copy_doc(test_records[0])
@ -150,7 +124,33 @@ def set_perpetual_inventory(enable=1):
accounts_settings.auto_accounting_for_stock = enable accounts_settings.auto_accounting_for_stock = enable
accounts_settings.save() 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_dependencies = ["BOM", "Item Price"]
test_records = frappe.get_test_records('Purchase Receipt') test_records = frappe.get_test_records('Purchase Receipt')

View File

@ -5,7 +5,6 @@
"conversion_rate": 1.0, "conversion_rate": 1.0,
"currency": "INR", "currency": "INR",
"doctype": "Purchase Receipt", "doctype": "Purchase Receipt",
"fiscal_year": "_Test Fiscal Year 2013",
"base_grand_total": 720.0, "base_grand_total": 720.0,
"naming_series": "_T-Purchase Receipt-", "naming_series": "_T-Purchase Receipt-",
"base_net_total": 500.0, "base_net_total": 500.0,
@ -47,8 +46,6 @@
"cost_center": "Main - _TC" "cost_center": "Main - _TC"
} }
], ],
"posting_date": "2013-02-12",
"posting_time": "15:33:30",
"items": [ "items": [
{ {
"base_amount": 250.0, "base_amount": 250.0,
@ -62,7 +59,7 @@
"rate": 50.0, "rate": 50.0,
"received_qty": 5.0, "received_qty": 5.0,
"rejected_qty": 0.0, "rejected_qty": 0.0,
"stock_uom": "Nos", "stock_uom": "_Test UOM",
"uom": "_Test UOM", "uom": "_Test UOM",
"warehouse": "_Test Warehouse - _TC", "warehouse": "_Test Warehouse - _TC",
"cost_center": "Main - _TC" "cost_center": "Main - _TC"
@ -79,7 +76,7 @@
"rate": 50.0, "rate": 50.0,
"received_qty": 5.0, "received_qty": 5.0,
"rejected_qty": 0.0, "rejected_qty": 0.0,
"stock_uom": "Nos", "stock_uom": "_Test UOM",
"uom": "_Test UOM", "uom": "_Test UOM",
"warehouse": "_Test Warehouse 1 - _TC", "warehouse": "_Test Warehouse 1 - _TC",
"cost_center": "Main - _TC" "cost_center": "Main - _TC"
@ -87,6 +84,8 @@
], ],
"supplier": "_Test Supplier" "supplier": "_Test Supplier"
}, },
{ {
"buying_price_list": "_Test Price List", "buying_price_list": "_Test Price List",
"company": "_Test Company", "company": "_Test Company",
@ -112,7 +111,7 @@
"rate": 500.0, "rate": 500.0,
"received_qty": 10.0, "received_qty": 10.0,
"rejected_qty": 0.0, "rejected_qty": 0.0,
"stock_uom": "Nos", "stock_uom": "_Test UOM",
"uom": "_Test UOM", "uom": "_Test UOM",
"warehouse": "_Test Warehouse - _TC", "warehouse": "_Test Warehouse - _TC",
"cost_center": "Main - _TC" "cost_center": "Main - _TC"

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe import frappe
import frappe.defaults 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 frappe import _
from erpnext.stock.utils import get_incoming_rate from erpnext.stock.utils import get_incoming_rate
@ -298,8 +298,6 @@ class StockEntry(StockController):
number_of_fg_items = len([t.t_warehouse for t in self.get("items") if t.t_warehouse]) number_of_fg_items = len([t.t_warehouse for t in self.get("items") if t.t_warehouse])
for d in self.get("items"): for d in self.get("items"):
if d.bom_no or (d.t_warehouse and number_of_fg_items == 1): 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.incoming_rate = operation_cost_per_unit + (raw_material_cost / flt(d.transfer_qty))
@ -394,13 +392,13 @@ class StockEntry(StockController):
frappe.throw(_("'Update Stock' for Sales Invoice {0} must be set").format(ref.doc.name), NotUpdateStockError) frappe.throw(_("'Update Stock' for Sales Invoice {0} must be set").format(ref.doc.name), NotUpdateStockError)
# posting date check # posting date check
ref_posting_datetime = "%s %s" % (cstr(ref.doc.posting_date), ref_posting_datetime = "%s %s" % (ref.doc.posting_date, ref.doc.posting_time or "00:00:00")
cstr(ref.doc.posting_time) or "00:00:00") this_posting_datetime = "%s %s" % (self.posting_date, self.posting_time)
this_posting_datetime = "%s %s" % (cstr(self.posting_date),
cstr(self.posting_time)) if get_datetime(ref_posting_datetime) < get_datetime(ref_posting_datetime):
if this_posting_datetime < ref_posting_datetime:
from frappe.utils.dateutils import datetime_in_user_format 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) stock_items = get_stock_items_for_return(ref.doc, ref.parentfields)
already_returned_item_qty = self.get_already_returned_item_qty(ref.fieldname) already_returned_item_qty = self.get_already_returned_item_qty(ref.fieldname)

View File

@ -2,7 +2,6 @@
{ {
"company": "_Test Company", "company": "_Test Company",
"doctype": "Stock Entry", "doctype": "Stock Entry",
"fiscal_year": "_Test Fiscal Year 2013",
"items": [ "items": [
{ {
"conversion_factor": 1.0, "conversion_factor": 1.0,
@ -19,10 +18,10 @@
"uom": "_Test UOM" "uom": "_Test UOM"
} }
], ],
"posting_date": "2013-01-01",
"posting_time": "17:14:24",
"purpose": "Material Receipt" "purpose": "Material Receipt"
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"doctype": "Stock Entry", "doctype": "Stock Entry",
@ -47,6 +46,8 @@
"posting_time": "17:15", "posting_time": "17:15",
"purpose": "Material Issue" "purpose": "Material Issue"
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"doctype": "Stock Entry", "doctype": "Stock Entry",
@ -72,6 +73,8 @@
"posting_time": "17:14:24", "posting_time": "17:14:24",
"purpose": "Material Transfer" "purpose": "Material Transfer"
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"doctype": "Stock Entry", "doctype": "Stock Entry",
@ -106,8 +109,6 @@
"uom": "_Test UOM" "uom": "_Test UOM"
} }
], ],
"posting_date": "2013-01-25",
"posting_time": "17:14:24",
"purpose": "Repack" "purpose": "Repack"
} }
] ]

View File

@ -4,10 +4,16 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, unittest import frappe, unittest
import frappe.defaults 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.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.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): def get_sle(**args):
condition, values = "", [] condition, values = "", []
@ -20,35 +26,25 @@ def get_sle(**args):
order by timestamp(posting_date, posting_time) desc, name desc limit 1"""% condition, order by timestamp(posting_date, posting_time) desc, name desc limit 1"""% condition,
values, as_dict=1) 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): class TestStockEntry(unittest.TestCase):
def tearDown(self): def tearDown(self):
frappe.set_user("Administrator") frappe.set_user("Administrator")
set_perpetual_inventory(0) set_perpetual_inventory(0)
if hasattr(self, "old_default_company"):
frappe.db.set_default("company", self.old_default_company)
def test_fifo(self): def test_fifo(self):
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
item_code = "_Test Item 2" item_code = "_Test Item 2"
warehouse = "_Test Warehouse - _TC" 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) make_stock_entry(item_code=item_code, target=warehouse, qty=1, incoming_rate=10)
sle = get_sle(item_code = item_code, warehouse = warehouse)[0] sle = get_sle(item_code = item_code, warehouse = warehouse)[0]
self.assertEqual([[1, 10]], eval(sle.stock_queue)) self.assertEqual([[1, 10]], eval(sle.stock_queue))
# negative qty # negative qty
make_zero(item_code, warehouse) make_stock_entry(item_code=item_code, source=warehouse, qty=2, incoming_rate=10)
make_stock_entry(item_code=item_code, source=warehouse, qty=1, incoming_rate=10)
sle = get_sle(item_code = item_code, warehouse = warehouse)[0] sle = get_sle(item_code = item_code, warehouse = warehouse)[0]
self.assertEqual([[-1, 10]], eval(sle.stock_queue)) self.assertEqual([[-1, 10]], eval(sle.stock_queue))
@ -60,10 +56,15 @@ class TestStockEntry(unittest.TestCase):
self.assertEqual([[-2, 10]], eval(sle.stock_queue)) self.assertEqual([[-2, 10]], eval(sle.stock_queue))
# move stock to positive # 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] 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)
@ -92,7 +93,7 @@ class TestStockEntry(unittest.TestCase):
# update re-level qty so that it is more than projected_qty # update re-level qty so that it is more than projected_qty
if projected_qty > template.reorder_levels[0].warehouse_reorder_level: 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() template.save()
from erpnext.stock.reorder_item import reorder_item from erpnext.stock.reorder_item import reorder_item
@ -108,12 +109,10 @@ class TestStockEntry(unittest.TestCase):
self.assertTrue(item_code in items) self.assertTrue(item_code in items)
def test_material_receipt_gl_entry(self): def test_material_receipt_gl_entry(self):
self._clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
mr = frappe.copy_doc(test_records[0]) mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
mr.insert() qty=50, incoming_rate=100)
mr.submit()
stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
"warehouse": mr.get("items")[0].t_warehouse}) "warehouse": mr.get("items")[0].t_warehouse})
@ -136,52 +135,45 @@ class TestStockEntry(unittest.TestCase):
self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Stock Entry' and voucher_no=%s""", mr.name)) where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
def test_material_issue_gl_entry(self): def test_material_issue_gl_entry(self):
self._clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
self._insert_material_receipt() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
qty=50, incoming_rate=100)
mi = frappe.copy_doc(test_records[1]) mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", qty=40)
mi.insert()
mi.submit()
self.check_stock_ledger_entries("Stock Entry", mi.name, self.check_stock_ledger_entries("Stock Entry", mi.name,
[["_Test Item", "_Test Warehouse - _TC", -40.0]]) [["_Test Item", "_Test Warehouse - _TC", -40.0]])
stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", 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, self.check_gl_entries("Stock Entry", mi.name,
sorted([ sorted([
[stock_in_hand_account, 0.0, 4000.0], [stock_in_hand_account, 0.0, stock_value_diff],
["Stock Adjustment - _TC", 4000.0, 0.0] ["Stock Adjustment - _TC", stock_value_diff, 0.0]
]) ])
) )
mi.cancel() 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)) 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)) 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): def test_material_transfer_gl_entry(self):
self._clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
self._insert_material_receipt() create_stock_reconciliation(qty=100, rate=100)
mtn = frappe.copy_doc(test_records[2]) mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
mtn.insert() target="_Test Warehouse 1 - _TC", qty=45)
mtn.submit()
self.check_stock_ledger_entries("Stock Entry", mtn.name, self.check_stock_ledger_entries("Stock Entry", mtn.name,
[["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]]) [["_Test Item", "_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", fixed_asset_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
"warehouse": mtn.get("items")[0].t_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, self.check_gl_entries("Stock Entry", mtn.name,
sorted([ sorted([
[stock_in_hand_account, 0.0, 4500.0], [stock_in_hand_account, 0.0, stock_value_diff],
[fixed_asset_account, 4500.0, 0.0], [fixed_asset_account, stock_value_diff, 0.0],
]) ])
) )
mtn.cancel() mtn.cancel()
self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry` self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry`
where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) 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` self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
def test_repack_no_change_in_valuation(self): def test_repack_no_change_in_valuation(self):
self._clear_stock_account_balance() set_perpetual_inventory(0)
set_perpetual_inventory()
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 = frappe.copy_doc(test_records[3])
repack.posting_date = nowdate()
repack.posting_time = nowtime()
repack.insert() repack.insert()
repack.submit() repack.submit()
@ -231,23 +226,32 @@ class TestStockEntry(unittest.TestCase):
set_perpetual_inventory(0) set_perpetual_inventory(0)
def test_repack_with_change_in_valuation(self): def test_repack_with_change_in_valuation(self):
self._clear_stock_account_balance()
set_perpetual_inventory() 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 = 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.insert()
repack.submit() repack.submit()
stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse",
"warehouse": repack.get("items")[1].t_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, self.check_gl_entries("Stock Entry", repack.name,
sorted([ sorted([
[stock_in_hand_account, 1000.0, 0.0], [stock_in_hand_account, stock_value_diff, 0.0],
["Stock Adjustment - _TC", 0.0, 1000.0], ["Stock Adjustment - _TC", 0.0, stock_value_diff],
]) ])
) )
set_perpetual_inventory(0) set_perpetual_inventory(0)
@ -274,6 +278,7 @@ class TestStockEntry(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type=%s and voucher_no=%s from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account asc, debit asc""", (voucher_type, voucher_no), as_list=1) order by account asc, debit asc""", (voucher_type, voucher_no), as_list=1)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
gl_entries.sort(key=lambda x: x[0]) 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][1], gle[1])
self.assertEquals(expected_gl_entries[i][2], gle[2]) 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): 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 \ si = create_sales_invoice(item_code=item_code, qty=delivered_qty)
import test_records as sales_invoice_test_records
# invalid sales invoice as update stock not checked se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=returned_qty,
si = frappe.copy_doc(sales_invoice_test_records[1]) purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True)
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
self.assertRaises(NotUpdateStockError, se.insert) 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 # 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 # insert a pos invoice with update stock
si = frappe.copy_doc(sales_invoice_test_records[1]) si = create_sales_invoice(update_stock=1, item_code=item_code, qty=5)
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()
# check available bin qty after invoice submission # 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) self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
# check if item is validated # check if item is validated
se = frappe.copy_doc(test_records[0]) se = make_stock_entry(item_code="_Test Item Home Desktop 200", target="_Test Warehouse - _TC",
se.purpose = "Sales Return" qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name, do_not_save=True)
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
# check if stock entry gets submitted
self.assertRaises(frappe.DoesNotExistError, se.insert) self.assertRaises(frappe.DoesNotExistError, se.insert)
# try again # try again
se = frappe.copy_doc(test_records[0]) se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
se.purpose = "Sales Return" qty=returned_qty, purpose="Sales Return", sales_invoice_no=si.name)
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()
# check if available qty is increased # 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) self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
return se return se
def test_sales_invoice_return_of_non_packing_item(self): def test_sales_invoice_return_of_non_packing_item(self):
self._clear_stock_account_balance()
self._test_sales_invoice_return("_Test Item", 5, 2) self._test_sales_invoice_return("_Test Item", 5, 2)
def test_sales_invoice_return_of_packing_item(self): 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) self._test_sales_invoice_return("_Test Sales BOM Item", 25, 20)
def _test_delivery_note_return(self, item_code, delivered_qty, returned_qty): 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 create_delivery_note
from erpnext.stock.doctype.delivery_note.test_delivery_note \
import test_records as delivery_note_test_records
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
actual_qty_0 = self._get_actual_qty() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100)
# 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()
actual_qty_1 = self._get_actual_qty() actual_qty_0 = get_qty_after_transaction()
# make a delivery note based on this invoice
dn = create_delivery_note(item_code="_Test Item",
warehouse="_Test Warehouse - _TC", qty=delivered_qty)
actual_qty_1 = get_qty_after_transaction()
self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
si_doc = make_sales_invoice(dn.name) si = 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.insert() si.insert()
si.submit() si.submit()
# insert and submit stock entry for sales return # insert and submit stock entry for sales return
se = frappe.copy_doc(test_records[0]) se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
se.purpose = "Sales Return" qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name)
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.insert() actual_qty_2 = get_qty_after_transaction()
se.submit()
actual_qty_2 = self._get_actual_qty()
self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
return se return se
def test_delivery_note_return_of_non_packing_item(self): def test_delivery_note_return_of_non_packing_item(self):
self._clear_stock_account_balance()
self._test_delivery_note_return("_Test Item", 5, 2) self._test_delivery_note_return("_Test Item", 5, 2)
def test_delivery_note_return_of_packing_item(self): 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) self._test_delivery_note_return("_Test Sales BOM Item", 25, 20)
def _test_sales_return_jv(self, se): 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) jv = make_return_jv(se.name)
self.assertEqual(len(jv.get("accounts")), 2) self.assertEqual(len(jv.get("accounts")), 2)
self.assertEqual(jv.get("voucher_type"), "Credit Note") self.assertEqual(jv.get("voucher_type"), "Credit Note")
self.assertEqual(jv.get("posting_date"), se.posting_date) 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_type"), "Customer")
self.assertEqual(jv.get("accounts")[0].get("party"), "_Test Customer") self.assertEqual(jv.get("accounts")[0].get("party"), "_Test Customer")
self.assertTrue(jv.get("accounts")[0].get("against_invoice")) self.assertTrue(jv.get("accounts")[0].get("against_invoice"))
self.assertEqual(jv.get("accounts")[1].get("account"), "Sales - _TC") self.assertEqual(jv.get("accounts")[1].get("account"), "Sales - _TC")
def test_make_return_jv_for_sales_invoice_non_packing_item(self): 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) se = self._test_sales_invoice_return("_Test Item", 5, 2)
self._test_sales_return_jv(se) self._test_sales_return_jv(se)
def test_make_return_jv_for_sales_invoice_packing_item(self): 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) se = self._test_sales_invoice_return("_Test Sales BOM Item", 25, 20)
self._test_sales_return_jv(se) self._test_sales_return_jv(se)
def test_make_return_jv_for_delivery_note_non_packing_item(self): 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) se = self._test_delivery_note_return("_Test Item", 5, 2)
self._test_sales_return_jv(se) self._test_sales_return_jv(se)
@ -463,7 +395,6 @@ class TestStockEntry(unittest.TestCase):
self._test_sales_return_jv(se) self._test_sales_return_jv(se)
def test_make_return_jv_for_delivery_note_packing_item(self): 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) se = self._test_delivery_note_return("_Test Sales BOM Item", 25, 20)
self._test_sales_return_jv(se) self._test_sales_return_jv(se)
@ -471,69 +402,37 @@ class TestStockEntry(unittest.TestCase):
self._test_sales_return_jv(se) self._test_sales_return_jv(se)
def _test_delivery_note_return_against_sales_order(self, item_code, delivered_qty, returned_qty): 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
from erpnext.selling.doctype.sales_order.test_sales_order import test_records as sales_order_test_records actual_qty_0 = get_qty_after_transaction()
from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice, make_delivery_note
actual_qty_0 = self._get_actual_qty() so = make_sales_order(qty=50)
so = frappe.copy_doc(sales_order_test_records[0]) dn = create_dn_against_so(so.name, delivered_qty)
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) actual_qty_1 = get_qty_after_transaction()
dn.status = "Draft"
dn.posting_date = so.delivery_date
dn.insert()
dn.submit()
actual_qty_1 = self._get_actual_qty()
self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1) self.assertEquals(actual_qty_0 - delivered_qty, actual_qty_1)
si = make_sales_invoice(so.name) 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.insert()
si.submit() si.submit()
# insert and submit stock entry for sales return # insert and submit stock entry for sales return
se = frappe.copy_doc(test_records[0]) se = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
se.purpose = "Sales Return" qty=returned_qty, purpose="Sales Return", delivery_note_no=dn.name)
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.insert() actual_qty_2 = get_qty_after_transaction()
se.submit()
actual_qty_2 = self._get_actual_qty()
self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2) self.assertEquals(actual_qty_1 + returned_qty, actual_qty_2)
return se return se
def test_purchase_receipt_return(self): def test_purchase_receipt_return(self):
self._clear_stock_account_balance() actual_qty_0 = get_qty_after_transaction()
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
# submit purchase receipt # submit purchase receipt
pr = frappe.copy_doc(purchase_receipt_test_records[0]) pr = make_purchase_receipt(item_code="_Test Item", warehouse="_Test Warehouse - _TC", qty=5)
pr.insert()
pr.submit()
actual_qty_1 = self._get_actual_qty() actual_qty_1 = get_qty_after_transaction()
self.assertEquals(actual_qty_0 + 5, actual_qty_1) self.assertEquals(actual_qty_0 + 5, actual_qty_1)
@ -549,52 +448,31 @@ class TestStockEntry(unittest.TestCase):
for d in pi.get("taxes"): for d in pi.get("taxes"):
d.cost_center = "_Test Cost Center - _TC" d.cost_center = "_Test Cost Center - _TC"
pi.run_method("calculate_taxes_and_totals")
pi.bill_no = "NA"
pi.insert() pi.insert()
pi.submit() pi.submit()
# submit purchase return # submit purchase return
se = frappe.copy_doc(test_records[0]) se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
se.purpose = "Purchase Return" qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name)
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()
actual_qty_2 = self._get_actual_qty() actual_qty_2 = get_qty_after_transaction()
self.assertEquals(actual_qty_1 - 5, actual_qty_2) self.assertEquals(actual_qty_1 - 5, actual_qty_2)
frappe.db.set_default("company", self.old_default_company)
return se, pr.name return se, pr.name
def test_over_stock_return(self): def test_over_stock_return(self):
from erpnext.stock.doctype.stock_entry.stock_entry import StockOverReturnError from erpnext.stock.doctype.stock_entry.stock_entry import StockOverReturnError
self._clear_stock_account_balance()
# out of 10, 5 gets returned # out of 10, 5 gets returned
prev_se, pr_docname = self.test_purchase_receipt_return() prev_se, pr_docname = self.test_purchase_receipt_return()
# submit purchase return - return another 6 qtys so that exception is raised se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
se = frappe.copy_doc(test_records[0]) qty=6, purpose="Purchase Return", purchase_receipt_no=pr_docname, do_not_save=True)
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"
self.assertRaises(StockOverReturnError, se.insert) self.assertRaises(StockOverReturnError, se.insert)
def _test_purchase_return_jv(self, se): 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) jv = make_return_jv(se.name)
self.assertEqual(len(jv.get("accounts")), 2) self.assertEqual(len(jv.get("accounts")), 2)
@ -606,7 +484,6 @@ class TestStockEntry(unittest.TestCase):
self.assertTrue(jv.get("accounts")[0].get("against_voucher")) self.assertTrue(jv.get("accounts")[0].get("against_voucher"))
def test_make_return_jv_for_purchase_receipt(self): def test_make_return_jv_for_purchase_receipt(self):
self._clear_stock_account_balance()
se, pr_name = self.test_purchase_receipt_return() se, pr_name = self.test_purchase_receipt_return()
self._test_purchase_return_jv(se) self._test_purchase_return_jv(se)
@ -614,9 +491,8 @@ class TestStockEntry(unittest.TestCase):
self._test_purchase_return_jv(se) self._test_purchase_return_jv(se)
def _test_purchase_return_return_against_purchase_order(self): 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 \ from erpnext.buying.doctype.purchase_order.test_purchase_order \
import test_records as purchase_order_test_records import test_records as purchase_order_test_records
@ -626,6 +502,7 @@ class TestStockEntry(unittest.TestCase):
# submit purchase receipt # submit purchase receipt
po = frappe.copy_doc(purchase_order_test_records[0]) po = frappe.copy_doc(purchase_order_test_records[0])
po.transaction_date = nowdate()
po.is_subcontracted = None po.is_subcontracted = None
po.get("items")[0].item_code = "_Test Item" po.get("items")[0].item_code = "_Test Item"
po.get("items")[0].rate = 50 po.get("items")[0].rate = 50
@ -639,7 +516,7 @@ class TestStockEntry(unittest.TestCase):
pr.insert() pr.insert()
pr.submit() 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) self.assertEquals(actual_qty_0 + 10, actual_qty_1)
@ -660,33 +537,15 @@ class TestStockEntry(unittest.TestCase):
pi.submit() pi.submit()
# submit purchase return # submit purchase return
se = frappe.copy_doc(test_records[0]) se = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
se.purpose = "Purchase Return" qty=5, purpose="Purchase Return", purchase_receipt_no=pr.name)
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()
actual_qty_2 = self._get_actual_qty() actual_qty_2 = get_qty_after_transaction()
self.assertEquals(actual_qty_1 - 5, actual_qty_2) self.assertEquals(actual_qty_1 - 5, actual_qty_2)
frappe.db.set_default("company", self.old_default_company)
return se, pr.name 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): def test_serial_no_not_reqd(self):
se = frappe.copy_doc(test_records[0]) se = frappe.copy_doc(test_records[0])
se.get("items")[0].serial_no = "ABCD" se.get("items")[0].serial_no = "ABCD"
@ -720,7 +579,6 @@ class TestStockEntry(unittest.TestCase):
self.assertRaises(SerialNoQtyError, se.submit) self.assertRaises(SerialNoQtyError, se.submit)
def test_serial_no_transfer_in(self): def test_serial_no_transfer_in(self):
self._clear_stock_account_balance()
se = frappe.copy_doc(test_records[0]) se = frappe.copy_doc(test_records[0])
se.get("items")[0].item_code = "_Test Serialized Item" se.get("items")[0].item_code = "_Test Serialized Item"
se.get("items")[0].qty = 2 se.get("items")[0].qty = 2
@ -736,7 +594,6 @@ class TestStockEntry(unittest.TestCase):
self.assertFalse(frappe.db.get_value("Serial No", "ABCD", "warehouse")) self.assertFalse(frappe.db.get_value("Serial No", "ABCD", "warehouse"))
def test_serial_no_not_exists(self): def test_serial_no_not_exists(self):
self._clear_stock_account_balance()
frappe.db.sql("delete from `tabSerial No` where name in ('ABCD', 'EFGH')") frappe.db.sql("delete from `tabSerial No` where name in ('ABCD', 'EFGH')")
make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC") make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC")
se = frappe.copy_doc(test_records[0]) se = frappe.copy_doc(test_records[0])
@ -752,7 +609,6 @@ class TestStockEntry(unittest.TestCase):
self.assertRaises(SerialNoNotExistsError, se.submit) self.assertRaises(SerialNoNotExistsError, se.submit)
def test_serial_duplicate(self): def test_serial_duplicate(self):
self._clear_stock_account_balance()
se, serial_nos = self.test_serial_by_series() se, serial_nos = self.test_serial_by_series()
se = frappe.copy_doc(test_records[0]) se = frappe.copy_doc(test_records[0])
@ -764,7 +620,6 @@ class TestStockEntry(unittest.TestCase):
self.assertRaises(SerialNoDuplicateError, se.submit) self.assertRaises(SerialNoDuplicateError, se.submit)
def test_serial_by_series(self): def test_serial_by_series(self):
self._clear_stock_account_balance()
se = make_serialized_item() se = make_serialized_item()
serial_nos = get_serial_nos(se.get("items")[0].serial_no) serial_nos = get_serial_nos(se.get("items")[0].serial_no)
@ -790,7 +645,6 @@ class TestStockEntry(unittest.TestCase):
self.assertRaises(SerialNoItemError, se.submit) self.assertRaises(SerialNoItemError, se.submit)
def test_serial_move(self): def test_serial_move(self):
self._clear_stock_account_balance()
se = make_serialized_item() se = make_serialized_item()
serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] 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") self.assertTrue(frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse - _TC")
def test_serial_warehouse_error(self): def test_serial_warehouse_error(self):
self._clear_stock_account_balance()
make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC") make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC")
t = make_serialized_item() t = make_serialized_item()
@ -828,7 +681,6 @@ class TestStockEntry(unittest.TestCase):
self.assertRaises(SerialNoWarehouseError, se.submit) self.assertRaises(SerialNoWarehouseError, se.submit)
def test_serial_cancel(self): def test_serial_cancel(self):
self._clear_stock_account_balance()
se, serial_nos = self.test_serial_by_series() se, serial_nos = self.test_serial_by_series()
se.cancel() se.cancel()
@ -837,7 +689,6 @@ class TestStockEntry(unittest.TestCase):
def test_warehouse_company_validation(self): def test_warehouse_company_validation(self):
set_perpetual_inventory(0) set_perpetual_inventory(0)
self._clear_stock_account_balance()
frappe.get_doc("User", "test2@example.com")\ frappe.get_doc("User", "test2@example.com")\
.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
frappe.set_user("test2@example.com") frappe.set_user("test2@example.com")
@ -880,25 +731,26 @@ class TestStockEntry(unittest.TestCase):
"test2@example.com", parenttype="User Permission") "test2@example.com", parenttype="User Permission")
def test_freeze_stocks(self): def test_freeze_stocks(self):
self._clear_stock_account_balance()
frappe.db.set_value('Stock Settings', None,'stock_auth_role', '') frappe.db.set_value('Stock Settings', None,'stock_auth_role', '')
# test freeze_stocks_upto # 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", add_days(nowdate(), 5))
frappe.db.set_value("Stock Settings", None, "stock_frozen_upto", date_newer_than_test_records)
se = frappe.copy_doc(test_records[0]).insert() 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", '') frappe.db.set_value("Stock Settings", None, "stock_frozen_upto", '')
# test freeze_stocks_upto_days # test freeze_stocks_upto_days
frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 7) frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 7)
se = frappe.copy_doc(test_records[0]).insert() se = frappe.copy_doc(test_records[0])
self.assertRaises (StockFreezeError, se.submit) 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) frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0)
def test_production_order(self): def test_production_order(self):
bom_no = frappe.db.get_value("BOM", {"item": "_Test FG Item 2", bom_no, bom_operation_cost = frappe.db.get_value("BOM", {"item": "_Test FG Item 2",
"is_default": 1, "docstatus": 1}) "is_default": 1, "docstatus": 1}, ["name", "operating_cost"])
production_order = frappe.new_doc("Production Order") production_order = frappe.new_doc("Production Order")
production_order.update({ production_order.update({
@ -907,13 +759,13 @@ class TestStockEntry(unittest.TestCase):
"production_item": "_Test FG Item 2", "production_item": "_Test FG Item 2",
"bom_no": bom_no, "bom_no": bom_no,
"qty": 1.0, "qty": 1.0,
"stock_uom": "Nos", "stock_uom": "_Test UOM",
"wip_warehouse": "_Test Warehouse - _TC" "wip_warehouse": "_Test Warehouse - _TC"
}) })
production_order.insert() production_order.insert()
production_order.submit() 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 = frappe.new_doc("Stock Entry")
stock_entry.update({ stock_entry.update({
@ -925,10 +777,15 @@ class TestStockEntry(unittest.TestCase):
}) })
stock_entry.get_items() stock_entry.get_items()
fg_rate = [d.amount for d in stock_entry.get("items") if d.item_code=="_Test FG Item 2"][0] rm_cost = 0
self.assertEqual(fg_rate, 1200.00) for d in stock_entry.get("items"):
fg_rate = [d.amount for d in stock_entry.get("items") if d.item_code=="_Test Item"][0] if d.s_warehouse:
self.assertEqual(fg_rate, 100.00) 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): def test_variant_production_order(self):
bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item", 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", "production_item": "_Test Variant Item-S",
"bom_no": bom_no, "bom_no": bom_no,
"qty": 1.0, "qty": 1.0,
"stock_uom": "Nos", "stock_uom": "_Test UOM",
"wip_warehouse": "_Test Warehouse - _TC" "wip_warehouse": "_Test Warehouse - _TC"
}) })
production_order.insert() production_order.insert()
@ -968,12 +825,15 @@ def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
return se return se
def make_stock_entry(**args): def make_stock_entry(**args):
from erpnext.accounts.utils import get_fiscal_year
s = frappe.new_doc("Stock Entry") s = frappe.new_doc("Stock Entry")
args = frappe._dict(args) args = frappe._dict(args)
if args.posting_date: if args.posting_date:
s.posting_date = args.posting_date s.posting_date = args.posting_date
if args.posting_time: if args.posting_time:
s.posting_time = args.posting_time s.posting_time = args.posting_time
if not args.purpose: if not args.purpose:
if args.source and args.target: if args.source and args.target:
s.purpose = "Material Transfer" s.purpose = "Material Transfer"
@ -981,19 +841,43 @@ def make_stock_entry(**args):
s.purpose = "Material Issue" s.purpose = "Material Issue"
else: else:
s.purpose = "Material Receipt" s.purpose = "Material Receipt"
else:
s.purpose = args.purpose
s.company = args.company or "_Test Company" 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", { 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, "s_warehouse": args.from_warehouse or args.source,
"t_warehouse": args.to_warehouse or args.target, "t_warehouse": args.to_warehouse or args.target,
"qty": args.qty, "qty": args.qty,
"incoming_rate": args.incoming_rate, "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" if not args.do_not_save:
s.insert() s.insert()
if not args.do_not_submit:
s.submit() s.submit()
return s 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') test_records = frappe.get_test_records('Stock Entry')

View File

@ -6,274 +6,114 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, unittest import frappe, unittest
from frappe.utils import flt from frappe.utils import flt, nowdate, nowtime
import json
from erpnext.accounts.utils import get_fiscal_year, get_stock_and_account_difference 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): class TestStockReconciliation(unittest.TestCase):
def setUp(self): def setUp(self):
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
self.insert_existing_sle()
def test_reco_for_fifo(self): def test_reco_for_fifo(self):
frappe.defaults.set_global_default("auto_accounting_for_stock", 0) self._test_reco_sle_gle("FIFO")
# [[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)
def test_reco_for_moving_average(self): 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, # [[qty, valuation_rate, posting_date,
# posting_time, expected_stock_value, bin_qty, bin_valuation]] # 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 = [ input_data = [
[50, 1000, "2012-12-26", "12:00"], [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"], [25, 900, "2012-12-26", "12:00"],
[20, 500, "2012-12-26", "12:00"], ["", 1000, "2012-12-20", "12:05"],
["", 1000, "2012-12-26", "12:05"],
[20, "", "2012-12-26", "12:05"], [20, "", "2012-12-26", "12:05"],
[10, 2000, "2012-12-26", "12:10"], [0, "", "2012-12-31", "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"],
] ]
for d in input_data: for d in input_data:
self.cleanup_data() repost_stock_as_per_valuation_method(valuation_method)
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])
last_sle = get_previous_sle({
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": [{
"item_code": "_Test Item", "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC", "warehouse": "_Test Warehouse - _TC",
"qty": qty, "posting_date": d[2],
"valuation_rate": rate "posting_time": d[3]
}]
}) })
stock_reco.insert()
stock_reco.submit()
frappe.db.commit()
return stock_reco
def insert_existing_sle(self, valuation_method): # 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)
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)
make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
source="_Test Warehouse - _TC", qty=15)
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) frappe.db.set_value("Item", "_Test Item", "valuation_method", valuation_method)
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) update_entries_after({
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", "item_code": "_Test Item",
"parentfield": "items", "warehouse": "_Test Warehouse - _TC",
"incoming_rate": 1000, }, allow_negative_stock=1)
"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"
}
]
}
pr = frappe.copy_doc(stock_entry)
pr.insert()
pr.submit()
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()
test_dependencies = ["Item", "Warehouse"] test_dependencies = ["Item", "Warehouse"]