Allow same serial nos for raw materials and fg item in repack / manufacture entry
This commit is contained in:
parent
03afb45e34
commit
38e4c6f2af
@ -53,7 +53,7 @@ class SerialNo(StockController):
|
|||||||
if not self.get("__islocal"):
|
if not self.get("__islocal"):
|
||||||
item_code, warehouse = frappe.db.get_value("Serial No",
|
item_code, warehouse = frappe.db.get_value("Serial No",
|
||||||
self.name, ["item_code", "warehouse"])
|
self.name, ["item_code", "warehouse"])
|
||||||
if item_code != self.item_code:
|
if not self.via_stock_ledger and item_code != self.item_code:
|
||||||
frappe.throw(_("Item Code cannot be changed for Serial No."),
|
frappe.throw(_("Item Code cannot be changed for Serial No."),
|
||||||
SerialNoCannotCannotChangeError)
|
SerialNoCannotCannotChangeError)
|
||||||
if not self.via_stock_ledger and warehouse != self.warehouse:
|
if not self.via_stock_ledger and warehouse != self.warehouse:
|
||||||
@ -205,9 +205,10 @@ def validate_serial_no(sle, item_det):
|
|||||||
sr = frappe.get_doc("Serial No", serial_no)
|
sr = frappe.get_doc("Serial No", serial_no)
|
||||||
|
|
||||||
if sr.item_code!=sle.item_code:
|
if sr.item_code!=sle.item_code:
|
||||||
frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
|
if not allow_serial_nos_with_different_item(serial_no, sle):
|
||||||
sle.item_code), SerialNoItemError)
|
frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
|
||||||
|
sle.item_code), SerialNoItemError)
|
||||||
|
|
||||||
if sr.warehouse and sle.actual_qty > 0:
|
if sr.warehouse and sle.actual_qty > 0:
|
||||||
frappe.throw(_("Serial No {0} has already been received").format(sr.name),
|
frappe.throw(_("Serial No {0} has already been received").format(sr.name),
|
||||||
SerialNoDuplicateError)
|
SerialNoDuplicateError)
|
||||||
@ -228,7 +229,24 @@ def validate_serial_no(sle, item_det):
|
|||||||
elif sle.actual_qty < 0 or not item_det.serial_no_series:
|
elif sle.actual_qty < 0 or not item_det.serial_no_series:
|
||||||
frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
|
frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
|
||||||
SerialNoRequiredError)
|
SerialNoRequiredError)
|
||||||
|
|
||||||
|
def allow_serial_nos_with_different_item(sle_serial_no, sle):
|
||||||
|
"""
|
||||||
|
Allows same serial nos for raw materials and finished goods
|
||||||
|
in Manufacture / Repack type Stock Entry
|
||||||
|
"""
|
||||||
|
allow_serial_nos = False
|
||||||
|
if sle.voucher_type=="Stock Entry" and sle.actual_qty > 0:
|
||||||
|
stock_entry = frappe.get_doc("Stock Entry", sle.voucher_no)
|
||||||
|
if stock_entry.purpose in ("Repack", "Manufacture"):
|
||||||
|
for d in stock_entry.get("items"):
|
||||||
|
if d.serial_no and (d.s_warehouse if sle.is_cancelled=="No" else d.t_warehouse):
|
||||||
|
serial_nos = get_serial_nos(d.serial_no)
|
||||||
|
if sle_serial_no in serial_nos:
|
||||||
|
allow_serial_nos = True
|
||||||
|
|
||||||
|
return allow_serial_nos
|
||||||
|
|
||||||
def update_serial_nos(sle, item_det):
|
def update_serial_nos(sle, item_det):
|
||||||
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
|
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
|
||||||
and item_det.has_serial_no == 1 and item_det.serial_no_series:
|
and item_det.has_serial_no == 1 and item_det.serial_no_series:
|
||||||
@ -245,6 +263,7 @@ def update_serial_nos(sle, item_det):
|
|||||||
if frappe.db.exists("Serial No", serial_no):
|
if frappe.db.exists("Serial No", serial_no):
|
||||||
sr = frappe.get_doc("Serial No", serial_no)
|
sr = frappe.get_doc("Serial No", serial_no)
|
||||||
sr.via_stock_ledger = True
|
sr.via_stock_ledger = True
|
||||||
|
sr.item_code = sle.item_code
|
||||||
sr.warehouse = sle.warehouse if sle.actual_qty > 0 else None
|
sr.warehouse = sle.warehouse if sle.actual_qty > 0 else None
|
||||||
sr.save(ignore_permissions=True)
|
sr.save(ignore_permissions=True)
|
||||||
elif sle.actual_qty > 0:
|
elif sle.actual_qty > 0:
|
||||||
|
@ -359,14 +359,17 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def update_stock_ledger(self):
|
def update_stock_ledger(self):
|
||||||
sl_entries = []
|
sl_entries = []
|
||||||
|
|
||||||
|
# make sl entries for source warehouse first, then do for target warehouse
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if cstr(d.s_warehouse) and self.docstatus == 1:
|
if cstr(d.s_warehouse):
|
||||||
sl_entries.append(self.get_sl_entries(d, {
|
sl_entries.append(self.get_sl_entries(d, {
|
||||||
"warehouse": cstr(d.s_warehouse),
|
"warehouse": cstr(d.s_warehouse),
|
||||||
"actual_qty": -flt(d.transfer_qty),
|
"actual_qty": -flt(d.transfer_qty),
|
||||||
"incoming_rate": 0
|
"incoming_rate": 0
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
for d in self.get('items'):
|
||||||
if cstr(d.t_warehouse):
|
if cstr(d.t_warehouse):
|
||||||
sl_entries.append(self.get_sl_entries(d, {
|
sl_entries.append(self.get_sl_entries(d, {
|
||||||
"warehouse": cstr(d.t_warehouse),
|
"warehouse": cstr(d.t_warehouse),
|
||||||
@ -374,15 +377,18 @@ class StockEntry(StockController):
|
|||||||
"incoming_rate": flt(d.valuation_rate)
|
"incoming_rate": flt(d.valuation_rate)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
# On cancellation, make stock ledger entry for
|
# On cancellation, make stock ledger entry for
|
||||||
# target warehouse first, to update serial no values properly
|
# target warehouse first, to update serial no values properly
|
||||||
|
|
||||||
if cstr(d.s_warehouse) and self.docstatus == 2:
|
# if cstr(d.s_warehouse) and self.docstatus == 2:
|
||||||
sl_entries.append(self.get_sl_entries(d, {
|
# sl_entries.append(self.get_sl_entries(d, {
|
||||||
"warehouse": cstr(d.s_warehouse),
|
# "warehouse": cstr(d.s_warehouse),
|
||||||
"actual_qty": -flt(d.transfer_qty),
|
# "actual_qty": -flt(d.transfer_qty),
|
||||||
"incoming_rate": 0
|
# "incoming_rate": 0
|
||||||
}))
|
# }))
|
||||||
|
|
||||||
|
if self.docstatus == 2:
|
||||||
|
sl_entries.reverse()
|
||||||
|
|
||||||
self.make_sl_entries(sl_entries, self.amended_from and 'Yes' or 'No')
|
self.make_sl_entries(sl_entries, self.amended_from and 'Yes' or 'No')
|
||||||
|
|
||||||
|
@ -566,6 +566,27 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
stock_entry = frappe.get_doc(make_stock_entry(production_order.name, "Manufacture", 1))
|
stock_entry = frappe.get_doc(make_stock_entry(production_order.name, "Manufacture", 1))
|
||||||
stock_entry.insert()
|
stock_entry.insert()
|
||||||
self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items])
|
self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items])
|
||||||
|
|
||||||
|
def test_same_serial_nos_in_repack_or_manufacture_entries(self):
|
||||||
|
s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
|
||||||
|
serial_nos = s1.get("items")[0].serial_no
|
||||||
|
|
||||||
|
s2 = make_stock_entry(item_code="_Test Serialized Item With Series", source="_Test Warehouse - _TC",
|
||||||
|
qty=2, basic_rate=100, purpose="Repack", serial_no=serial_nos, do_not_save=True)
|
||||||
|
|
||||||
|
s2.append("items", {
|
||||||
|
"item_code": "_Test Serialized Item",
|
||||||
|
"t_warehouse": "_Test Warehouse - _TC",
|
||||||
|
"qty": 2,
|
||||||
|
"basic_rate": 120,
|
||||||
|
"expense_account": "Stock Adjustment - _TC",
|
||||||
|
"conversion_factor": 1.0,
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"serial_no": serial_nos
|
||||||
|
})
|
||||||
|
|
||||||
|
s2.submit()
|
||||||
|
s2.cancel()
|
||||||
|
|
||||||
def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
|
def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
|
||||||
se = frappe.copy_doc(test_records[0])
|
se = frappe.copy_doc(test_records[0])
|
||||||
@ -616,7 +637,8 @@ def make_stock_entry(**args):
|
|||||||
"basic_rate": args.basic_rate,
|
"basic_rate": args.basic_rate,
|
||||||
"expense_account": args.expense_account or "Stock Adjustment - _TC",
|
"expense_account": args.expense_account or "Stock Adjustment - _TC",
|
||||||
"conversion_factor": 1.0,
|
"conversion_factor": 1.0,
|
||||||
"cost_center": "_Test Cost Center - _TC"
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"serial_no": args.serial_no
|
||||||
})
|
})
|
||||||
|
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
|
Loading…
Reference in New Issue
Block a user