fix(stock): pick list serial batch posting date (#56957)

* fix(stock): fall back to current date/time for serial and batch bundle posting datetime

Pick List has no posting_date/posting_time fields, so creating or updating a
Serial and Batch Bundle from a Pick List row crashed with
"TypeError: combine() argument 1 must be datetime.date, not None". Fall back
to today/now when the parent voucher doesn't carry its own posting date.

Fixes #56951

* fix(stock): accept a plain dict for add_serial_batch_ledgers' doc and child_row

The whitelisted add_serial_batch_ledgers only converted child_row into an
attribute-accessible frappe._dict when it arrived as a JSON string, and doc's
type hint only allowed Document | str. Frappe's JSON API delivers both as
plain dicts (see frappe.app.make_form_dict, which parses the request body
with orjson and only wraps the top-level dict, not nested values), so every
real request was rejected before the handler body ever ran: first with a
FrappeTypeError on doc, and once that's fixed, with an AttributeError on
child_row.serial_and_batch_bundle. parse_json already wraps a plain dict in
frappe._dict (and leaves a real Document instance untouched), so routing
child_row through it unconditionally fixes both.
This commit is contained in:
Pandiyan P
2026-07-09 17:28:03 +05:30
committed by GitHub
parent e2178a5f19
commit 8b3caeb578

View File

@@ -21,6 +21,7 @@ from frappe.utils import (
get_link_to_form,
getdate,
now,
nowtime,
parse_json,
today,
)
@@ -2184,12 +2185,11 @@ def get_reference_serial_and_batch_bundle(child_row):
def add_serial_batch_ledgers(
entries: list | str,
child_row: PurchaseReceiptItem | dict | str,
doc: Document | str,
doc: Document | dict | str,
warehouse: str | None = None,
do_not_save: bool = False,
):
if isinstance(child_row, str):
child_row = frappe._dict(parse_json(child_row))
child_row = parse_json(child_row)
if isinstance(entries, str):
entries = parse_json(entries)
@@ -2221,7 +2221,9 @@ def create_serial_batch_no_ledgers(
if parent_doc.get("doctype") == "Stock Entry":
warehouse = warehouse or child_row.s_warehouse or child_row.t_warehouse
posting_datetime = combine_datetime(parent_doc.get("posting_date"), parent_doc.get("posting_time"))
posting_datetime = combine_datetime(
parent_doc.get("posting_date") or today(), parent_doc.get("posting_time") or nowtime()
)
doc = frappe.get_doc(
{
@@ -2338,7 +2340,9 @@ def update_serial_batch_no_ledgers(bundle, entries, child_row, parent_doc, wareh
)
doc.voucher_detail_no = child_row.name
doc.posting_datetime = combine_datetime(parent_doc.get("posting_date"), parent_doc.get("posting_time"))
doc.posting_datetime = combine_datetime(
parent_doc.get("posting_date") or today(), parent_doc.get("posting_time") or nowtime()
)
doc.warehouse = warehouse or doc.warehouse
doc.set("entries", [])