Overhauled entire project config, added notifications, email templates, optimized stripe subscriptions, redis caching, and webdriver utilities

This commit is contained in:
Keannu Christian Bernasol 2024-05-10 23:15:29 +08:00
parent 7cbe8fd720
commit 99dfcef67b
84 changed files with 4300 additions and 867 deletions

View file

View file

@ -0,0 +1,15 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from .models import UserGroup
from unfold.contrib.filters.admin import RangeDateFilter
@admin.register(UserGroup)
class UserGroupAdmin(ModelAdmin):
list_filter_submit = True
list_filter = ((
"date_created", RangeDateFilter
),)
list_display = ['id', 'name']
search_fields = ['id', 'name']

View file

@ -0,0 +1,9 @@
from django.apps import AppConfig
class EnterpriseGroupsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "user_groups"
def ready(self):
import user_groups.signals

View file

@ -0,0 +1,23 @@
# Generated by Django 5.0.6 on 2024-05-10 06:37
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='UserGroup',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128)),
('date_created', models.DateTimeField(default=django.utils.timezone.now, editable=False)),
],
),
]

View file

@ -0,0 +1,31 @@
# Generated by Django 5.0.6 on 2024-05-10 06:38
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('user_groups', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='usergroup',
name='managers',
field=models.ManyToManyField(related_name='usergroup_managers', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='usergroup',
name='members',
field=models.ManyToManyField(related_name='usergroup_members', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='usergroup',
name='owner',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='usergroup_owner', to=settings.AUTH_USER_MODEL),
),
]

View file

@ -0,0 +1,24 @@
from django.db import models
from django.utils.timezone import now
from config.settings import STRIPE_SECRET_KEY
import stripe
stripe.api_key = STRIPE_SECRET_KEY
class UserGroup(models.Model):
name = models.CharField(max_length=128, null=False)
owner = models.ForeignKey(
'accounts.CustomUser', on_delete=models.SET_NULL, null=True, related_name='usergroup_owner')
managers = models.ManyToManyField(
'accounts.CustomUser', related_name='usergroup_managers')
members = models.ManyToManyField(
'accounts.CustomUser', related_name='usergroup_members')
date_created = models.DateTimeField(default=now, editable=False)
# Derived from email of owner, may be used for billing
@property
def email(self):
return self.owner.email
def __str__(self):
return self.name

View file

@ -0,0 +1,12 @@
from rest_framework import serializers
from .models import UserGroup
class SimpleUserGroupSerializer(serializers.ModelSerializer):
date_created = serializers.DateTimeField(
format="%m-%d-%Y %I:%M %p", read_only=True)
class Meta:
model = UserGroup
fields = ['id', 'name', 'date_created']
read_only_fields = ['id', 'name', 'date_created']

View file

@ -0,0 +1,107 @@
from subscriptions.models import SubscriptionPlan
from accounts.models import CustomUser
from .models import UserGroup
from subscriptions.tasks import get_user_group_subscription
from django.db.models.signals import m2m_changed, post_migrate
from django.dispatch import receiver
from config.settings import STRIPE_SECRET_KEY, ROOT_DIR
import os
import json
import stripe
stripe.api_key = STRIPE_SECRET_KEY
@receiver(m2m_changed, sender=UserGroup.managers.through)
def update_group_managers(sender, instance, action, **kwargs):
# When adding new managers to a UserGroup, associate them with it
if action == 'post_add':
# Get the newly added managers
new_managers = kwargs.get('pk_set', set())
for manager in new_managers:
# Retrieve the member
USER = CustomUser.objects.get(pk=manager)
if not USER.user_group:
# Update their group assiociation
USER.user_group = instance
USER.save()
if USER not in instance.members.all():
instance.members.add(USER)
# When removing managers from a UserGroup, remove their association with it
elif action == 'post_remove':
for manager in kwargs['pk_set']:
# Retrieve the manager
USER = CustomUser.objects.get(pk=manager)
if USER not in instance.members.all():
USER.user_group = None
USER.save()
@receiver(m2m_changed, sender=UserGroup.members.through)
def update_group_members(sender, instance, action, **kwargs):
# When adding new members to a UserGroup, associate them with it
if action == 'post_add':
# Get the newly added members
new_members = kwargs.get('pk_set', set())
for member in new_members:
# Retrieve the member
USER = CustomUser.objects.get(pk=member)
if not USER.user_group:
# Update their group assiociation
USER.user_group = instance
USER.save()
# When removing members from a UserGroup, remove their association with it
elif action == 'post_remove':
for client in kwargs['pk_set']:
USER = CustomUser.objects.get(pk=client)
if USER not in instance.members.all() and USER not in instance.managers.all():
USER.user_group = None
USER.save()
# Update usage records
SUBSCRIPTION_GROUP = get_user_group_subscription(instance.id)
if SUBSCRIPTION_GROUP:
try:
print(f"Updating usage record for UserGroup {instance.name}")
# Update usage for members
SUBSCRIPTION_ITEM = SUBSCRIPTION_GROUP.subscription
stripe.SubscriptionItem.create_usage_record(
SUBSCRIPTION_ITEM.stripe_id,
quantity=len(instance.members.all()),
action="set"
)
except:
print(
f'Warning: Unable to update usage record for SubscriptionGroup ID:{instance.id}')
@receiver(post_migrate)
def create_groups(sender, **kwargs):
if sender.name == "agencies":
with open(os.path.join(ROOT_DIR, 'seed_data.json'), "r") as f:
seed_data = json.loads(f.read())
for user_group in seed_data['user_groups']:
OWNER = CustomUser.objects.filter(
email=user_group['owner']).first()
USER_GROUP, CREATED = UserGroup.objects.get_or_create(
owner=OWNER,
agency_name=user_group['name'],
)
if CREATED:
print(f"Created UserGroup {USER_GROUP.agency_name}")
# Add managers
USERS = CustomUser.objects.filter(
email__in=user_group['managers'])
for USER in USERS:
if USER not in USER_GROUP.managers.all():
print(
f"Adding User {USER.full_name} as manager to UserGroup {USER_GROUP.agency_name}")
USER_GROUP.managers.add(USER)
# Add members
USERS = CustomUser.objects.filter(
email__in=user_group['members'])
for USER in USERS:
if USER not in USER_GROUP.members.all():
print(
f"Adding User {USER.full_name} as member to UserGroup {USER_GROUP.agency_name}")
USER_GROUP.clients.add(USER)
USER_GROUP.save()