feat: Apply Putaway Rules within transaction itself

- Added checkbox 'Apply Putaway Rule' in PR and SE
- Added link to rule in child tables
- Rule is applied on Save
- Validation for over receipt
- Apply Rule on Stock Entry as well for Material Transfer and Receipt
This commit is contained in:
marination
2020-12-07 21:35:49 +05:30
parent 1087d97c03
commit fac4035f23
11 changed files with 217 additions and 58 deletions

View File

@@ -6,6 +6,7 @@ import frappe, erpnext
from frappe.utils import cint, flt, cstr, get_link_to_form, today, getdate
from frappe import _
import frappe.defaults
from collections import defaultdict
from erpnext.accounts.utils import get_fiscal_year
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries, process_gl_map
from erpnext.controllers.accounts_controller import AccountsController
@@ -23,6 +24,7 @@ class StockController(AccountsController):
self.validate_inspection()
self.validate_serialized_batch()
self.validate_customer_provided_item()
self.validate_putaway_capacity()
def make_gl_entries(self, gl_entries=None):
if self.docstatus == 2:
@@ -399,6 +401,42 @@ class StockController(AccountsController):
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
d.allow_zero_valuation_rate = 1
def validate_putaway_capacity(self):
# if over receipt is attempted while 'apply putaway rule' is disabled
# and if rule was applied on the transaction, validate it.
from erpnext.stock.doctype.putaway_rule.putaway_rule import get_putaway_capacity
valid_doctype = self.doctype in ("Purchase Receipt", "Stock Entry")
rule_applied = any(item.get("putaway_rule") for item in self.get("items"))
if valid_doctype and rule_applied and not self.apply_putaway_rule:
rule_map = defaultdict(dict)
for item in self.get("items"):
if item.get("putaway_rule"):
rule = item.get("putaway_rule")
disabled = frappe.db.get_value("Putaway Rule", rule, "disable")
if disabled: return # dont validate for disabled rule
stock_qty = flt(item.transfer_qty) if self.doctype == "Stock Entry" else flt(item.stock_qty)
warehouse_field = "t_warehouse" if self.doctype == "Stock Entry" else "warehouse"
if not rule_map[rule]:
rule_map[rule]["warehouse"] = item.get(warehouse_field)
rule_map[rule]["item"] = item.get("item_code")
rule_map[rule]["qty_put"] = 0
rule_map[rule]["capacity"] = get_putaway_capacity(rule)
rule_map[rule]["qty_put"] += flt(stock_qty)
for rule, values in rule_map.items():
if flt(values["qty_put"]) > flt(values["capacity"]):
message = _("{0} qty of Item {1} is being received into Warehouse {2} with capacity {3}.") \
.format(
frappe.bold(values["qty_put"]), frappe.bold(values["item"]),
frappe.bold(values["warehouse"]), frappe.bold(values["capacity"])
)
message += "<br><br>"
rule_link = frappe.utils.get_link_to_form("Putaway Rule", rule)
message += _(" Please adjust the qty or edit {0} to proceed.").format(rule_link)
frappe.throw(msg=message, title=_("Over Receipt"))
return rule_map
def compare_existing_and_expected_gle(existing_gle, expected_gle):
matched = True
for entry in expected_gle: