mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-14 04:15:10 +00:00
fix: LCV is not changing the valuation of the repacked item
(cherry picked from commit ccbbc60585)
# Conflicts:
# erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
This commit is contained in:
committed by
Mergify
parent
626c799b60
commit
8b22d9d95e
@@ -4448,6 +4448,207 @@ class TestPurchaseReceipt(FrappeTestCase):
|
|||||||
|
|
||||||
self.assertEqual(srbnb_cost, 1000)
|
self.assertEqual(srbnb_cost, 1000)
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
def test_purchase_expense_account(self):
|
||||||
|
item = "Test Item with Purchase Expense Account"
|
||||||
|
make_item(item, {"is_stock_item": 1})
|
||||||
|
company = "_Test Company with perpetual inventory"
|
||||||
|
|
||||||
|
expense_account = "_Test Account Purchase Expense - TCP1"
|
||||||
|
expense_contra_account = "_Test Account Purchase Contra Expense - TCP1"
|
||||||
|
if not frappe.db.exists("Account", expense_account):
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Account",
|
||||||
|
"account_name": "_Test Account Purchase Expense",
|
||||||
|
"parent_account": "Stock Expenses - TCP1",
|
||||||
|
"company": company,
|
||||||
|
"is_group": 0,
|
||||||
|
"root_type": "Expense",
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
if not frappe.db.exists("Account", expense_contra_account):
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Account",
|
||||||
|
"account_name": "_Test Account Purchase Contra Expense",
|
||||||
|
"parent_account": "Stock Expenses - TCP1",
|
||||||
|
"company": company,
|
||||||
|
"is_group": 0,
|
||||||
|
"root_type": "Expense",
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
item_doc = frappe.get_doc("Item", item)
|
||||||
|
item_doc.append(
|
||||||
|
"item_defaults",
|
||||||
|
{
|
||||||
|
"company": company,
|
||||||
|
"default_warehouse": "Stores - TCP1",
|
||||||
|
"purchase_expense_account": expense_account,
|
||||||
|
"purchase_expense_contra_account": expense_contra_account,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
item_doc.save()
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(
|
||||||
|
item_code=item,
|
||||||
|
qty=10,
|
||||||
|
rate=100,
|
||||||
|
company=company,
|
||||||
|
warehouse="Stores - TCP1",
|
||||||
|
)
|
||||||
|
|
||||||
|
gl_entries = get_gl_entries(pr.doctype, pr.name)
|
||||||
|
accounts = [d.account for d in gl_entries]
|
||||||
|
self.assertTrue(expense_account in accounts)
|
||||||
|
self.assertTrue(expense_contra_account in accounts)
|
||||||
|
|
||||||
|
for row in gl_entries:
|
||||||
|
if row.account == expense_account:
|
||||||
|
self.assertEqual(row.debit, 1000)
|
||||||
|
if row.account == expense_contra_account:
|
||||||
|
self.assertEqual(row.credit, 1000)
|
||||||
|
|
||||||
|
def test_repost_gl_entries(self):
|
||||||
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
|
|
||||||
|
item = "Test Item for Repost GL Entries"
|
||||||
|
make_item(item, {"is_stock_item": 1})
|
||||||
|
company = "_Test Company with perpetual inventory"
|
||||||
|
|
||||||
|
account = "Reposting Adjustment - TCP1"
|
||||||
|
if not frappe.db.exists("Account", account):
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Account",
|
||||||
|
"account_name": "Reposting Adjustment",
|
||||||
|
"parent_account": "Stock Expenses - TCP1",
|
||||||
|
"company": company,
|
||||||
|
"is_group": 0,
|
||||||
|
"account_type": "Expense Account",
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
se = make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
qty=10,
|
||||||
|
rate=100,
|
||||||
|
company=company,
|
||||||
|
target="Stores - TCP1",
|
||||||
|
)
|
||||||
|
|
||||||
|
gl_entries = get_gl_entries(se.doctype, se.name)
|
||||||
|
for row in gl_entries:
|
||||||
|
self.assertTrue(row.account in ["Stock In Hand - TCP1", "Stock Adjustment - TCP1"])
|
||||||
|
|
||||||
|
se.items[0].db_set("expense_account", account)
|
||||||
|
se.reload()
|
||||||
|
|
||||||
|
repost_doc = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Repost Item Valuation",
|
||||||
|
"based_on": "Transaction",
|
||||||
|
"voucher_type": se.doctype,
|
||||||
|
"voucher_no": se.name,
|
||||||
|
"posting_date": se.posting_date,
|
||||||
|
"posting_time": se.posting_time,
|
||||||
|
"company": se.company,
|
||||||
|
"repost_only_accounting_ledgers": 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
repost_doc.submit()
|
||||||
|
|
||||||
|
gl_entries = get_gl_entries(se.doctype, se.name)
|
||||||
|
for row in gl_entries:
|
||||||
|
self.assertTrue(row.account in ["Stock In Hand - TCP1", account])
|
||||||
|
|
||||||
|
def test_lcv_for_repack_entry(self):
|
||||||
|
from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import (
|
||||||
|
create_landed_cost_voucher,
|
||||||
|
)
|
||||||
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
|
|
||||||
|
for item in [
|
||||||
|
"Potatoes Raw Material Item",
|
||||||
|
"Fries Finished Goods Item",
|
||||||
|
]:
|
||||||
|
create_item(item)
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(
|
||||||
|
item_code="Potatoes Raw Material Item",
|
||||||
|
warehouse="_Test Warehouse - _TC",
|
||||||
|
qty=100,
|
||||||
|
rate=50,
|
||||||
|
)
|
||||||
|
|
||||||
|
wh1 = create_warehouse("WH A1", company=pr.company)
|
||||||
|
wh2 = create_warehouse("WH A2", company=pr.company)
|
||||||
|
|
||||||
|
ste = make_stock_entry(
|
||||||
|
purpose="Repack",
|
||||||
|
source="_Test Warehouse - _TC",
|
||||||
|
item_code="Potatoes Raw Material Item",
|
||||||
|
qty=100,
|
||||||
|
company=pr.company,
|
||||||
|
do_not_save=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
ste.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": "Fries Finished Goods Item",
|
||||||
|
"qty": 50,
|
||||||
|
"t_warehouse": wh1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ste.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": "Fries Finished Goods Item",
|
||||||
|
"qty": 50,
|
||||||
|
"t_warehouse": wh2,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ste.insert()
|
||||||
|
ste.submit()
|
||||||
|
ste.reload()
|
||||||
|
|
||||||
|
for row in ste.items:
|
||||||
|
if row.t_warehouse:
|
||||||
|
self.assertEqual(row.valuation_rate, 50)
|
||||||
|
|
||||||
|
sles = frappe.get_all(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
filters={"voucher_type": ste.doctype, "voucher_no": ste.name, "actual_qty": (">", 0)},
|
||||||
|
pluck="stock_value_difference",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(sles, [2500.0, 2500.0])
|
||||||
|
|
||||||
|
create_landed_cost_voucher("Purchase Receipt", pr.name, pr.company, charges=2000 * -1)
|
||||||
|
|
||||||
|
ste.reload()
|
||||||
|
|
||||||
|
for row in ste.items:
|
||||||
|
if row.t_warehouse:
|
||||||
|
self.assertEqual(row.valuation_rate, 30)
|
||||||
|
|
||||||
|
sles = frappe.get_all(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
filters={"voucher_type": ste.doctype, "voucher_no": ste.name, "actual_qty": (">", 0)},
|
||||||
|
pluck="stock_value_difference",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(sles, [1500.0, 1500.0])
|
||||||
|
|
||||||
|
>>>>>>> ccbbc60585 (fix: LCV is not changing the valuation of the repacked item)
|
||||||
|
|
||||||
def prepare_data_for_internal_transfer():
|
def prepare_data_for_internal_transfer():
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
||||||
|
|||||||
@@ -647,10 +647,32 @@ class update_entries_after:
|
|||||||
|
|
||||||
if sle.dependant_sle_voucher_detail_no:
|
if sle.dependant_sle_voucher_detail_no:
|
||||||
entries_to_fix = self.get_dependent_entries_to_fix(entries_to_fix, sle)
|
entries_to_fix = self.get_dependent_entries_to_fix(entries_to_fix, sle)
|
||||||
|
if sle.voucher_type == "Stock Entry" and is_repack_entry(sle.voucher_no):
|
||||||
|
# for repack entries, we need to repost both source and target warehouses
|
||||||
|
self.update_distinct_item_warehouses_for_repack(sle)
|
||||||
|
|
||||||
if self.exceptions:
|
if self.exceptions:
|
||||||
self.raise_exceptions()
|
self.raise_exceptions()
|
||||||
|
|
||||||
|
def update_distinct_item_warehouses_for_repack(self, sle):
|
||||||
|
sles = (
|
||||||
|
frappe.get_all(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
filters={
|
||||||
|
"voucher_type": "Stock Entry",
|
||||||
|
"voucher_no": sle.voucher_no,
|
||||||
|
"actual_qty": (">", 0),
|
||||||
|
"is_cancelled": 0,
|
||||||
|
"voucher_detail_no": ("!=", sle.dependant_sle_voucher_detail_no),
|
||||||
|
},
|
||||||
|
fields=["*"],
|
||||||
|
)
|
||||||
|
or []
|
||||||
|
)
|
||||||
|
|
||||||
|
for dependant_sle in sles:
|
||||||
|
self.update_distinct_item_warehouses(dependant_sle)
|
||||||
|
|
||||||
def has_stock_reco_with_serial_batch(self, sle):
|
def has_stock_reco_with_serial_batch(self, sle):
|
||||||
if (
|
if (
|
||||||
sle.voucher_type == "Stock Reconciliation"
|
sle.voucher_type == "Stock Reconciliation"
|
||||||
@@ -1156,7 +1178,11 @@ class update_entries_after:
|
|||||||
|
|
||||||
def get_dynamic_incoming_outgoing_rate(self, sle):
|
def get_dynamic_incoming_outgoing_rate(self, sle):
|
||||||
# Get updated incoming/outgoing rate from transaction
|
# Get updated incoming/outgoing rate from transaction
|
||||||
if sle.recalculate_rate or self.has_landed_cost_based_on_pi(sle):
|
if (
|
||||||
|
sle.recalculate_rate
|
||||||
|
or self.has_landed_cost_based_on_pi(sle)
|
||||||
|
or (sle.voucher_type == "Stock Entry" and sle.actual_qty > 0 and is_repack_entry(sle.voucher_no))
|
||||||
|
):
|
||||||
rate = self.get_incoming_outgoing_rate_from_transaction(sle)
|
rate = self.get_incoming_outgoing_rate_from_transaction(sle)
|
||||||
|
|
||||||
if flt(sle.actual_qty) >= 0:
|
if flt(sle.actual_qty) >= 0:
|
||||||
@@ -2454,3 +2480,8 @@ def get_incoming_rate_for_serial_and_batch(item_code, row, sn_obj):
|
|||||||
incoming_rate = abs(flt(sn_obj.batch_avg_rate.get(row.batch_no)))
|
incoming_rate = abs(flt(sn_obj.batch_avg_rate.get(row.batch_no)))
|
||||||
|
|
||||||
return incoming_rate
|
return incoming_rate
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.request_cache
|
||||||
|
def is_repack_entry(stock_entry_id):
|
||||||
|
return frappe.get_cached_value("Stock Entry", stock_entry_id, "purpose") == "Repack"
|
||||||
|
|||||||
Reference in New Issue
Block a user