def create_file(self, results: typing.Iterable, engine: Engine) -> HttpResponse: column_headers: (typing.List[str], typing.List[str]) = self.get_column_headers( engine, False) column_header_names = column_headers[0] first_row, results = peek(self.preprocess_rows(results, False)) response = HttpResponse(content_type="text/csv") filename = f'{self.slug}-report-{today_date().strftime("%Y-%m-%d")}.csv' response["Content-Disposition"] = f'attachment; filename="{filename}"' response.write("\ufeff".encode("utf8")) writer = csv.writer(response, delimiter=settings.EXPENSES_CSV_DELIMITER) writer.writerow(column_header_names) for row in results: writer.writerow(row) if not results: return no_results_to_show() if len(column_header_names) != len(first_row): raise ValueError("Results do not match expected column headers") return response
def tabulate(self, results: typing.Iterable, engine: Engine) -> SafeString: column_headers: (typing.List[str], typing.List[str]) = self.get_column_headers(engine) column_header_names, column_alignment = column_headers column_headers_with_alignment = zip(*column_headers) first_row, results = peek(self.preprocess_rows(results)) if not results: return no_results_to_show() if len(column_header_names) != len(first_row): raise ValueError("Results do not match expected column headers") results_with_alignment = (zip(row, column_alignment) for row in results) return mark_safe( render_to_string( "expenses/reports/report_basic_table.html", { "results_with_alignment": results_with_alignment, "column_headers_with_alignment": column_headers_with_alignment, }, self.request, ))
def tabulate(self, results: typing.Iterable, engine: Engine) -> SafeString: column_headers: (typing.List[str], typing.List[str]) = self.get_column_headers(engine) column_header_names, column_alignment = column_headers column_headers_with_alignment = list(zip(*column_headers)) if not results: return no_results_to_show() main_groups = {(row[0], row[1]) for row in results} vendor_groups = {row[0] for row in main_groups} product_groups = {row[1] for row in main_groups} partition_product = self.settings.get(self.options[0][2], False) partition_vendor = self.settings.get(self.options[0][3], False) if partition_vendor and partition_product and len(vendor_groups) > 1 and len(product_groups) > 1: group_title = _("{1} — {0}") elif partition_vendor and len(vendor_groups) > 1: group_title = _("{0}") elif partition_product and len(product_groups) > 1: group_title = _("{1}") else: group_title = "" if partition_vendor and partition_product: grouper = lambda row: (row[0], row[1]) elif partition_vendor: grouper = lambda row: row[0] elif partition_product: grouper = lambda row: row[1] else: grouper = lambda row: True first_row, results = peek(results) if len(column_header_names) != len(first_row): raise ValueError("Results do not match expected column headers") current_group = None results_grouped = [] for row in results: group = grouper(row) row = list(row) if group != current_group: results_grouped.append({"title": group_title.format(*row), "rows": []}) current_group = group results_grouped[-1]["rows"].append({k: v for k, v in zip(self.column_names, row)}) return mark_safe( render_to_string( "expenses/reports/report_product_price_history.html", { "results_grouped": results_grouped, "column_headers_with_alignment": column_headers_with_alignment, "show_group_title": bool(group_title), }, self.request, ) )