From cb76c96cf1abeb824be535d9df39d29d839caf5d Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Mon, 13 Apr 2020 15:15:45 +0200 Subject: [PATCH] Add bulk status change --- formity/admin.py | 58 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/formity/admin.py b/formity/admin.py index 475909a..c77d029 100644 --- a/formity/admin.py +++ b/formity/admin.py @@ -11,6 +11,11 @@ from sqlalchemy import inspect, func from sqlalchemy.orm import class_mapper from sqlalchemy.orm.attributes import get_history +diff_sanitization_rules = [ + (enum.Enum, lambda v: v.name), + (decimal.Decimal, float), +] + def get_diff(target, blacklist=['created', 'updated']): state_before = {} state_after = {} @@ -23,13 +28,12 @@ def get_diff(target, blacklist=['created', 'updated']): hist = getattr(inspr.attrs, attr.key).history if hist.has_changes(): state_before[attr.key] = get_history(target, attr.key)[2].pop() - if isinstance(state_before[attr.key], enum.Enum): - state_before[attr.key] = state_before[attr.key].name state_after[attr.key] = getattr(target, attr.key) - if isinstance(state_before[attr.key], decimal.Decimal): - state_before[attr.key] = float(state_before[attr.key]) - if isinstance(state_after[attr.key], decimal.Decimal): - state_after[attr.key] = float(state_after[attr.key]) + + for data in [state_before, state_after]: + for t, c in diff_sanitization_rules: + if isinstance(data[attr.key], t): + data[attr.key] = c(data[attr.key]) if state_after[attr.key] == state_before[attr.key] or (state_after[attr.key] in ['', None] and state_before[attr.key] in ['', None]): state_after.pop(attr.key) @@ -167,6 +171,48 @@ class FaceshieldRequestAdmin(ModelView): return self.render('label.html', model=model, label_count=label_count) + + def bulk_status_change(self, ids, status): + try: + query = self.get_query().filter(FaceshieldRequest.id.in_(ids)) + + count = 0 + for req in query.all(): + if req.status != status: + req.status = status + count += 1 + self.on_model_change(None, req, False) + + db.session.commit() + + flash('{} requests were successfully marked as {}.'.format(count, status.name)) + except Exception as ex: + if not self.handle_view_exception(ex): + raise + + flash('Failed to mark request as {}: {}'.format(status.name, str(ex)), 'error') + + @flask_admin.actions.action('new', 'Mark as new', 'Are you sure you want to mark as new?') + def action_new(self, ids): + self.bulk_status_change(ids, Status.new) + + @flask_admin.actions.action('fulfilled', 'Mark as fulfilled', 'Are you sure you want to mark as fulfilled?') + def action_fulfilled(self, ids): + self.bulk_status_change(ids, Status.fulfilled) + + @flask_admin.actions.action('intransit', 'Mark as intransit', 'Are you sure you want to mark as intransit?') + def action_intransit(self, ids): + self.bulk_status_change(ids, Status.intransit) + + @flask_admin.actions.action('shippingpending', 'Mark as shippingpending', 'Are you sure you want to mark as shippingpending?') + def action_shippingpending(self, ids): + self.bulk_status_change(ids, Status.shippingpending) + + @flask_admin.actions.action('pickuppending', 'Mark as pickuppending', 'Are you sure you want to mark as pickuppending?') + def action_pickuppending(self, ids): + self.bulk_status_change(ids, Status.pickuppending) + + class FilteredFaceshieldRequestAdmin(FaceshieldRequestAdmin): def get_query(self): return super(FilteredFaceshieldRequestAdmin, self).get_query().filter(~FaceshieldRequest.status.in_([Status.rejected, Status.spam, Status.fulfilled, Status.delegated]))