fix: map DN items based on SRE

This commit is contained in:
s-aga-r 2023-03-26 17:33:01 +05:30
parent 15cb99290c
commit 3602d1909e
3 changed files with 96 additions and 3 deletions

View File

@ -622,7 +622,36 @@ def make_project(source_name, target_doc=None):
@frappe.whitelist()
def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False):
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
get_stock_reservation_entry_for_voucher,
has_reserved_stock,
)
def set_missing_values(source, target):
if not target.items and has_reserved_stock("Sales Order", source_name):
sre_list = get_stock_reservation_entry_for_voucher("Sales Order", source_name)
sre_dict = {d.pop("voucher_detail_no"): d for d in sre_list}
for item in source.get("items"):
if item.name in sre_dict:
qty_to_deliver = (
sre_dict[item.name]["reserved_qty"] - sre_dict[item.name]["delivered_qty"]
) / item.conversion_factor
row = frappe.new_doc("Delivery Note Item")
row.against_sales_order = source.name
row.against_sre = sre_dict[item.name]["name"]
row.so_detail = item.name
row.item_code = item.item_code
row.item_name = item.item_name
row.description = item.description
row.qty = qty_to_deliver
row.stock_uom = item.stock_uom
row.uom = item.uom
row.conversion_factor = item.conversion_factor
target.append("items", row)
target.run_method("set_missing_values")
target.run_method("set_po_nos")
target.run_method("calculate_taxes_and_totals")
@ -651,6 +680,9 @@ def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False):
or item_group.get("buying_cost_center")
)
if has_reserved_stock("Sales Order", source_name):
skip_item_mapping = True
mapper = {
"Sales Order": {"doctype": "Delivery Note", "validation": {"docstatus": ["=", 1]}},
"Sales Taxes and Charges": {"doctype": "Sales Taxes and Charges", "add_if_empty": True},
@ -678,7 +710,6 @@ def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False):
}
target_doc = get_mapped_doc("Sales Order", source_name, mapper, target_doc, set_missing_values)
target_doc.set_onload("ignore_price_list", True)
return target_doc

View File

@ -239,6 +239,8 @@ class DeliveryNote(SellingController):
self.update_prevdoc_status()
self.update_billing_status()
self.update_stock_reservation_entry()
if not self.is_return:
self.check_credit_limit()
elif self.issue_credit_note:
@ -258,6 +260,8 @@ class DeliveryNote(SellingController):
self.update_prevdoc_status()
self.update_billing_status()
self.update_stock_reservation_entry()
# Updating stock ledger should always be called after updating prevdoc status,
# because updating reserved qty in bin depends upon updated delivered qty in SO
self.update_stock_ledger()
@ -268,6 +272,16 @@ class DeliveryNote(SellingController):
self.repost_future_sle_and_gle()
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Repost Item Valuation")
def update_stock_reservation_entry(self):
if not self.is_return:
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
update_delivered_qty,
)
for item in self.get("items"):
if item.against_sre:
update_delivered_qty(item.doctype, item.against_sre)
def check_credit_limit(self):
from erpnext.selling.doctype.customer.customer import check_credit_limit

View File

@ -3,6 +3,7 @@
import frappe
from frappe import _
from frappe.query_builder.functions import Sum
from erpnext.utilities.transaction_base import TransactionBase
@ -62,8 +63,6 @@ class StockReservationEntry(TransactionBase):
frappe.db.set_value(self.doctype, self.name, "status", status, update_modified=update_modified)
def update_reserved_qty_in_voucher(self, update_modified=True):
from frappe.query_builder.functions import Sum
sre = frappe.qb.DocType("Stock Reservation Entry")
reserved_qty = (
frappe.qb.from_(sre)
@ -83,3 +82,52 @@ class StockReservationEntry(TransactionBase):
reserved_qty,
update_modified=update_modified,
)
def get_stock_reservation_entry_for_voucher(voucher_type, voucher_no, voucher_detail_no=None):
sre = frappe.qb.DocType("Stock Reservation Entry")
query = (
frappe.qb.from_(sre)
.select(
sre.name,
sre.item_code,
sre.warehouse,
sre.voucher_detail_no,
sre.reserved_qty,
sre.delivered_qty,
sre.stock_uom,
)
.where(
(sre.docstatus == 1)
& (sre.voucher_type == voucher_type)
& (sre.voucher_no == voucher_no)
& (sre.status.notin(["Delivered", "Cancelled"]))
)
.orderby(sre.creation)
)
if voucher_detail_no:
query = query.where(sre.voucher_detail_no == voucher_detail_no)
return query.run(as_dict=True)
def has_reserved_stock(voucher_type, voucher_no, voucher_detail_no=None):
if get_stock_reservation_entry_for_voucher(voucher_type, voucher_no, voucher_detail_no):
return True
return False
def update_delivered_qty(doctype, sre_name, sre_field="against_sre", qty_field="stock_qty"):
table = frappe.qb.DocType(doctype)
delivered_qty = (
frappe.qb.from_(table)
.select(Sum(table[qty_field]))
.where((table.docstatus == 1) & (table[sre_field] == sre_name))
).run(as_list=True)[0][0] or 0.0
sre_doc = frappe.get_doc("Stock Reservation Entry", sre_name)
sre_doc.delivered_qty = delivered_qty
sre_doc.db_update()
sre_doc.update_status()