| # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors |
| # License: GNU General Public License v3. See license.txt |
| |
| |
| import frappe |
| from frappe import _ |
| from frappe.utils import getdate |
| |
| |
| def get_columns(filters, trans): |
| validate_filters(filters) |
| |
| # get conditions for based_on filter cond |
| based_on_details = based_wise_columns_query(filters.get("based_on"), trans) |
| # get conditions for periodic filter cond |
| period_cols, period_select = period_wise_columns_query(filters, trans) |
| # get conditions for grouping filter cond |
| group_by_cols = group_wise_column(filters.get("group_by")) |
| |
| columns = ( |
| based_on_details["based_on_cols"] |
| + period_cols |
| + [_("Total(Qty)") + ":Float:120", _("Total(Amt)") + ":Currency:120"] |
| ) |
| if group_by_cols: |
| columns = ( |
| based_on_details["based_on_cols"] |
| + group_by_cols |
| + period_cols |
| + [_("Total(Qty)") + ":Float:120", _("Total(Amt)") + ":Currency:120"] |
| ) |
| |
| conditions = { |
| "based_on_select": based_on_details["based_on_select"], |
| "period_wise_select": period_select, |
| "columns": columns, |
| "group_by": based_on_details["based_on_group_by"], |
| "grbc": group_by_cols, |
| "trans": trans, |
| "addl_tables": based_on_details["addl_tables"], |
| "addl_tables_relational_cond": based_on_details.get("addl_tables_relational_cond", ""), |
| } |
| |
| return conditions |
| |
| |
| def validate_filters(filters): |
| for f in ["Fiscal Year", "Based On", "Period", "Company"]: |
| if not filters.get(f.lower().replace(" ", "_")): |
| frappe.throw(_("{0} is mandatory").format(f)) |
| |
| if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")): |
| frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year"))) |
| |
| if filters.get("based_on") == filters.get("group_by"): |
| frappe.throw(_("'Based On' and 'Group By' can not be same")) |
| |
| |
| def get_data(filters, conditions): |
| data = [] |
| inc, cond = "", "" |
| query_details = conditions["based_on_select"] + conditions["period_wise_select"] |
| |
| posting_date = "t1.transaction_date" |
| if conditions.get("trans") in [ |
| "Sales Invoice", |
| "Purchase Invoice", |
| "Purchase Receipt", |
| "Delivery Note", |
| ]: |
| posting_date = "t1.posting_date" |
| if filters.period_based_on: |
| posting_date = "t1." + filters.period_based_on |
| |
| if conditions["based_on_select"] in ["t1.project,", "t2.project,"]: |
| cond = " and " + conditions["based_on_select"][:-1] + " IS Not NULL" |
| if conditions.get("trans") in ["Sales Order", "Purchase Order"]: |
| cond += " and t1.status != 'Closed'" |
| |
| if conditions.get("trans") == "Quotation" and filters.get("group_by") == "Customer": |
| cond += " and t1.quotation_to = 'Customer'" |
| |
| year_start_date, year_end_date = frappe.get_cached_value( |
| "Fiscal Year", filters.get("fiscal_year"), ["year_start_date", "year_end_date"] |
| ) |
| |
| if filters.get("group_by"): |
| sel_col = "" |
| ind = conditions["columns"].index(conditions["grbc"][0]) |
| |
| if filters.get("group_by") == "Item": |
| sel_col = "t2.item_code" |
| elif filters.get("group_by") == "Customer": |
| sel_col = "t1.party_name" if conditions.get("trans") == "Quotation" else "t1.customer" |
| elif filters.get("group_by") == "Supplier": |
| sel_col = "t1.supplier" |
| |
| if filters.get("based_on") in ["Item", "Customer", "Supplier"]: |
| inc = 2 |
| else: |
| inc = 1 |
| data1 = frappe.db.sql( |
| """ select %s from `tab%s` t1, `tab%s Item` t2 %s |
| where t2.parent = t1.name and t1.company = %s and %s between %s and %s and |
| t1.docstatus = 1 %s %s |
| group by %s |
| """ |
| % ( |
| query_details, |
| conditions["trans"], |
| conditions["trans"], |
| conditions["addl_tables"], |
| "%s", |
| posting_date, |
| "%s", |
| "%s", |
| conditions.get("addl_tables_relational_cond"), |
| cond, |
| conditions["group_by"], |
| ), |
| (filters.get("company"), year_start_date, year_end_date), |
| as_list=1, |
| ) |
| |
| for d in range(len(data1)): |
| # to add blanck column |
| dt = data1[d] |
| dt.insert(ind, "") |
| data.append(dt) |
| |
| # to get distinct value of col specified by group_by in filter |
| row = frappe.db.sql( |
| """select DISTINCT(%s) from `tab%s` t1, `tab%s Item` t2 %s |
| where t2.parent = t1.name and t1.company = %s and %s between %s and %s |
| and t1.docstatus = 1 and %s = %s %s %s |
| """ |
| % ( |
| sel_col, |
| conditions["trans"], |
| conditions["trans"], |
| conditions["addl_tables"], |
| "%s", |
| posting_date, |
| "%s", |
| "%s", |
| conditions["group_by"], |
| "%s", |
| conditions.get("addl_tables_relational_cond"), |
| cond, |
| ), |
| (filters.get("company"), year_start_date, year_end_date, data1[d][0]), |
| as_list=1, |
| ) |
| |
| for i in range(len(row)): |
| des = ["" for q in range(len(conditions["columns"]))] |
| |
| # get data for group_by filter |
| row1 = frappe.db.sql( |
| """ select %s , %s from `tab%s` t1, `tab%s Item` t2 %s |
| where t2.parent = t1.name and t1.company = %s and %s between %s and %s |
| and t1.docstatus = 1 and %s = %s and %s = %s %s %s |
| """ |
| % ( |
| sel_col, |
| conditions["period_wise_select"], |
| conditions["trans"], |
| conditions["trans"], |
| conditions["addl_tables"], |
| "%s", |
| posting_date, |
| "%s", |
| "%s", |
| sel_col, |
| "%s", |
| conditions["group_by"], |
| "%s", |
| conditions.get("addl_tables_relational_cond"), |
| cond, |
| ), |
| (filters.get("company"), year_start_date, year_end_date, row[i][0], data1[d][0]), |
| as_list=1, |
| ) |
| |
| des[ind] = row[i][0] |
| |
| for j in range(1, len(conditions["columns"]) - inc): |
| des[j + inc] = row1[0][j] |
| |
| data.append(des) |
| else: |
| data = frappe.db.sql( |
| """ select %s from `tab%s` t1, `tab%s Item` t2 %s |
| where t2.parent = t1.name and t1.company = %s and %s between %s and %s and |
| t1.docstatus = 1 %s %s |
| group by %s |
| """ |
| % ( |
| query_details, |
| conditions["trans"], |
| conditions["trans"], |
| conditions["addl_tables"], |
| "%s", |
| posting_date, |
| "%s", |
| "%s", |
| cond, |
| conditions.get("addl_tables_relational_cond", ""), |
| conditions["group_by"], |
| ), |
| (filters.get("company"), year_start_date, year_end_date), |
| as_list=1, |
| ) |
| |
| return data |
| |
| |
| def get_mon(dt): |
| return getdate(dt).strftime("%b") |
| |
| |
| def period_wise_columns_query(filters, trans): |
| query_details = "" |
| pwc = [] |
| bet_dates = get_period_date_ranges(filters.get("period"), filters.get("fiscal_year")) |
| |
| if trans in ["Purchase Receipt", "Delivery Note", "Purchase Invoice", "Sales Invoice"]: |
| trans_date = "posting_date" |
| if filters.period_based_on: |
| trans_date = filters.period_based_on |
| else: |
| trans_date = "transaction_date" |
| |
| if filters.get("period") != "Yearly": |
| for dt in bet_dates: |
| get_period_wise_columns(dt, filters.get("period"), pwc) |
| query_details = get_period_wise_query(dt, trans_date, query_details) |
| else: |
| pwc = [ |
| _(filters.get("fiscal_year")) + " (" + _("Qty") + "):Float:120", |
| _(filters.get("fiscal_year")) + " (" + _("Amt") + "):Currency:120", |
| ] |
| query_details = " SUM(t2.stock_qty), SUM(t2.base_net_amount)," |
| |
| query_details += "SUM(t2.stock_qty), SUM(t2.base_net_amount)" |
| return pwc, query_details |
| |
| |
| def get_period_wise_columns(bet_dates, period, pwc): |
| if period == "Monthly": |
| pwc += [ |
| _(get_mon(bet_dates[0])) + " (" + _("Qty") + "):Float:120", |
| _(get_mon(bet_dates[0])) + " (" + _("Amt") + "):Currency:120", |
| ] |
| else: |
| pwc += [ |
| _(get_mon(bet_dates[0])) + "-" + _(get_mon(bet_dates[1])) + " (" + _("Qty") + "):Float:120", |
| _(get_mon(bet_dates[0])) + "-" + _(get_mon(bet_dates[1])) + " (" + _("Amt") + "):Currency:120", |
| ] |
| |
| |
| def get_period_wise_query(bet_dates, trans_date, query_details): |
| query_details += """SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.stock_qty, NULL)), |
| SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.base_net_amount, NULL)), |
| """ % { |
| "trans_date": trans_date, |
| "sd": bet_dates[0], |
| "ed": bet_dates[1], |
| } |
| return query_details |
| |
| |
| @frappe.whitelist(allow_guest=True) |
| def get_period_date_ranges(period, fiscal_year=None, year_start_date=None): |
| from dateutil.relativedelta import relativedelta |
| |
| if not year_start_date: |
| year_start_date, year_end_date = frappe.get_cached_value( |
| "Fiscal Year", fiscal_year, ["year_start_date", "year_end_date"] |
| ) |
| |
| increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(period) |
| |
| period_date_ranges = [] |
| for i in range(1, 13, increment): |
| period_end_date = getdate(year_start_date) + relativedelta(months=increment, days=-1) |
| if period_end_date > getdate(year_end_date): |
| period_end_date = year_end_date |
| period_date_ranges.append([year_start_date, period_end_date]) |
| year_start_date = period_end_date + relativedelta(days=1) |
| if period_end_date == year_end_date: |
| break |
| |
| return period_date_ranges |
| |
| |
| def get_period_month_ranges(period, fiscal_year): |
| from dateutil.relativedelta import relativedelta |
| |
| period_month_ranges = [] |
| |
| for start_date, end_date in get_period_date_ranges(period, fiscal_year): |
| months_in_this_period = [] |
| while start_date <= end_date: |
| months_in_this_period.append(start_date.strftime("%B")) |
| start_date += relativedelta(months=1) |
| period_month_ranges.append(months_in_this_period) |
| |
| return period_month_ranges |
| |
| |
| def based_wise_columns_query(based_on, trans): |
| based_on_details = {} |
| |
| # based_on_cols, based_on_select, based_on_group_by, addl_tables |
| if based_on == "Item": |
| based_on_details["based_on_cols"] = ["Item:Link/Item:120", "Item Name:Data:120"] |
| based_on_details["based_on_select"] = "t2.item_code, t2.item_name," |
| based_on_details["based_on_group_by"] = "t2.item_code" |
| based_on_details["addl_tables"] = "" |
| |
| elif based_on == "Item Group": |
| based_on_details["based_on_cols"] = ["Item Group:Link/Item Group:120"] |
| based_on_details["based_on_select"] = "t2.item_group," |
| based_on_details["based_on_group_by"] = "t2.item_group" |
| based_on_details["addl_tables"] = "" |
| |
| elif based_on == "Customer": |
| based_on_details["based_on_cols"] = [ |
| "Customer:Link/Customer:120", |
| "Territory:Link/Territory:120", |
| ] |
| based_on_details["based_on_select"] = "t1.customer_name, t1.territory, " |
| based_on_details["based_on_group_by"] = ( |
| "t1.party_name" if trans == "Quotation" else "t1.customer" |
| ) |
| based_on_details["addl_tables"] = "" |
| |
| elif based_on == "Customer Group": |
| based_on_details["based_on_cols"] = ["Customer Group:Link/Customer Group"] |
| based_on_details["based_on_select"] = "t1.customer_group," |
| based_on_details["based_on_group_by"] = "t1.customer_group" |
| based_on_details["addl_tables"] = "" |
| |
| elif based_on == "Supplier": |
| based_on_details["based_on_cols"] = [ |
| "Supplier:Link/Supplier:120", |
| "Supplier Group:Link/Supplier Group:140", |
| ] |
| based_on_details["based_on_select"] = "t1.supplier, t3.supplier_group," |
| based_on_details["based_on_group_by"] = "t1.supplier" |
| based_on_details["addl_tables"] = ",`tabSupplier` t3" |
| based_on_details["addl_tables_relational_cond"] = " and t1.supplier = t3.name" |
| |
| elif based_on == "Supplier Group": |
| based_on_details["based_on_cols"] = ["Supplier Group:Link/Supplier Group:140"] |
| based_on_details["based_on_select"] = "t3.supplier_group," |
| based_on_details["based_on_group_by"] = "t3.supplier_group" |
| based_on_details["addl_tables"] = ",`tabSupplier` t3" |
| based_on_details["addl_tables_relational_cond"] = " and t1.supplier = t3.name" |
| |
| elif based_on == "Territory": |
| based_on_details["based_on_cols"] = ["Territory:Link/Territory:120"] |
| based_on_details["based_on_select"] = "t1.territory," |
| based_on_details["based_on_group_by"] = "t1.territory" |
| based_on_details["addl_tables"] = "" |
| |
| elif based_on == "Project": |
| if trans in ["Sales Invoice", "Delivery Note", "Sales Order"]: |
| based_on_details["based_on_cols"] = ["Project:Link/Project:120"] |
| based_on_details["based_on_select"] = "t1.project," |
| based_on_details["based_on_group_by"] = "t1.project" |
| based_on_details["addl_tables"] = "" |
| elif trans in ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]: |
| based_on_details["based_on_cols"] = ["Project:Link/Project:120"] |
| based_on_details["based_on_select"] = "t2.project," |
| based_on_details["based_on_group_by"] = "t2.project" |
| based_on_details["addl_tables"] = "" |
| else: |
| frappe.throw(_("Project-wise data is not available for Quotation")) |
| |
| return based_on_details |
| |
| |
| def group_wise_column(group_by): |
| if group_by: |
| return [group_by + ":Link/" + group_by + ":120"] |
| else: |
| return [] |