Merge pull request #32527 from s-aga-r/refactor/buying/reports

refactor: rewrite buying reports queries in qb
This commit is contained in:
Deepesh Garg 2022-10-18 10:06:10 +05:30 committed by GitHub
commit 7184330acd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 159 additions and 164 deletions

View File

@ -127,32 +127,27 @@ def get_columns(filters):
return columns
def get_conditions(filters):
conditions = ""
def apply_filters_on_query(filters, parent, child, query):
if filters.get("company"):
conditions += " AND parent.company=%s" % frappe.db.escape(filters.get("company"))
query = query.where(parent.company == filters.get("company"))
if filters.get("cost_center") or filters.get("project"):
conditions += """
AND (child.`cost_center`=%s OR child.`project`=%s)
""" % (
frappe.db.escape(filters.get("cost_center")),
frappe.db.escape(filters.get("project")),
query = query.where(
(child.cost_center == filters.get("cost_center")) | (child.project == filters.get("project"))
)
if filters.get("from_date"):
conditions += " AND parent.transaction_date>='%s'" % filters.get("from_date")
query = query.where(parent.transaction_date >= filters.get("from_date"))
if filters.get("to_date"):
conditions += " AND parent.transaction_date<='%s'" % filters.get("to_date")
return conditions
query = query.where(parent.transaction_date <= filters.get("to_date"))
return query
def get_data(filters):
conditions = get_conditions(filters)
purchase_order_entry = get_po_entries(conditions)
mr_records, procurement_record_against_mr = get_mapped_mr_details(conditions)
purchase_order_entry = get_po_entries(filters)
mr_records, procurement_record_against_mr = get_mapped_mr_details(filters)
pr_records = get_mapped_pr_records()
pi_records = get_mapped_pi_records()
@ -187,11 +182,15 @@ def get_data(filters):
return procurement_record
def get_mapped_mr_details(conditions):
def get_mapped_mr_details(filters):
mr_records = {}
mr_details = frappe.db.sql(
"""
SELECT
parent = frappe.qb.DocType("Material Request")
child = frappe.qb.DocType("Material Request Item")
query = (
frappe.qb.from_(parent)
.from_(child)
.select(
parent.transaction_date,
parent.per_ordered,
parent.owner,
@ -203,18 +202,13 @@ def get_mapped_mr_details(conditions):
child.uom,
parent.status,
child.project,
child.cost_center
FROM `tabMaterial Request` parent, `tabMaterial Request Item` child
WHERE
parent.per_ordered>=0
AND parent.name=child.parent
AND parent.docstatus=1
{conditions}
""".format(
conditions=conditions
),
as_dict=1,
) # nosec
child.cost_center,
)
.where((parent.per_ordered >= 0) & (parent.name == child.parent) & (parent.docstatus == 1))
)
query = apply_filters_on_query(filters, parent, child, query)
mr_details = query.run(as_dict=True)
procurement_record_against_mr = []
for record in mr_details:
@ -241,46 +235,49 @@ def get_mapped_mr_details(conditions):
def get_mapped_pi_records():
return frappe._dict(
frappe.db.sql(
"""
SELECT
pi_item.po_detail,
pi_item.base_amount
FROM `tabPurchase Invoice Item` as pi_item
INNER JOIN `tabPurchase Order` as po
ON pi_item.`purchase_order` = po.`name`
WHERE
pi_item.docstatus = 1
AND po.status not in ('Closed','Completed','Cancelled')
AND pi_item.po_detail IS NOT NULL
"""
po = frappe.qb.DocType("Purchase Order")
pi_item = frappe.qb.DocType("Purchase Invoice Item")
pi_records = (
frappe.qb.from_(pi_item)
.inner_join(po)
.on(pi_item.purchase_order == po.name)
.select(pi_item.po_detail, pi_item.base_amount)
.where(
(pi_item.docstatus == 1)
& (po.status.notin(("Closed", "Completed", "Cancelled")))
& (pi_item.po_detail.isnotnull())
)
)
).run()
return frappe._dict(pi_records)
def get_mapped_pr_records():
return frappe._dict(
frappe.db.sql(
"""
SELECT
pr_item.purchase_order_item,
pr.posting_date
FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
WHERE
pr.docstatus=1
AND pr.name=pr_item.parent
AND pr_item.purchase_order_item IS NOT NULL
AND pr.status not in ('Closed','Completed','Cancelled')
"""
pr = frappe.qb.DocType("Purchase Receipt")
pr_item = frappe.qb.DocType("Purchase Receipt Item")
pr_records = (
frappe.qb.from_(pr)
.from_(pr_item)
.select(pr_item.purchase_order_item, pr.posting_date)
.where(
(pr.docstatus == 1)
& (pr.name == pr_item.parent)
& (pr_item.purchase_order_item.isnotnull())
& (pr.status.notin(("Closed", "Completed", "Cancelled")))
)
)
).run()
return frappe._dict(pr_records)
def get_po_entries(conditions):
return frappe.db.sql(
"""
SELECT
def get_po_entries(filters):
parent = frappe.qb.DocType("Purchase Order")
child = frappe.qb.DocType("Purchase Order Item")
query = (
frappe.qb.from_(parent)
.from_(child)
.select(
child.name,
child.parent,
child.cost_center,
@ -297,17 +294,15 @@ def get_po_entries(conditions):
parent.transaction_date,
parent.supplier,
parent.status,
parent.owner
FROM `tabPurchase Order` parent, `tabPurchase Order Item` child
WHERE
parent.docstatus = 1
AND parent.name = child.parent
AND parent.status not in ('Closed','Completed','Cancelled')
{conditions}
GROUP BY
parent.name, child.item_code
""".format(
conditions=conditions
),
as_dict=1,
) # nosec
parent.owner,
)
.where(
(parent.docstatus == 1)
& (parent.name == child.parent)
& (parent.status.notin(("Closed", "Completed", "Cancelled")))
)
.groupby(parent.name, child.item_code)
)
query = apply_filters_on_query(filters, parent, child, query)
return query.run(as_dict=True)

