Skip to content

Commit

Permalink
v1.2.0
Browse files Browse the repository at this point in the history
v1.2.0
  • Loading branch information
javiercavlop committed May 22, 2023
2 parents c560135 + ccd10ac commit 1ad069d
Show file tree
Hide file tree
Showing 29 changed files with 409 additions and 181 deletions.
4 changes: 3 additions & 1 deletion backend/authentication/admin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.contrib import admin
from .models import FlatterUser, Role, Tag, UserPreferences, Plan, Promotion
from .models import FlatterUser, Role, Tag, UserPreferences, Plan, Promotion, ReferralProgram, ReferralProgramController

admin.site.register(FlatterUser)
admin.site.register(Role)
admin.site.register(Tag)
admin.site.register(UserPreferences)
admin.site.register(Plan)
admin.site.register(Promotion)
admin.site.register(ReferralProgram)
admin.site.register(ReferralProgramController)
1 change: 1 addition & 0 deletions backend/authentication/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ class AuthenticationConfig(AppConfig):

def ready(self):
from .background_tasks import start
import authentication.signals
start()
16 changes: 14 additions & 2 deletions backend/authentication/background_tasks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .models import FlatterUser
from .models import FlatterUser, Promotion, ReferralProgram
from django.utils import timezone
from apscheduler.schedulers.background import BackgroundScheduler

Expand All @@ -10,4 +10,16 @@ def start():

def delete_users():
date = timezone.datetime.now() - timezone.timedelta(years=5)
FlatterUser.objects.filter(last_login_lt=date).delete()
FlatterUser.objects.filter(last_login_lt=date).delete()
promotions = Promotion.objects.filter(max_date__lt=timezone.now(), is_disabled=False)
for promotion in promotions:
promotion.is_disabled = True
promotion.save()
promotions2 = Promotion.objects.filter(times_to_be_used__lte=0, is_disabled=False, can_be_used_always=False)
for promotion in promotions2:
promotion.is_disabled = True
promotion.save()
referral_program = ReferralProgram.objects.filter(end_date__lt=timezone.now(), is_disabled=False)
for program in referral_program:
program.is_disabled = True
program.save()
72 changes: 20 additions & 52 deletions backend/authentication/models.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
from datetime import datetime
from django.db import models
from django.db.models import signals
from django.contrib.auth.models import AbstractUser
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.core.validators import MinLengthValidator
from django.core.exceptions import ValidationError


class RoleType(models.TextChoices):
owner = 'OWNER'
Expand Down Expand Up @@ -119,52 +114,25 @@ class Promotion(models.Model):
is_discount = models.BooleanField(default=False)
users_used = models.ManyToManyField(FlatterUser, related_name=_('users_used'), blank=True)
is_disabled = models.BooleanField(default=False)
can_be_used_always = models.BooleanField(default=False)
max_date = models.DateField(null=True, blank=True)
times_to_be_used = models.PositiveIntegerField(null=True, blank=True)
is_welcome_promotion = models.BooleanField(default=False)

@receiver(signals.post_save, sender=Promotion)
def create_promotion(sender, instance, created, **kwargs):
if instance.is_discount:
if instance.quantity > 1 or instance.quantity < 0:
raise ValidationError("The quantity must be between 0 and 1")
else:
if instance.quantity < 0:
raise ValidationError("The quantity must be greater than 0")
if int(instance.quantity) != instance.quantity:
raise ValidationError("The quantity must be an integer")

def add_roles(sender=None, **kwargs):
for role in RoleType:
Role.objects.get_or_create(role=role)

signals.post_migrate.connect(add_roles)

def create_plans(sender=None, **kwargs):
if Plan.objects.count() == 0:

Plan.objects.get_or_create(flatter_coins=0, visits_number=10,
tags_number=6, advertisement=True,
chat_creation=False, standard_support=False,
premium_support=False, view_self_profile_opinions=False,
initial_date=timezone.now(), end_date=None,
plan_type='B')

Plan.objects.get_or_create(flatter_coins=30, visits_number=30,
tags_number=10, advertisement=False,
chat_creation=True, standard_support=True,
premium_support=False, view_self_profile_opinions=True,
initial_date=timezone.now(), end_date=None,
plan_type='A')

Plan.objects.get_or_create(flatter_coins=65, visits_number=10**10,
tags_number=10, advertisement=False,
chat_creation=True, standard_support=True,
premium_support=True, view_self_profile_opinions=True,
initial_date=timezone.now(), end_date=None,
plan_type='P')

signals.post_migrate.connect(create_plans)

