Merge pull request #23512 from GursheenK/include-filter-values-in-exported-report-excel
This commit is contained in:
commit
2564d0e939
4 changed files with 101 additions and 25 deletions
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue