From b019eb826643dcc6a0663134ad0ec9ccd6cc357e Mon Sep 17 00:00:00 2001 From: Gabriel von Heijne Date: Fri, 20 Jul 2012 16:33:40 +0200 Subject: [PATCH] Add form validation to eliminate duplicate partnerships of same type Extend RSR_PartnershipInlineFormFormSet.clean() to include checking if an organisation is has duplicate partnerships of the same partner_type and complain if that is the case [Fix #35] --- akvo/rsr/admin.py | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/akvo/rsr/admin.py b/akvo/rsr/admin.py index 2b62dcb193..a76e63620f 100644 --- a/akvo/rsr/admin.py +++ b/akvo/rsr/admin.py @@ -376,29 +376,53 @@ class GoalInline(admin.TabularInline): class RSR_PartnershipInlineFormFormSet(forms.models.BaseInlineFormSet): def clean(self): + def duplicates_in_list(seq): + "return True if the list contains duplicate items" + seq_set = list(set(seq)) + # need to sort since set() doesn't preserver order + seq.sort() + seq_set.sort() + return seq != seq_set + user = self.request.user user_profile = user.get_profile() + errors = [] # superusers can do whatever they like! if user.is_superuser: - found = True + my_org_found = True # if the user is a partner org we try to avoid foot shooting elif user_profile.get_is_org_admin() or user_profile.get_is_org_editor(): my_org = user_profile.organisation - found = False - for i in range(0, self.total_form_count()): - form = self.forms[i] + my_org_found = False + for form in self.forms: try: form_org = form.cleaned_data['organisation'] if not form.cleaned_data.get('DELETE', False) and my_org == form_org: # found our own org, all is well move on! - found = True + my_org_found = True break except: pass else: - found = True - if not found: - self._non_form_errors = ErrorList([_(u'Your organisation should be somewhere here.')]) + my_org_found = True + if not my_org_found: + errors += [_(u'Your organisation should be somewhere here.')] + + # now check that the same org isn't assigned the same partner_type more than once + partner_types = {} + for form in self.forms: + # populate a dict with org names as keys and a list of partner_types as values + try: + if not form.cleaned_data.get('DELETE', False): + partner_types.setdefault(form.cleaned_data['organisation'], []).append(form.cleaned_data['partner_type']) + except: + pass + for org, types in partner_types.items(): + # are there duplicates in the list of partner_types? + if duplicates_in_list(types): + errors += [_(u'%s has duplicate partner types of the same kind.' % org)] + self._non_form_errors = ErrorList(errors) + class PartnershipInline(admin.TabularInline): model = get_model('rsr', 'Partnership') @@ -406,6 +430,7 @@ class PartnershipInline(admin.TabularInline): formset = RSR_PartnershipInlineFormFormSet def get_formset(self, request, *args, **kwargs): + "Add the request to the formset for use in RSR_PartnershipInlineFormFormSet.clean()" formset = super(PartnershipInline, self).get_formset(request, *args, **kwargs) formset.request = request return formset