| # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors |
| # License: GNU General Public License v3. See license.txt |
| |
| from __future__ import unicode_literals |
| import frappe |
| from frappe.utils import getdate |
| from frappe import _ |
| |
| 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 exists").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 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'" |
| |
| year_start_date, year_end_date = frappe.db.get_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.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' |
| 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.qty), SUM(t2.base_net_amount)," |
| |
| query_details += 'SUM(t2.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.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.db.get_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 xrange(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.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 Type:Link/Supplier Type:140"] |
| based_on_details["based_on_select"] = "t1.supplier, t3.supplier_type," |
| 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 Type': |
| based_on_details["based_on_cols"] = ["Supplier Type:Link/Supplier Type:140"] |
| based_on_details["based_on_select"] = "t3.supplier_type," |
| based_on_details["based_on_group_by"] = 't3.supplier_type' |
| 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 [] |