View File

@ -6,6 +6,7 @@ import copy
import frappe
from frappe import _
from frappe.query_builder.functions import IfNull
from frappe.utils import date_diff, flt, getdate
@ -16,9 +17,7 @@ def execute(filters=None):
validate_filters(filters)
columns = get_columns(filters)
conditions = get_conditions(filters)
data = get_data(conditions, filters)
data = get_data(filters)
if not data:
return [], [], None, []
@ -37,60 +36,61 @@ def validate_filters(filters):
frappe.throw(_("To Date cannot be before From Date."))
def get_conditions(filters):
conditions = ""
if filters.get("from_date") and filters.get("to_date"):
conditions += " and po.transaction_date between %(from_date)s and %(to_date)s"
def get_data(filters):
po = frappe.qb.DocType("Purchase Order")
po_item = frappe.qb.DocType("Purchase Order Item")
pi_item = frappe.qb.DocType("Purchase Invoice Item")
for field in ["company", "name"]:
query = (
frappe.qb.from_(po)
.from_(po_item)
.left_join(pi_item)
.on(pi_item.po_detail == po_item.name)
.select(
po.transaction_date.as_("date"),
po_item.schedule_date.as_("required_date"),
po_item.project,
po.name.as_("purchase_order"),
po.status,
po.supplier,
po_item.item_code,
po_item.qty,
po_item.received_qty,
(po_item.qty - po_item.received_qty).as_("pending_qty"),
IfNull(pi_item.qty, 0).as_("billed_qty"),
po_item.base_amount.as_("amount"),
(po_item.received_qty * po_item.base_rate).as_("received_qty_amount"),
(po_item.billed_amt * IfNull(po.conversion_rate, 1)).as_("billed_amount"),
(po_item.base_amount - (po_item.billed_amt * IfNull(po.conversion_rate, 1))).as_(
"pending_amount"
),
po.set_warehouse.as_("warehouse"),
po.company,
po_item.name,
)
.where(
(po_item.parent == po.name) & (po.status.notin(("Stopped", "Closed"))) & (po.docstatus == 1)
)
.groupby(po_item.name)
.orderby(po.transaction_date)
)
for field in ("company", "name"):
if filters.get(field):
conditions += f" and po.{field} = %({field})s"
query = query.where(po[field] == filters.get(field))
if filters.get("from_date") and filters.get("to_date"):
query = query.where(
po.transaction_date.between(filters.get("from_date"), filters.get("to_date"))
)
if filters.get("status"):
conditions += " and po.status in %(status)s"
query = query.where(po.status.isin(filters.get("status")))
if filters.get("project"):
conditions += " and poi.project = %(project)s"
query = query.where(po_item.project == filters.get("project"))
return conditions
def get_data(conditions, filters):
data = frappe.db.sql(
"""
SELECT
po.transaction_date as date,
poi.schedule_date as required_date,
poi.project,
po.name as purchase_order,
po.status, po.supplier, poi.item_code,
poi.qty, poi.received_qty,
(poi.qty - poi.received_qty) AS pending_qty,
IFNULL(pii.qty, 0) as billed_qty,
poi.base_amount as amount,
(poi.received_qty * poi.base_rate) as received_qty_amount,
(poi.billed_amt * IFNULL(po.conversion_rate, 1)) as billed_amount,
(poi.base_amount - (poi.billed_amt * IFNULL(po.conversion_rate, 1))) as pending_amount,
po.set_warehouse as warehouse,
po.company, poi.name
FROM
`tabPurchase Order` po,
`tabPurchase Order Item` poi
LEFT JOIN `tabPurchase Invoice Item` pii
ON pii.po_detail = poi.name
WHERE
poi.parent = po.name
and po.status not in ('Stopped', 'Closed')
and po.docstatus = 1
{0}
GROUP BY poi.name
ORDER BY po.transaction_date ASC
""".format(
conditions
),
filters,
as_dict=1,
)
data = query.run(as_dict=True)
return data

