Merge pull request #23512 from GursheenK/include-filter-values-in-exported-report-excel

This commit is contained in:
Suraj Shetty 2023-12-18 12:40:37 +05:30 committed by GitHub
commit 2564d0e939
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 25 deletions

View file

@ -318,6 +318,7 @@ def export_query():
file_format_type = form_params.file_format_type
custom_columns = frappe.parse_json(form_params.custom_columns or "[]")
include_indentation = form_params.include_indentation
include_filters = form_params.include_filters
visible_idx = form_params.visible_idx
if isinstance(visible_idx, str):
@ -327,6 +328,8 @@ def export_query():
report_name, form_params.filters, custom_columns=custom_columns, are_default_filters=False
)
data = frappe._dict(data)
data.filters = form_params.applied_filters
if not data.columns:
frappe.respond_as_web_page(
_("No data to export"),
@ -335,7 +338,9 @@ def export_query():
return
format_duration_fields(data)
xlsx_data, column_widths = build_xlsx_data(data, visible_idx, include_indentation)
xlsx_data, column_widths = build_xlsx_data(
data, visible_idx, include_indentation, include_filters=include_filters
)
if file_format_type == "CSV":
content = get_csv_bytes(xlsx_data, csv_params)
@ -360,7 +365,9 @@ def format_duration_fields(data: frappe._dict) -> None:
row[index] = format_duration(row[index])
def build_xlsx_data(data, visible_idx, include_indentation, ignore_visible_idx=False):
def build_xlsx_data(
data, visible_idx, include_indentation, include_filters=False, ignore_visible_idx=False
):
EXCEL_TYPES = (
str,
bool,
@ -380,17 +387,34 @@ def build_xlsx_data(data, visible_idx, include_indentation, ignore_visible_idx=F
# Note: converted for faster lookups
visible_idx = set(visible_idx)
result = [[]]
result = []
column_widths = []
if cint(include_filters):
filter_data = []
filters = data.filters
for filter_name, filter_value in filters.items():
if not filter_value:
continue
filter_value = (
", ".join([cstr(x) for x in filter_value])
if isinstance(filter_value, list)
else cstr(filter_value)
)
filter_data.append([cstr(filter_name), filter_value])
filter_data.append([])
result += filter_data
column_data = []
for column in data.columns:
if column.get("hidden"):
continue
result[0].append(_(column.get("label")))
column_data.append(_(column.get("label")))
column_width = cint(column.get("width", 0))
# to convert into scale accepted by openpyxl
column_width /= 10
column_widths.append(column_width)
result.append(column_data)
# build table from result
for row_idx, row in enumerate(data.result):

View file

@ -217,6 +217,8 @@ def clean_params(data):
def parse_json(data):
if (filters := data.get("filters")) and isinstance(filters, str):
data["filters"] = json.loads(filters)
if (applied_filters := data.get("applied_filters")) and isinstance(applied_filters, str):
data["applied_filters"] = json.loads(applied_filters)
if (or_filters := data.get("or_filters")) and isinstance(or_filters, str):
data["or_filters"] = json.loads(or_filters)
if (fields := data.get("fields")) and isinstance(fields, str):

View file

@ -1473,21 +1473,34 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
return;
}
let extra_fields = null;
let extra_fields = [];
if (this.tree_report) {
extra_fields = [
{
label: __("Include indentation"),
fieldname: "include_indentation",
fieldtype: "Check",
},
];
extra_fields.push({
label: __("Include indentation"),
fieldname: "include_indentation",
fieldtype: "Check",
});
}
if (this.filters.length > 0) {
extra_fields.push({
label: __("Include filters"),
fieldname: "include_filters",
fieldtype: "Check",
});
}
this.export_dialog = frappe.report_utils.get_export_dialog(
__(this.report_name),
extra_fields,
({ file_format, include_indentation, csv_delimiter, csv_quoting }) => {
({
file_format,
include_indentation,
include_filters,
csv_delimiter,
csv_quoting,
}) => {
this.make_access_log("Export", file_format);
let filters = this.get_filter_values(true);
@ -1497,6 +1510,15 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
filters
);
}
let boolean_labels = { 1: __("Yes"), 0: __("No") };
let applied_filters = Object.fromEntries(
Object.entries(filters).map(([key, value]) => [
frappe.query_report.get_filter(key).df.label,
frappe.query_report.get_filter(key).df.fieldtype == "Check"
? boolean_labels[value]
: value,
])
);
const visible_idx = this.datatable.bodyRenderer.visibleRowIndices;
if (visible_idx.length + 1 === this.data.length) {
@ -1509,10 +1531,12 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
custom_columns: this.custom_columns.length ? this.custom_columns : [],
file_format_type: file_format,
filters: filters,
applied_filters: applied_filters,
visible_idx,
csv_delimiter,
csv_quoting,
include_indentation,
include_filters,
};
open_url_post(frappe.request.url, args);

View file

@ -22,18 +22,7 @@ class TestQueryReport(FrappeTestCase):
"""Test exporting report using rows with multiple datatypes (list, dict)"""
# Create mock data
data = frappe._dict()
data.columns = [
{"label": "Column A", "fieldname": "column_a", "fieldtype": "Float"},
{"label": "Column B", "fieldname": "column_b", "width": 100, "fieldtype": "Float"},
{"label": "Column C", "fieldname": "column_c", "width": 150, "fieldtype": "Duration"},
]
data.result = [
[1.0, 3.0, 600],
{"column_a": 22.1, "column_b": 21.8, "column_c": 86412},
{"column_b": 5.1, "column_c": 53234, "column_a": 11.1},
[3.0, 1.5, 333],
]
data = create_mock_data()
# Define the visible rows
visible_idx = [0, 2, 3]
@ -54,6 +43,27 @@ class TestQueryReport(FrappeTestCase):
for cell in row:
self.assertIsInstance(cell, (int, float))
def test_xlsx_data_with_filters(self):
"""Test building xlsx data along with filters"""
# Create mock data
data = create_mock_data()
data.filters = {"Label 1": "Filter Value", "Label 2": None, "Label 3": list(range(5))}
# Define the visible rows
visible_idx = [0, 2, 3]
# Build the result
xlsx_data, column_widths = build_xlsx_data(
data, visible_idx, include_indentation=False, include_filters=True
)
# Check if unset filters are skipped | Rows - 2 filters + 1 empty + 1 column + 3 data
self.assertEqual(len(xlsx_data), 7)
# Check filter formatting
self.assertListEqual(xlsx_data[:2], [["Label 1", "Filter Value"], ["Label 3", "0, 1, 2, 3, 4"]])
def test_xlsx_export_with_composite_cell_value(self):
"""Test excel export using rows with composite cell value"""
@ -236,3 +246,19 @@ data = columns, result
except Exception as e:
raise e
frappe.db.rollback()
def create_mock_data():
data = frappe._dict()
data.columns = [
{"label": "Column A", "fieldname": "column_a", "fieldtype": "Float"},
{"label": "Column B", "fieldname": "column_b", "width": 100, "fieldtype": "Float"},
{"label": "Column C", "fieldname": "column_c", "width": 150, "fieldtype": "Duration"},
]
data.result = [
[1.0, 3.0, 600],
{"column_a": 22.1, "column_b": 21.8, "column_c": 86412},
{"column_b": 5.1, "column_c": 53234, "column_a": 11.1},
[3.0, 1.5, 333],
]
return data