@receiver(signals.post_save, sender=FlatterUser)
def create_user_preferences(sender, instance, created, **kwargs):
if created:
UserPreferences.objects.create(user=instance)
class ReferralProgram(models.Model):
initial_date = models.DateField(default=datetime.now)
end_date = models.DateField()
user = models.OneToOneField(FlatterUser, on_delete=models.CASCADE)
code = models.CharField(max_length=64, unique=True)
users_referred = models.ManyToManyField(FlatterUser, related_name=_('users_referred'), blank=True)
user_quantity = models.PositiveIntegerField(default=0)
user_referred_quantity = models.PositiveIntegerField(default=0)
times_to_be_used = models.PositiveIntegerField()
is_disabled = models.BooleanField(default=False)

class ReferralProgramController(models.Model):
max_days = models.PositiveIntegerField(default=0)
max_users = models.PositiveIntegerField(default=0)
quantity = models.PositiveIntegerField(default=0)
quantity_referred = models.PositiveIntegerField(default=0)
is_disabled = models.BooleanField(default=False)
144 changes: 54 additions & 90 deletions backend/authentication/mutations.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import datetime
import graphene, graphql_jwt
from .models import FlatterUser, Plan, Role, Contract, UserPreferences, Promotion
from .models import FlatterUser, Plan, Role, Contract, UserPreferences, Promotion, ReferralProgram
from social.models import Group
from mainApp.models import Property, Application, Petition, Review
from .types import ContractType, FlatterUserType, PlanType, PromotionType
Expand Down Expand Up @@ -178,6 +178,7 @@ class Input:
email = graphene.String(required=True)
genre = graphene.String(required=True)
roles = graphene.String(required=True)
code = graphene.String(required=False)

user = graphene.Field(FlatterUserType)
contract = graphene.Field(ContractType)
Expand All @@ -191,6 +192,10 @@ def mutate(root, info, **kwargs):
email = kwargs.get("email", "").strip()
genre = kwargs.get("genre", "").strip()
roles = kwargs.get("roles", [])
code = kwargs.get("code", '').strip()

if not code:
code = None

if not username or len(username) < 6 or len(username) > 25:
raise ValueError(_("El usuario debe tener entre 6 y 24 caracteres"))
Expand Down Expand Up @@ -221,16 +226,48 @@ def mutate(root, info, **kwargs):

genre = parse_genre(genre)
roles = parse_roles(roles)


coins = 0

obj = FlatterUser.objects.create_user(username=username,
password=password,
first_name=first_name,
last_name=last_name,
email=email,
profile_picture="users/images/default.jpg",
flatter_coins=0,
flatter_coins=coins,
genre=genre,
)

if code:
today = timezone.now()
if not ReferralProgram.objects.filter(code=code, is_disabled=False, end_date__gte=today, times_to_be_used__gte=1).exists():
try:
promotion = Promotion.objects.get(code=code, is_welcome_promotion=True, is_disabled=False, max_date__gte=today)
if not promotion.can_be_used_always and promotion.times_to_be_used <= 0:
raise ValueError(_("El código de promoción no es válido"))
coins = promotion.quantity
if promotion.times_to_be_used is not None:
promotion.times_to_be_used -= 1
if promotion.times_to_be_used == 0:
promotion.is_disabled = True
promotion.save()
except Promotion.DoesNotExist:
raise ValueError(_("El código de promoción no es válido"))
else:
promotion = ReferralProgram.objects.get(code=code, is_disabled=False, end_date__gte=today, times_to_be_used__gte=1)
coins = promotion.user_referred_quantity
user_referral = FlatterUser.objects.get(pk=promotion.user.pk)
user_referral.flatter_coins += promotion.user_quantity
user_referral.save()
promotion.users_referred.add(obj)
promotion.times_to_be_used -= 1
if promotion.times_to_be_used == 0:
promotion.is_disabled = True
promotion.save()

obj.flatter_coins += coins
obj.save()

obj.roles.add(*roles)

Expand Down Expand Up @@ -351,108 +388,36 @@ def mutate(root, info, **kwargs):
check_token(token, user)

try:
promotion = Promotion.objects.get(code=code)
promotion = Promotion.objects.get(code=code, is_welcome_promotion=False)
except Promotion.DoesNotExist:
raise ValueError(_("El código introducido no existe"))

if promotion.is_disabled:
raise ValueError(_("El código ya no está activo"))

if promotion.max_date < datetime.now():
raise ValueError(_("El código ya no está activo"))

if promotion.users_used.filter(username=username).exists():
raise ValueError(_("Ya has canjeado el código"))

if not promotion.times_to_be_used:
raise ValueError(_("El código ya no está activo"))

if not promotion.is_discount:
user.flatter_coins += promotion.quantity
user.save()

promotion.users_used.add(user)
promotion.save()
if not promotion.can_be_used_always and promotion.times_to_be_used is None:
promotion.users_used.add(user)
if promotion.times_to_be_used:
promotion.times_to_be_used -= 1
if promotion.times_to_be_used == 0:
promotion.is_disabled = True
promotion.save()

