feat: Stock value and account balance sync. (#19233)

* feat: Allow user to sync stock_value and account_balance jv if perpetual inventory is checked

* fix(test): Sales Invoice

* fix(test): Purchase Invoice

* fix(test): Delivery Note

* fix: more test_case

* fix(test): Stock Entry

* fix(test): Purchase Receipt

* fix(more-test): Stock Entries

* fix(more-test): Sales Invoice and Delivery Note

* fix: tests for delivery note

* fix: tests for stock reconciliation

* refactor: stock and account balance function

* fix(more-test): Warehouse

* fix(test): Landed Cost Voucher

* fix: changes requested
This commit is contained in:
Anurag Mishra 2019-10-31 15:55:03 +05:30 committed by Nabin Hait
parent 7e9b90ad06
commit a11e738801
27 changed files with 596 additions and 477 deletions

View File

@ -160,7 +160,7 @@ def _make_test_records(verbose):
["_Test Payable USD", "Current Liabilities", 0, "Payable", "USD"] ["_Test Payable USD", "Current Liabilities", 0, "Payable", "USD"]
] ]
for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"]]: for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"], ["_Test Company with perpetual inventory", "TCP1"]]:
test_objects = make_test_objects("Account", [{ test_objects = make_test_objects("Account", [{
"doctype": "Account", "doctype": "Account",
"account_name": account_name, "account_name": account_name,

View File

@ -8,10 +8,12 @@ import unittest
from frappe.utils import today, cint, flt, getdate from frappe.utils import today, cint, flt, getdate
from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
from erpnext.accounts.party import get_dashboard_info from erpnext.accounts.party import get_dashboard_info
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestLoyaltyProgram(unittest.TestCase): class TestLoyaltyProgram(unittest.TestCase):
@classmethod @classmethod
def setUpClass(self): def setUpClass(self):
set_perpetual_inventory(0)
# create relevant item, customer, loyalty program, etc # create relevant item, customer, loyalty program, etc
create_records() create_records()

View File

@ -10,7 +10,7 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_ent
from frappe.utils import cint, flt, today, nowdate, add_days from frappe.utils import cint, flt, today, nowdate, add_days
import frappe.defaults import frappe.defaults
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, \
test_records as pr_test_records test_records as pr_test_records, make_purchase_receipt, get_taxes
from erpnext.controllers.accounts_controller import get_payment_terms from erpnext.controllers.accounts_controller import get_payment_terms
from erpnext.exceptions import InvalidCurrency from erpnext.exceptions import InvalidCurrency
from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction
@ -57,16 +57,11 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account)) self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account))
def test_gl_entries_with_perpetual_inventory(self): def test_gl_entries_with_perpetual_inventory(self):
pi = frappe.copy_doc(test_records[1]) pi = make_purchase_invoice(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1", get_taxes_and_charges=True, qty=10)
set_perpetual_inventory(1, pi.company)
self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pi.company)), 1) self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pi.company)), 1)
pi.insert()
pi.submit()
self.check_gle_for_pi(pi.name) self.check_gle_for_pi(pi.name)
set_perpetual_inventory(0, pi.company)
def test_terms_added_after_save(self): def test_terms_added_after_save(self):
pi = frappe.copy_doc(test_records[1]) pi = frappe.copy_doc(test_records[1])
pi.insert() pi.insert()
@ -196,21 +191,21 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(pi.on_hold, 0) self.assertEqual(pi.on_hold, 0)
def test_gl_entries_with_perpetual_inventory_against_pr(self): def test_gl_entries_with_perpetual_inventory_against_pr(self):
pr = frappe.copy_doc(pr_test_records[0])
set_perpetual_inventory(1, pr.company)
self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1)
pr.submit()
pi = frappe.copy_doc(test_records[1]) pr = make_purchase_receipt(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", get_taxes_and_charges=True,)
for d in pi.get("items"):
self.assertTrue(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1)
pi = make_purchase_invoice(company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1", get_taxes_and_charges=True, qty=10,do_not_save= "True")
for d in pi.items:
d.purchase_receipt = pr.name d.purchase_receipt = pr.name
pi.insert() pi.insert()
pi.submit() pi.submit()
self.check_gle_for_pi(pi.name) self.check_gle_for_pi(pi.name)
set_perpetual_inventory(0, pr.company)
def check_gle_for_pi(self, pi): def check_gle_for_pi(self, pi):
gl_entries = frappe.db.sql("""select account, debit, credit gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
@ -218,10 +213,10 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
expected_values = dict((d[0], d) for d in [ expected_values = dict((d[0], d) for d in [
["_Test Payable - _TC", 0, 720], ["Creditors - TCP1", 0, 720],
["Stock Received But Not Billed - _TC", 500.0, 0], ["Stock Received But Not Billed - TCP1", 500.0, 0],
["_Test Account Shipping Charges - _TC", 100.0, 0], ["_Test Account Shipping Charges - TCP1", 100.0, 0],
["_Test Account VAT - _TC", 120.0, 0], ["_Test Account VAT - TCP1", 120.0, 0],
]) ])
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
@ -524,10 +519,9 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertFalse(gle) self.assertFalse(gle)
def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self): def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime()) posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1", company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1")
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit, gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency debit_in_account_currency, credit_in_account_currency
@ -548,9 +542,9 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(expected_gl_entries[gle.account][2], gle.credit) self.assertEqual(expected_gl_entries[gle.account][2], gle.credit)
def test_purchase_invoice_for_is_paid_and_update_stock_gl_entry_with_perpetual_inventory(self): def test_purchase_invoice_for_is_paid_and_update_stock_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - _TC", is_paid=1) posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1", is_paid=1, company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", warehouse= "Stores - TCP1", cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1")
gl_entries = frappe.db.sql("""select account, account_currency, sum(debit) as debit, gl_entries = frappe.db.sql("""select account, account_currency, sum(debit) as debit,
sum(credit) as credit, debit_in_account_currency, credit_in_account_currency sum(credit) as credit, debit_in_account_currency, credit_in_account_currency
@ -563,7 +557,7 @@ class TestPurchaseInvoice(unittest.TestCase):
expected_gl_entries = dict((d[0], d) for d in [ expected_gl_entries = dict((d[0], d) for d in [
[pi.credit_to, 250.0, 250.0], [pi.credit_to, 250.0, 250.0],
[stock_in_hand_account, 250.0, 0.0], [stock_in_hand_account, 250.0, 0.0],
["Cash - _TC", 0.0, 250.0] ["Cash - TCP1", 0.0, 250.0]
]) ])
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
@ -630,6 +624,7 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(pi.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2)) self.assertEqual(pi.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))
def test_rejected_serial_no(self): def test_rejected_serial_no(self):
set_perpetual_inventory(0)
pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1, pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1,
rejected_qty=1, rate=500, update_stock=1, rejected_qty=1, rate=500, update_stock=1,
rejected_warehouse = "_Test Rejected Warehouse - _TC") rejected_warehouse = "_Test Rejected Warehouse - _TC")
@ -881,7 +876,7 @@ def make_purchase_invoice(**args):
pi.is_return = args.is_return pi.is_return = args.is_return
pi.return_against = args.return_against pi.return_against = args.return_against
pi.is_subcontracted = args.is_subcontracted or "No" pi.is_subcontracted = args.is_subcontracted or "No"
pi.supplier_warehouse = "_Test Warehouse 1 - _TC" pi.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC"
pi.append("items", { pi.append("items", {
"item_code": args.item or args.item_code or "_Test Item", "item_code": args.item or args.item_code or "_Test Item",
@ -890,14 +885,21 @@ def make_purchase_invoice(**args):
"received_qty": args.received_qty or 0, "received_qty": args.received_qty or 0,
"rejected_qty": args.rejected_qty or 0, "rejected_qty": args.rejected_qty or 0,
"rate": args.rate or 50, "rate": args.rate or 50,
'expense_account': args.expense_account or '_Test Account Cost for Goods Sold - _TC',
"conversion_factor": 1.0, "conversion_factor": 1.0,
"serial_no": args.serial_no, "serial_no": args.serial_no,
"stock_uom": "_Test UOM", "stock_uom": "_Test UOM",
"cost_center": "_Test Cost Center - _TC", "cost_center": args.cost_center or "_Test Cost Center - _TC",
"project": args.project, "project": args.project,
"rejected_warehouse": args.rejected_warehouse or "", "rejected_warehouse": args.rejected_warehouse or "",
"rejected_serial_no": args.rejected_serial_no or "" "rejected_serial_no": args.rejected_serial_no or ""
}) })
if args.get_taxes_and_charges:
taxes = get_taxes()
for tax in taxes:
pi.append("taxes", tax)
if not args.do_not_save: if not args.do_not_save:
pi.insert() pi.insert()
if not args.do_not_submit: if not args.do_not_submit:

View File

@ -402,14 +402,21 @@ def make_invoice(doc_list={}, email_queue_list={}, customers_list={}):
for docs in doc_list: for docs in doc_list:
for name, doc in iteritems(docs): for name, doc in iteritems(docs):
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}): if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
validate_records(doc) if isinstance(doc, dict):
si_doc = frappe.new_doc('Sales Invoice') validate_records(doc)
si_doc.offline_pos_name = name si_doc = frappe.new_doc('Sales Invoice')
si_doc.update(doc) si_doc.offline_pos_name = name
si_doc.set_posting_time = 1 si_doc.update(doc)
si_doc.customer = get_customer_id(doc) si_doc.set_posting_time = 1
si_doc.due_date = doc.get('posting_date') si_doc.customer = get_customer_id(doc)
name_list = submit_invoice(si_doc, name, doc, name_list) si_doc.due_date = doc.get('posting_date')
name_list = submit_invoice(si_doc, name, doc, name_list)
else:
doc.due_date = doc.get('posting_date')
doc.customer = get_customer_id(doc)
doc.set_posting_time = 1
doc.offline_pos_name = name
name_list = submit_invoice(doc, name, doc, name_list)
else: else:
name_list.append(name) name_list.append(name)

View File

@ -686,7 +686,6 @@ class SalesInvoice(SellingController):
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False): def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company) auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
if not gl_entries: if not gl_entries:
gl_entries = self.get_gl_entries() gl_entries = self.get_gl_entries()

View File

@ -68,8 +68,6 @@
"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,
@ -276,7 +274,6 @@
"uom": "_Test UOM 1", "uom": "_Test UOM 1",
"conversion_factor": 1, "conversion_factor": 1,
"stock_uom": "_Test UOM 1" "stock_uom": "_Test UOM 1"
}, },
{ {
"cost_center": "_Test Cost Center - _TC", "cost_center": "_Test Cost Center - _TC",

View File

@ -20,6 +20,9 @@ from erpnext.stock.doctype.item.test_item import create_item
from six import iteritems from six import iteritems
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction
from erpnext.regional.india.utils import get_ewb_data from erpnext.regional.india.utils import get_ewb_data
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
class TestSalesInvoice(unittest.TestCase): class TestSalesInvoice(unittest.TestCase):
def make(self): def make(self):
@ -550,7 +553,6 @@ class TestSalesInvoice(unittest.TestCase):
si.get("taxes")[6].tax_amount = 2 si.get("taxes")[6].tax_amount = 2
si.insert() si.insert()
print(si.name)
expected_values = [ expected_values = [
{ {
@ -679,56 +681,67 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle) self.assertFalse(gle)
def test_pos_gl_entry_with_perpetual_inventory(self): def test_pos_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
make_pos_profile() make_pos_profile()
self._insert_purchase_receipt() pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
pos = copy.deepcopy(test_records[1])
pos["is_pos"] = 1 pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
pos["update_stock"] = 1
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, pos.is_pos = 1
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300}] pos.update_stock = 1
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 50})
taxes = get_taxes_and_charges()
pos.taxes = []
for tax in taxes:
pos.append("taxes", tax)
si = frappe.copy_doc(pos) si = frappe.copy_doc(pos)
si.insert() si.insert()
si.submit() si.submit()
self.assertEqual(si.paid_amount, 100.0)
self.assertEqual(si.paid_amount, 600.0) self.pos_gl_entry(si, pos, 50)
self.pos_gl_entry(si, pos, 300)
def test_pos_change_amount(self): def test_pos_change_amount(self):
set_perpetual_inventory()
make_pos_profile() make_pos_profile()
self._insert_purchase_receipt() pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
pos = copy.deepcopy(test_records[1])
pos["is_pos"] = 1
pos["update_stock"] = 1
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 340}]
si = frappe.copy_doc(pos) pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
si.change_amount = 5.0
si.insert()
si.submit()
self.assertEqual(si.grand_total, 630.0) pos.is_pos = 1
self.assertEqual(si.write_off_amount, -5) pos.update_stock = 1
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 60})
pos.change_amount = 5.0
pos.insert()
pos.submit()
self.assertEqual(pos.grand_total, 100.0)
self.assertEqual(pos.write_off_amount, -5)
def test_make_pos_invoice(self): def test_make_pos_invoice(self):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
set_perpetual_inventory()
make_pos_profile() make_pos_profile()
self._insert_purchase_receipt() pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
pos = copy.deepcopy(test_records[1]) pos.is_pos = 1
pos["is_pos"] = 1 pos.update_stock = 1
pos["update_stock"] = 1
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}] pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 50})
taxes = get_taxes_and_charges()
pos.taxes = []
for tax in taxes:
pos.append("taxes", tax)
invoice_data = [{'09052016142': pos}] invoice_data = [{'09052016142': pos}]
si = make_invoice(invoice_data).get('invoice') si = make_invoice(invoice_data).get('invoice')
@ -736,16 +749,15 @@ class TestSalesInvoice(unittest.TestCase):
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1}) sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1})
si = frappe.get_doc('Sales Invoice', sales_invoice[0].name) si = frappe.get_doc('Sales Invoice', sales_invoice[0].name)
self.assertEqual(si.grand_total, 630.0)
self.pos_gl_entry(si, pos, 330) self.assertEqual(si.grand_total, 100)
self.pos_gl_entry(si, pos, 50)
def test_make_pos_invoice_in_draft(self): def test_make_pos_invoice_in_draft(self):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.item.test_item import make_item
set_perpetual_inventory()
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock') allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
if allow_negative_stock: if allow_negative_stock:
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0) frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
@ -789,7 +801,7 @@ class TestSalesInvoice(unittest.TestCase):
si.name, as_dict=1)[0] si.name, as_dict=1)[0]
self.assertTrue(sle) self.assertTrue(sle)
self.assertEqual([sle.item_code, sle.warehouse, sle.actual_qty], self.assertEqual([sle.item_code, sle.warehouse, sle.actual_qty],
["_Test Item", "_Test Warehouse - _TC", -1.0]) ['_Test FG Item', 'Stores - TCP1', -1.0])
# check gl entries # check gl entries
gl_entries = frappe.db.sql("""select account, debit, credit gl_entries = frappe.db.sql("""select account, debit, credit
@ -797,19 +809,19 @@ class TestSalesInvoice(unittest.TestCase):
order by account asc, debit asc, credit asc""", si.name, as_dict=1) order by account asc, debit asc, credit asc""", si.name, as_dict=1)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
stock_in_hand = get_inventory_account('_Test Company') stock_in_hand = get_inventory_account('_Test Company with perpetual inventory')
expected_gl_entries = sorted([ expected_gl_entries = sorted([
[si.debit_to, 630.0, 0.0], [si.debit_to, 100.0, 0.0],
[pos["items"][0]["income_account"], 0.0, 500.0], [pos.items[0].income_account, 0.0, 89.09],
[pos["taxes"][0]["account_head"], 0.0, 80.0], ['Round Off - TCP1', 0.0, 0.01],
[pos["taxes"][1]["account_head"], 0.0, 50.0], [pos.taxes[0].account_head, 0.0, 10.69],
[pos.taxes[1].account_head, 0.0, 0.21],
[stock_in_hand, 0.0, abs(sle.stock_value_difference)], [stock_in_hand, 0.0, abs(sle.stock_value_difference)],
[pos["items"][0]["expense_account"], abs(sle.stock_value_difference), 0.0], [pos.items[0].expense_account, abs(sle.stock_value_difference), 0.0],
[si.debit_to, 0.0, 300.0], [si.debit_to, 0.0, 50.0],
[si.debit_to, 0.0, cash_amount], [si.debit_to, 0.0, cash_amount],
["_Test Bank - _TC", 300.0, 0.0], ["_Test Bank - TCP1", 50, 0.0],
["Cash - _TC", cash_amount, 0.0] ["Cash - TCP1", cash_amount, 0.0]
]) ])
for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)): for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
@ -823,9 +835,9 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle) self.assertFalse(gle)
set_perpetual_inventory(0)
frappe.db.sql("delete from `tabPOS Profile`") frappe.db.sql("delete from `tabPOS Profile`")
si.delete()
def test_pos_si_without_payment(self): def test_pos_si_without_payment(self):
set_perpetual_inventory() set_perpetual_inventory()
@ -1008,7 +1020,6 @@ class TestSalesInvoice(unittest.TestCase):
""" """
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
se = make_serialized_item() se = make_serialized_item()
@ -1023,14 +1034,17 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(si.get("items")[0].serial_no, dn.get("items")[0].serial_no) self.assertEqual(si.get("items")[0].serial_no, dn.get("items")[0].serial_no)
def test_return_sales_invoice(self): def test_return_sales_invoice(self):
set_perpetual_inventory() make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=50, basic_rate=100)
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
actual_qty_0 = get_qty_after_transaction() actual_qty_0 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1")
si = create_sales_invoice(qty=5, rate=500, update_stock=1) si = create_sales_invoice(qty = 5, rate=500, update_stock=1, company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1")
actual_qty_1 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1")
frappe.db.commit()
actual_qty_1 = get_qty_after_transaction()
self.assertEqual(actual_qty_0 - 5, actual_qty_1) self.assertEqual(actual_qty_0 - 5, actual_qty_1)
# outgoing_rate # outgoing_rate
@ -1038,10 +1052,9 @@ class TestSalesInvoice(unittest.TestCase):
"voucher_no": si.name}, "stock_value_difference") / 5 "voucher_no": si.name}, "stock_value_difference") / 5
# return entry # return entry
si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1) si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1, company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1")
actual_qty_2 = get_qty_after_transaction()
actual_qty_2 = get_qty_after_transaction(item_code = "_Test Item", warehouse = "Stores - TCP1")
self.assertEqual(actual_qty_1 + 2, actual_qty_2) self.assertEqual(actual_qty_1 + 2, actual_qty_2)
incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
@ -1049,7 +1062,7 @@ class TestSalesInvoice(unittest.TestCase):
["incoming_rate", "stock_value_difference"]) ["incoming_rate", "stock_value_difference"])
self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
stock_in_hand_account = get_inventory_account('_Test Company', si1.items[0].warehouse) stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory', si1.items[0].warehouse)
# Check gl entry # Check gl entry
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice", gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
@ -1058,7 +1071,7 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(gle_warehouse_amount, stock_value_difference) self.assertEqual(gle_warehouse_amount, stock_value_difference)
party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice", party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
"voucher_no": si1.name, "account": "Debtors - _TC", "party": "_Test Customer"}, "credit") "voucher_no": si1.name, "account": "Debtors - TCP1", "party": "_Test Customer"}, "credit")
self.assertEqual(party_credited, 1000) self.assertEqual(party_credited, 1000)
@ -1066,7 +1079,6 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(si1.outstanding_amount) self.assertFalse(si1.outstanding_amount)
self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500) self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500)
set_perpetual_inventory(0)
def test_discount_on_net_total(self): def test_discount_on_net_total(self):
si = frappe.copy_doc(test_records[2]) si = frappe.copy_doc(test_records[2])
@ -1524,6 +1536,8 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(si.total_taxes_and_charges, 577.05) self.assertEqual(si.total_taxes_and_charges, 577.05)
self.assertEqual(si.grand_total, 1827.05) self.assertEqual(si.grand_total, 1827.05)
def test_create_invoice_without_terms(self): def test_create_invoice_without_terms(self):
si = create_sales_invoice(do_not_save=1) si = create_sales_invoice(do_not_save=1)
self.assertFalse(si.get('payment_schedule')) self.assertFalse(si.get('payment_schedule'))
@ -1930,4 +1944,29 @@ def get_outstanding_amount(against_voucher_type, against_voucher, account, party
if against_voucher_type == 'Purchase Invoice': if against_voucher_type == 'Purchase Invoice':
bal = bal * -1 bal = bal * -1
return bal return bal
def get_taxes_and_charges():
return [{
"account_head": "_Test Account Excise Duty - TCP1",
"charge_type": "On Net Total",
"cost_center": "Main - TCP1",
"description": "Excise Duty",
"doctype": "Sales Taxes and Charges",
"idx": 1,
"included_in_print_rate": 1,
"parentfield": "taxes",
"rate": 12
},
{
"account_head": "_Test Account Education Cess - TCP1",
"charge_type": "On Previous Row Amount",
"cost_center": "Main - TCP1",
"description": "Education Cess",
"doctype": "Sales Taxes and Charges",
"idx": 2,
"included_in_print_rate": 1,
"parentfield": "taxes",
"rate": 2,
"row_id": 1
}]

View File

@ -14,13 +14,13 @@ class TestShippingRule(unittest.TestCase):
shipping_rule.name = test_records[0].get('name') shipping_rule.name = test_records[0].get('name')
shipping_rule.get("conditions")[0].from_value = 101 shipping_rule.get("conditions")[0].from_value = 101
self.assertRaises(FromGreaterThanToError, shipping_rule.insert) self.assertRaises(FromGreaterThanToError, shipping_rule.insert)
def test_many_zero_to_values(self): def test_many_zero_to_values(self):
shipping_rule = frappe.copy_doc(test_records[0]) shipping_rule = frappe.copy_doc(test_records[0])
shipping_rule.name = test_records[0].get('name') shipping_rule.name = test_records[0].get('name')
shipping_rule.get("conditions")[0].to_value = 0 shipping_rule.get("conditions")[0].to_value = 0
self.assertRaises(ManyBlankToValuesError, shipping_rule.insert) self.assertRaises(ManyBlankToValuesError, shipping_rule.insert)
def test_overlapping_conditions(self): def test_overlapping_conditions(self):
for range_a, range_b in [ for range_a, range_b in [
((50, 150), (0, 100)), ((50, 150), (0, 100)),
@ -38,6 +38,10 @@ class TestShippingRule(unittest.TestCase):
self.assertRaises(OverlappingConditionError, shipping_rule.insert) self.assertRaises(OverlappingConditionError, shipping_rule.insert)
def create_shipping_rule(shipping_rule_type, shipping_rule_name): def create_shipping_rule(shipping_rule_type, shipping_rule_name):
if frappe.db.exists("Shipping Rule", shipping_rule_name):
return frappe.get_doc("Shipping Rule", shipping_rule_name)
sr = frappe.new_doc("Shipping Rule") sr = frappe.new_doc("Shipping Rule")
sr.account = "_Test Account Shipping Charges - _TC" sr.account = "_Test Account Shipping Charges - _TC"
sr.calculate_based_on = "Net Total" sr.calculate_based_on = "Net Total"
@ -70,4 +74,4 @@ def create_shipping_rule(shipping_rule_type, shipping_rule_name):
}) })
sr.insert(ignore_permissions=True) sr.insert(ignore_permissions=True)
sr.submit() sr.submit()
return sr return sr

View File

@ -3,8 +3,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, erpnext import frappe, erpnext
from frappe.utils import flt, cstr, cint from frappe.utils import flt, cstr, cint, comma_and
from frappe import _ from frappe import _
from erpnext.accounts.utils import get_stock_and_account_balance
from frappe.model.meta import get_field_precision from frappe.model.meta import get_field_precision
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
@ -12,6 +13,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import g
class ClosedAccountingPeriod(frappe.ValidationError): pass class ClosedAccountingPeriod(frappe.ValidationError): pass
class StockAccountInvalidTransaction(frappe.ValidationError): pass class StockAccountInvalidTransaction(frappe.ValidationError): pass
class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False): def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False):
if gl_map: if gl_map:
@ -115,11 +117,9 @@ def check_if_in_list(gle, gl_map, dimensions=None):
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False): def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
if not from_repost: if not from_repost:
validate_account_for_perpetual_inventory(gl_map)
validate_cwip_accounts(gl_map) validate_cwip_accounts(gl_map)
round_off_debit_credit(gl_map) round_off_debit_credit(gl_map)
for entry in gl_map: for entry in gl_map:
make_entry(entry, adv_adj, update_outstanding, from_repost) make_entry(entry, adv_adj, update_outstanding, from_repost)
@ -127,6 +127,10 @@ def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
if not from_repost: if not from_repost:
validate_expense_against_budget(entry) validate_expense_against_budget(entry)
if not from_repost:
validate_account_for_perpetual_inventory(gl_map)
def make_entry(args, adv_adj, update_outstanding, from_repost=False): def make_entry(args, adv_adj, update_outstanding, from_repost=False):
args.update({"doctype": "GL Entry"}) args.update({"doctype": "GL Entry"})
gle = frappe.get_doc(args) gle = frappe.get_doc(args)
@ -137,15 +141,31 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
gle.submit() gle.submit()
def validate_account_for_perpetual_inventory(gl_map): def validate_account_for_perpetual_inventory(gl_map):
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)) \ if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
and gl_map[0].voucher_type=="Journal Entry": account_list = [gl_entries.account for gl_entries in gl_map]
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
where account_type = 'Stock' and is_group=0""")]
for entry in gl_map: aii_accounts = [d.name for d in frappe.get_all("Account",
if entry.account in aii_accounts: filters={'account_type': 'Stock', 'is_group': 0, 'company': gl_map[0].company})]
for account in account_list:
if account not in aii_accounts:
continue
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(account,
gl_map[0].posting_date, gl_map[0].company)
if gl_map[0].voucher_type=="Journal Entry":
# In case of Journal Entry, there are no corresponding SL entries,
# hence deducting currency amount
account_bal -= flt(gl_map[0].debit) - flt(gl_map[0].credit)
if account_bal == stock_bal:
frappe.throw(_("Account: {0} can only be updated via Stock Transactions") frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(entry.account), StockAccountInvalidTransaction) .format(account), StockAccountInvalidTransaction)
elif account_bal != stock_bal:
frappe.throw(_("Account Balance ({0}) and Stock Value ({1}) is out of sync for account {2} and linked warehouse ({3}). Please create adjustment Journal Entry for amount {4}.")
.format(account_bal, stock_bal, account, comma_and(warehouse_list), stock_bal - account_bal),
StockValueAndAccountBalanceOutOfSync)
def validate_cwip_accounts(gl_map): def validate_cwip_accounts(gl_map):
if not cint(frappe.db.get_value("Asset Settings", None, "disable_cwip_accounting")) \ if not cint(frappe.db.get_value("Asset Settings", None, "disable_cwip_accounting")) \

View File

@ -13,6 +13,10 @@ from six import iteritems
# imported to enable erpnext.accounts.utils.get_account_currency # imported to enable erpnext.accounts.utils.get_account_currency
from erpnext.accounts.doctype.account.account import get_account_currency from erpnext.accounts.doctype.account.account import get_account_currency
from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map
class FiscalYearError(frappe.ValidationError): pass class FiscalYearError(frappe.ValidationError): pass
@frappe.whitelist() @frappe.whitelist()
@ -560,23 +564,23 @@ def fix_total_debit_credit():
(dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr), (dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr),
(d.diff, d.voucher_type, d.voucher_no)) (d.diff, d.voucher_type, d.voucher_no))
def get_stock_and_account_difference(account_list=None, posting_date=None, company=None): def get_stock_and_account_balance(account=None, posting_date=None, company=None):
from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map
if not posting_date: posting_date = nowdate() if not posting_date: posting_date = nowdate()
difference = {}
warehouse_account = get_warehouse_account_map(company) warehouse_account = get_warehouse_account_map(company)
for warehouse, account_data in iteritems(warehouse_account): account_balance = get_balance_on(account, posting_date, in_account_currency=False)
if account_data.get('account') in account_list:
account_balance = get_balance_on(account_data.get('account'), posting_date, in_account_currency=False)
stock_value = get_stock_value_on(warehouse, posting_date)
if abs(flt(stock_value) - flt(account_balance)) > 0.005:
difference.setdefault(account_data.get('account'), flt(stock_value) - flt(account_balance))
return difference related_warehouses = [wh for wh, wh_details in warehouse_account.items()
if wh_details.account == account and not wh_details.is_group]
total_stock_value = 0.0
for warehouse in related_warehouses:
value = get_stock_value_on(warehouse, posting_date)
total_stock_value += value
precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
return flt(account_balance, precision), flt(total_stock_value, precision), related_warehouses
def get_currency_precision(): def get_currency_precision():
precision = cint(frappe.db.get_default("currency_precision")) precision = cint(frappe.db.get_default("currency_precision"))

