diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py index f2f1e4cfbaa..42bdf571738 100644 --- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py @@ -197,6 +197,8 @@ def prepare_data( ): details[p_key] += r.get(qty_or_amount_field, 0) details[variance_key] = details.get(p_key) - details.get(target_key) + else: + details[variance_key] = details.get(p_key) - details.get(target_key) details["total_achieved"] += details.get(p_key) details["total_variance"] = details.get("total_achieved") - details.get("total_target") @@ -209,31 +211,32 @@ def get_actual_data(filters, sales_users_or_territory_data, date_field, sales_fi parent_doc = frappe.qb.DocType(filters.get("doctype")) child_doc = frappe.qb.DocType(filters.get("doctype") + " Item") - sales_team = frappe.qb.DocType("Sales Team") - query = ( - frappe.qb.from_(parent_doc) - .inner_join(child_doc) - .on(child_doc.parent == parent_doc.name) - .inner_join(sales_team) - .on(sales_team.parent == parent_doc.name) - .select( - child_doc.item_group, - (child_doc.stock_qty * sales_team.allocated_percentage / 100).as_("stock_qty"), - (child_doc.base_net_amount * sales_team.allocated_percentage / 100).as_("base_net_amount"), - sales_team.sales_person, - parent_doc[date_field], - ) - .where( - (parent_doc.docstatus == 1) - & (parent_doc[date_field].between(fiscal_year.year_start_date, fiscal_year.year_end_date)) - ) - ) + query = frappe.qb.from_(parent_doc).inner_join(child_doc).on(child_doc.parent == parent_doc.name) if sales_field == "sales_person": - query = query.where(sales_team.sales_person.isin(sales_users_or_territory_data)) + sales_team = frappe.qb.DocType("Sales Team") + stock_qty = child_doc.stock_qty * sales_team.allocated_percentage / 100 + net_amount = child_doc.base_net_amount * sales_team.allocated_percentage / 100 + sales_field_col = sales_team[sales_field] + + query = query.inner_join(sales_team).on(sales_team.parent == parent_doc.name) else: - query = query.where(parent_doc[sales_field].isin(sales_users_or_territory_data)) + stock_qty = child_doc.stock_qty + net_amount = child_doc.base_net_amount + sales_field_col = parent_doc[sales_field] + + query = query.select( + child_doc.item_group, + parent_doc[date_field], + (stock_qty).as_("stock_qty"), + (net_amount).as_("base_net_amount"), + sales_field_col, + ).where( + (parent_doc.docstatus == 1) + & (parent_doc[date_field].between(fiscal_year.year_start_date, fiscal_year.year_end_date)) + & (sales_field_col.isin(sales_users_or_territory_data)) + ) return query.run(as_dict=True) diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/test_sales_partner_target_variance_based_on_item_group.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/test_sales_partner_target_variance_based_on_item_group.py new file mode 100644 index 00000000000..17186687d97 --- /dev/null +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/test_sales_partner_target_variance_based_on_item_group.py @@ -0,0 +1,57 @@ +import frappe +from frappe.tests.utils import FrappeTestCase +from frappe.utils import flt, nowdate + +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.utils import get_fiscal_year +from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.sales_partner_target_variance_based_on_item_group import ( + execute, +) +from erpnext.selling.report.sales_person_target_variance_based_on_item_group.test_sales_person_target_variance_based_on_item_group import ( + create_sales_target_doc, + create_target_distribution, +) + + +class TestSalesPartnerTargetVarianceBasedOnItemGroup(FrappeTestCase): + def setUp(self): + self.fiscal_year = get_fiscal_year(nowdate())[0] + + def tearDown(self): + frappe.db.rollback() + + def test_achieved_target_and_variance_for_partner(self): + # Create a Target Distribution + distribution = create_target_distribution(self.fiscal_year) + + # Create Sales Partner with targets for the current fiscal year + sales_partner = create_sales_target_doc( + "Sales Partner", "partner_name", "Sales Partner 1", self.fiscal_year, distribution.name + ) + + # Create a Sales Invoice for the Partner + si = create_sales_invoice( + rate=1000, + qty=20, + do_not_submit=True, + ) + si.sales_partner = sales_partner + si.commission_rate = 5 + si.submit() + + # Check Achieved Target and Variance for the Sales Partner + result = execute( + frappe._dict( + { + "fiscal_year": self.fiscal_year, + "doctype": "Sales Invoice", + "period": "Yearly", + "target_on": "Quantity", + } + ) + )[1] + row = frappe._dict(result[0]) + self.assertSequenceEqual( + [flt(value, 2) for value in (row.total_target, row.total_achieved, row.total_variance)], + [50, 20, -30], + ) diff --git a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/test_sales_person_target_variance_based_on_item_group.py b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/test_sales_person_target_variance_based_on_item_group.py index 4ae5d2bee88..73ae6d0c852 100644 --- a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/test_sales_person_target_variance_based_on_item_group.py +++ b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/test_sales_person_target_variance_based_on_item_group.py @@ -18,17 +18,17 @@ class TestSalesPersonTargetVarianceBasedOnItemGroup(FrappeTestCase): def test_achieved_target_and_variance(self): # Create a Target Distribution - distribution = frappe.new_doc("Monthly Distribution") - distribution.distribution_id = "Target Report Distribution" - distribution.fiscal_year = self.fiscal_year - distribution.get_months() - distribution.insert() + distribution = create_target_distribution(self.fiscal_year) - # Create sales people with targets - person_1 = create_sales_person_with_target("Sales Person 1", self.fiscal_year, distribution.name) - person_2 = create_sales_person_with_target("Sales Person 2", self.fiscal_year, distribution.name) + # Create sales people with targets for the current fiscal year + person_1 = create_sales_target_doc( + "Sales Person", "sales_person_name", "Sales Person 1", self.fiscal_year, distribution.name + ) + person_2 = create_sales_target_doc( + "Sales Person", "sales_person_name", "Sales Person 2", self.fiscal_year, distribution.name + ) - # Create a Sales Order with 50-50 contribution + # Create a Sales Order with 50-50 contribution between both Sales people so = make_sales_order( rate=1000, qty=20, @@ -69,10 +69,20 @@ class TestSalesPersonTargetVarianceBasedOnItemGroup(FrappeTestCase): ) -def create_sales_person_with_target(sales_person_name, fiscal_year, distribution_id): - sales_person = frappe.new_doc("Sales Person") - sales_person.sales_person_name = sales_person_name - sales_person.append( +def create_target_distribution(fiscal_year): + distribution = frappe.new_doc("Monthly Distribution") + distribution.distribution_id = "Target Report Distribution" + distribution.fiscal_year = fiscal_year + distribution.get_months() + return distribution.insert() + + +def create_sales_target_doc( + sales_field_dt, sales_field_name, sales_field_value, fiscal_year, distribution_id +): + sales_target_doc = frappe.new_doc(sales_field_dt) + sales_target_doc.set(sales_field_name, sales_field_value) + sales_target_doc.append( "targets", { "fiscal_year": fiscal_year, @@ -81,4 +91,6 @@ def create_sales_person_with_target(sales_person_name, fiscal_year, distribution "distribution_id": distribution_id, }, ) - return sales_person.insert() + if sales_field_dt == "Sales Partner": + sales_target_doc.commission_rate = 5 + return sales_target_doc.insert()