return RedeemPromotion(promotion=promotion)

class WelcomeUserMutation(graphene.Mutation):

class Input:
username = graphene.String(required=True)
password = graphene.String(required=True)
first_name = graphene.String(required=True)
last_name = graphene.String(required=True)
email = graphene.String(required=True)
genre = graphene.String(required=True)
roles = graphene.String(required=True)

user = graphene.Field(FlatterUserType)
contract = graphene.Field(ContractType)

@staticmethod
def mutate(root, info, **kwargs):
username = kwargs.get('username', '').strip()
password = kwargs.get("password", '').strip()
first_name = kwargs.get("first_name", "").strip()
last_name = kwargs.get("last_name", "").strip()
email = kwargs.get("email", "").strip()
genre = kwargs.get("genre", "").strip()
roles = kwargs.get("roles", [])
flatter_coins = 0
now = datetime.now()

if (now.month == 5 or now.month == 6) and now.year == 2023:
flatter_coins = 500

if not username or len(username) < 6 or len(username) > 25:
raise ValueError(_("El usuario debe tener entre 6 y 24 caracteres"))

if not username or len(password) < 6:
raise ValueError(_("La contraseña debe tener al menos 6 caracteres"))

if not first_name or len(first_name) < 3 or len(first_name) >= 50:
raise ValueError(_("El nombre debe tener entre 3 y 50 caracteres"))

if not last_name or len(last_name) < 3 or len(last_name) >= 50:
raise ValueError(_("Los apellidos deben tener entre 3 y 50 caracteres"))

if not email or ("@" not in email) or ("." not in email):
raise ValueError(_("El email no es válido"))

if _exists_user(username):
raise ValueError(_("Este nombre de usuario ya está registrado. Por favor, elige otro."))

if _exists_email(email):
raise ValueError(_("Este email ya está registrado. Por favor, elige otro."))

if not valid_genre(genre):
raise ValueError(_("El género no es válido"))

if not valid_roles(roles):
raise ValueError(_("Los roles no son válidos"))

genre = parse_genre(genre)
roles = parse_roles(roles)

obj = FlatterUser.objects.create_user(username=username,
password=password,
first_name=first_name,
last_name=last_name,
email=email,
profile_picture="users/images/default.jpg",
flatter_coins=flatter_coins,
genre=genre,
)

obj.roles.add(*roles)

# Create user contract

new_user_contract = Contract.objects.create(
initial_date=datetime.now(),
end_date = None,
choices = None,
plan=Plan.objects.get(plan_type=Plan.choices_type[0][0], end_date=None),
user=obj,
)

return WelcomeUserMutation(user=obj, contract=new_user_contract)

class AuthenticationMutation(graphene.ObjectType):
token_auth = ObtainJSONWebToken.Field()
verify_token = graphql_jwt.Verify.Field()
Expand All @@ -463,7 +428,6 @@ class AuthenticationMutation(graphene.ObjectType):
edit_user_flatter_coins = EditUserFlatterCoins.Field()
delete_user = DeleteUser.Field()
redeem_promotion = RedeemPromotion.Field()
welcome_user = WelcomeUserMutation.Field()

# ----------------------------------- PRIVATE FUNCTIONS ----------------------------------- #

Expand Down
10 changes: 7 additions & 3 deletions backend/authentication/queries.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import graphene
from .types import FlatterUserType, FlatterUserPageType, RoleType, PlanType, ContractType, get_user_rating
from .models import Contract, FlatterUser, Plan, Role
from .types import FlatterUserType, FlatterUserPageType, RoleType, PlanType, ContractType, ReferralProgramControllerType, get_user_rating
from .models import Contract, FlatterUser, Plan, Role, ReferralProgramController
from django.db.models import Q
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
Expand All @@ -13,6 +13,7 @@ class AuthenticationQuery(object):
get_plans = graphene.List(PlanType)
get_contract_by_username = graphene.Field(ContractType, username=graphene.String(), user_token = graphene.String(required=True))
get_all_contracts_by_username = graphene.List(ContractType, username=graphene.String(), user_token = graphene.String(required=True))
get_referral_program_controller = graphene.Field(ReferralProgramControllerType)

def resolve_get_user_by_username(self, info, username):

Expand Down Expand Up @@ -113,4 +114,7 @@ def resolve_get_contract_by_username(self, info, username, user_token=''):
def resolve_get_all_contracts_by_username(self, info, username, user_token=''):
user = FlatterUser.objects.get(username=username)
# Get all contracts in descending order by initial date and end date
return Contract.objects.filter(user=user).order_by('-initial_date', '-end_date')
return Contract.objects.filter(user=user).order_by('-initial_date', '-end_date')

def resolve_get_referral_program_controller(self, info):
return ReferralProgramController.objects.all().first()
Loading

0 comments on commit 1ad069d

Please sign in to comment.