fix: do not validate batch qty for LCV (cherry picked from commitbaf0c83cc5) (cherry picked from commit5de9b6ac75) Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
This commit is contained in:
@@ -1119,7 +1119,7 @@ class StockController(AccountsController):
|
|||||||
message += _("Please adjust the qty or edit {0} to proceed.").format(rule_link)
|
message += _("Please adjust the qty or edit {0} to proceed.").format(rule_link)
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def repost_future_sle_and_gle(self, force=False):
|
def repost_future_sle_and_gle(self, force=False, via_landed_cost_voucher=False):
|
||||||
args = frappe._dict(
|
args = frappe._dict(
|
||||||
{
|
{
|
||||||
"posting_date": self.posting_date,
|
"posting_date": self.posting_date,
|
||||||
@@ -1127,6 +1127,7 @@ class StockController(AccountsController):
|
|||||||
"voucher_type": self.doctype,
|
"voucher_type": self.doctype,
|
||||||
"voucher_no": self.name,
|
"voucher_no": self.name,
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
|
"via_landed_cost_voucher": via_landed_cost_voucher,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1138,7 +1139,11 @@ class StockController(AccountsController):
|
|||||||
frappe.db.get_single_value("Stock Reposting Settings", "item_based_reposting")
|
frappe.db.get_single_value("Stock Reposting Settings", "item_based_reposting")
|
||||||
)
|
)
|
||||||
if item_based_reposting:
|
if item_based_reposting:
|
||||||
create_item_wise_repost_entries(voucher_type=self.doctype, voucher_no=self.name)
|
create_item_wise_repost_entries(
|
||||||
|
voucher_type=self.doctype,
|
||||||
|
voucher_no=self.name,
|
||||||
|
via_landed_cost_voucher=via_landed_cost_voucher,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
create_repost_item_valuation_entry(args)
|
create_repost_item_valuation_entry(args)
|
||||||
|
|
||||||
@@ -1510,11 +1515,14 @@ def create_repost_item_valuation_entry(args):
|
|||||||
repost_entry.allow_zero_rate = args.allow_zero_rate
|
repost_entry.allow_zero_rate = args.allow_zero_rate
|
||||||
repost_entry.flags.ignore_links = True
|
repost_entry.flags.ignore_links = True
|
||||||
repost_entry.flags.ignore_permissions = True
|
repost_entry.flags.ignore_permissions = True
|
||||||
|
repost_entry.via_landed_cost_voucher = args.via_landed_cost_voucher
|
||||||
repost_entry.save()
|
repost_entry.save()
|
||||||
repost_entry.submit()
|
repost_entry.submit()
|
||||||
|
|
||||||
|
|
||||||
def create_item_wise_repost_entries(voucher_type, voucher_no, allow_zero_rate=False):
|
def create_item_wise_repost_entries(
|
||||||
|
voucher_type, voucher_no, allow_zero_rate=False, via_landed_cost_voucher=False
|
||||||
|
):
|
||||||
"""Using a voucher create repost item valuation records for all item-warehouse pairs."""
|
"""Using a voucher create repost item valuation records for all item-warehouse pairs."""
|
||||||
|
|
||||||
stock_ledger_entries = get_items_to_be_repost(voucher_type, voucher_no)
|
stock_ledger_entries = get_items_to_be_repost(voucher_type, voucher_no)
|
||||||
@@ -1538,6 +1546,7 @@ def create_item_wise_repost_entries(voucher_type, voucher_no, allow_zero_rate=Fa
|
|||||||
repost_entry.allow_zero_rate = allow_zero_rate
|
repost_entry.allow_zero_rate = allow_zero_rate
|
||||||
repost_entry.flags.ignore_links = True
|
repost_entry.flags.ignore_links = True
|
||||||
repost_entry.flags.ignore_permissions = True
|
repost_entry.flags.ignore_permissions = True
|
||||||
|
repost_entry.via_landed_cost_voucher = via_landed_cost_voucher
|
||||||
repost_entry.submit()
|
repost_entry.submit()
|
||||||
repost_entries.append(repost_entry)
|
repost_entries.append(repost_entry)
|
||||||
|
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ class LandedCostVoucher(Document):
|
|||||||
doc.make_bundle_using_old_serial_batch_fields(via_landed_cost_voucher=True)
|
doc.make_bundle_using_old_serial_batch_fields(via_landed_cost_voucher=True)
|
||||||
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
|
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
|
||||||
doc.make_gl_entries()
|
doc.make_gl_entries()
|
||||||
doc.repost_future_sle_and_gle()
|
doc.repost_future_sle_and_gle(via_landed_cost_voucher=True)
|
||||||
|
|
||||||
def validate_asset_qty_and_status(self, receipt_document_type, receipt_document):
|
def validate_asset_qty_and_status(self, receipt_document_type, receipt_document):
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
|
|||||||
@@ -745,6 +745,207 @@ class TestLandedCostVoucher(FrappeTestCase):
|
|||||||
frappe.db.get_value("Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"),
|
frappe.db.get_value("Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_do_not_validate_landed_cost_voucher_with_serial_batch_for_legacy_pr(self):
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import get_auto_batch_nos
|
||||||
|
|
||||||
|
frappe.flags.ignore_serial_batch_bundle_validation = True
|
||||||
|
frappe.flags.use_serial_and_batch_fields = True
|
||||||
|
sn_item = "Test Don't Validate Landed Cost Voucher Serial NO for Legacy PR"
|
||||||
|
batch_item = "Test Don't Validate Landed Cost Voucher Batch NO for Legacy PR"
|
||||||
|
sn_item_doc = make_item(
|
||||||
|
sn_item,
|
||||||
|
{
|
||||||
|
"has_serial_no": 1,
|
||||||
|
"serial_no_series": "SN-TDVLCVSNO-.####",
|
||||||
|
"is_stock_item": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
batch_item_doc = make_item(
|
||||||
|
batch_item,
|
||||||
|
{
|
||||||
|
"has_batch_no": 1,
|
||||||
|
"batch_number_series": "BATCH-TDVLCVSNO-.####",
|
||||||
|
"create_new_batch": 1,
|
||||||
|
"is_stock_item": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
serial_nos = [
|
||||||
|
"SN-TDVLCVSNO-0001",
|
||||||
|
"SN-TDVLCVSNO-0002",
|
||||||
|
"SN-TDVLCVSNO-0003",
|
||||||
|
"SN-TDVLCVSNO-0004",
|
||||||
|
"SN-TDVLCVSNO-0005",
|
||||||
|
]
|
||||||
|
|
||||||
|
for sn in serial_nos:
|
||||||
|
if not frappe.db.exists("Serial No", sn):
|
||||||
|
sn_doc = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Serial No",
|
||||||
|
"item_code": sn_item,
|
||||||
|
"serial_no": sn,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
sn_doc.insert()
|
||||||
|
|
||||||
|
if not frappe.db.exists("Batch", "BATCH-TDVLCVSNO-0001"):
|
||||||
|
batch_doc = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Batch",
|
||||||
|
"item": batch_item,
|
||||||
|
"batch_id": "BATCH-TDVLCVSNO-0001",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
batch_doc.insert()
|
||||||
|
|
||||||
|
warehouse = "_Test Warehouse - _TC"
|
||||||
|
company = frappe.db.get_value("Warehouse", warehouse, "company")
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(
|
||||||
|
company=company,
|
||||||
|
warehouse=warehouse,
|
||||||
|
item_code=sn_item,
|
||||||
|
qty=5,
|
||||||
|
rate=100,
|
||||||
|
uom=sn_item_doc.stock_uom,
|
||||||
|
stock_uom=sn_item_doc.stock_uom,
|
||||||
|
do_not_submit=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
pr.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": batch_item,
|
||||||
|
"item_name": batch_item,
|
||||||
|
"description": "Test Batch Item",
|
||||||
|
"uom": batch_item_doc.stock_uom,
|
||||||
|
"stock_uom": batch_item_doc.stock_uom,
|
||||||
|
"qty": 5,
|
||||||
|
"rate": 100,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
pr.submit()
|
||||||
|
pr.reload()
|
||||||
|
|
||||||
|
for sn in serial_nos:
|
||||||
|
sn_doc = frappe.get_doc("Serial No", sn)
|
||||||
|
sn_doc.db_set(
|
||||||
|
{
|
||||||
|
"warehouse": warehouse,
|
||||||
|
"status": "Active",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
batch_doc.db_set(
|
||||||
|
{
|
||||||
|
"batch_qty": 5,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in pr.items:
|
||||||
|
if row.item_code == sn_item:
|
||||||
|
row.db_set("serial_no", ", ".join(serial_nos))
|
||||||
|
else:
|
||||||
|
row.db_set("batch_no", "BATCH-TDVLCVSNO-0001")
|
||||||
|
|
||||||
|
stock_ledger_entries = frappe.get_all("Stock Ledger Entry", filters={"voucher_no": pr.name})
|
||||||
|
for sle in stock_ledger_entries:
|
||||||
|
doc = frappe.get_doc("Stock Ledger Entry", sle.name)
|
||||||
|
if doc.item_code == sn_item:
|
||||||
|
doc.db_set("serial_no", ", ".join(serial_nos))
|
||||||
|
else:
|
||||||
|
doc.db_set("batch_no", "BATCH-TDVLCVSNO-0001")
|
||||||
|
|
||||||
|
dn = create_delivery_note(
|
||||||
|
company=company,
|
||||||
|
warehouse=warehouse,
|
||||||
|
item_code=sn_item,
|
||||||
|
qty=5,
|
||||||
|
rate=100,
|
||||||
|
uom=sn_item_doc.stock_uom,
|
||||||
|
stock_uom=sn_item_doc.stock_uom,
|
||||||
|
do_not_submit=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
dn.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": batch_item,
|
||||||
|
"item_name": batch_item,
|
||||||
|
"description": "Test Batch Item",
|
||||||
|
"uom": batch_item_doc.stock_uom,
|
||||||
|
"stock_uom": batch_item_doc.stock_uom,
|
||||||
|
"qty": 5,
|
||||||
|
"rate": 100,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
dn.submit()
|
||||||
|
|
||||||
|
stock_ledger_entries = frappe.get_all("Stock Ledger Entry", filters={"voucher_no": dn.name})
|
||||||
|
for sle in stock_ledger_entries:
|
||||||
|
doc = frappe.get_doc("Stock Ledger Entry", sle.name)
|
||||||
|
if doc.item_code == sn_item:
|
||||||
|
doc.db_set("serial_no", ", ".join(serial_nos))
|
||||||
|
else:
|
||||||
|
doc.db_set("batch_no", "BATCH-TDVLCVSNO-0001")
|
||||||
|
|
||||||
|
available_batches = get_auto_batch_nos(
|
||||||
|
frappe._dict(
|
||||||
|
{
|
||||||
|
"item_code": batch_item,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
"batch_no": ["BATCH-TDVLCVSNO-0001"],
|
||||||
|
"consider_negative_batches": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)[0]
|
||||||
|
|
||||||
|
self.assertFalse(available_batches.get("qty"))
|
||||||
|
|
||||||
|
frappe.flags.ignore_serial_batch_bundle_validation = False
|
||||||
|
frappe.flags.use_serial_and_batch_fields = False
|
||||||
|
|
||||||
|
lcv = make_landed_cost_voucher(
|
||||||
|
company=pr.company,
|
||||||
|
receipt_document_type="Purchase Receipt",
|
||||||
|
receipt_document=pr.name,
|
||||||
|
charges=20,
|
||||||
|
distribute_charges_based_on="Qty",
|
||||||
|
do_not_save=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
lcv.get_items_from_purchase_receipts()
|
||||||
|
lcv.save()
|
||||||
|
lcv.submit()
|
||||||
|
|
||||||
|
pr.reload()
|
||||||
|
|
||||||
|
for row in pr.items:
|
||||||
|
self.assertEqual(row.valuation_rate, 102)
|
||||||
|
self.assertTrue(row.serial_and_batch_bundle)
|
||||||
|
self.assertEqual(
|
||||||
|
row.valuation_rate,
|
||||||
|
frappe.db.get_value("Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"),
|
||||||
|
)
|
||||||
|
|
||||||
|
lcv.cancel()
|
||||||
|
pr.reload()
|
||||||
|
|
||||||
|
for row in pr.items:
|
||||||
|
self.assertEqual(row.valuation_rate, 100)
|
||||||
|
self.assertTrue(row.serial_and_batch_bundle)
|
||||||
|
self.assertEqual(
|
||||||
|
row.valuation_rate,
|
||||||
|
frappe.db.get_value("Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_landed_cost_voucher(**args):
|
def make_landed_cost_voucher(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
@@ -860,6 +860,12 @@ class SerialandBatchBundle(Document):
|
|||||||
self.validate_batch_inventory()
|
self.validate_batch_inventory()
|
||||||
|
|
||||||
def validate_batch_inventory(self):
|
def validate_batch_inventory(self):
|
||||||
|
if (
|
||||||
|
self.voucher_type in ["Purchase Invoice", "Purchase Receipt"]
|
||||||
|
and frappe.db.get_value(self.voucher_type, self.voucher_no, "docstatus") == 1
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
if not self.has_batch_no:
|
if not self.has_batch_no:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user