Remove separate membershipworks database, merging it into default

This commit is contained in:
Adam Goldsmith 2024-02-23 13:01:37 -05:00
parent 61c81e05b6
commit dc9a06b415
5 changed files with 40 additions and 78 deletions

View File

@ -82,10 +82,6 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
WSGI_APPLICATION = "cmsmanage.wsgi.application" WSGI_APPLICATION = "cmsmanage.wsgi.application"
DATABASE_ROUTERS = [
"membershipworks.routers.MembershipWorksRouter",
]
# Default URL to redirect to after authentication # Default URL to redirect to after authentication
LOGIN_REDIRECT_URL = "/" LOGIN_REDIRECT_URL = "/"
LOGIN_URL = "/auth/login/" LOGIN_URL = "/auth/login/"

View File

@ -1,23 +0,0 @@
class MembershipWorksRouter:
app_label = "membershipworks"
db = "membershipworks"
def db_for_read(self, model, **hints):
if model._meta.app_label == self.app_label:
return self.db
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == self.app_label:
return self.db
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == self.app_label:
return db == self.db
return None
def allow_relation(self, obj1, obj2, **hints):
if self.app_label in (obj1._meta.app_label, obj2._meta.app_label):
return True
return None

View File

@ -1,4 +1,4 @@
from django.db.models import Prefetch, Q from django.db.models import Q
from rest_framework import routers, serializers, viewsets from rest_framework import routers, serializers, viewsets
from rest_framework.decorators import action from rest_framework.decorators import action
@ -33,10 +33,6 @@ class DepartmentViewSet(viewsets.ModelViewSet):
departments = self.queryset.prefetch_related( departments = self.queryset.prefetch_related(
"children", "children",
"shop_lead_flag__members", "shop_lead_flag__members",
Prefetch(
"certificationdefinition_set__certificationversion_set__certification_set__member",
queryset=Member.objects.with_is_active(),
),
) )
lists = {} lists = {}
for department in departments.filter(has_mailing_list=True): for department in departments.filter(has_mailing_list=True):
@ -48,14 +44,12 @@ class DepartmentViewSet(viewsets.ModelViewSet):
else: else:
moderator_emails = [] moderator_emails = []
# TODO: this could be done in SQL instead if
# membershipworks was in the same database
active_certified_members = { active_certified_members = {
member_cert.member.sanitized_mailbox() member.sanitized_mailbox()
for certification in department.certificationdefinition_set.all() for member in Member.objects.with_is_active().filter(
for version in certification.certificationversion_set.all() is_active=True,
for member_cert in version.certification_set.all() certification__certification_version__definition__department=department,
if member_cert.member and member_cert.member.is_active )
} }
lists[department.list_name] = { lists[department.list_name] = {

View File

@ -71,11 +71,11 @@ class CmsRedRiverVeteransScholarship(models.Model):
class DepartmentQuerySet(models.QuerySet): class DepartmentQuerySet(models.QuerySet):
def filter_by_shop_lead(self, member: Member) -> models.QuerySet["Department"]: def filter_by_shop_lead(self, member: Member) -> models.QuerySet["Department"]:
"""Get departments for which `member` is a shop lead""" """Get departments for which `member` is a shop lead"""
# TODO: could be a lot simpler if membershipworks was in the same database # TODO: should select children recursively, instead of specific levels
# TODO: should also select children return self.filter(
member_flags = list(member.flags.all().values_list("pk", flat=True)) Q(shop_lead_flag__members=member)
return self.prefetch_related("shop_lead_flag__members").filter( | Q(parent__shop_lead_flag__members=member)
shop_lead_flag__in=member_flags | Q(parent__parent__shop_lead_flag__members=member)
) )

View File

@ -3,7 +3,17 @@ from django.contrib import staticfiles
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db import models from django.db import models
from django.db.models import Case, Count, Max, Q, Value, When from django.db.models import (
Case,
Count,
Exists,
Max,
OuterRef,
Q,
Subquery,
Value,
When,
)
from django.db.models.functions import Concat from django.db.models.functions import Concat
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
@ -236,49 +246,24 @@ class AccessVerificationReport(
export_formats = ("csv", "xlsx", "ods") export_formats = ("csv", "xlsx", "ods")
def get_queryset(self): def get_queryset(self):
# TODO: could be done with subqueries if membershipworks was not a separate DB
def shop_error(access_field: str, shop_name: str): def shop_error(access_field: str, shop_name: str):
member_list = list( member_list = CertificationVersion.objects.filter(
CertificationVersion.objects.filter(
is_current=True, is_current=True,
definition__department__name=shop_name, definition__department__name=shop_name,
certification__member__pk__isnull=False, certification__member__pk__isnull=False,
) ).values("certification__member__pk")
.values_list(
"certification__member__pk",
flat=True,
)
.distinct()
)
return Case( return Case(
When( When(
Q(**{access_field: True}) & ~Q(uid__in=member_list), Q(**{access_field: True}) & ~Q(uid__in=Subquery(member_list)),
Value("Has access but no cert"), Value("Has access but no cert"),
), ),
When( When(
Q(**{access_field: False}) & Q(uid__in=member_list), Q(**{access_field: False}) & Q(uid__in=Subquery(member_list)),
Value("Has cert but no access"), Value("Has cert but no access"),
), ),
default=None, default=None,
) )
# TODO: could be a lot cleaner if membershipworks was not a separate DB
storage_closet_members = (
Member.objects.filter(
Member.objects.has_flag("label", "Volunteer: Desker")
| Q(billing_method__startswith="Desker")
)
.union(
*[
department.shop_lead_flag.members.all()
for department in Department.objects.filter(
shop_lead_flag__isnull=False
)
]
)
.values_list("pk", flat=True)
)
qs = ( qs = (
Member.objects.with_is_active() Member.objects.with_is_active()
.filter(is_active=True) .filter(is_active=True)
@ -307,7 +292,17 @@ class AccessVerificationReport(
storage_closet_error=Case( storage_closet_error=Case(
When( When(
Q(access_storage_closet=True) Q(access_storage_closet=True)
& ~Q(uid__in=storage_closet_members), & ~(
Member.objects.has_flag("label", "Volunteer: Desker")
| Q(billing_method__startswith="Desker")
| Q(
Exists(
Department.objects.filter(
shop_lead_flag__members=OuterRef("pk")
)
)
)
),
Value("Has access but not shop lead or desker"), Value("Has access but not shop lead or desker"),
), ),
default=None, default=None,