0001-formdata-move-submission-channel-to-its-own-attribut.patch
tests/test_api.py | ||
---|---|---|
348 | 348 |
assert data_class.get(resp.json['data']['id']).status == 'draft' |
349 | 349 | |
350 | 350 |
resp = get_app(pub).post_json(url, {'meta': {'backoffice-submission': True}, 'data': {}, |
351 |
'context': {'channel': 'mail'} }) |
|
351 |
'context': {'channel': 'mail', 'comments': 'blah'} })
|
|
352 | 352 |
assert data_class.get(resp.json['data']['id']).status == 'wf-new' |
353 | 353 |
assert data_class.get(resp.json['data']['id']).backoffice_submission is True |
354 | 354 |
assert data_class.get(resp.json['data']['id']).user_id is None |
355 |
assert data_class.get(resp.json['data']['id']).submission_context == {'channel': 'mail'} |
|
355 |
assert data_class.get(resp.json['data']['id']).submission_context == {'comments': 'blah'} |
|
356 |
assert data_class.get(resp.json['data']['id']).submission_channel == 'mail' |
|
356 | 357 | |
357 | 358 |
data_class.wipe() |
358 | 359 |
tests/test_backoffice_pages.py | ||
---|---|---|
458 | 458 |
# check there's nothing in the sidebar |
459 | 459 |
assert not 'Channel' in resp.body |
460 | 460 | |
461 |
number31.submission_channel = 'mail' |
|
461 | 462 |
number31.submission_context = { |
462 |
'channel': 'mail', |
|
463 | 463 |
'mail_url': 'http://www.example.com/test.pdf', |
464 | 464 |
'thumbnail_url': 'http://www.example.com/thumbnail.png', |
465 | 465 |
'user_id': user.id, |
... | ... | |
746 | 746 |
resp = app.get('/backoffice/submission/') |
747 | 747 |
assert '%s/%s' % (formdef.url_name, formdata_no) in resp.body |
748 | 748 |
assert '>#%s' % formdata_no in resp.body |
749 |
formdata.submission_context = {'channel': 'mail'}
|
|
749 |
formdata.submission_channel = 'mail'
|
|
750 | 750 |
formdata.store() |
751 | 751 |
resp = app.get('/backoffice/submission/') |
752 | 752 |
assert '>Mail #%s' % formdata_no in resp.body |
... | ... | |
816 | 816 |
formdata.backoffice_submission = True |
817 | 817 |
formdata.status = 'draft' |
818 | 818 |
formdata.data = {} |
819 |
formdata.submission_context = {'channel': 'mail', 'user_id': other_user.id} |
|
819 |
formdata.submission_channel = 'mail' |
|
820 |
formdata.submission_context = {'user_id': other_user.id} |
|
820 | 821 |
formdata.store() |
821 | 822 | |
822 | 823 |
formdata2 = formdef.data_class()() |
823 | 824 |
formdata2.backoffice_submission = True |
824 | 825 |
formdata2.status = 'draft' |
825 | 826 |
formdata2.data = {} |
826 |
formdata2.submission_context = {'channel': 'mail'} |
|
827 |
formdata.submission_channel = 'mail' |
|
828 |
formdata2.submission_context = {} |
|
827 | 829 |
formdata2.store() |
828 | 830 | |
829 | 831 |
app = login(get_app(pub)) |
tests/test_sql.py | ||
---|---|---|
110 | 110 | |
111 | 111 |
formdata = data_class.get(id) |
112 | 112 |
assert formdata.user_id == '5' |
113 |
assert formdata.status == 'wf-0' |
|
114 | ||
115 |
@postgresql |
|
116 |
def test_sql_store_channel(): |
|
117 |
data_class = formdef.data_class(mode='sql') |
|
118 |
formdata = data_class() |
|
119 |
formdata.status = 'wf-0' |
|
120 |
formdata.user_id = '5' |
|
121 |
formdata.submission_channel = 'mail' |
|
122 |
formdata.store() |
|
123 | ||
124 |
assert data_class.get(formdata.id).submission_channel == 'mail' |
|
125 | ||
126 |
formdata.submission_channel = None |
|
127 |
formdata.store() |
|
128 |
assert data_class.get(formdata.id).submission_channel is None |
|
113 | 129 | |
114 | 130 |
@postgresql |
115 | 131 |
def test_sql_get_missing(): |
... | ... | |
721 | 737 |
conn.commit() |
722 | 738 |
cur.close() |
723 | 739 | |
740 |
def migration_level(cur): |
|
741 |
cur.execute('SELECT value FROM wcs_meta WHERE key = %s', ('sql_level',)) |
|
742 |
row = cur.fetchone() |
|
743 |
return int(row[0]) |
|
744 | ||
724 | 745 |
@postgresql |
725 | 746 |
def test_migration_1_tracking_code(): |
726 | 747 |
conn, cur = sql.get_connection_and_cursor() |
... | ... | |
729 | 750 |
sql.migrate() |
730 | 751 |
assert table_exists(cur, 'tracking_codes') |
731 | 752 |
assert table_exists(cur, 'wcs_meta') |
753 |
assert migration_level(cur) >= 1 |
|
732 | 754 |
conn.commit() |
733 | 755 |
cur.close() |
734 | 756 | |
... | ... | |
770 | 792 |
sql.migrate() |
771 | 793 | |
772 | 794 |
assert column_exists_in_table(cur, 'wcs_all_forms', 'formdef_id') |
795 |
assert migration_level(cur) >= 2 |
|
773 | 796 | |
774 | 797 |
conn.commit() |
775 | 798 |
cur.close() |
... | ... | |
794 | 817 |
assert column_exists_in_table(cur, 'formdata_1_tests', 'actions_roles_array') |
795 | 818 |
assert column_exists_in_table(cur, 'wcs_view_1_tests', 'actions_roles_array') |
796 | 819 |
assert column_exists_in_table(cur, 'wcs_all_forms', 'actions_roles_array') |
820 |
assert migration_level(cur) >= 6 |
|
821 | ||
822 |
conn.commit() |
|
823 |
cur.close() |
|
824 | ||
825 |
@postgresql |
|
826 |
def test_migration_10_submission_channel(): |
|
827 |
conn, cur = sql.get_connection_and_cursor() |
|
828 |
cur.execute('UPDATE wcs_meta SET value = 9 WHERE key = %s', ('sql_level',)) |
|
829 |
cur.execute('DROP VIEW wcs_all_forms') |
|
830 | ||
831 |
# hack a formdef table the wrong way, to check it is reconstructed |
|
832 |
# properly before the views are created |
|
833 |
formdef.fields[4] = fields.StringField(id='4', label='item') |
|
834 |
cur.execute('DROP VIEW wcs_view_1_tests') |
|
835 |
cur.execute('ALTER TABLE formdata_1_tests DROP COLUMN submission_channel') |
|
836 |
sql.drop_views(formdef, conn, cur) |
|
837 |
formdef.fields[4] = fields.ItemField(id='4', label='item', items=('apple', 'pear', 'peach', 'apricot')), |
|
838 |
assert not column_exists_in_table(cur, 'formdata_1_tests', 'submission_channel') |
|
839 | ||
840 |
sql.migrate() |
|
841 | ||
842 |
assert column_exists_in_table(cur, 'formdata_1_tests', 'submission_channel') |
|
843 |
assert column_exists_in_table(cur, 'wcs_view_1_tests', 'submission_channel') |
|
844 |
assert column_exists_in_table(cur, 'wcs_all_forms', 'submission_channel') |
|
845 |
assert migration_level(cur) >= 10 |
|
797 | 846 | |
798 | 847 |
conn.commit() |
799 | 848 |
cur.close() |
... | ... | |
910 | 959 |
# set receipt_time to make sure all entries are unique. |
911 | 960 |
formdata.receipt_time = (now + datetime.timedelta(seconds=cnt)).timetuple() |
912 | 961 |
formdata.status = ['wf-new', 'wf-accepted', 'wf-rejected', 'wf-finished'][(i+j)%4] |
962 |
if j < 5: |
|
963 |
formdata.submission_channel = 'mail' |
|
913 | 964 |
formdata.store() |
914 | 965 |
cnt += 1 |
915 | 966 | |
... | ... | |
936 | 987 |
objects2 = sql.AnyFormData.select([st.Equal('is_at_endpoint', True)]) |
937 | 988 |
assert len(objects2) == len([x for x in objects if x.status in ('wf-rejected', 'wf-finished')]) |
938 | 989 | |
990 |
objects2 = sql.AnyFormData.select([st.Equal('submission_channel', 'mail')]) |
|
991 |
assert len(objects2) == len([x for x in objects if x.submission_channel == 'mail']) |
|
992 | ||
939 | 993 |
# test offset/limit |
940 | 994 |
objects2 = sql.AnyFormData.select(order_by='receipt_time', limit=10, offset=0) |
941 | 995 |
assert [(x.formdef_id, x.id) for x in objects2] == [(x.formdef_id, x.id) for x in objects][:10] |
wcs/api.py | ||
---|---|---|
234 | 234 |
formdata.user_id = user.id |
235 | 235 |
if json_input.get('context'): |
236 | 236 |
formdata.submission_context = json_input['context'] |
237 |
formdata.submission_channel = formdata.submission_context.pop('channel') |
|
237 | 238 |
formdata.store() |
238 | 239 |
if self.formdef.enable_tracking_codes: |
239 | 240 |
code = get_publisher().tracking_code_class() |
wcs/backoffice/management.py | ||
---|---|---|
1291 | 1291 |
formdata = self.filled |
1292 | 1292 | |
1293 | 1293 |
r = TemplateIO(html=True) |
1294 |
if formdata.submission_context: |
|
1294 |
if formdata.submission_context or formdata.submission_channel:
|
|
1295 | 1295 |
extra_context = formdata.submission_context or {} |
1296 | 1296 |
r += htmltext('<div class="extra-context">') |
1297 |
if extra_context.get('channel'): |
|
1298 |
channel_labels = { |
|
1299 |
'mail': _('Mail'), |
|
1300 |
} |
|
1297 |
if formdata.submission_channel: |
|
1301 | 1298 |
r += htmltext('<h3>%s</h3>') % '%s: %s' % ( |
1302 |
_('Channel'), channel_labels.get(extra_context.get('channel'), '?'))
|
|
1299 |
_('Channel'), formdata.get_submission_channel_label())
|
|
1303 | 1300 |
if extra_context.get('thumbnail_url'): |
1304 | 1301 |
r += htmltext('<p class="thumbnail"><img src="%s" alt=""/></p>' |
1305 | 1302 |
) % extra_context.get('thumbnail_url') |
wcs/backoffice/submission.py | ||
---|---|---|
206 | 206 |
for formdata in formdatas: |
207 | 207 |
r += htmltext('<li class="smallitem">') |
208 | 208 |
label = '' |
209 |
if formdata.submission_context and formdata.submission_context.get('channel'): |
|
210 |
label = { |
|
211 |
'mail': _('Mail'), |
|
212 |
}.get(formdata.submission_context['channel']) or '' |
|
213 |
if label: |
|
214 |
label += ' ' |
|
209 |
if formdata.submission_channel: |
|
210 |
label = '%s ' % formdata.get_submission_channel_label() |
|
215 | 211 |
label += _('#%s, %s') % (formdata.id, |
216 | 212 |
misc.localstrftime(formdata.receipt_time)) |
217 | 213 |
r += htmltext('<a href="%s/%s">%s</a>') % ( |
wcs/formdata.py | ||
---|---|---|
162 | 162 |
tracking_code = None |
163 | 163 |
backoffice_submission = False |
164 | 164 |
submission_context = None |
165 |
submission_channel = None |
|
165 | 166 | |
166 | 167 |
workflow_data = None |
167 | 168 |
workflow_roles = None |
... | ... | |
228 | 229 |
empty &= (self.data.get(key) is None) |
229 | 230 |
return empty |
230 | 231 | |
232 |
def get_submission_channel_label(self): |
|
233 |
channel_labels = { |
|
234 |
'mail': _('Mail'), |
|
235 |
} |
|
236 |
return channel_labels.get(self.submission_channel, _('Unknown')) |
|
237 | ||
231 | 238 |
def just_created(self): |
232 | 239 |
self.receipt_time = time.localtime() |
233 | 240 |
self.status = 'wf-%s' % self.formdef.workflow.possible_status[0].id |
wcs/sql.py | ||
---|---|---|
309 | 309 |
'anonymised', 'workflow_roles', 'workflow_roles_array', |
310 | 310 |
'concerned_roles_array', 'tracking_code', |
311 | 311 |
'actions_roles_array', 'backoffice_submission', |
312 |
'submission_context']) |
|
312 |
'submission_context', 'submission_channel'])
|
|
313 | 313 | |
314 | 314 |
# migrations |
315 | 315 |
if not 'fts' in existing_fields: |
... | ... | |
341 | 341 |
if not 'submission_context' in existing_fields: |
342 | 342 |
cur.execute('''ALTER TABLE %s ADD COLUMN submission_context bytea''' % table_name) |
343 | 343 | |
344 |
if not 'submission_channel' in existing_fields: |
|
345 |
cur.execute('''ALTER TABLE %s ADD COLUMN submission_channel varchar''' % table_name) |
|
346 | ||
344 | 347 |
# add new fields |
345 | 348 |
for field in formdef.fields: |
346 | 349 |
assert field.id is not None |
... | ... | |
538 | 541 |
view_fields = [] |
539 | 542 |
view_fields.append(("int '%s'" % (formdef.category_id or 0), 'category_id')) |
540 | 543 |
view_fields.append(("int '%s'" % (formdef.id or 0), 'formdef_id')) |
541 |
for field in ('id', 'user_id', 'user_hash', 'receipt_time', 'status', 'id_display'): |
|
544 |
for field in ('id', 'user_id', 'user_hash', 'receipt_time', 'status', |
|
545 |
'id_display', 'submission_channel'): |
|
542 | 546 |
view_fields.append((field, field)) |
543 | 547 |
return view_fields |
544 | 548 | |
... | ... | |
938 | 942 |
('tracking_code', 'varchar'), |
939 | 943 |
('backoffice_submission', 'boolean'), |
940 | 944 |
('submission_context', 'bytea'), |
945 |
('submission_channel', 'varchar'), |
|
941 | 946 |
] |
942 | 947 | |
943 | 948 |
def __init__(self, id=None): |
... | ... | |
1031 | 1036 |
'tracking_code': self.tracking_code, |
1032 | 1037 |
'backoffice_submission': self.backoffice_submission, |
1033 | 1038 |
'submission_context': self.submission_context, |
1039 |
'submission_channel': self.submission_channel, |
|
1034 | 1040 |
} |
1035 | 1041 |
if self.receipt_time: |
1036 | 1042 |
sql_dict['receipt_time'] = datetime.datetime.fromtimestamp(time.mktime(self.receipt_time)), |
... | ... | |
1679 | 1685 |
return result |
1680 | 1686 | |
1681 | 1687 | |
1682 |
SQL_LEVEL = 8
|
|
1688 |
SQL_LEVEL = 10
|
|
1683 | 1689 | |
1684 | 1690 |
def migrate_global_views(conn, cur): |
1685 | 1691 |
cur.execute('''SELECT COUNT(*) FROM information_schema.tables |
... | ... | |
1728 | 1734 |
migrate_views(conn, cur) |
1729 | 1735 |
for formdef in FormDef.select(): |
1730 | 1736 |
formdef.data_class().rebuild_security() |
1731 |
if sql_level < 9:
|
|
1737 |
if sql_level < 10:
|
|
1732 | 1738 |
# 7: add backoffice_submission to tables and views |
1733 | 1739 |
# 8: add submission_context to tables |
1734 | 1740 |
# 9: add last_update_time to views |
1741 |
# 10: add submission_channel to tables |
|
1735 | 1742 |
migrate_views(conn, cur) |
1736 | 1743 | |
1737 | 1744 |
cur.execute('''UPDATE wcs_meta SET value = %s WHERE key = %s''', ( |
1738 |
- |