View File

@ -207,41 +207,6 @@ class StockController(AccountsController):
reference_doctype=self.doctype, reference_doctype=self.doctype,
reference_name=self.name)).insert().name reference_name=self.name)).insert().name
def make_adjustment_entry(self, expected_gle, voucher_obj):
from erpnext.accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle]
acc_diff = get_stock_and_account_difference(account_list,
expected_gle[0].posting_date, self.company)
cost_center = self.get_company_default("cost_center")
stock_adjustment_account = self.get_company_default("stock_adjustment_account")
gl_entries = []
for account, diff in acc_diff.items():
if diff:
gl_entries.append([
# stock in hand account
voucher_obj.get_gl_dict({
"account": account,
"against": stock_adjustment_account,
"debit": diff,
"remarks": "Adjustment Accounting Entry for Stock",
}),
# account against stock in hand
voucher_obj.get_gl_dict({
"account": stock_adjustment_account,
"against": account,
"credit": diff,
"cost_center": cost_center or None,
"remarks": "Adjustment Accounting Entry for Stock",
}),
])
if gl_entries:
from erpnext.accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries)
def check_expense_account(self, item): def check_expense_account(self, item):
if not item.get("expense_account"): if not item.get("expense_account"):
frappe.throw(_("Expense or Difference account is mandatory for Item {0} as it impacts overall stock value").format(item.item_code)) frappe.throw(_("Expense or Difference account is mandatory for Item {0} as it impacts overall stock value").format(item.item_code))

