Skip to content

Commit 1b0251a

Browse files
committed
Implementation
1 parent cd9a372 commit 1b0251a

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Changelog
88
alphabetically after the current form fields.
99
[folix-01]
1010

11+
- Add current form columns to CSV export event if field are empty.
12+
[folix-01]
13+
1114

1215
3.2.1 (2025-01-09)
1316
------------------

src/collective/volto/formsupport/restapi/services/form_data/csv.py

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from plone.restapi.serializer.converters import json_compatible
44
from plone.restapi.services import Service
55
from zope.component import getMultiAdapter
6+
from collective.volto.formsupport.utils import get_blocks
7+
from copy import deepcopy
68

79
import csv
810

@@ -23,12 +25,37 @@ def __init__(self, context, request):
2325
block_type = block.get("@type", "")
2426
if block_type == "form":
2527
self.form_block = block
28+
self.form_block_id = id
2629

2730
if self.form_block:
2831
for field in self.form_block.get("subblocks", []):
2932
field_id = field["field_id"]
3033
self.form_fields_order.append(field_id)
3134

35+
def get_form_fields(self):
36+
blocks = get_blocks(self.context)
37+
38+
if not blocks:
39+
return {}
40+
form_block = {}
41+
for id, block in blocks.items():
42+
if id != self.form_block_id:
43+
continue
44+
block_type = block.get("@type", "")
45+
if block_type == "form":
46+
form_block = deepcopy(block)
47+
if not form_block:
48+
return {}
49+
50+
subblocks = form_block.get("subblocks", [])
51+
52+
# Add the 'custom_field_id' field back in as this isn't stored with each subblock
53+
for index, field in enumerate(subblocks):
54+
if form_block.get(field["field_id"]):
55+
subblocks[index]["custom_field_id"] = form_block.get(field["field_id"])
56+
57+
return subblocks
58+
3259
def get_ordered_keys(self, record):
3360
"""
3461
We need this method because we want to maintain the fields order set in the form.
@@ -61,8 +88,12 @@ def render(self):
6188
data = data.encode("utf-8")
6289
self.request.response.write(data)
6390

64-
def get_fields_labels(self, item):
65-
return item.attrs.get("fields_labels", {})
91+
def get_fields_labels(self):
92+
return {
93+
x["field_id"]: x.get("custom_field_id", x.get("label", x["field_id"]))
94+
for x in self.get_form_fields()
95+
if x.get("field_type", "") != "static_text"
96+
}
6697

6798
def get_data(self):
6899
store = getMultiAdapter((self.context, self.request), IFormDataStore)
@@ -71,24 +102,23 @@ def get_data(self):
71102
columns = []
72103
legacy_columns = []
73104
rows = []
105+
fields_labels = self.get_fields_labels()
74106

75107
for item in store.search():
76108
data = {}
77-
fields_labels = self.get_fields_labels(item)
78109

79110
for k in self.get_ordered_keys(item):
80111
if k in SKIP_ATTRS:
81112
continue
82113

83114
value = item.attrs.get(k, None)
84-
label = fields_labels.get(k, k)
115+
label = {**item.attrs.get("fields_labels", {}), **fields_labels}.get(
116+
k, k
117+
)
85118

86-
if k not in self.form_fields_order:
119+
if k not in self.form_fields_order and label not in legacy_columns:
87120
legacy_columns.append(label)
88121

89-
elif label not in columns and label not in fixed_columns:
90-
columns.append(label)
91-
92122
data[label] = json_compatible(value)
93123

94124
for k in fixed_columns:
@@ -98,8 +128,10 @@ def get_data(self):
98128

99129
rows.append(data)
100130

131+
columns.extend(fields_labels.values())
101132
columns.extend(fixed_columns)
102133
columns.extend(sorted(legacy_columns))
134+
103135
writer = csv.DictWriter(sbuf, fieldnames=columns, quoting=csv.QUOTE_ALL)
104136
writer.writeheader()
105137

0 commit comments

Comments
 (0)