From 4b7db9b36eeab177c724679668bf4d725db60eb8 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Wed, 18 Nov 2020 02:52:35 +0100 Subject: [PATCH] Fix has_access global filter on different membership and connexion invoices --- re2o/utils.py | 115 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 34 deletions(-) diff --git a/re2o/utils.py b/re2o/utils.py index 89921db6..7af88a1d 100644 --- a/re2o/utils.py +++ b/re2o/utils.py @@ -75,7 +75,23 @@ def get_group_having_permission(*permission_name): return groups -def all_adherent(search_time=None, including_asso=True): +def filter_results(query_filter, dormitory, user_type): + """Wrapper function. + Take a query filter in main argument + Returns a filtered results : + - on dormitory if specified + - on user_type (adherent or club) is specified + Returns the filter""" + if dormitory: + query_filter &= (Q(adherent__room__building__dormitory=dormitory) | Q(club__room__building__dormitory=dormitory)) + if user_type == "adherent": + query_filter &= Q(adherent__isnull=False) + if user_type == "club": + query_filter &= Q(club__isnull=False) + return query_filter + + +def all_adherent(search_time=None, including_asso=True, dormitory=None, user_type="all"): """Return all people who have a valid membership at org. Optimised to make only one sql query. Build a filter and then apply it to User. Check for each user if a valid membership is registered at the desired search_time. @@ -104,10 +120,11 @@ def all_adherent(search_time=None, including_asso=True): asso_user = AssoOption.get_cached_value("utilisateur_asso") if asso_user: filter_user |= Q(id=asso_user.id) + filter_user = filter_results(filter_user, dormitory, user_type) return User.objects.filter(filter_user).distinct() -def all_baned(search_time=None): +def all_baned(search_time=None, dormitory=None, user_type="all"): """Return all people who are banned at org. Optimised to make only one sql query. Build a filter and then apply it to User. Check for each user banned at the desired search_time. @@ -122,14 +139,16 @@ def all_baned(search_time=None): """ if search_time is None: search_time = timezone.now() - return User.objects.filter( + filter_user = Q( ban__in=Ban.objects.filter( Q(date_start__lt=search_time) & Q(date_end__gt=search_time) ) - ).distinct() + ) + filter_user = filter_results(filter_user, dormitory, user_type) + return User.objects.filter(filter_user).distinct() -def all_whitelisted(search_time=None): +def all_whitelisted(search_time=None, dormitory=None, user_type="all"): """Return all people who have a free access at org. Optimised to make only one sql query. Build a filter and then apply it to User. Check for each user with a whitelisted free access at the desired search_time. @@ -144,16 +163,51 @@ def all_whitelisted(search_time=None): """ if search_time is None: search_time = timezone.now() - return User.objects.filter( + filter_user = Q( whitelist__in=Whitelist.objects.filter( Q(date_start__lt=search_time) & Q(date_end__gt=search_time) ) - ).distinct() + ) + filter_user = filter_results(filter_user, dormitory, user_type) + return User.objects.filter(filter_user).distinct() -def all_has_access(search_time=None, including_asso=True): - """Return all people who have an valid internet access at org. Optimised to make - only one sql query. Build a filter and then apply it to User. Return users +def all_conn(search_time=None, including_asso=True, dormitory=None, user_type="all"): + """Return all people who have a valid connection payment at org. Optimised to make only one + sql query. Build a filter and then apply it to User. Check for each user if a valid + connection is registered at the desired search_time. + + Parameters: + search_time (django datetime): Datetime to perform this search, + if not provided, search_time will be set à timezone.now() + including_asso (boolean): Decide if org itself is included in results + + Returns: + django queryset: Django queryset containing all users with valid connection perdiod + + """ + if search_time is None: + search_time = timezone.now() + filter_user = Q( + facture__in=Facture.objects.filter( + vente__cotisation__in=Cotisation.objects.filter( + Q(vente__facture__facture__valid=True) & + Q(date_start_con__lt=search_time) & + Q(date_end_con__gt=search_time) + ) + ) + ) + if including_asso: + asso_user = AssoOption.get_cached_value("utilisateur_asso") + if asso_user: + filter_user |= Q(id=asso_user.id) + filter_user = filter_results(filter_user, dormitory, user_type) + return User.objects.filter(filter_user).distinct() + + +def all_has_access(search_time=None, including_asso=True, dormitory=None, user_type="all"): + """Return all people who have an valid internet access at org. Call previously buid filters. + Can't do that in one sql query unfortunatly. Apply each filters, and return users with a whitelist, or a valid paid access, except banned users. Parameters: @@ -170,35 +224,28 @@ def all_has_access(search_time=None, including_asso=True): filter_user = ( Q(state=User.STATE_ACTIVE) & ~Q(email_state=User.EMAIL_STATE_UNVERIFIED) - & ~Q( - ban__in=Ban.objects.filter( - Q(date_start__lt=search_time) & Q(date_end__gt=search_time) - ) - ) - & ( - Q( - whitelist__in=Whitelist.objects.filter( - Q(date_start__lt=search_time) & Q(date_end__gt=search_time) - ) - ) - | Q( - facture__in=Facture.objects.filter( - vente__cotisation__in=Cotisation.objects.filter( - Q(vente__facture__facture__valid=True) & - Q(date_start_con__lt=search_time) & - Q(date_end_con__gt=search_time) & - Q(date_start_memb__lt=search_time) & - Q(date_end_memb__gt=search_time) - ) - ) - ) - ) ) + filter_user = filter_results(filter_user, dormitory, user_type) if including_asso: asso_user = AssoOption.get_cached_value("utilisateur_asso") if asso_user: filter_user |= Q(id=asso_user.id) - return User.objects.filter(filter_user).distinct() + filter_user = filter_results(filter_user, dormitory, user_type) + return User.objects.filter( + Q(filter_user) & ( + Q( + id__in=all_whitelisted(search_time=search_time, dormitory=dormitory, user_type=user_type) + ) | ( + Q( + id__in=all_adherent(search_time=search_time, including_asso=including_asso, dormitory=dormitory, user_type=user_type) + ) & Q( + id__in=all_conn(search_time=search_time, including_asso=including_asso, dormitory=dormitory, user_type=user_type) + ) + ) + ) & ~Q( + id__in=all_baned(search_time=search_time, dormitory=dormitory, user_type=user_type) + ) + ).distinct() def filter_active_interfaces(interface_set):