mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 19:29:10 +00:00
refactor: move validate trigger to controller
This commit is contained in:
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user