mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-13 22:51:49 +00:00
feat: add Purchase Person reports mirroring Sales Person reports
Three new Script Reports in the Buying module: - Purchase Person-wise Transaction Summary (mirrors Sales Person-wise) - Purchase Person Commission Summary (mirrors Sales Person Commission) - Purchase Person Target Variance Based On Item Group (mirrors Sales Person Target) The shared `item_group_wise_sales_target_variance.get_actual_data` helper gains a `purchase_person` branch that joins `Purchase Team` the same way the existing `sales_person` branch joins `Sales Team`. All three reports are added to the Buying workspace under a Purchase Person card. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.query_reports["Purchase Person Commission Summary"] = {
|
||||
filters: [
|
||||
{
|
||||
fieldname: "purchase_person",
|
||||
label: __("Purchase Person"),
|
||||
fieldtype: "Link",
|
||||
options: "Purchase Person",
|
||||
},
|
||||
{
|
||||
fieldname: "doc_type",
|
||||
label: __("Document Type"),
|
||||
fieldtype: "Select",
|
||||
options: "Purchase Order\nPurchase Receipt\nPurchase Invoice",
|
||||
default: "Purchase Order",
|
||||
},
|
||||
{
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
||||
},
|
||||
{
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today(),
|
||||
},
|
||||
{
|
||||
fieldname: "company",
|
||||
label: __("Company"),
|
||||
fieldtype: "Link",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
},
|
||||
{
|
||||
fieldname: "supplier",
|
||||
label: __("Supplier"),
|
||||
fieldtype: "Link",
|
||||
options: "Supplier",
|
||||
},
|
||||
{
|
||||
fieldname: "territory",
|
||||
label: __("Territory"),
|
||||
fieldtype: "Link",
|
||||
options: "Territory",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"add_total_row": 1,
|
||||
"creation": "2026-06-17 00:00:00",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2026-06-17 00:00:00",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Person Commission Summary",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Purchase Order",
|
||||
"report_name": "Purchase Person Commission Summary",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Purchase Manager"
|
||||
},
|
||||
{
|
||||
"role": "Accounts User"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from frappe import _, msgprint, qb
|
||||
from frappe.query_builder import Criterion
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
columns = get_columns(filters)
|
||||
entries = get_entries(filters)
|
||||
data = []
|
||||
|
||||
for d in entries:
|
||||
data.append(
|
||||
[
|
||||
d.name,
|
||||
d.supplier,
|
||||
d.territory,
|
||||
d.posting_date,
|
||||
d.base_net_amount,
|
||||
d.purchase_person,
|
||||
d.allocated_percentage,
|
||||
d.commission_rate,
|
||||
d.allocated_amount,
|
||||
d.incentives,
|
||||
]
|
||||
)
|
||||
|
||||
if data:
|
||||
total_row = [""] * len(data[0])
|
||||
data.append(total_row)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns(filters):
|
||||
if not filters.get("doc_type"):
|
||||
msgprint(_("Please select the document type first"), raise_exception=1)
|
||||
|
||||
return [
|
||||
{
|
||||
"label": _(filters["doc_type"]),
|
||||
"options": filters["doc_type"],
|
||||
"fieldname": filters["doc_type"],
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Supplier"),
|
||||
"options": "Supplier",
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Territory"),
|
||||
"options": "Territory",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"width": 100,
|
||||
},
|
||||
{"label": _("Posting Date"), "fieldname": "posting_date", "fieldtype": "Date", "width": 100},
|
||||
{"label": _("Amount"), "fieldname": "amount", "fieldtype": "Currency", "width": 120},
|
||||
{
|
||||
"label": _("Purchase Person"),
|
||||
"options": "Purchase Person",
|
||||
"fieldname": "purchase_person",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Contribution %"),
|
||||
"fieldname": "contribution_percentage",
|
||||
"fieldtype": "Data",
|
||||
"width": 110,
|
||||
},
|
||||
{
|
||||
"label": _("Commission Rate %"),
|
||||
"fieldname": "commission_rate",
|
||||
"fieldtype": "Data",
|
||||
"width": 100,
|
||||
},
|
||||
{
|
||||
"label": _("Contribution Amount"),
|
||||
"fieldname": "contribution_amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 120,
|
||||
},
|
||||
{"label": _("Incentives"), "fieldname": "incentives", "fieldtype": "Currency", "width": 120},
|
||||
]
|
||||
|
||||
|
||||
def get_entries(filters):
|
||||
dt = qb.DocType(filters["doc_type"])
|
||||
pt = qb.DocType("Purchase Team")
|
||||
date_field = dt["transaction_date"] if filters["doc_type"] == "Purchase Order" else dt["posting_date"]
|
||||
|
||||
conditions = get_conditions(dt, pt, filters, date_field)
|
||||
return (
|
||||
qb.from_(dt)
|
||||
.join(pt)
|
||||
.on(pt.parent.eq(dt.name) & pt.parenttype.eq(filters["doc_type"]))
|
||||
.select(
|
||||
dt.name,
|
||||
dt.supplier,
|
||||
dt.territory,
|
||||
date_field.as_("posting_date"),
|
||||
dt.base_net_total.as_("base_net_amount"),
|
||||
pt.commission_rate,
|
||||
pt.purchase_person,
|
||||
pt.allocated_percentage,
|
||||
pt.allocated_amount,
|
||||
pt.incentives,
|
||||
)
|
||||
.where(Criterion.all(conditions))
|
||||
.orderby(dt.name, pt.purchase_person)
|
||||
.run(as_dict=True)
|
||||
)
|
||||
|
||||
|
||||
def get_conditions(dt, pt, filters, date_field):
|
||||
conditions = [dt.docstatus.eq(1)]
|
||||
|
||||
from_dt = filters.get("from_date")
|
||||
to_dt = filters.get("to_date")
|
||||
if from_dt and to_dt:
|
||||
conditions.append(date_field.between(from_dt, to_dt))
|
||||
elif from_dt:
|
||||
conditions.append(date_field.gte(from_dt))
|
||||
elif to_dt:
|
||||
conditions.append(date_field.lte(to_dt))
|
||||
|
||||
for field in ["company", "supplier", "territory"]:
|
||||
if filters.get(field):
|
||||
conditions.append(dt[field].eq(filters.get(field)))
|
||||
|
||||
if filters.get("purchase_person"):
|
||||
conditions.append(pt["purchase_person"].eq(filters.get("purchase_person")))
|
||||
|
||||
return conditions
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.query_reports["Purchase Person Target Variance Based On Item Group"] = {
|
||||
filters: [
|
||||
{
|
||||
fieldname: "company",
|
||||
label: __("Company"),
|
||||
fieldtype: "Link",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
},
|
||||
{
|
||||
fieldname: "fiscal_year",
|
||||
label: __("Fiscal Year"),
|
||||
fieldtype: "Link",
|
||||
options: "Fiscal Year",
|
||||
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||
},
|
||||
{
|
||||
fieldname: "doctype",
|
||||
label: __("Document Type"),
|
||||
fieldtype: "Select",
|
||||
options: "Purchase Order\nPurchase Receipt\nPurchase Invoice",
|
||||
default: "Purchase Order",
|
||||
},
|
||||
{
|
||||
fieldname: "period",
|
||||
label: __("Period"),
|
||||
fieldtype: "Select",
|
||||
options: [
|
||||
{ value: "Monthly", label: __("Monthly") },
|
||||
{ value: "Quarterly", label: __("Quarterly") },
|
||||
{ value: "Half-Yearly", label: __("Half-Yearly") },
|
||||
{ value: "Yearly", label: __("Yearly") },
|
||||
],
|
||||
default: "Monthly",
|
||||
},
|
||||
{
|
||||
fieldname: "target_on",
|
||||
label: __("Target On"),
|
||||
fieldtype: "Select",
|
||||
options: "Quantity\nAmount",
|
||||
default: "Quantity",
|
||||
},
|
||||
],
|
||||
formatter: function (value, row, column, data, default_formatter) {
|
||||
value = default_formatter(value, row, column, data);
|
||||
|
||||
if (column.fieldname.includes("variance")) {
|
||||
if (data[column.fieldname] < 0) {
|
||||
value = "<span style='color:red'>" + value + "</span>";
|
||||
} else if (data[column.fieldname] > 0) {
|
||||
value = "<span style='color:green'>" + value + "</span>";
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"creation": "2026-06-17 00:00:00",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2026-06-17 00:00:00",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Person Target Variance Based On Item Group",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Purchase Order",
|
||||
"report_name": "Purchase Person Target Variance Based On Item Group",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Purchase User"
|
||||
},
|
||||
{
|
||||
"role": "Purchase Manager"
|
||||
},
|
||||
{
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"role": "Stock User"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.item_group_wise_sales_target_variance import (
|
||||
get_data_column,
|
||||
)
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
return get_data_column(filters, "Purchase Person")
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.query_reports["Purchase Person-wise Transaction Summary"] = {
|
||||
filters: [
|
||||
{
|
||||
fieldname: "purchase_person",
|
||||
label: __("Purchase Person"),
|
||||
fieldtype: "Link",
|
||||
options: "Purchase Person",
|
||||
},
|
||||
{
|
||||
fieldname: "doc_type",
|
||||
label: __("Document Type"),
|
||||
fieldtype: "Select",
|
||||
options: "Purchase Order\nPurchase Receipt\nPurchase Invoice",
|
||||
default: "Purchase Order",
|
||||
},
|
||||
{
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
||||
},
|
||||
{
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today(),
|
||||
},
|
||||
{
|
||||
fieldname: "company",
|
||||
label: __("Company"),
|
||||
fieldtype: "Link",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "item_group",
|
||||
label: __("Item Group"),
|
||||
fieldtype: "Link",
|
||||
options: "Item Group",
|
||||
},
|
||||
{
|
||||
fieldname: "brand",
|
||||
label: __("Brand"),
|
||||
fieldtype: "Link",
|
||||
options: "Brand",
|
||||
},
|
||||
{
|
||||
fieldname: "supplier",
|
||||
label: __("Supplier"),
|
||||
fieldtype: "Link",
|
||||
options: "Supplier",
|
||||
},
|
||||
{
|
||||
fieldname: "territory",
|
||||
label: __("Territory"),
|
||||
fieldtype: "Link",
|
||||
options: "Territory",
|
||||
},
|
||||
{
|
||||
fieldname: "show_return_entries",
|
||||
label: __("Show Return Entries"),
|
||||
fieldtype: "Check",
|
||||
default: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"add_total_row": 1,
|
||||
"creation": "2026-06-17 00:00:00",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2026-06-17 00:00:00",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Person-wise Transaction Summary",
|
||||
"owner": "Administrator",
|
||||
"ref_doctype": "Purchase Order",
|
||||
"report_name": "Purchase Person-wise Transaction Summary",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Purchase User"
|
||||
},
|
||||
{
|
||||
"role": "Purchase Manager"
|
||||
},
|
||||
{
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"role": "Stock User"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe import _, msgprint, qb
|
||||
from frappe.query_builder import Case, Criterion
|
||||
|
||||
from erpnext import get_company_currency
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
validate_filters(filters)
|
||||
|
||||
columns = get_columns(filters)
|
||||
entries = get_entries(filters)
|
||||
item_details = get_item_details()
|
||||
data = []
|
||||
|
||||
company_currency = get_company_currency(filters.get("company"))
|
||||
|
||||
for d in entries:
|
||||
if d.stock_qty > 0 or filters.get("show_return_entries", 0):
|
||||
data.append(
|
||||
[
|
||||
d.name,
|
||||
d.supplier,
|
||||
d.territory,
|
||||
d.warehouse,
|
||||
d.posting_date,
|
||||
d.item_code,
|
||||
item_details.get(d.item_code, {}).get("item_group"),
|
||||
item_details.get(d.item_code, {}).get("brand"),
|
||||
d.stock_qty,
|
||||
d.base_net_amount,
|
||||
d.purchase_person,
|
||||
d.allocated_percentage,
|
||||
(d.stock_qty * d.allocated_percentage / 100),
|
||||
d.contribution_amt,
|
||||
company_currency,
|
||||
]
|
||||
)
|
||||
|
||||
if data:
|
||||
total_row = [""] * len(data[0])
|
||||
data.append(total_row)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def validate_filters(filters):
|
||||
ALLOWED_DOCTYPES = ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]
|
||||
|
||||
if not filters.get("doc_type"):
|
||||
msgprint(_("Please select the document type first"), raise_exception=1)
|
||||
|
||||
if filters.get("doc_type") not in ALLOWED_DOCTYPES:
|
||||
frappe.throw(_("{0}, {1} or {2} are the only allowed options.").format(*ALLOWED_DOCTYPES))
|
||||
|
||||
|
||||
def get_columns(filters):
|
||||
return [
|
||||
{
|
||||
"label": _(filters["doc_type"]),
|
||||
"options": filters["doc_type"],
|
||||
"fieldname": frappe.scrub(filters["doc_type"]),
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Supplier"),
|
||||
"options": "Supplier",
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Territory"),
|
||||
"options": "Territory",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Warehouse"),
|
||||
"options": "Warehouse",
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{"label": _("Posting Date"), "fieldname": "posting_date", "fieldtype": "Date", "width": 140},
|
||||
{
|
||||
"label": _("Item Code"),
|
||||
"options": "Item",
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Item Group"),
|
||||
"options": "Item Group",
|
||||
"fieldname": "item_group",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Brand"),
|
||||
"options": "Brand",
|
||||
"fieldname": "brand",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{"label": _("Total Qty"), "fieldname": "qty", "fieldtype": "Float", "width": 140},
|
||||
{
|
||||
"label": _("Amount"),
|
||||
"options": "currency",
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Purchase Person"),
|
||||
"options": "Purchase Person",
|
||||
"fieldname": "purchase_person",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
},
|
||||
{"label": _("Contribution %"), "fieldname": "contribution", "fieldtype": "Float", "width": 140},
|
||||
{
|
||||
"label": _("Contribution Qty"),
|
||||
"fieldname": "contribution_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Contribution Amount"),
|
||||
"options": "currency",
|
||||
"fieldname": "contribution_amt",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140,
|
||||
},
|
||||
{
|
||||
"label": _("Currency"),
|
||||
"options": "Currency",
|
||||
"fieldname": "currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def get_entries(filters):
|
||||
doc_type = filters["doc_type"]
|
||||
|
||||
date_field = "transaction_date" if doc_type == "Purchase Order" else "posting_date"
|
||||
qty_field = "received_qty" if doc_type == "Purchase Order" else "qty"
|
||||
|
||||
dt = frappe.qb.DocType(doc_type)
|
||||
dt_item = frappe.qb.DocType(f"{doc_type} Item")
|
||||
pt = frappe.qb.DocType("Purchase Team")
|
||||
|
||||
calc_qty = dt_item[qty_field] * dt_item.conversion_factor
|
||||
calc_net_amount = dt_item.base_net_rate * calc_qty
|
||||
|
||||
stock_qty_case = Case().when(dt.status == "Closed", calc_qty).else_(dt_item.stock_qty).as_("stock_qty")
|
||||
|
||||
base_net_amount_case = (
|
||||
Case()
|
||||
.when(dt.status == "Closed", calc_net_amount)
|
||||
.else_(dt_item.base_net_amount)
|
||||
.as_("base_net_amount")
|
||||
)
|
||||
|
||||
contribution_amt_case = (
|
||||
Case()
|
||||
.when(dt.status == "Closed", (calc_net_amount * pt.allocated_percentage / 100))
|
||||
.else_(dt_item.base_net_amount * pt.allocated_percentage / 100)
|
||||
.as_("contribution_amt")
|
||||
)
|
||||
|
||||
conditions = get_conditions(dt, pt, filters, date_field)
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(dt)
|
||||
.join(dt_item)
|
||||
.on(dt.name == dt_item.parent)
|
||||
.join(pt)
|
||||
.on(dt.name == pt.parent)
|
||||
.select(
|
||||
dt.name,
|
||||
dt.supplier,
|
||||
dt.territory,
|
||||
dt[date_field].as_("posting_date"),
|
||||
dt_item.item_code,
|
||||
pt.purchase_person,
|
||||
pt.allocated_percentage,
|
||||
dt_item.warehouse,
|
||||
stock_qty_case,
|
||||
base_net_amount_case,
|
||||
contribution_amt_case,
|
||||
)
|
||||
.where(pt.parenttype == doc_type)
|
||||
.where(dt.docstatus == 1)
|
||||
.where(Criterion.all(conditions))
|
||||
.orderby(pt.purchase_person)
|
||||
.orderby(dt.name, order=frappe.qb.desc)
|
||||
)
|
||||
|
||||
return query.run(as_dict=True)
|
||||
|
||||
|
||||
def get_conditions(dt, pt, filters, date_field):
|
||||
conditions = []
|
||||
|
||||
for field in ["company", "supplier", "territory"]:
|
||||
if filters.get(field):
|
||||
conditions.append(dt[field].eq(filters[field]))
|
||||
|
||||
if filters.get("purchase_person"):
|
||||
lft, rgt = frappe.get_value("Purchase Person", filters.get("purchase_person"), ["lft", "rgt"])
|
||||
purchase_person_tbl = frappe.qb.DocType("Purchase Person")
|
||||
subquery = (
|
||||
frappe.qb.from_(purchase_person_tbl)
|
||||
.select(purchase_person_tbl.name)
|
||||
.where(purchase_person_tbl.lft >= lft)
|
||||
.where(purchase_person_tbl.rgt <= rgt)
|
||||
)
|
||||
conditions.append(pt.purchase_person.isin(subquery))
|
||||
|
||||
if filters.get("from_date"):
|
||||
conditions.append(dt[date_field].gte(filters["from_date"]))
|
||||
|
||||
if filters.get("to_date"):
|
||||
conditions.append(dt[date_field].lte(filters["to_date"]))
|
||||
|
||||
items = get_items(filters)
|
||||
if items:
|
||||
conditions.append(
|
||||
frappe.qb.DocType(f"{filters['doc_type']} Item").item_code.isin([i[0] for i in items])
|
||||
)
|
||||
elif filters.get("item_group") or filters.get("brand"):
|
||||
conditions.append(frappe.qb.terms.ValueWrapper(0).eq(1))
|
||||
|
||||
return conditions
|
||||
|
||||
|
||||
def get_items(filters):
|
||||
item = qb.DocType("Item")
|
||||
|
||||
item_query_conditions = []
|
||||
if filters.get("item_group"):
|
||||
item_group = qb.DocType("Item Group")
|
||||
lft, rgt = frappe.db.get_all(
|
||||
"Item Group", filters={"name": filters.get("item_group")}, fields=["lft", "rgt"], as_list=True
|
||||
)[0]
|
||||
item_group_query = (
|
||||
qb.from_(item_group)
|
||||
.select(item_group.name)
|
||||
.where((item_group.lft >= lft) & (item_group.rgt <= rgt))
|
||||
)
|
||||
item_query_conditions.append(item.item_group.isin(item_group_query))
|
||||
if filters.get("brand"):
|
||||
item_query_conditions.append(item.brand == filters.get("brand"))
|
||||
|
||||
if not item_query_conditions:
|
||||
return []
|
||||
|
||||
return qb.from_(item).select(item.name).where(Criterion.all(item_query_conditions)).run()
|
||||
|
||||
|
||||
def get_item_details():
|
||||
items = frappe.get_all("Item", fields=["name", "item_group", "brand"])
|
||||
return {d.name: d for d in items}
|
||||
@@ -23,6 +23,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Buying",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -86,6 +87,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Items & Pricing",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -171,6 +173,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Settings",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -212,6 +215,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Supplier",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -264,6 +268,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Supplier Scorecard",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -316,6 +321,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Key Reports",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -390,6 +396,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Purchase Partner",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -415,25 +422,6 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Purchase Person",
|
||||
"link_count": 0,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Purchase Person",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Person",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Purchase Partner",
|
||||
"hidden": 0,
|
||||
@@ -467,11 +455,65 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Purchase Person",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Purchase Person",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Person",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Purchase Person",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Purchase Person-wise Transaction Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Person-wise Transaction Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Purchase Person",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Purchase Person Commission Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Person Commission Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Purchase Person",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Purchase Person Target Variance Based On Item Group",
|
||||
"link_count": 0,
|
||||
"link_to": "Purchase Person Target Variance Based On Item Group",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Other Reports",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -579,6 +621,7 @@
|
||||
"is_query_report": 0,
|
||||
"label": "Regional",
|
||||
"link_count": 0,
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@@ -594,7 +637,7 @@
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2026-01-02 14:55:59.078773",
|
||||
"modified": "2026-06-17 13:01:33.296280",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Buying",
|
||||
|
||||
@@ -243,6 +243,13 @@ def get_actual_data(filters, sales_users_or_territory_data, date_field, sales_fi
|
||||
sales_field_col = sales_team[sales_field]
|
||||
|
||||
query = query.inner_join(sales_team).on(sales_team.parent == parent_doc.name)
|
||||
elif sales_field == "purchase_person":
|
||||
purchase_team = frappe.qb.DocType("Purchase Team")
|
||||
stock_qty = child_doc.stock_qty * purchase_team.allocated_percentage / 100
|
||||
net_amount = child_doc.base_net_amount * purchase_team.allocated_percentage / 100
|
||||
sales_field_col = purchase_team[sales_field]
|
||||
|
||||
query = query.inner_join(purchase_team).on(purchase_team.parent == parent_doc.name)
|
||||
else:
|
||||
stock_qty = child_doc.stock_qty
|
||||
net_amount = child_doc.base_net_amount
|
||||
|
||||
Reference in New Issue
Block a user