mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-20 13:39:18 +00:00
fix: incorrect serial and batch get reserved
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import frappe.utils
|
import frappe.utils
|
||||||
@@ -534,14 +535,24 @@ class SalesOrder(SellingController):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_stock_reservation_entries(self, items_details=None, notify=True) -> None:
|
def create_stock_reservation_entries(
|
||||||
|
self,
|
||||||
|
items_details: list[dict] = None,
|
||||||
|
from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
|
||||||
|
notify=True,
|
||||||
|
) -> None:
|
||||||
"""Creates Stock Reservation Entries for Sales Order Items."""
|
"""Creates Stock Reservation Entries for Sales Order Items."""
|
||||||
|
|
||||||
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
|
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
|
||||||
create_stock_reservation_entries_for_so_items as create_stock_reservation_entries,
|
create_stock_reservation_entries_for_so_items as create_stock_reservation_entries,
|
||||||
)
|
)
|
||||||
|
|
||||||
create_stock_reservation_entries(sales_order=self, items_details=items_details, notify=notify)
|
create_stock_reservation_entries(
|
||||||
|
sales_order=self,
|
||||||
|
items_details=items_details,
|
||||||
|
from_voucher_type=from_voucher_type,
|
||||||
|
notify=notify,
|
||||||
|
)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def cancel_stock_reservation_entries(self, sre_list=None, notify=True) -> None:
|
def cancel_stock_reservation_entries(self, sre_list=None, notify=True) -> None:
|
||||||
|
|||||||
@@ -229,20 +229,27 @@ class PickList(Document):
|
|||||||
def create_stock_reservation_entries(self, notify=True) -> None:
|
def create_stock_reservation_entries(self, notify=True) -> None:
|
||||||
"""Creates Stock Reservation Entries for Sales Order Items against Pick List."""
|
"""Creates Stock Reservation Entries for Sales Order Items against Pick List."""
|
||||||
|
|
||||||
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
|
so_items_details_map = {}
|
||||||
create_stock_reservation_entries_for_so_items,
|
|
||||||
)
|
|
||||||
|
|
||||||
so_details = {}
|
|
||||||
for location in self.locations:
|
for location in self.locations:
|
||||||
if location.warehouse and location.sales_order and location.sales_order_item:
|
if location.warehouse and location.sales_order and location.sales_order_item:
|
||||||
so_details.setdefault(location.sales_order, []).append(location)
|
item_details = {
|
||||||
|
"name": location.sales_order_item,
|
||||||
|
"item_code": location.item_code,
|
||||||
|
"warehouse": location.warehouse,
|
||||||
|
"qty_to_reserve": (flt(location.picked_qty) - flt(location.stock_reserved_qty)),
|
||||||
|
"from_voucher_no": location.parent,
|
||||||
|
"from_voucher_detail_no": location.name,
|
||||||
|
"serial_and_batch_bundle": location.serial_and_batch_bundle,
|
||||||
|
}
|
||||||
|
so_items_details_map.setdefault(location.sales_order, []).append(item_details)
|
||||||
|
|
||||||
if so_details:
|
if so_items_details_map:
|
||||||
for so, locations in so_details.items():
|
for so, items_details in so_items_details_map.items():
|
||||||
so_doc = frappe.get_doc("Sales Order", so)
|
so_doc = frappe.get_doc("Sales Order", so)
|
||||||
create_stock_reservation_entries_for_so_items(
|
so_doc.create_stock_reservation_entries(
|
||||||
sales_order=so_doc, items_details=locations, from_voucher_type="Pick List", notify=notify
|
items_details=items_details,
|
||||||
|
from_voucher_type="Pick List",
|
||||||
|
notify=notify,
|
||||||
)
|
)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -846,14 +846,20 @@ class PurchaseReceipt(BuyingController):
|
|||||||
"item_code": item.item_code,
|
"item_code": item.item_code,
|
||||||
"warehouse": item.warehouse,
|
"warehouse": item.warehouse,
|
||||||
"qty_to_reserve": item.stock_qty,
|
"qty_to_reserve": item.stock_qty,
|
||||||
"serial_and_batch_bundle": item.get("serial_and_batch_bundle"),
|
"from_voucher_no": item.parent,
|
||||||
|
"from_voucher_detail_no": item.name,
|
||||||
|
"serial_and_batch_bundle": item.serial_and_batch_bundle,
|
||||||
}
|
}
|
||||||
so_items_details_map.setdefault(item.sales_order, []).append(item_details)
|
so_items_details_map.setdefault(item.sales_order, []).append(item_details)
|
||||||
|
|
||||||
if so_items_details_map:
|
if so_items_details_map:
|
||||||
for so, items_details in so_items_details_map.items():
|
for so, items_details in so_items_details_map.items():
|
||||||
so_doc = frappe.get_doc("Sales Order", so)
|
so_doc = frappe.get_doc("Sales Order", so)
|
||||||
so_doc.create_stock_reservation_entries(items_details)
|
so_doc.create_stock_reservation_entries(
|
||||||
|
items_details=items_details,
|
||||||
|
from_voucher_type="Purchase Receipt",
|
||||||
|
notify=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def update_billed_amount_based_on_po(po_details, update_modified=True):
|
def update_billed_amount_based_on_po(po_details, update_modified=True):
|
||||||
|
|||||||
@@ -794,22 +794,21 @@ def create_stock_reservation_entries_for_so_items(
|
|||||||
|
|
||||||
items = []
|
items = []
|
||||||
if items_details:
|
if items_details:
|
||||||
item_field = "sales_order_item" if from_voucher_type == "Pick List" else "name"
|
|
||||||
|
|
||||||
for item in items_details:
|
for item in items_details:
|
||||||
so_item = frappe.get_doc("Sales Order Item", item.get(item_field))
|
so_item = frappe.get_doc("Sales Order Item", item.get("name"))
|
||||||
so_item.warehouse = item.get("warehouse")
|
so_item.warehouse = item.get("warehouse")
|
||||||
so_item.qty_to_reserve = (
|
so_item.qty_to_reserve = (
|
||||||
item.get("picked_qty") - item.get("stock_reserved_qty", 0)
|
flt(item.get("qty_to_reserve"))
|
||||||
if from_voucher_type == "Pick List"
|
if from_voucher_type in ["Pick List", "Purchase Receipt"]
|
||||||
else (flt(item.get("qty_to_reserve")) * flt(so_item.conversion_factor, 1))
|
else (
|
||||||
|
flt(item.get("qty_to_reserve"))
|
||||||
|
* (flt(item.get("conversion_factor")) or flt(so_item.conversion_factor) or 1)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
so_item.from_voucher_no = item.get("from_voucher_no")
|
||||||
|
so_item.from_voucher_detail_no = item.get("from_voucher_detail_no")
|
||||||
so_item.serial_and_batch_bundle = item.get("serial_and_batch_bundle")
|
so_item.serial_and_batch_bundle = item.get("serial_and_batch_bundle")
|
||||||
|
|
||||||
if from_voucher_type == "Pick List":
|
|
||||||
so_item.from_voucher_no = item.get("parent")
|
|
||||||
so_item.from_voucher_detail_no = item.get("name")
|
|
||||||
|
|
||||||
items.append(so_item)
|
items.append(so_item)
|
||||||
|
|
||||||
sre_count = 0
|
sre_count = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user