async def orders_by_employee(query_fn, options): errors = {} if options["date"]["from"] == '' or options["date"]["to"] == '': errors["date"] = "Please enter order date range." if "category" not in options: errors["category"] = "Please choose at least one product category." if len(errors) > 0: return {'status': 'error', 'errors': errors} query = """\ SELECT CONCAT(E.FirstName, ' ', E.LastName) AS name, O.OrderID, O.OrderDate, C.CustomerName, inter.value FROM Employees AS E INNER JOIN Orders AS O ON E.EmployeeID = O.EmployeeID LEFT JOIN Customers AS C on O.CustomerID = C.CustomerID INNER JOIN ( SELECT OD.OrderID, SUM(OD.Quantity * P.Price) AS value FROM OrderDetails AS OD LEFT JOIN Products AS P ON OD.ProductID = P.ProductID WHERE P.CategoryID IN ({}) GROUP BY OD.OrderID ) AS inter ON O.OrderID = inter.OrderID WHERE O.OrderDate BETWEEN %s AND %s;""".format(",".join(['%s'] * len(options["category"]))) rows = await query_fn(query, [*options["category"].keys(), options["date"]["from"], options["date"]["to"]]) results = [] for row in rows: row = list(row) row[2] = row[2].date().strftime('%Y-%m-%d') results.append(row) return {'status': 'ok', 'rows': results, 'period': f'{options["date"]["from"]} - {options["date"]["to"]}'} async def orders_by_location(query_fn, options): errors = {} if "location" not in options: errors["location"] = "Please choose how to group locations." if options["date"]["from"] == '' or options["date"]["to"] == '': errors["date"] = "Please enter order date range." if "category" not in options: errors["category"] = "Please choose at least one product category." if len(errors) > 0: return {'status': 'error', 'errors': errors} location_query = { 'city': "CONCAT(C.country, ' - ', C.city)", 'country': "C.country" } query = """\ SELECT {}, C.CustomerName, O.OrderID, O.OrderDate, inter.value FROM Orders AS O LEFT JOIN Customers AS C ON O.CustomerID = C.CustomerID INNER JOIN ( SELECT OD.OrderID, SUM(OD.quantity * P.Price) AS value FROM OrderDetails AS OD LEFT JOIN Products AS P ON OD.ProductID = P.ProductID WHERE P.CategoryID IN ({}) GROUP BY OD.OrderID ) AS inter ON O.OrderID = inter.OrderID WHERE O.OrderDate BETWEEN %s AND %s;\ """.format(location_query[options["location"]], ",".join(['%s'] * len(options["category"]))) rows = await query_fn(query, [*options["category"].keys(), options["date"]["from"], options["date"]["to"]]) results = [] for row in rows: row = list(row) row[3] = row[3].date().strftime('%Y-%m-%d') results.append(row) return {'status': 'ok', 'rows': results, 'period': f'{options["date"]["from"]} - {options["date"]["to"]}'} async def orders_by_product(query_fn, options): errors = {} if options["date"]["from"] == '' or options["date"]["to"] == '': errors["date"] = "Please enter order date range." if "category" not in options: errors["category"] = "Please choose at least one product category." if len(errors) > 0: return {'status': 'error', 'errors': errors} query = """\ SELECT P.ProductName, C.CustomerName, O.OrderID, O.OrderDate, OD.Quantity, OD.Quantity * P.Price AS value FROM OrderDetails AS OD LEFT JOIN Orders AS O ON OD.OrderID = O.OrderID LEFT JOIN Products AS P ON OD.ProductID = P.ProductID LEFT JOIN Customers AS C ON O.CustomerID = C.CustomerID WHERE P.CategoryID IN ({}) AND O.OrderDate BETWEEN %s AND %s;\ """.format(",".join(['%s'] * len(options["category"]))) rows = await query_fn(query, [*options["category"].keys(), options["date"]["from"], options["date"]["to"]]) results = [] for row in rows: row = list(row) row[3] = row[3].date().strftime('%Y-%m-%d') results.append(row) return {'status': 'ok', 'rows': results, 'period': f'{options["date"]["from"]} - {options["date"]["to"]}'} async def orders_by_supplier(query_fn, options): errors = {} if options["date"]["from"] == '' or options["date"]["to"] == '': errors["date"] = "Please enter order date range." if "category" not in options: errors["category"] = "Please choose at least one product category." if len(errors) > 0: return {'status': 'error', 'errors': errors} query = """\ SELECT S.suppliername, P.ProductName, C.CustomerName, O.OrderID, O.OrderDate, OD.Quantity, OD.Quantity * P.Price AS value FROM OrderDetails AS OD LEFT JOIN Orders AS O ON OD.OrderID = O.OrderID LEFT JOIN Products AS P ON OD.ProductID = P.ProductID LEFT JOIN Customers AS C ON O.CustomerID = C.CustomerID LEFT JOIN Suppliers AS S ON P.SupplierID = S.SupplierID WHERE P.CategoryID IN ({}) AND O.OrderDate BETWEEN %s AND %s;\ """.format(",".join(['%s'] * len(options["category"]))) rows = await query_fn(query, [*options["category"].keys(), options["date"]["from"], options["date"]["to"]]) results = [] for row in rows: row = list(row) row[4] = row[4].date().strftime('%Y-%m-%d') results.append(row) return {'status': 'ok', 'rows': results, 'period': f'{options["date"]["from"]} - {options["date"]["to"]}'} async def pivot_table(query_fn, options): errors = {} valid_rows = set(['month', 'year', 'employee', 'shipper', 'customer', 'supplier', 'category', 'product']) valid_columns = set(['month', 'year', 'employee', 'shipper', 'category']) valid_values = set(['sales', 'qty']) if options["date"]["from"] == '' or options["date"]["to"] == '': errors["date"] = "Please enter order date range." if "category" not in options: errors["category"] = "Please choose at least one product category." if options["rows"] not in valid_rows: errors["rows"] = "Please choose the data to display as rows." if options["columns"] not in valid_columns: options["columns"] = "none" if options["rows"] == options["columns"]: errors["columns"] = "Columns and Rows should be different." if options["values"] not in valid_values: errors["values"] = "Value selection invalid." if len(errors) > 0: return {'status': 'error', 'errors': errors} # SELECT, GROUP BY, JOIN parts = { 'none' : ("", "", ""), 'month' : ("CONCAT(YEAR(O.OrderDate), '-', LPAD(MONTH(O.OrderDate), 2, '0')) AS month", "month", ""), 'year' : ("YEAR(O.OrderDate) AS year", "year", ""), 'employee': ("CONCAT(E.FirstName, ' ', E.LastName) AS employeename", "employeename", "LEFT JOIN Employees AS E ON O.EmployeeID = E.EmployeeID"), 'shipper' : ("SH.ShipperName", "SH.ShipperName", "LEFT JOIN Shippers AS SH ON O.ShipperID = SH.ShipperID"), 'customer': ("C.CustomerName", "C.CustomerName", "LEFT JOIN Customers AS C ON O.CustomerID = C.CustomerID"), 'supplier': ("S.SupplierName", "S.SupplierName", "LEFT JOIN Suppliers AS S ON P.SupplierID = S.SupplierID"), 'category': ("CA.CategoryName", "CA.CategoryName", "LEFT JOIN Categories AS CA ON P.CategoryID = CA.CategoryID"), 'product' : ("P.ProductName", "P.ProductName", "") } values = { 'sales' : 'SUM(OD.Quantity * P.Price)', 'qty' : 'SUM(OD.Quantity)' } query = """ SELECT {rows} {columns} {values} FROM OrderDetails AS OD LEFT JOIN Orders AS O ON OD.OrderID = O.OrderID LEFT JOIN Products AS P ON OD.ProductID = P.ProductID {joins} WHERE P.CategoryID IN ({categories}) AND O.OrderDate BETWEEN %s AND %s GROUP BY {grouprows}{groupcols} """.format( rows=f"{parts[options['rows']][0]},", columns=f"{parts[options['columns']][0]}," if options["columns"] != 'none' else '', values=f"{values[options['values']]}", joins=f"{parts[options['rows']][2]} {parts[options['columns']][2]}", categories=",".join(['%s'] * len(options["category"])), grouprows=parts[options['rows']][1], groupcols=', '+parts[options['columns']][1] if options["columns"] != 'none' else '' ) rows = await query_fn(query, [*options["category"].keys(), options["date"]["from"], options["date"]["to"]]) if options["columns"] == 'none': results = [ list(row) for row in rows ] value_lookup = {'sales': 'Order Value', 'qty': 'Item Quantity'} rv = {'status': 'ok', 'rows': results, 'columns': [{'name': options['rows'].capitalize()}, {'name': value_lookup[options["values"]], 'format': '$'}]} return rv else: results = [] intermediate = {} cols = set() for row in rows: if row[0] is None: continue cols.add(row[1]) if row[0] not in intermediate: intermediate[row[0]] = {'Total': 0} assert row[1] not in intermediate[row[0]] intermediate[row[0]][row[1]] = row[2] intermediate[row[0]]['Total'] += row[2] cols = list(sorted(cols)) + ['Total'] for row in sorted(intermediate): values = [row] + [ intermediate[row].get(col, '') for col in cols ] results.append(values) headings = [{'name': options['rows'].capitalize(), 'frozen': True}] + [ {'name': col, 'format': '$'} for col in cols ] headings[-1]['frozen'] = True return {'status': 'ok', 'rows': results, 'columns': headings, 'period': f'{options["date"]["from"]} - {options["date"]["to"]}'}