View File

@ -11,9 +11,11 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import get_sa
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestProductionPlan(unittest.TestCase): class TestProductionPlan(unittest.TestCase):
def setUp(self): def setUp(self):
set_perpetual_inventory(0)
for item in ['Test Production Item 1', 'Subassembly Item 1', for item in ['Test Production Item 1', 'Subassembly Item 1',
'Raw Material Item 1', 'Raw Material Item 2']: 'Raw Material Item 1', 'Raw Material Item 2']:
create_item(item, valuation_rate=100) create_item(item, valuation_rate=100)

View File

@ -17,11 +17,11 @@ from erpnext.manufacturing.doctype.production_plan.test_production_plan import m
class TestWorkOrder(unittest.TestCase): class TestWorkOrder(unittest.TestCase):
def setUp(self): def setUp(self):
set_perpetual_inventory(0)
self.warehouse = '_Test Warehouse 2 - _TC' self.warehouse = '_Test Warehouse 2 - _TC'
self.item = '_Test Item' self.item = '_Test Item'
def check_planned_qty(self): def check_planned_qty(self):
set_perpetual_inventory(0)
planned0 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item", planned0 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item",
"warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") or 0 "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") or 0

View File

@ -22,7 +22,7 @@ class TestCompany(unittest.TestCase):
company.create_chart_of_accounts_based_on = "Existing Company" company.create_chart_of_accounts_based_on = "Existing Company"
company.existing_company = "_Test Company" company.existing_company = "_Test Company"
company.save() company.save()
expected_results = { expected_results = {
"Debtors - CFEC": { "Debtors - CFEC": {
"account_type": "Receivable", "account_type": "Receivable",
@ -37,7 +37,7 @@ class TestCompany(unittest.TestCase):
"parent_account": "Cash In Hand - CFEC" "parent_account": "Cash In Hand - CFEC"
} }
} }
for account, acc_property in expected_results.items(): for account, acc_property in expected_results.items():
acc = frappe.get_doc("Account", account) acc = frappe.get_doc("Account", account)
for prop, val in acc_property.items(): for prop, val in acc_property.items():
@ -50,14 +50,14 @@ class TestCompany(unittest.TestCase):
countries = ["India", "Brazil", "United Arab Emirates", "Canada", "Germany", "France", countries = ["India", "Brazil", "United Arab Emirates", "Canada", "Germany", "France",
"Guatemala", "Indonesia", "Italy", "Mexico", "Nicaragua", "Netherlands", "Singapore", "Guatemala", "Indonesia", "Italy", "Mexico", "Nicaragua", "Netherlands", "Singapore",
"Brazil", "Argentina", "Hungary", "Taiwan"] "Brazil", "Argentina", "Hungary", "Taiwan"]
for country in countries: for country in countries:
templates = get_charts_for_country(country) templates = get_charts_for_country(country)
if len(templates) != 1 and "Standard" in templates: if len(templates) != 1 and "Standard" in templates:
templates.remove("Standard") templates.remove("Standard")
self.assertTrue(templates) self.assertTrue(templates)
for template in templates: for template in templates:
try: try:
company = frappe.new_doc("Company") company = frappe.new_doc("Company")
@ -67,11 +67,11 @@ class TestCompany(unittest.TestCase):
company.create_chart_of_accounts_based_on = "Standard Template" company.create_chart_of_accounts_based_on = "Standard Template"
company.chart_of_accounts = template company.chart_of_accounts = template
company.save() company.save()
account_types = ["Cost of Goods Sold", "Depreciation", account_types = ["Cost of Goods Sold", "Depreciation",
"Expenses Included In Valuation", "Fixed Asset", "Payable", "Receivable", "Expenses Included In Valuation", "Fixed Asset", "Payable", "Receivable",
"Stock Adjustment", "Stock Received But Not Billed", "Bank", "Cash", "Stock"] "Stock Adjustment", "Stock Received But Not Billed", "Bank", "Cash", "Stock"]
for account_type in account_types: for account_type in account_types:
filters = { filters = {
"company": template, "company": template,

View File

@ -62,5 +62,16 @@
"domain": "Manufacturing", "domain": "Manufacturing",
"chart_of_accounts": "Standard", "chart_of_accounts": "Standard",
"default_holiday_list": "_Test Holiday List" "default_holiday_list": "_Test Holiday List"
},
{
"abbr": "TCP1",
"company_name": "_Test Company with perpetual inventory",
"country": "India",
"default_currency": "INR",
"doctype": "Company",
"domain": "Manufacturing",
"chart_of_accounts": "Standard",
"enable_perpetual_inventory": 1,
"default_holiday_list": "_Test Holiday List"
} }
] ]

