backoffice: sort by criticality and receipt_time (#76644) #537

Merged
lguerin merged 1 commits from wip/76644-sort-by-priority into main 2023-08-11 09:58:10 +02:00
3 changed files with 60 additions and 42 deletions

View File

@ -137,38 +137,35 @@ def test_backoffice_criticality_in_formdef_listing_order(pub):
data_class = formdef.data_class()
data_class.wipe()
for i in range(0, 4):
for i in range(0, 10):
formdata = data_class()
formdata.data = {}
formdata.just_created()
formdata.jump_status('new')
formdata.receipt_time = datetime.datetime(2015, 1, 1, 10, i).timetuple()
if i < 8:
if i % 3 == 0:
formdata.set_criticality_level(1)
if i % 3 == 1:
formdata.set_criticality_level(2)
if i % 3 == 2:
formdata.set_criticality_level(3)
formdata.store()
formdata1, formdata2, formdata3, formdata4 = [
x for x in formdef.data_class().select() if x.status == 'wf-new'
][:4]
formdata1.set_criticality_level(1)
formdata1.store()
formdata1_str = '>%s<' % formdata1.get_display_id()
formdata2.set_criticality_level(2)
formdata2.store()
formdata2_str = '>%s<' % formdata2.get_display_id()
formdata3.set_criticality_level(2)
formdata3.store()
formdata3_str = '>%s<' % formdata3.get_display_id()
formdata4_str = '>%s<' % formdata4.get_display_id()
app = login(get_app(pub))
resp = app.get('/backoffice/management/form-title/?order_by=-criticality_level&limit=100')
assert resp.text.index(formdata1_str) > resp.text.index(formdata2_str)
assert resp.text.index(formdata1_str) > resp.text.index(formdata3_str)
assert resp.text.index(formdata1_str) < resp.text.index(formdata4_str)
order = [8, 6, 5, 3, 2, 7, 4, 1, 10, 9]
for i, o in enumerate(order):
if i == 9:
break
assert resp.text.index('>1-%s<' % o) < resp.text.index('>1-%s<' % order[i + 1])
resp = app.get('/backoffice/management/form-title/?order_by=criticality_level&limit=100')
assert resp.text.index(formdata1_str) < resp.text.index(formdata2_str)
assert resp.text.index(formdata1_str) < resp.text.index(formdata3_str)
assert resp.text.index(formdata1_str) > resp.text.index(formdata4_str)
reversed_order = list(reversed(order))
for i, o in enumerate(reversed_order):
if i == 9:
break
assert resp.text.index('>1-%s<' % o) < resp.text.index('>1-%s<' % reversed_order[i + 1])
def test_backoffice_criticality_in_global_listing_order(pub):

View File

@ -361,7 +361,12 @@ class FormDef(StorableObject):
elif field.store_display_value:
order_by += "_display"
break
return '%s%s' % (direction, order_by)
order_by = '%s%s' % (direction, order_by)
if order_by == 'criticality_level':
order_by = [order_by, 'receipt_time']
elif order_by == '-criticality_level':
order_by = [order_by, '-receipt_time']
return order_by
def has_admin_access(self, user):
# return True if user 1/ is global administrator for this type of object, or

View File

@ -1855,28 +1855,44 @@ class SqlMixin:
def get_order_by_clause(cls, order_by):
if not order_by:
return ''
# [SEC_ORDER] security note: it is not possible to use
# prepared statements for ORDER BY clauses, therefore input
# is controlled beforehand (see misc.get_order_by_or_400).
direction = 'ASC'
if order_by.startswith('-'):
order_by = order_by[1:]
direction = 'DESC'
if '->' in order_by:
# sort on field of block field: f42->'data'->0->>'bf13e4d8a8-fb08-4808-b5ae-02d6247949b9'
parts = order_by.split('->')
order_by = '%s->%s' % (parts[0].replace('-', '_'), '->'.join(parts[1:]))
else:
order_by = order_by.replace('-', '_')
fields = ['formdef_name', 'user_name'] # global view fields
fields.extend([x[0] for x in cls._table_static_fields])
fields.extend(cls.get_data_fields())
if order_by.split('->')[0] not in fields:
# for a sort on field of block field, just check the existence of the block field
def _get_order_by_part(part):
# [SEC_ORDER] security note: it is not possible to use
# prepared statements for ORDER BY clauses, therefore input
# is controlled beforehand (see misc.get_order_by_or_400).
direction = 'ASC'
if part.startswith('-'):
part = part[1:]
direction = 'DESC'
if '->' in part:
# sort on field of block field: f42->'data'->0->>'bf13e4d8a8-fb08-4808-b5ae-02d6247949b9'
parts = part.split('->')
part = '%s->%s' % (parts[0].replace('-', '_'), '->'.join(parts[1:]))
else:
part = part.replace('-', '_')
fields = ['formdef_name', 'user_name'] # global view fields
fields.extend([x[0] for x in cls._table_static_fields])
fields.extend(cls.get_data_fields())
if part.split('->')[0] not in fields:
# for a sort on field of block field, just check the existence of the block field
return None, None
return part, direction
if not isinstance(order_by, list):
order_by = [order_by]
ordering = []
for part in order_by:
order, direction = _get_order_by_part(part)
if order is None:
continue
ordering.append(f'{order} {direction}')
if not ordering:
return ''
return ' ORDER BY %s %s' % (order_by, direction)
return ' ORDER BY %s' % ', '.join(ordering)
@classmethod
@guard_postgres