mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-16 07:58:38 +00:00
refactor(stock): extract Delivery Note PackingService
Move packing slip / product bundle handling into stock/doctype/delivery_note/services/packing.py: - validate_packed_qty stays as a controller delegator (called via hasattr contract in accounts/utils.py); has_unpacked_items stays for onload/JS - get_product_bundle_list and cancel_packing_slips move into the service (internal-only; on_cancel repointed) Pre-existing raw SQL in cancel_packing_slips moved verbatim. No behaviour change.
This commit is contained in:
@@ -8,6 +8,7 @@ from frappe.utils import cint, flt
|
||||
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from erpnext.stock.doctype.delivery_note.services.billing_status import BillingStatusService
|
||||
from erpnext.stock.doctype.delivery_note.services.packing import PackingService
|
||||
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
|
||||
|
||||
form_grid_templates = {"items": "templates/form_grid/item_grid.html"}
|
||||
@@ -509,7 +510,7 @@ class DeliveryNote(SellingController):
|
||||
# because updating reserved qty in bin depends upon updated delivered qty in SO
|
||||
self.update_stock_ledger()
|
||||
|
||||
self.cancel_packing_slips()
|
||||
PackingService(self).cancel_packing_slips()
|
||||
self.update_pick_list_status()
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
@@ -600,20 +601,7 @@ class DeliveryNote(SellingController):
|
||||
|
||||
def validate_packed_qty(self):
|
||||
"""Validate that if packed qty exists, it should be equal to qty"""
|
||||
|
||||
if frappe.db.exists("Packing Slip", {"docstatus": 1, "delivery_note": self.name}):
|
||||
product_bundle_list = self.get_product_bundle_list()
|
||||
for item in self.items + self.packed_items:
|
||||
if (
|
||||
item.item_code not in product_bundle_list
|
||||
and flt(item.packed_qty)
|
||||
and flt(item.packed_qty) != flt(item.qty)
|
||||
):
|
||||
frappe.throw(
|
||||
_("Row {0}: Packed Qty must be equal to {1} Qty.").format(
|
||||
item.idx, frappe.bold(item.doctype)
|
||||
)
|
||||
)
|
||||
PackingService(self).validate_packed_qty()
|
||||
|
||||
def check_next_docstatus(self):
|
||||
submit_rv = frappe.db.sql(
|
||||
@@ -634,22 +622,6 @@ class DeliveryNote(SellingController):
|
||||
if submit_in:
|
||||
frappe.throw(_("Installation Note {0} has already been submitted").format(submit_in[0][0]))
|
||||
|
||||
def cancel_packing_slips(self):
|
||||
"""
|
||||
Cancel submitted packing slips related to this delivery note
|
||||
"""
|
||||
res = frappe.db.sql(
|
||||
"""SELECT name FROM `tabPacking Slip` WHERE delivery_note = %s
|
||||
AND docstatus = 1""",
|
||||
self.name,
|
||||
)
|
||||
|
||||
if res:
|
||||
for r in res:
|
||||
ps = frappe.get_doc("Packing Slip", r[0])
|
||||
ps.cancel()
|
||||
frappe.msgprint(_("Packing Slip(s) cancelled"))
|
||||
|
||||
def update_status(self, status):
|
||||
BillingStatusService(self).update_status(status)
|
||||
|
||||
@@ -657,21 +629,7 @@ class DeliveryNote(SellingController):
|
||||
BillingStatusService(self).update_billing_status(update_modified)
|
||||
|
||||
def has_unpacked_items(self):
|
||||
product_bundle_list = self.get_product_bundle_list()
|
||||
|
||||
for item in self.items + self.packed_items:
|
||||
if item.item_code not in product_bundle_list and flt(item.packed_qty) < flt(item.qty):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_product_bundle_list(self):
|
||||
items_list = [item.item_code for item in self.items]
|
||||
return frappe.db.get_all(
|
||||
"Product Bundle",
|
||||
filters={"new_item_code": ["in", items_list], "disabled": 0},
|
||||
pluck="name",
|
||||
)
|
||||
return PackingService(self).has_unpacked_items()
|
||||
|
||||
|
||||
def get_list_context(context=None):
|
||||
|
||||
63
erpnext/stock/doctype/delivery_note/services/packing.py
Normal file
63
erpnext/stock/doctype/delivery_note/services/packing.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
"""Packing slip and product bundle handling for Delivery Note."""
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
|
||||
|
||||
class PackingService:
|
||||
def __init__(self, doc):
|
||||
self.doc = doc
|
||||
|
||||
def validate_packed_qty(self) -> None:
|
||||
"""Validate that if packed qty exists, it should be equal to qty"""
|
||||
doc = self.doc
|
||||
|
||||
if frappe.db.exists("Packing Slip", {"docstatus": 1, "delivery_note": doc.name}):
|
||||
product_bundle_list = self.get_product_bundle_list()
|
||||
for item in doc.items + doc.packed_items:
|
||||
if (
|
||||
item.item_code not in product_bundle_list
|
||||
and flt(item.packed_qty)
|
||||
and flt(item.packed_qty) != flt(item.qty)
|
||||
):
|
||||
frappe.throw(
|
||||
_("Row {0}: Packed Qty must be equal to {1} Qty.").format(
|
||||
item.idx, frappe.bold(item.doctype)
|
||||
)
|
||||
)
|
||||
|
||||
def has_unpacked_items(self) -> bool:
|
||||
doc = self.doc
|
||||
product_bundle_list = self.get_product_bundle_list()
|
||||
|
||||
for item in doc.items + doc.packed_items:
|
||||
if item.item_code not in product_bundle_list and flt(item.packed_qty) < flt(item.qty):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_product_bundle_list(self) -> list[str]:
|
||||
items_list = [item.item_code for item in self.doc.items]
|
||||
return frappe.db.get_all(
|
||||
"Product Bundle",
|
||||
filters={"new_item_code": ["in", items_list], "disabled": 0},
|
||||
pluck="name",
|
||||
)
|
||||
|
||||
def cancel_packing_slips(self) -> None:
|
||||
"""Cancel submitted packing slips related to this delivery note"""
|
||||
res = frappe.db.sql(
|
||||
"""SELECT name FROM `tabPacking Slip` WHERE delivery_note = %s
|
||||
AND docstatus = 1""",
|
||||
self.doc.name,
|
||||
)
|
||||
|
||||
if res:
|
||||
for r in res:
|
||||
ps = frappe.get_doc("Packing Slip", r[0])
|
||||
ps.cancel()
|
||||
frappe.msgprint(_("Packing Slip(s) cancelled"))
|
||||
Reference in New Issue
Block a user