View File

@ -21,7 +21,7 @@ def get_warehouse_account_map(company=None):
filters['company'] = company filters['company'] = company
for d in frappe.get_all('Warehouse', for d in frappe.get_all('Warehouse',
fields = ["name", "account", "parent_warehouse", "company"], fields = ["name", "account", "parent_warehouse", "company", "is_group"],
filters = filters, filters = filters,
order_by="lft, rgt"): order_by="lft, rgt"):
if not d.account: if not d.account:

View File

@ -8,10 +8,13 @@ import unittest
from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError, get_batch_no from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError, get_batch_no
from frappe.utils import cint from frappe.utils import cint
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestBatch(unittest.TestCase): class TestBatch(unittest.TestCase):
def setUp(self):
set_perpetual_inventory(0)
def test_item_has_batch_enabled(self): def test_item_has_batch_enabled(self):
self.assertRaises(ValidationError, frappe.get_doc({ self.assertRaises(ValidationError, frappe.get_doc({
"doctype": "Batch", "doctype": "Batch",

View File

@ -20,18 +20,11 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation \
import create_stock_reconciliation, set_valuation_method import create_stock_reconciliation, set_valuation_method
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order, create_dn_against_so from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order, create_dn_against_so
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse
class TestDeliveryNote(unittest.TestCase): class TestDeliveryNote(unittest.TestCase):
def tearDown(self): def setUp(self):
target_warehouse = "_Test Warehouse 1 - _TC" set_perpetual_inventory(0)
company = "_Test Company"
if not frappe.db.exists("Account", target_warehouse):
parent_account = frappe.db.get_value('Account',
{'company': company, 'is_group':1, 'account_type': 'Stock'},'name')
account = create_account(account_name="_Test Warehouse 1", \
account_type="Stock", parent_account= parent_account, company=company)
frappe.db.set_value('Warehouse', target_warehouse, 'account', account)
def test_over_billing_against_dn(self): def test_over_billing_against_dn(self):
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
@ -68,17 +61,16 @@ class TestDeliveryNote(unittest.TestCase):
self.assertFalse(get_gl_entries("Delivery Note", dn.name)) self.assertFalse(get_gl_entries("Delivery Note", dn.name))
def test_delivery_note_gl_entry(self): def test_delivery_note_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100) make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company') stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
prev_bal = get_balance_on(stock_in_hand_account) prev_bal = get_balance_on(stock_in_hand_account)
dn = create_delivery_note() dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
gl_entries = get_gl_entries("Delivery Note", dn.name) gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
@ -88,7 +80,7 @@ class TestDeliveryNote(unittest.TestCase):
expected_values = { expected_values = {
stock_in_hand_account: [0.0, stock_value_difference], stock_in_hand_account: [0.0, stock_value_difference],
"Cost of Goods Sold - _TC": [stock_value_difference, 0.0] "Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
@ -98,7 +90,7 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(bal, prev_bal - stock_value_difference) self.assertEqual(bal, prev_bal - stock_value_difference)
# back dated incoming entry # back dated incoming entry
make_stock_entry(posting_date=add_days(nowdate(), -2), target="_Test Warehouse - _TC", make_stock_entry(posting_date=add_days(nowdate(), -2), target="Stores - TCP1",
qty=5, basic_rate=100) qty=5, basic_rate=100)
gl_entries = get_gl_entries("Delivery Note", dn.name) gl_entries = get_gl_entries("Delivery Note", dn.name)
@ -109,27 +101,25 @@ class TestDeliveryNote(unittest.TestCase):
expected_values = { expected_values = {
stock_in_hand_account: [0.0, stock_value_difference], stock_in_hand_account: [0.0, stock_value_difference],
"Cost of Goods Sold - _TC": [stock_value_difference, 0.0] "Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
dn.cancel() dn.cancel()
self.assertFalse(get_gl_entries("Delivery Note", dn.name)) self.assertFalse(get_gl_entries("Delivery Note", dn.name))
set_perpetual_inventory(0, company)
def test_delivery_note_gl_entry_packing_item(self): def test_delivery_note_gl_entry_packing_item(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=10, basic_rate=100) make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=10, basic_rate=100)
make_stock_entry(item_code="_Test Item Home Desktop 100", make_stock_entry(item_code="_Test Item Home Desktop 100",
target="_Test Warehouse - _TC", qty=10, basic_rate=100) target="Stores - TCP1", qty=10, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company') stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
prev_bal = get_balance_on(stock_in_hand_account) prev_bal = get_balance_on(stock_in_hand_account)
dn = create_delivery_note(item_code="_Test Product Bundle Item") dn = create_delivery_note(item_code="_Test Product Bundle Item", company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
stock_value_diff_rm1 = abs(frappe.db.get_value("Stock Ledger Entry", stock_value_diff_rm1 = abs(frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"}, {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"},
@ -146,7 +136,7 @@ class TestDeliveryNote(unittest.TestCase):
expected_values = { expected_values = {
stock_in_hand_account: [0.0, stock_value_diff], stock_in_hand_account: [0.0, stock_value_diff],
"Cost of Goods Sold - _TC": [stock_value_diff, 0.0] "Cost of Goods Sold - TCP1": [stock_value_diff, 0.0]
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
@ -158,8 +148,6 @@ class TestDeliveryNote(unittest.TestCase):
dn.cancel() dn.cancel()
self.assertFalse(get_gl_entries("Delivery Note", dn.name)) self.assertFalse(get_gl_entries("Delivery Note", dn.name))
set_perpetual_inventory(0, company)
def test_serialized(self): def test_serialized(self):
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]
@ -218,16 +206,16 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(cstr(serial_no.get(field)), value) self.assertEqual(cstr(serial_no.get(field)), value)
def test_sales_return_for_non_bundled_items(self): def test_sales_return_for_non_bundled_items(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=50, basic_rate=100)
actual_qty_0 = get_qty_after_transaction() actual_qty_0 = get_qty_after_transaction(warehouse="Stores - TCP1")
dn = create_delivery_note(qty=5, rate=500) dn = create_delivery_note(qty=5, rate=500, warehouse="Stores - TCP1", company=company,
expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
actual_qty_1 = get_qty_after_transaction() actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_0 - 5, actual_qty_1) self.assertEqual(actual_qty_0 - 5, actual_qty_1)
# outgoing_rate # outgoing_rate
@ -235,9 +223,10 @@ class TestDeliveryNote(unittest.TestCase):
"voucher_no": dn.name}, "stock_value_difference") / 5 "voucher_no": dn.name}, "stock_value_difference") / 5
# return entry # return entry
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, rate=500) dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, rate=500,
company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
actual_qty_2 = get_qty_after_transaction() actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_1 + 2, actual_qty_2) self.assertEqual(actual_qty_1 + 2, actual_qty_2)
@ -246,27 +235,29 @@ class TestDeliveryNote(unittest.TestCase):
["incoming_rate", "stock_value_difference"]) ["incoming_rate", "stock_value_difference"])
self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
stock_in_hand_account = get_inventory_account('_Test Company', dn1.items[0].warehouse) stock_in_hand_account = get_inventory_account(company, dn1.items[0].warehouse)
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note",
"voucher_no": dn1.name, "account": stock_in_hand_account}, "debit") "voucher_no": dn1.name, "account": stock_in_hand_account}, "debit")
self.assertEqual(gle_warehouse_amount, stock_value_difference) self.assertEqual(gle_warehouse_amount, stock_value_difference)
set_perpetual_inventory(0, company)
def test_return_single_item_from_bundled_items(self): def test_return_single_item_from_bundled_items(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100) create_stock_reconciliation(item_code="_Test Item",
create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", warehouse="Stores - TCP1", qty=50, rate=100,
qty=50, rate=100) company=company, expense_account = "Stock Adjustment - TCP1")
create_stock_reconciliation(item_code="_Test Item Home Desktop 100",
warehouse="Stores - TCP1", qty=50, rate=100,
company=company, expense_account = "Stock Adjustment - TCP1")
dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500) dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500,
company=company, warehouse="Stores - TCP1",
expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# Qty after delivery # Qty after delivery
actual_qty_1 = get_qty_after_transaction() actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_1, 25) self.assertEqual(actual_qty_1, 25)
# outgoing_rate # outgoing_rate
@ -274,10 +265,12 @@ class TestDeliveryNote(unittest.TestCase):
"voucher_no": dn.name, "item_code": "_Test Item"}, "stock_value_difference") / 25 "voucher_no": dn.name, "item_code": "_Test Item"}, "stock_value_difference") / 25
# return 'test item' from packed items # return 'test item' from packed items
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500) dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500,
company=company, warehouse="Stores - TCP1",
expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# qty after return # qty after return
actual_qty_2 = get_qty_after_transaction() actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty_2, 35) self.assertEqual(actual_qty_2, 35)
# Check incoming rate for return entry # Check incoming rate for return entry
@ -286,7 +279,7 @@ class TestDeliveryNote(unittest.TestCase):
["incoming_rate", "stock_value_difference"]) ["incoming_rate", "stock_value_difference"])
self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
stock_in_hand_account = get_inventory_account('_Test Company', dn1.items[0].warehouse) stock_in_hand_account = get_inventory_account(company, dn1.items[0].warehouse)
# Check gl entry for warehouse # Check gl entry for warehouse
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note",
@ -294,33 +287,33 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(gle_warehouse_amount, stock_value_difference) self.assertEqual(gle_warehouse_amount, stock_value_difference)
set_perpetual_inventory(0, company)
def test_return_entire_bundled_items(self): def test_return_entire_bundled_items(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
create_stock_reconciliation(item_code="_Test Item", create_stock_reconciliation(item_code="_Test Item",
target="_Test Warehouse - _TC", qty=50, rate=100) warehouse="Stores - TCP1", qty=50, rate=100,
company=company, expense_account = "Stock Adjustment - TCP1")
create_stock_reconciliation(item_code="_Test Item Home Desktop 100", create_stock_reconciliation(item_code="_Test Item Home Desktop 100",
target="_Test Warehouse - _TC", qty=50, rate=100) warehouse="Stores - TCP1", qty=50, rate=100,
company=company, expense_account = "Stock Adjustment - TCP1")
actual_qty = get_qty_after_transaction() actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty, 50) self.assertEqual(actual_qty, 50)
dn = create_delivery_note(item_code="_Test Product Bundle Item", dn = create_delivery_note(item_code="_Test Product Bundle Item",
qty=5, rate=500) qty=5, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# qty after return # qty after return
actual_qty = get_qty_after_transaction() actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty, 25) self.assertEqual(actual_qty, 25)
# return bundled item # return bundled item
dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1, dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1,
return_against=dn.name, qty=-2, rate=500) return_against=dn.name, qty=-2, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
# qty after return # qty after return
actual_qty = get_qty_after_transaction() actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty, 35) self.assertEqual(actual_qty, 35)
# Check incoming rate for return entry # Check incoming rate for return entry
@ -337,8 +330,6 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(gle_warehouse_amount, 1400) self.assertEqual(gle_warehouse_amount, 1400)
set_perpetual_inventory(0, company)
def test_return_for_serialized_items(self): def test_return_for_serialized_items(self):
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]
@ -375,56 +366,44 @@ class TestDeliveryNote(unittest.TestCase):
}) })
def test_delivery_of_bundled_items_to_target_warehouse(self): def test_delivery_of_bundled_items_to_target_warehouse(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item", "FIFO")
set_valuation_method("_Test Item Home Desktop 100", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO")
for warehouse in ("_Test Warehouse - _TC", "_Test Warehouse 1 - _TC"): target_warehouse=get_warehouse(company=company, abbr="TCP1",
create_stock_reconciliation(item_code="_Test Item", target=warehouse, warehouse_name="_Test Customer Warehouse").name
qty=100, rate=100)
create_stock_reconciliation(item_code="_Test Item Home Desktop 100", for warehouse in ("Stores - TCP1", target_warehouse):
target=warehouse, qty=100, rate=100) create_stock_reconciliation(item_code="_Test Item", warehouse=warehouse, company = company,
expense_account = "Stock Adjustment - TCP1", qty=500, rate=100)
create_stock_reconciliation(item_code="_Test Item Home Desktop 100", company = company,
expense_account = "Stock Adjustment - TCP1", warehouse=warehouse, qty=500, rate=100)
opening_qty_test_warehouse_1 = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC")
dn = create_delivery_note(item_code="_Test Product Bundle Item", dn = create_delivery_note(item_code="_Test Product Bundle Item",
qty=5, rate=500, target_warehouse="_Test Warehouse 1 - _TC", do_not_submit=True) company='_Test Company with perpetual inventory', cost_center = 'Main - TCP1',
expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True, qty=5, rate=500,
warehouse="Stores - TCP1", target_warehouse=target_warehouse)
dn.submit() dn.submit()
# qty after delivery # qty after delivery
actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse - _TC") actual_qty_at_source = get_qty_after_transaction(warehouse="Stores - TCP1")
self.assertEqual(actual_qty, 75) self.assertEqual(actual_qty_at_source, 475)
actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC") actual_qty_at_target = get_qty_after_transaction(warehouse=target_warehouse)
self.assertEqual(actual_qty, opening_qty_test_warehouse_1 + 25) self.assertEqual(actual_qty_at_target, 525)
# stock value diff for source warehouse # stock value diff for source warehouse for "_Test Item"
# for "_Test Item"
stock_value_difference = frappe.db.get_value("Stock Ledger Entry", stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name, {"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}, "item_code": "_Test Item", "warehouse": "Stores - TCP1"},
"stock_value_difference") "stock_value_difference")
# stock value diff for target warehouse # stock value diff for target warehouse
stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name, {"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item", "warehouse": "_Test Warehouse 1 - _TC"}, "item_code": "_Test Item", "warehouse": target_warehouse},
"stock_value_difference")
self.assertEqual(abs(stock_value_difference), stock_value_difference1)
# for "_Test Item Home Desktop 100"
stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse - _TC"},
"stock_value_difference")
# stock value diff for target warehouse
stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Delivery Note", "voucher_no": dn.name,
"item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse 1 - _TC"},
"stock_value_difference") "stock_value_difference")
self.assertEqual(abs(stock_value_difference), stock_value_difference1) self.assertEqual(abs(stock_value_difference), stock_value_difference1)
@ -435,21 +414,20 @@ class TestDeliveryNote(unittest.TestCase):
stock_value_difference = abs(frappe.db.sql("""select sum(stock_value_difference) stock_value_difference = abs(frappe.db.sql("""select sum(stock_value_difference)
from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s
and warehouse='_Test Warehouse - _TC'""", dn.name)[0][0]) and warehouse='Stores - TCP1'""", dn.name)[0][0])
expected_values = { expected_values = {
"Stock In Hand - _TC": [0.0, stock_value_difference], "Stock In Hand - TCP1": [0.0, stock_value_difference],
"_Test Warehouse 1 - _TC": [stock_value_difference, 0.0] target_warehouse: [stock_value_difference, 0.0]
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
set_perpetual_inventory(0, company)
def test_closed_delivery_note(self): def test_closed_delivery_note(self):
from erpnext.stock.doctype.delivery_note.delivery_note import update_delivery_note_status from erpnext.stock.doctype.delivery_note.delivery_note import update_delivery_note_status
dn = create_delivery_note(do_not_submit=True) dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True)
dn.submit() dn.submit()
update_delivery_note_status(dn.name, "Closed") update_delivery_note_status(dn.name, "Closed")
@ -574,24 +552,23 @@ class TestDeliveryNote(unittest.TestCase):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings') accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1 accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save() accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC" cost_center = "_Test Cost Center for BS Account - TCP1"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company") create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory")
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100) make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company') stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
dn = create_delivery_note(cost_center=cost_center) dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', expense_account = "Cost of Goods Sold - TCP1", cost_center=cost_center)
gl_entries = get_gl_entries("Delivery Note", dn.name) gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
expected_values = { expected_values = {
"Cost of Goods Sold - _TC": { "Cost of Goods Sold - TCP1": {
"cost_center": cost_center "cost_center": cost_center
}, },
stock_in_hand_account: { stock_in_hand_account: {
@ -600,8 +577,6 @@ class TestDeliveryNote(unittest.TestCase):
} }
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, company)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save() accounts_settings.save()
@ -609,23 +584,22 @@ class TestDeliveryNote(unittest.TestCase):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings') accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save() accounts_settings.save()
cost_center = "_Test Cost Center - _TC" cost_center = "Main - TCP1"
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100) make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company') stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
dn = create_delivery_note() dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
gl_entries = get_gl_entries("Delivery Note", dn.name) gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
expected_values = { expected_values = {
"Cost of Goods Sold - _TC": { "Cost of Goods Sold - TCP1": {
"cost_center": cost_center "cost_center": cost_center
}, },
stock_in_hand_account: { stock_in_hand_account: {
@ -635,8 +609,6 @@ class TestDeliveryNote(unittest.TestCase):
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, company)
def test_make_sales_invoice_from_dn_for_returned_qty(self): def test_make_sales_invoice_from_dn_for_returned_qty(self):
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
@ -702,7 +674,7 @@ def create_delivery_note(**args):
"rate": args.rate or 100, "rate": args.rate or 100,
"conversion_factor": 1.0, "conversion_factor": 1.0,
"allow_zero_valuation_rate": args.allow_zero_valuation_rate or 1, "allow_zero_valuation_rate": args.allow_zero_valuation_rate or 1,
"expense_account": "Cost of Goods Sold - _TC", "expense_account": args.expense_account or "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC", "cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no, "serial_no": args.serial_no,
"target_warehouse": args.target_warehouse "target_warehouse": args.target_warehouse

View File

@ -12,9 +12,11 @@ from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt, make_rm_stock_entry from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt, make_rm_stock_entry
import unittest import unittest
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestItemAlternative(unittest.TestCase): class TestItemAlternative(unittest.TestCase):
def setUp(self): def setUp(self):
set_perpetual_inventory(0)
make_items() make_items()
def test_alternative_item_for_subcontract_rm(self): def test_alternative_item_for_subcontract_rm(self):

View File

@ -14,15 +14,15 @@ from erpnext.accounts.doctype.account.test_account import get_inventory_account
class TestLandedCostVoucher(unittest.TestCase): class TestLandedCostVoucher(unittest.TestCase):
def test_landed_cost_voucher(self): def test_landed_cost_voucher(self):
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
set_perpetual_inventory(1)
pr = frappe.copy_doc(pr_test_records[0]) pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True)
pr.submit()
last_sle = frappe.db.get_value("Stock Ledger Entry", { last_sle = frappe.db.get_value("Stock Ledger Entry", {
"voucher_type": pr.doctype, "voucher_type": pr.doctype,
"voucher_no": pr.name, "voucher_no": pr.name,
"item_code": "_Test Item", "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC" "warehouse": "Stores - TCP1"
}, },
fieldname=["qty_after_transaction", "stock_value"], as_dict=1) fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
@ -35,7 +35,7 @@ class TestLandedCostVoucher(unittest.TestCase):
"voucher_type": pr.doctype, "voucher_type": pr.doctype,
"voucher_no": pr.name, "voucher_no": pr.name,
"item_code": "_Test Item", "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC" "warehouse": "Stores - TCP1"
}, },
fieldname=["qty_after_transaction", "stock_value"], as_dict=1) fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
@ -48,55 +48,56 @@ class TestLandedCostVoucher(unittest.TestCase):
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse) fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse)
if stock_in_hand_account == fixed_asset_account: if stock_in_hand_account == fixed_asset_account:
expected_values = { expected_values = {
stock_in_hand_account: [800.0, 0.0], stock_in_hand_account: [800.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0], "Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 300.0] "Expenses Included In Valuation - TCP1": [0.0, 300.0]
} }
else: else:
expected_values = { expected_values = {
stock_in_hand_account: [400.0, 0.0], stock_in_hand_account: [400.0, 0.0],
fixed_asset_account: [400.0, 0.0], fixed_asset_account: [400.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0], "Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 300.0] "Expenses Included In Valuation - TCP1": [0.0, 300.0]
} }
for gle in gl_entries: for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit) self.assertEqual(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_landed_cost_voucher_against_purchase_invoice(self): def test_landed_cost_voucher_against_purchase_invoice(self):
set_perpetual_inventory(1)
pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(), pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime()) posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - TCP1",
company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1",
warehouse= "Stores - TCP1", cost_center = "Main - TCP1",
expense_account ="_Test Account Cost for Goods Sold - TCP1")
last_sle = frappe.db.get_value("Stock Ledger Entry", { last_sle = frappe.db.get_value("Stock Ledger Entry", {
"voucher_type": pi.doctype, "voucher_type": pi.doctype,
"voucher_no": pi.name, "voucher_no": pi.name,
"item_code": "_Test Item", "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC" "warehouse": "Stores - TCP1"
}, },
fieldname=["qty_after_transaction", "stock_value"], as_dict=1) fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
submit_landed_cost_voucher("Purchase Invoice", pi.name) submit_landed_cost_voucher("Purchase Invoice", pi.name)
pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name}, pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name},
"landed_cost_voucher_amount") "landed_cost_voucher_amount")
self.assertEqual(pi_lc_value, 50.0) self.assertEqual(pi_lc_value, 50.0)
last_sle_after_landed_cost = frappe.db.get_value("Stock Ledger Entry", { last_sle_after_landed_cost = frappe.db.get_value("Stock Ledger Entry", {
"voucher_type": pi.doctype, "voucher_type": pi.doctype,
"voucher_no": pi.name, "voucher_no": pi.name,
"item_code": "_Test Item", "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC" "warehouse": "Stores - TCP1"
}, },
fieldname=["qty_after_transaction", "stock_value"], as_dict=1) fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
@ -111,21 +112,21 @@ class TestLandedCostVoucher(unittest.TestCase):
expected_values = { expected_values = {
stock_in_hand_account: [300.0, 0.0], stock_in_hand_account: [300.0, 0.0],
"Creditors - _TC": [0.0, 250.0], "Creditors - TCP1": [0.0, 250.0],
"Expenses Included In Valuation - _TC": [0.0, 50.0] "Expenses Included In Valuation - TCP1": [0.0, 50.0]
} }
for gle in gl_entries: for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit) self.assertEqual(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_landed_cost_voucher_for_serialized_item(self):
set_perpetual_inventory(1)
frappe.db.sql("delete from `tabSerial No` where name in ('SN001', 'SN002', 'SN003', 'SN004', 'SN005')")
pr = frappe.copy_doc(pr_test_records[0]) def test_landed_cost_voucher_for_serialized_item(self):
frappe.db.sql("delete from `tabSerial No` where name in ('SN001', 'SN002', 'SN003', 'SN004', 'SN005')")
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1",
supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True,
get_taxes_and_charges = True, do_not_submit = True)
pr.items[0].item_code = "_Test Serialized Item" pr.items[0].item_code = "_Test Serialized Item"
pr.items[0].serial_no = "SN001\nSN002\nSN003\nSN004\nSN005" pr.items[0].serial_no = "SN001\nSN002\nSN003\nSN004\nSN005"
pr.submit() pr.submit()
@ -138,39 +139,36 @@ class TestLandedCostVoucher(unittest.TestCase):
["warehouse", "purchase_rate"], as_dict=1) ["warehouse", "purchase_rate"], as_dict=1)
self.assertEqual(serial_no.purchase_rate - serial_no_rate, 5.0) self.assertEqual(serial_no.purchase_rate - serial_no_rate, 5.0)
self.assertEqual(serial_no.warehouse, "_Test Warehouse - _TC") self.assertEqual(serial_no.warehouse, "Stores - TCP1")
set_perpetual_inventory(0)
def test_landed_cost_voucher_for_odd_numbers (self): def test_landed_cost_voucher_for_odd_numbers (self):
set_perpetual_inventory(1)
pr = make_purchase_receipt(do_not_save=True) pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", do_not_save=True)
pr.items[0].cost_center = "_Test Company - _TC" pr.items[0].cost_center = "Main - TCP1"
for x in range(2): for x in range(2):
pr.append("items", { pr.append("items", {
"item_code": "_Test Item", "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC", "warehouse": "Stores - TCP1",
"cost_center": "_Test Company - _TC", "cost_center": "Main - TCP1",
"qty": 5, "qty": 5,
"rate": 50 "rate": 50
}) })
pr.submit() pr.submit()
lcv = submit_landed_cost_voucher("Purchase Receipt", pr.name, 123.22) lcv = submit_landed_cost_voucher("Purchase Receipt", pr.name, 123.22)
self.assertEqual(lcv.items[0].applicable_charges, 41.07) self.assertEqual(lcv.items[0].applicable_charges, 41.07)
self.assertEqual(lcv.items[2].applicable_charges, 41.08) self.assertEqual(lcv.items[2].applicable_charges, 41.08)
set_perpetual_inventory(0)
def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=50): def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=50):
ref_doc = frappe.get_doc(receipt_document_type, receipt_document) ref_doc = frappe.get_doc(receipt_document_type, receipt_document)
lcv = frappe.new_doc("Landed Cost Voucher") lcv = frappe.new_doc("Landed Cost Voucher")
lcv.company = "_Test Company" lcv.company = "_Test Company"
lcv.distribute_charges_based_on = 'Amount' lcv.distribute_charges_based_on = 'Amount'
lcv.set("purchase_receipts", [{ lcv.set("purchase_receipts", [{
"receipt_document_type": receipt_document_type, "receipt_document_type": receipt_document_type,
"receipt_document": receipt_document, "receipt_document": receipt_document,
@ -178,7 +176,7 @@ def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=
"posting_date": ref_doc.posting_date, "posting_date": ref_doc.posting_date,
"grand_total": ref_doc.base_grand_total "grand_total": ref_doc.base_grand_total
}]) }])
lcv.set("taxes", [{ lcv.set("taxes", [{
"description": "Insurance Charges", "description": "Insurance Charges",
"account": "_Test Account Insurance Charges - _TC", "account": "_Test Account Insurance Charges - _TC",
@ -186,13 +184,13 @@ def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=
}]) }])
lcv.insert() lcv.insert()
distribute_landed_cost_on_items(lcv) distribute_landed_cost_on_items(lcv)
lcv.submit() lcv.submit()
return lcv return lcv
def distribute_landed_cost_on_items(lcv): def distribute_landed_cost_on_items(lcv):
based_on = lcv.distribute_charges_based_on.lower() based_on = lcv.distribute_charges_based_on.lower()
total = sum([flt(d.get(based_on)) for d in lcv.get("items")]) total = sum([flt(d.get(based_on)) for d in lcv.get("items")])

