mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-13 14:41:53 +00:00
fix: throw when the transaction company has no sample retention warehouse
Item.retain_sample is validated against any company having one configured, since Item is not company-scoped. The transaction company may still not be, in which case get_batch_qty received warehouse=None and returned its batch list, which was then compared numerically -> TypeError. Resolve company -> retention warehouse through one helper that throws a clear message instead, covering both the sample stock entry and the whitelisted quantity validation.
This commit is contained in:
@@ -1178,7 +1178,7 @@ def ceil_qty_if_uom_has_whole_number(qty, stock_uom):
|
||||
def move_sample_to_retention_warehouse(company: str, items: str | list):
|
||||
items = frappe.parse_json(items)
|
||||
|
||||
retention_warehouse = frappe.get_cached_value("Company", company, "sample_retention_warehouse")
|
||||
retention_warehouse = get_sample_retention_warehouse(company)
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.company = company
|
||||
stock_entry.purpose = "Material Transfer"
|
||||
@@ -1281,10 +1281,22 @@ def validate_sample_quantity(
|
||||
_("Sample quantity {0} cannot be more than received quantity {1}").format(sample_quantity, qty)
|
||||
)
|
||||
|
||||
retention_warehouse = frappe.get_cached_value("Company", company, "sample_retention_warehouse")
|
||||
retention_warehouse = get_sample_retention_warehouse(company)
|
||||
return _adjust_sample_quantity(item_code, sample_quantity, batch_no, get_batch_qty, retention_warehouse)
|
||||
|
||||
|
||||
def get_sample_retention_warehouse(company: str) -> str:
|
||||
warehouse = frappe.get_cached_value("Company", company, "sample_retention_warehouse")
|
||||
if not warehouse:
|
||||
frappe.throw(
|
||||
_("Please set {0} in Company {1} to retain samples.").format(
|
||||
bold(_("Sample Retention Warehouse")), bold(company)
|
||||
),
|
||||
title=_("Sample Retention Warehouse Missing"),
|
||||
)
|
||||
return warehouse
|
||||
|
||||
|
||||
def _adjust_sample_quantity(item_code, sample_quantity, batch_no, get_batch_qty, retention_warehouse):
|
||||
retainted_qty = get_batch_qty(batch_no, retention_warehouse, item_code) if batch_no else 0
|
||||
max_retain_qty = frappe.get_value("Item", item_code, "sample_quantity")
|
||||
|
||||
@@ -3236,6 +3236,30 @@ class TestStockEntryCoverage(ERPNextTestSuite):
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, validate_sample_quantity, item.name, 10, 5, "_Test Company")
|
||||
|
||||
def test_validate_sample_quantity_raises_when_company_has_no_retention_warehouse(self):
|
||||
"""Item.retain_sample only needs *some* company configured, so the transaction company may not be."""
|
||||
from erpnext.stock.doctype.stock_entry.services.manufacturing import (
|
||||
validate_sample_quantity,
|
||||
)
|
||||
|
||||
frappe.db.set_value(
|
||||
"Company", "_Test Company", "sample_retention_warehouse", "_Test Warehouse 1 - _TC"
|
||||
)
|
||||
frappe.db.set_value("Company", "_Test Company 1", "sample_retention_warehouse", None)
|
||||
item = make_item(
|
||||
"_Sample Qty No Retention Item",
|
||||
{"is_stock_item": 1, "retain_sample": 1, "sample_quantity": 2, "has_batch_no": 1},
|
||||
)
|
||||
self.assertRaises(
|
||||
frappe.ValidationError,
|
||||
validate_sample_quantity,
|
||||
item.name,
|
||||
1,
|
||||
5,
|
||||
"_Test Company 1",
|
||||
"_Sample Batch",
|
||||
)
|
||||
|
||||
# ── get_expired_batches ────────────────────────────────────────────────────
|
||||
|
||||
def test_get_expired_batches_includes_expired_batch(self):
|
||||
|
||||
Reference in New Issue
Block a user