refactor: move validate trigger to controller

This commit is contained in:
ruthra kumar
2025-01-01 11:32:47 +05:30
parent fb667f5e09
commit 10c3bb4971
3 changed files with 49 additions and 29 deletions

View File

@@ -481,12 +481,6 @@ class PurchaseOrder(BuyingController):
self.notify_update() self.notify_update()
clear_doctype_notifications(self) clear_doctype_notifications(self)
def validate_budget(self):
from erpnext.controllers.budget_controller import BudgetValidation
val = BudgetValidation(self)
val.validate()
frappe.throw("stop")
def on_submit(self): def on_submit(self):
super().on_submit() super().on_submit()

View File

@@ -2,6 +2,8 @@ from collections import OrderedDict
import frappe import frappe
from frappe import qb from frappe import qb
from frappe.query_builder import Criterion
from frappe.query_builder.functions import IfNull, Sum
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
@@ -94,7 +96,7 @@ class BudgetValidation:
self.doc_or_item_map.setdefault(key, []).append(itm) self.doc_or_item_map.setdefault(key, []).append(itm)
self.doc_or_item_keys = self.doc_or_item_map.keys() self.doc_or_item_keys = self.doc_or_item_map.keys()
def build_to_validate_map(self): def build_validation_map(self):
self.overlap = self.budget_keys & self.doc_or_item_keys self.overlap = self.budget_keys & self.doc_or_item_keys
self.to_validate = OrderedDict() self.to_validate = OrderedDict()
@@ -109,36 +111,54 @@ class BudgetValidation:
def validate(self): def validate(self):
self.build_budget_keys_and_map() self.build_budget_keys_and_map()
self.build_doc_or_item_keys_and_map() self.build_doc_or_item_keys_and_map()
self.build_to_validate_map() self.build_validation_map()
self.validate_for_overbooking() self.validate_for_overbooking()
def get_ordered_amount(self): def get_ordered_amount(self, key: tuple | None = None):
items = set([x.item_code for x in self.doc.items]) if key:
exp_accounts = set([x.expense_account for x in self.doc.items]) # Initialize
self.to_validate[key]["ordered_amount"] = 0
po = qb.DocType("Purchase Order") items = set([x.item_code for x in self.doc.items])
poi = qb.DocType("Purchase Order Item") exp_accounts = set([x.expense_account for x in self.doc.items])
query = ( po = qb.DocType("Purchase Order")
qb.from_(po) poi = qb.DocType("Purchase Order Item")
.inner_join(poi)
.on(po.name == poi.parent) conditions = []
.select(po.name) conditions.append(po.company.eq(self.company))
.where( conditions.append(po.docstatus.eq(1))
po.docstatus.eq(1) conditions.append(poi.amount.gt(poi.billed_amt))
& (poi.amount > poi.billed_amt) conditions.append(poi.expense_account.isin(exp_accounts))
& po.status.ne("Closed") conditions.append(poi.item_code.isin(items))
& poi.item_code.isin(items) conditions.append(po.status.ne("Closed"))
& poi.expense_account.isin(exp_accounts) conditions.append(po.transaction_date[self.fy_start_date : self.fy_end_date])
& po.transaction_date[self.fy_start_date : self.fy_end_date]
# key structure - (dimension_type, dimension, GL account)
conditions.append(poi[key[0]].eq(key[1]))
ordered_amount = (
qb.from_(po)
.inner_join(poi)
.on(po.name == poi.parent)
.select(Sum(IfNull(poi.amount, 0) - IfNull(poi.billed_amt, 0)).as_("amount"))
.where(Criterion.all(conditions))
.run(as_dict=True)
) )
) if ordered_amount:
print("Query:", query) self.to_validate[key]["ordered_amount"] = 0
def validate_for_overbooking(self): def validate_for_overbooking(self):
# TODO: Need to fetch historical amount and add them to the current document # TODO: Need to fetch historical amount and add them to the current document
# TODO: handle applicable checkboxes # TODO: handle applicable checkboxes
for v in self.to_validate.values(): self.ordered_amount = frappe._dict()
for k, v in self.to_validate.items():
# Amt from current Purchase Order is included in `self.ordered_amount` as doc is
# in submitted status by the time the validation occurs
if self.doc.doctype == "Purchase Order":
self.get_ordered_amount(k)
v["current_amount"] = sum([x.amount for x in v.get("items_to_process")]) v["current_amount"] = sum([x.amount for x in v.get("items_to_process")])
self.get_ordered_amount() print(self.to_validate)

View File

@@ -775,6 +775,12 @@ class BuyingController(SubcontractingController):
self.update_fixed_asset(field, delete_asset=True) self.update_fixed_asset(field, delete_asset=True)
def validate_budget(self): def validate_budget(self):
from erpnext.controllers.budget_controller import BudgetValidation
val = BudgetValidation(self)
val.validate()
return
if self.docstatus == 1: if self.docstatus == 1:
for data in self.get("items"): for data in self.get("items"):
args = data.as_dict() args = data.as_dict()