View File

@ -14,6 +14,7 @@ from erpnext.stock.doctype.item.test_item import make_item
from six import iteritems from six import iteritems
class TestPurchaseReceipt(unittest.TestCase): class TestPurchaseReceipt(unittest.TestCase):
def setUp(self): def setUp(self):
set_perpetual_inventory(0)
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
def test_make_purchase_invoice(self): def test_make_purchase_invoice(self):
@ -32,7 +33,6 @@ class TestPurchaseReceipt(unittest.TestCase):
def test_purchase_receipt_no_gl_entry(self): def test_purchase_receipt_no_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(0, company)
existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item", existing_bin_stock_value = frappe.db.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"}, "stock_value") "warehouse": "_Test Warehouse - _TC"}, "stock_value")
@ -52,33 +52,29 @@ class TestPurchaseReceipt(unittest.TestCase):
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):
pr = frappe.copy_doc(test_records[0]) pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True)
set_perpetual_inventory(1, pr.company)
self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1) self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(pr.company)), 1)
pr.insert()
pr.submit()
gl_entries = get_gl_entries("Purchase Receipt", pr.name) gl_entries = get_gl_entries("Purchase Receipt", pr.name)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) stock_in_hand_account = get_inventory_account(pr.company, pr.items[0].warehouse)
fixed_asset_account = get_inventory_account(pr.company, pr.get("items")[1].warehouse) fixed_asset_account = get_inventory_account(pr.company, pr.items[1].warehouse)
if stock_in_hand_account == fixed_asset_account: if stock_in_hand_account == fixed_asset_account:
expected_values = { expected_values = {
stock_in_hand_account: [750.0, 0.0], stock_in_hand_account: [750.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0], "Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 250.0] "Expenses Included In Valuation - TCP1": [0.0, 250.0]
} }
else: else:
expected_values = { expected_values = {
stock_in_hand_account: [375.0, 0.0], stock_in_hand_account: [375.0, 0.0],
fixed_asset_account: [375.0, 0.0], fixed_asset_account: [375.0, 0.0],
"Stock Received But Not Billed - _TC": [0.0, 500.0], "Stock Received But Not Billed - TCP1": [0.0, 500.0],
"Expenses Included In Valuation - _TC": [0.0, 250.0] "Expenses Included In Valuation - TCP1": [0.0, 250.0]
} }
for gle in gl_entries: for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit) self.assertEqual(expected_values[gle.account][1], gle.credit)
@ -86,8 +82,6 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.cancel() pr.cancel()
self.assertFalse(get_gl_entries("Purchase Receipt", pr.name)) self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
set_perpetual_inventory(0, pr.company)
def test_subcontracting(self): def test_subcontracting(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
@ -132,11 +126,10 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.get("items")[0].rejected_warehouse) pr.get("items")[0].rejected_warehouse)
def test_purchase_return(self): def test_purchase_return(self):
set_perpetual_inventory()
pr = make_purchase_receipt() pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
return_pr = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-2) return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, qty=-2)
# check sle # check sle
outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
@ -153,28 +146,28 @@ class TestPurchaseReceipt(unittest.TestCase):
expected_values = { expected_values = {
stock_in_hand_account: [0.0, 100.0], stock_in_hand_account: [0.0, 100.0],
"Stock Received But Not Billed - _TC": [100.0, 0.0], "Stock Received But Not Billed - TCP1": [100.0, 0.0],
} }
for gle in gl_entries: for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.debit) self.assertEqual(expected_values[gle.account][0], gle.debit)
self.assertEqual(expected_values[gle.account][1], gle.credit) self.assertEqual(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_purchase_return_for_rejected_qty(self): def test_purchase_return_for_rejected_qty(self):
set_perpetual_inventory() from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse
pr = make_purchase_receipt(received_qty=4, qty=2) rejected_warehouse=get_warehouse(company = "_Test Company with perpetual inventory", abbr = " - TCP1", warehouse_name = "_Test Rejected Warehouse").name
print(rejected_warehouse)
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", received_qty=4, qty=2, rejected_warehouse=rejected_warehouse)
return_pr = make_purchase_receipt(is_return=1, return_against=pr.name, received_qty = -4, qty=-2) return_pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", is_return=1, return_against=pr.name, received_qty = -4, qty=-2, rejected_warehouse=rejected_warehouse)
actual_qty = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt", actual_qty = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
"voucher_no": return_pr.name, 'warehouse': return_pr.items[0].rejected_warehouse}, "actual_qty") "voucher_no": return_pr.name, 'warehouse': return_pr.items[0].rejected_warehouse}, "actual_qty")
self.assertEqual(actual_qty, -2) self.assertEqual(actual_qty, -2)
set_perpetual_inventory(0)
def test_purchase_return_for_serialized_items(self): def test_purchase_return_for_serialized_items(self):
def _check_serial_no_values(serial_no, field_values): def _check_serial_no_values(serial_no, field_values):
@ -337,7 +330,6 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.cancel() pr.cancel()
serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or [] serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or []
self.assertEquals(len(serial_nos), 0) self.assertEquals(len(serial_nos), 0)
#frappe.db.sql("delete from `tabLocation")
frappe.db.sql("delete from `tabAsset`") frappe.db.sql("delete from `tabAsset`")
def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self): def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self):
@ -345,8 +337,8 @@ class TestPurchaseReceipt(unittest.TestCase):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings') accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1 accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save() accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC" cost_center = "_Test Cost Center for BS Account - TCP1"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company") create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory")
if not frappe.db.exists('Location', 'Test Location'): if not frappe.db.exists('Location', 'Test Location'):
frappe.get_doc({ frappe.get_doc({
@ -354,8 +346,7 @@ class TestPurchaseReceipt(unittest.TestCase):
'location_name': 'Test Location' 'location_name': 'Test Location'
}).insert() }).insert()
set_perpetual_inventory(1, "_Test Company") pr = make_purchase_receipt(cost_center=cost_center, company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
pr = make_purchase_receipt(cost_center=cost_center)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
gl_entries = get_gl_entries("Purchase Receipt", pr.name) gl_entries = get_gl_entries("Purchase Receipt", pr.name)
@ -363,7 +354,7 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
expected_values = { expected_values = {
"Stock Received But Not Billed - _TC": { "Stock Received But Not Billed - TCP1": {
"cost_center": cost_center "cost_center": cost_center
}, },
stock_in_hand_account: { stock_in_hand_account: {
@ -373,7 +364,6 @@ class TestPurchaseReceipt(unittest.TestCase):
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, pr.company)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save() accounts_settings.save()
@ -387,9 +377,7 @@ class TestPurchaseReceipt(unittest.TestCase):
'doctype': 'Location', 'doctype': 'Location',
'location_name': 'Test Location' 'location_name': 'Test Location'
}).insert() }).insert()
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1")
set_perpetual_inventory(1, "_Test Company")
pr = make_purchase_receipt()
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse) stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
gl_entries = get_gl_entries("Purchase Receipt", pr.name) gl_entries = get_gl_entries("Purchase Receipt", pr.name)
@ -397,7 +385,7 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
expected_values = { expected_values = {
"Stock Received But Not Billed - _TC": { "Stock Received But Not Billed - TCP1": {
"cost_center": None "cost_center": None
}, },
stock_in_hand_account: { stock_in_hand_account: {
@ -407,8 +395,6 @@ class TestPurchaseReceipt(unittest.TestCase):
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, pr.company)
def test_make_purchase_invoice_from_pr_for_returned_qty(self): def test_make_purchase_invoice_from_pr_for_returned_qty(self):
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po
@ -452,6 +438,78 @@ def get_gl_entries(voucher_type, voucher_no):
from `tabGL Entry` where voucher_type=%s and voucher_no=%s from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account desc""", (voucher_type, voucher_no), as_dict=1) order by account desc""", (voucher_type, voucher_no), as_dict=1)
def get_taxes(**args):
args = frappe._dict(args)
return [{'account_head': '_Test Account Shipping Charges - TCP1',
'add_deduct_tax': 'Add',
'category': 'Valuation and Total',
'charge_type': 'Actual',
'cost_center': args.cost_center or 'Main - TCP1',
'description': 'Shipping Charges',
'doctype': 'Purchase Taxes and Charges',
'parentfield': 'taxes',
'rate': 100.0,
'tax_amount': 100.0},
{'account_head': '_Test Account VAT - TCP1',
'add_deduct_tax': 'Add',
'category': 'Total',
'charge_type': 'Actual',
'cost_center': args.cost_center or 'Main - TCP1',
'description': 'VAT',
'doctype': 'Purchase Taxes and Charges',
'parentfield': 'taxes',
'rate': 120.0,
'tax_amount': 120.0},
{'account_head': '_Test Account Customs Duty - TCP1',
'add_deduct_tax': 'Add',
'category': 'Valuation',
'charge_type': 'Actual',
'cost_center': args.cost_center or 'Main - TCP1',
'description': 'Customs Duty',
'doctype': 'Purchase Taxes and Charges',
'parentfield': 'taxes',
'rate': 150.0,
'tax_amount': 150.0}]
def get_items(**args):
args = frappe._dict(args)
return [{
"base_amount": 250.0,
"conversion_factor": 1.0,
"description": "_Test Item",
"doctype": "Purchase Receipt Item",
"item_code": "_Test Item",
"item_name": "_Test Item",
"parentfield": "items",
"qty": 5.0,
"rate": 50.0,
"received_qty": 5.0,
"rejected_qty": 0.0,
"stock_uom": "_Test UOM",
"uom": "_Test UOM",
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"cost_center": args.cost_center or "Main - _TC"
},
{
"base_amount": 250.0,
"conversion_factor": 1.0,
"description": "_Test Item Home Desktop 100",
"doctype": "Purchase Receipt Item",
"item_code": "_Test Item Home Desktop 100",
"item_name": "_Test Item Home Desktop 100",
"parentfield": "items",
"qty": 5.0,
"rate": 50.0,
"received_qty": 5.0,
"rejected_qty": 0.0,
"stock_uom": "_Test UOM",
"uom": "_Test UOM",
"warehouse": args.warehouse or "_Test Warehouse 1 - _TC",
"cost_center": args.cost_center or "Main - _TC"
}]
def make_purchase_receipt(**args): def make_purchase_receipt(**args):
if not frappe.db.exists('Location', 'Test Location'): if not frappe.db.exists('Location', 'Test Location'):
frappe.get_doc({ frappe.get_doc({
@ -468,7 +526,7 @@ def make_purchase_receipt(**args):
pr.company = args.company or "_Test Company" pr.company = args.company or "_Test Company"
pr.supplier = args.supplier or "_Test Supplier" pr.supplier = args.supplier or "_Test Supplier"
pr.is_subcontracted = args.is_subcontracted or "No" pr.is_subcontracted = args.is_subcontracted or "No"
pr.supplier_warehouse = "_Test Warehouse 1 - _TC" pr.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC"
pr.currency = args.currency or "INR" pr.currency = args.currency or "INR"
pr.is_return = args.is_return pr.is_return = args.is_return
pr.return_against = args.return_against pr.return_against = args.return_against
@ -492,6 +550,16 @@ def make_purchase_receipt(**args):
"asset_location": args.location or "Test Location" "asset_location": args.location or "Test Location"
}) })
if args.get_multiple_items:
pr.items = []
for item in get_items(warehouse= args.warehouse, cost_center = args.cost_center or frappe.get_cached_value('Company', pr.company, 'cost_center')):
pr.append("items", item)
if args.get_taxes_and_charges:
for tax in get_taxes():
pr.append("taxes", tax)
if not args.do_not_save: if not args.do_not_save:
pr.insert() pr.insert()
if not args.do_not_submit: if not args.do_not_submit:

View File

@ -83,39 +83,5 @@
} }
], ],
"supplier": "_Test Supplier" "supplier": "_Test Supplier"
},
{
"buying_price_list": "_Test Price List",
"company": "_Test Company",
"conversion_rate": 1.0,
"currency": "INR",
"doctype": "Purchase Receipt",
"base_grand_total": 5000.0,
"is_subcontracted": "Yes",
"base_net_total": 5000.0,
"posting_date": "2013-02-12",
"items": [
{
"base_amount": 5000.0,
"conversion_factor": 1.0,
"description": "_Test FG Item",
"doctype": "Purchase Receipt Item",
"item_code": "_Test FG Item",
"item_name": "_Test FG Item",
"parentfield": "items",
"qty": 10.0,
"rate": 500.0,
"received_qty": 10.0,
"rejected_qty": 0.0,
"stock_uom": "_Test UOM",
"uom": "_Test UOM",
"warehouse": "_Test Warehouse - _TC",
"cost_center": "Main - _TC"
}
],
"supplier": "_Test Supplier",
"supplier_warehouse": "_Test Warehouse - _TC"
} }
] ]