View File

@ -16,8 +16,7 @@ def execute(filters=None):
return [], []
columns = get_columns(filters)
conditions = get_conditions(filters)
supplier_quotation_data = get_data(filters, conditions)
supplier_quotation_data = get_data(filters)
data, chart_data = prepare_data(supplier_quotation_data, filters)
message = get_message()
@ -25,50 +24,51 @@ def execute(filters=None):
return columns, data, message, chart_data
def get_conditions(filters):
conditions = ""
def get_data(filters):
sq = frappe.qb.DocType("Supplier Quotation")
sq_item = frappe.qb.DocType("Supplier Quotation Item")
query = (
frappe.qb.from_(sq_item)
.from_(sq)
.select(
sq_item.parent,
sq_item.item_code,
sq_item.qty,
sq_item.stock_qty,
sq_item.amount,
sq_item.uom,
sq_item.stock_uom,
sq_item.request_for_quotation,
sq_item.lead_time_days,
sq.supplier.as_("supplier_name"),
sq.valid_till,
)
.where(
(sq_item.parent == sq.name)
& (sq_item.docstatus < 2)
& (sq.company == filters.get("company"))
& (sq.transaction_date.between(filters.get("from_date"), filters.get("to_date")))
)
.orderby(sq.transaction_date, sq_item.item_code)
)
if filters.get("item_code"):
conditions += " AND sqi.item_code = %(item_code)s"
query = query.where(sq_item.item_code == filters.get("item_code"))
if filters.get("supplier_quotation"):
conditions += " AND sqi.parent in %(supplier_quotation)s"
query = query.where(sq_item.parent.isin(filters.get("supplier_quotation")))
if filters.get("request_for_quotation"):
conditions += " AND sqi.request_for_quotation = %(request_for_quotation)s"
query = query.where(sq_item.request_for_quotation == filters.get("request_for_quotation"))
if filters.get("supplier"):
conditions += " AND sq.supplier in %(supplier)s"
query = query.where(sq.supplier.isin(filters.get("supplier")))
if not filters.get("include_expired"):
conditions += " AND sq.status != 'Expired'"
query = query.where(sq.status != "Expired")
return conditions
def get_data(filters, conditions):
supplier_quotation_data = frappe.db.sql(
"""
SELECT
sqi.parent, sqi.item_code,
sqi.qty, sqi.stock_qty, sqi.amount,
sqi.uom, sqi.stock_uom,
sqi.request_for_quotation,
sqi.lead_time_days, sq.supplier as supplier_name, sq.valid_till
FROM
`tabSupplier Quotation Item` sqi,
`tabSupplier Quotation` sq
WHERE
sqi.parent = sq.name
AND sqi.docstatus < 2
AND sq.company = %(company)s
AND sq.transaction_date between %(from_date)s and %(to_date)s
{0}
order by sq.transaction_date, sqi.item_code""".format(
conditions
),
filters,
as_dict=1,
)
supplier_quotation_data = query.run(as_dict=True)
return supplier_quotation_data