View File

@ -12,6 +12,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
test_dependencies = ["Item"] test_dependencies = ["Item"]
test_records = frappe.get_test_records('Serial No') test_records = frappe.get_test_records('Serial No')
@ -37,6 +38,8 @@ class TestSerialNo(unittest.TestCase):
self.assertTrue(SerialNoCannotCannotChangeError, sr.save) self.assertTrue(SerialNoCannotCannotChangeError, sr.save)
def test_inter_company_transfer(self): def test_inter_company_transfer(self):
set_perpetual_inventory(0, "_Test Company 1")
set_perpetual_inventory(0)
se = make_serialized_item(target_warehouse="_Test Warehouse - _TC") se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
serial_nos = get_serial_nos(se.get("items")[0].serial_no) serial_nos = get_serial_nos(se.get("items")[0].serial_no)

View File

@ -16,7 +16,6 @@ from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse, make_stock_in_entry from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse, make_stock_in_entry
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError
from six import iteritems from six import iteritems
def get_sle(**args): def get_sle(**args):
@ -132,20 +131,19 @@ 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):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company,
qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1")
stock_in_hand_account = get_inventory_account(mr.company, mr.get("items")[0].t_warehouse) stock_in_hand_account = get_inventory_account(mr.company, mr.get("items")[0].t_warehouse)
self.check_stock_ledger_entries("Stock Entry", mr.name, self.check_stock_ledger_entries("Stock Entry", mr.name,
[["_Test Item", "_Test Warehouse - _TC", 50.0]]) [["_Test Item", "Stores - TCP1", 50.0]])
self.check_gl_entries("Stock Entry", mr.name, self.check_gl_entries("Stock Entry", mr.name,
sorted([ sorted([
[stock_in_hand_account, 5000.0, 0.0], [stock_in_hand_account, 5000.0, 0.0],
["Stock Adjustment - _TC", 0.0, 5000.0] ["Stock Adjustment - TCP1", 0.0, 5000.0]
]) ])
) )
@ -158,29 +156,26 @@ class TestStockEntry(unittest.TestCase):
where voucher_type='Stock Entry' and voucher_no=%s""", mr.name)) 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):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company) make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company,
qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1")
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", mi = make_stock_entry(item_code="_Test Item", source="Stores - TCP1", company=company,
qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") qty=40, expense_account="Stock Adjustment - TCP1")
mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC",
qty=40, expense_account="Stock Adjustment - _TC")
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", "Stores - TCP1", -40.0]])
stock_in_hand_account = get_inventory_account(mi.company, "_Test Warehouse - _TC") stock_in_hand_account = get_inventory_account(mi.company, "Stores - TCP1")
stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
"voucher_no": mi.name}, "stock_value_difference")) "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, stock_value_diff], [stock_in_hand_account, 0.0, stock_value_diff],
["Stock Adjustment - _TC", stock_value_diff, 0.0] ["Stock Adjustment - TCP1", stock_value_diff, 0.0]
]) ])
) )
mi.cancel() mi.cancel()
self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry` self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry`
@ -190,16 +185,15 @@ class TestStockEntry(unittest.TestCase):
where voucher_type='Stock Entry' and voucher_no=%s""", mi.name)) where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
def test_material_transfer_gl_entry(self): def test_material_transfer_gl_entry(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
create_stock_reconciliation(qty=100, rate=100) create_stock_reconciliation(qty=100, rate=100)
mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", mtn = make_stock_entry(item_code="_Test Item", source="Stores - TCP1",
target="_Test Warehouse 1 - _TC", qty=45) target="Finished Goods - TCP1", qty=45)
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", "Stores - TCP1", -45.0], ["_Test Item", "Finished Goods - TCP1", 45.0]])
stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse) stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse)
@ -212,7 +206,7 @@ class TestStockEntry(unittest.TestCase):
else: else:
stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry",
"voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference")) "voucher_no": mtn.name, "warehouse": "Stores - TCP1"}, "stock_value_difference"))
self.check_gl_entries("Stock Entry", mtn.name, self.check_gl_entries("Stock Entry", mtn.name,
sorted([ sorted([
@ -255,14 +249,21 @@ class TestStockEntry(unittest.TestCase):
set_perpetual_inventory(0, repack.company) set_perpetual_inventory(0, repack.company)
def test_repack_with_additional_costs(self): def test_repack_with_additional_costs(self):
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
set_perpetual_inventory(1, company)
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company= company,
repack = frappe.copy_doc(test_records[3]) qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1")
repack = make_stock_entry(company = company, purpose="Repack", do_not_save=True)
repack.posting_date = nowdate() repack.posting_date = nowdate()
repack.posting_time = nowtime() repack.posting_time = nowtime()
items = get_multiple_items()
repack.items = []
for item in items:
repack.append("items", item)
repack.set("additional_costs", [ repack.set("additional_costs", [
{ {
"description": "Actual Oerating Cost", "description": "Actual Oerating Cost",
@ -292,13 +293,12 @@ class TestStockEntry(unittest.TestCase):
self.check_gl_entries("Stock Entry", repack.name, self.check_gl_entries("Stock Entry", repack.name,
sorted([ sorted([
[stock_in_hand_account, 1200, 0.0], [stock_in_hand_account, 1200, 0.0],
["Expenses Included In Valuation - _TC", 0.0, 1200.0] ["Expenses Included In Valuation - TCP1", 0.0, 1200.0]
]) ])
) )
set_perpetual_inventory(0, repack.company)
def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle): def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle):
expected_sle.sort(key=lambda x: x[0]) expected_sle.sort(key=lambda x: x[1])
# check stock ledger entries # check stock ledger entries
sle = frappe.db.sql("""select item_code, warehouse, actual_qty sle = frappe.db.sql("""select item_code, warehouse, actual_qty
@ -306,7 +306,7 @@ class TestStockEntry(unittest.TestCase):
and voucher_no = %s order by item_code, warehouse, actual_qty""", and voucher_no = %s order by item_code, warehouse, actual_qty""",
(voucher_type, voucher_no), as_list=1) (voucher_type, voucher_no), as_list=1)
self.assertTrue(sle) self.assertTrue(sle)
sle.sort(key=lambda x: x[0]) sle.sort(key=lambda x: x[1])
for i, sle in enumerate(sle): for i, sle in enumerate(sle):
self.assertEqual(expected_sle[i][0], sle[0]) self.assertEqual(expected_sle[i][0], sle[0])
@ -773,14 +773,12 @@ class TestStockEntry(unittest.TestCase):
self.assertEqual(doc.per_transferred, 100) self.assertEqual(doc.per_transferred, 100)
def test_gle_for_opening_stock_entry(self): def test_gle_for_opening_stock_entry(self):
set_perpetual_inventory(1) mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True)
mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC",
qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC", is_opening="Yes", do_not_save=True)
self.assertRaises(OpeningEntryAccountError, mr.save) self.assertRaises(OpeningEntryAccountError, mr.save)
mr.items[0].expense_account = "Temporary Opening - _TC" mr.items[0].expense_account = "Temporary Opening - TCP1"
mr.save() mr.save()
mr.submit() mr.submit()
@ -805,14 +803,42 @@ def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
def get_qty_after_transaction(**args): def get_qty_after_transaction(**args):
args = frappe._dict(args) args = frappe._dict(args)
last_sle = get_previous_sle({ last_sle = get_previous_sle({
"item_code": args.item_code or "_Test Item", "item_code": args.item_code or "_Test Item",
"warehouse": args.warehouse or "_Test Warehouse - _TC", "warehouse": args.warehouse or "_Test Warehouse - _TC",
"posting_date": args.posting_date or nowdate(), "posting_date": args.posting_date or nowdate(),
"posting_time": args.posting_time or nowtime() "posting_time": args.posting_time or nowtime()
}) })
return flt(last_sle.get("qty_after_transaction")) return flt(last_sle.get("qty_after_transaction"))
def get_multiple_items():
return [
{
"conversion_factor": 1.0,
"cost_center": "Main - TCP1",
"doctype": "Stock Entry Detail",
"expense_account": "Stock Adjustment - TCP1",
"basic_rate": 100,
"item_code": "_Test Item",
"qty": 50.0,
"s_warehouse": "Stores - TCP1",
"stock_uom": "_Test UOM",
"transfer_qty": 50.0,
"uom": "_Test UOM"
},
{
"conversion_factor": 1.0,
"cost_center": "Main - TCP1",
"doctype": "Stock Entry Detail",
"expense_account": "Stock Adjustment - TCP1",
"basic_rate": 5000,
"item_code": "_Test Item Home Desktop 100",
"qty": 1,
"stock_uom": "_Test UOM",
"t_warehouse": "Stores - TCP1",
"transfer_qty": 1,
"uom": "_Test UOM"
}
]
test_records = frappe.get_test_records('Stock Entry') test_records = frappe.get_test_records('Stock Entry')

View File

@ -7,7 +7,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, unittest import frappe, unittest
from frappe.utils import flt, nowdate, nowtime from frappe.utils import flt, nowdate, nowtime
from erpnext.accounts.utils import get_stock_and_account_difference from erpnext.accounts.utils import get_stock_and_account_balance
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items
@ -21,7 +21,6 @@ class TestStockReconciliation(unittest.TestCase):
def setUpClass(self): def setUpClass(self):
create_batch_or_serial_no_items() create_batch_or_serial_no_items()
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
insert_existing_sle()
def test_reco_for_fifo(self): def test_reco_for_fifo(self):
self._test_reco_sle_gle("FIFO") self._test_reco_sle_gle("FIFO")
@ -30,7 +29,8 @@ class TestStockReconciliation(unittest.TestCase):
self._test_reco_sle_gle("Moving Average") self._test_reco_sle_gle("Moving Average")
def _test_reco_sle_gle(self, valuation_method): def _test_reco_sle_gle(self, valuation_method):
set_perpetual_inventory() insert_existing_sle(warehouse='Stores - TCP1')
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
# [[qty, valuation_rate, posting_date, # [[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 = [ input_data = [
@ -46,14 +46,15 @@ class TestStockReconciliation(unittest.TestCase):
last_sle = get_previous_sle({ last_sle = get_previous_sle({
"item_code": "_Test Item", "item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC", "warehouse": "Stores - TCP1",
"posting_date": d[2], "posting_date": d[2],
"posting_time": d[3] "posting_time": d[3]
}) })
# submit stock reconciliation # submit stock reconciliation
stock_reco = create_stock_reconciliation(qty=d[0], rate=d[1], stock_reco = create_stock_reconciliation(qty=d[0], rate=d[1],
posting_date=d[2], posting_time=d[3]) posting_date=d[2], posting_time=d[3], warehouse="Stores - TCP1",
company=company, expense_account = "Stock Adjustment - TCP1")
# check stock value # check stock value
sle = frappe.db.sql("""select * from `tabStock Ledger Entry` sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
@ -73,17 +74,18 @@ class TestStockReconciliation(unittest.TestCase):
# no gl entries # no gl entries
self.assertTrue(frappe.db.get_value("Stock Ledger Entry", self.assertTrue(frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"]))
stock_reco.cancel() acc_bal, stock_bal, wh_list = get_stock_and_account_balance("Stock In Hand - TCP1",
stock_reco.posting_date, stock_reco.company)
self.assertEqual(acc_bal, stock_bal)
self.assertFalse(frappe.db.get_value("Stock Ledger Entry", stock_reco.cancel()
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
self.assertFalse(frappe.db.get_value("GL Entry", self.assertFalse(frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name})) {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
set_perpetual_inventory(0) self.assertFalse(frappe.db.get_value("GL Entry",
{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
def test_get_items(self): def test_get_items(self):
create_warehouse("_Test Warehouse Group 1", {"is_group": 1}) create_warehouse("_Test Warehouse Group 1", {"is_group": 1})
@ -203,17 +205,17 @@ class TestStockReconciliation(unittest.TestCase):
stock_doc.cancel() stock_doc.cancel()
def insert_existing_sle(): def insert_existing_sle(warehouse):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry 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", make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item",
target="_Test Warehouse - _TC", qty=10, basic_rate=700) target=warehouse, qty=10, basic_rate=700)
make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item", make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
source="_Test Warehouse - _TC", qty=15) source=warehouse, qty=15)
make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item", make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item",
target="_Test Warehouse - _TC", qty=15, basic_rate=1200) target=warehouse, qty=15, basic_rate=1200)
def create_batch_or_serial_no_items(): def create_batch_or_serial_no_items():
create_warehouse("_Test Warehouse for Stock Reco1", create_warehouse("_Test Warehouse for Stock Reco1",
@ -244,7 +246,10 @@ def create_stock_reconciliation(**args):
sr.company = args.company or "_Test Company" sr.company = args.company or "_Test Company"
sr.expense_account = args.expense_account or \ sr.expense_account = args.expense_account or \
("Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC") ("Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC")
sr.cost_center = args.cost_center or "_Test Cost Center - _TC" sr.cost_center = args.cost_center \
or frappe.get_cached_value("Company", sr.company, "cost_center") \
or "_Test Cost Center - _TC"
sr.append("items", { sr.append("items", {
"item_code": args.item_code or "_Test Item", "item_code": args.item_code or "_Test Item",
"warehouse": args.warehouse or "_Test Warehouse - _TC", "warehouse": args.warehouse or "_Test Warehouse - _TC",

View File

@ -1,42 +1,36 @@
[ [
{ {
"company": "_Test Company", "company": "_Test Company",
"create_account_under": "Stock Assets - _TC",
"doctype": "Warehouse", "doctype": "Warehouse",
"warehouse_name": "_Test Warehouse", "warehouse_name": "_Test Warehouse",
"is_group": 0 "is_group": 0
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"create_account_under": "Stock Assets - _TC",
"doctype": "Warehouse", "doctype": "Warehouse",
"warehouse_name": "_Test Scrap Warehouse", "warehouse_name": "_Test Scrap Warehouse",
"is_group": 0 "is_group": 0
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"create_account_under": "Fixed Assets - _TC",
"doctype": "Warehouse", "doctype": "Warehouse",
"warehouse_name": "_Test Warehouse 1", "warehouse_name": "_Test Warehouse 1",
"is_group": 0 "is_group": 0
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"create_account_under": "Fixed Assets - _TC",
"doctype": "Warehouse", "doctype": "Warehouse",
"warehouse_name": "_Test Warehouse 2", "warehouse_name": "_Test Warehouse 2",
"is_group": 0 "is_group": 0
}, },
{ {
"company": "_Test Company", "company": "_Test Company",
"create_account_under": "Stock Assets - _TC",
"doctype": "Warehouse", "doctype": "Warehouse",
"warehouse_name": "_Test Rejected Warehouse", "warehouse_name": "_Test Rejected Warehouse",
"is_group": 0 "is_group": 0
}, },
{ {
"company": "_Test Company 1", "company": "_Test Company 1",
"create_account_under": "Stock Assets - _TC1",
"doctype": "Warehouse", "doctype": "Warehouse",
"warehouse_name": "_Test Warehouse 2", "warehouse_name": "_Test Warehouse 2",
"is_group": 0 "is_group": 0

View File

@ -101,8 +101,7 @@ def create_warehouse(warehouse_name, properties=None, company=None):
w.warehouse_name = warehouse_name w.warehouse_name = warehouse_name
w.parent_warehouse = "_Test Warehouse Group - _TC" w.parent_warehouse = "_Test Warehouse Group - _TC"
w.company = company w.company = company
make_account_for_warehouse(warehouse_name, w) w.account = get_warehouse_account(warehouse_name, company)
w.account = warehouse_id
if properties: if properties:
w.update(properties) w.update(properties)
w.save() w.save()
@ -110,9 +109,40 @@ def create_warehouse(warehouse_name, properties=None, company=None):
else: else:
return warehouse_id return warehouse_id
def make_account_for_warehouse(warehouse_name, warehouse_obj): def get_warehouse(**args):
if not frappe.db.exists("Account", warehouse_name + " - _TC"): args = frappe._dict(args)
parent_account = frappe.db.get_value('Account', if(frappe.db.exists("Warehouse", args.warehouse_name + " - " + args.abbr)):
{'company': warehouse_obj.company, 'is_group':1, 'account_type': 'Stock'},'name') return frappe.get_doc("Warehouse", args.warehouse_name + " - " + args.abbr)
account = create_account(account_name=warehouse_name, \ else:
account_type="Stock", parent_account= parent_account, company=warehouse_obj.company) w = frappe.get_doc({
"company": args.company or "_Test Company",
"doctype": "Warehouse",
"warehouse_name": args.warehouse_name,
"is_group": 0,
"account": get_warehouse_account(args.warehouse_name, args.company, args.abbr)
})
w.insert()
return w
def get_warehouse_account(warehouse_name, company, company_abbr=None):
if not company_abbr:
company_abbr = frappe.get_cached_value("Company", company, 'abbr')
if not frappe.db.exists("Account", warehouse_name + " - " + company_abbr):
return create_account(
account_name=warehouse_name,
parent_account=get_group_stock_account(company, company_abbr),
account_type='Stock',
company=company)
else:
return warehouse_name + " - " + company_abbr
def get_group_stock_account(company, company_abbr=None):
group_stock_account = frappe.db.get_value("Account",
filters={'account_type': 'Stock', 'is_group': 1, 'company': company}, fieldname='name')
if not group_stock_account:
if not company_abbr:
company_abbr = frappe.get_cached_value("Company", company, 'abbr')
group_stock_account = "Current Assets - " + company_abbr
return group_stock_account