diff --git a/blt/urls.py b/blt/urls.py index efc9e822e..1b275f219 100644 --- a/blt/urls.py +++ b/blt/urls.py @@ -35,7 +35,6 @@ AllIssuesView, CompanySettings, CreateHunt, - CreateInviteFriend, CustomObtainAuthToken, DomainDetailView, DomainList, @@ -108,6 +107,8 @@ handler500 = "website.views.handler500" urlpatterns = [ + path("invite-friend/", website.views.invite_friend, name="invite_friend"), + path("referral/", website.views.referral_signup, name="referral_signup"), path("captcha/", include("captcha.urls")), re_path(r"^auth/registration/", include("dj_rest_auth.registration.urls")), path( @@ -329,11 +330,6 @@ re_path(r"^hunt/$", login_required(HuntCreate.as_view()), name="hunt"), re_path(r"^hunts/$", ListHunts.as_view(), name="hunts"), re_path(r"^invite/$", InviteCreate.as_view(template_name="invite.html")), - re_path( - r"^invite-friend/$", - login_required(CreateInviteFriend.as_view()), - name="invite_friend", - ), re_path(r"^terms/$", TemplateView.as_view(template_name="terms.html"), name="terms"), re_path(r"^about/$", TemplateView.as_view(template_name="about.html")), re_path(r"^teams/$", TemplateView.as_view(template_name="teams.html")), diff --git a/website/forms.py b/website/forms.py index 7b84d748c..a8fa1154b 100644 --- a/website/forms.py +++ b/website/forms.py @@ -2,14 +2,7 @@ from django import forms from mdeditor.fields import MDTextFormField -from .models import InviteFriend, UserProfile - - -class FormInviteFriend(forms.ModelForm): - class Meta: - model = InviteFriend - fields = ["recipient"] - widgets = {"recipient": forms.TextInput(attrs={"class": "form-control"})} +from .models import UserProfile class UserProfileForm(forms.ModelForm): diff --git a/website/migrations/0083_alter_invitefriend_options_and_more.py b/website/migrations/0083_alter_invitefriend_options_and_more.py new file mode 100644 index 000000000..7c97970e0 --- /dev/null +++ b/website/migrations/0083_alter_invitefriend_options_and_more.py @@ -0,0 +1,55 @@ +# Generated by Django 5.0.2 on 2024-02-25 15:28 + +import uuid + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0082_issue_reporter_ip_address"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterModelOptions( + name="invitefriend", + options={}, + ), + migrations.RemoveField( + model_name="invitefriend", + name="recipient", + ), + migrations.RemoveField( + model_name="invitefriend", + name="sent", + ), + migrations.AddField( + model_name="invitefriend", + name="point_by_referral", + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name="invitefriend", + name="recipients", + field=models.ManyToManyField( + blank=True, related_name="received_invites", to=settings.AUTH_USER_MODEL + ), + ), + migrations.AddField( + model_name="invitefriend", + name="referral_code", + field=models.CharField(default=uuid.uuid4, editable=False, max_length=100), + ), + migrations.AlterField( + model_name="invitefriend", + name="sender", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sent_invites", + to=settings.AUTH_USER_MODEL, + ), + ), + ] diff --git a/website/models.py b/website/models.py index b91e78881..8bfb8cb2a 100644 --- a/website/models.py +++ b/website/models.py @@ -374,14 +374,13 @@ class Points(models.Model): class InviteFriend(models.Model): - sender = models.ForeignKey(User, on_delete=models.CASCADE) - recipient = models.EmailField() - sent = models.DateTimeField(auto_now_add=True, db_index=True) + sender = models.ForeignKey(User, related_name="sent_invites", on_delete=models.CASCADE) + recipients = models.ManyToManyField(User, related_name="received_invites", blank=True) + referral_code = models.CharField(max_length=100, default=uuid.uuid4, editable=False) + point_by_referral = models.IntegerField(default=0) - class Meta: - ordering = ("-sent",) - verbose_name = "invitation" - verbose_name_plural = "invitations" + def __str__(self): + return f"Invite from {self.sender}" def user_images_path(instance, filename): diff --git a/website/templates/invite_friend.html b/website/templates/invite_friend.html index 051aaf923..a6838a1a0 100644 --- a/website/templates/invite_friend.html +++ b/website/templates/invite_friend.html @@ -1,26 +1,30 @@ {% extends "base.html" %} +{% block title %} invite friend {% endblock title %} {% block content %} -
-{% endblock %} +{% include "includes/sidenav.html" %} + +{% endblock content %} +{% block after_js %} + +{% endblock %} \ No newline at end of file diff --git a/website/views.py b/website/views.py index e88c3548c..20103fa97 100644 --- a/website/views.py +++ b/website/views.py @@ -22,7 +22,7 @@ # from django_cron import CronJobBase, Schedule from allauth.account.models import EmailAddress -from allauth.account.signals import user_logged_in +from allauth.account.signals import user_logged_in, user_signed_up from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter @@ -34,6 +34,7 @@ from django.contrib.auth import get_user_model from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User +from django.contrib.sites.shortcuts import get_current_site from django.core import serializers from django.core.exceptions import ValidationError from django.core.files import File @@ -57,7 +58,7 @@ ) from django.shortcuts import get_object_or_404, redirect, render from django.template.loader import render_to_string -from django.urls import reverse, reverse_lazy +from django.urls import reverse from django.utils.decorators import method_decorator from django.utils.timezone import now from django.views.decorators.csrf import csrf_exempt @@ -88,7 +89,7 @@ Winner, ) -from .forms import CaptchaForm, FormInviteFriend, HuntForm, QuickIssueForm, UserProfileForm +from .forms import CaptchaForm, HuntForm, QuickIssueForm, UserProfileForm def is_valid_https_url(url): @@ -2071,44 +2072,6 @@ def assign_issue_to_user(request, user, **kwargs): assigner.process_issue(user, issue, created, domain) -class CreateInviteFriend(CreateView): - template_name = "invite_friend.html" - model = InviteFriend - form_class = FormInviteFriend - success_url = reverse_lazy("invite_friend") - - def form_valid(self, form): - from django.conf import settings - from django.contrib.sites.shortcuts import get_current_site - - instance = form.save(commit=False) - instance.sender = self.request.user - instance.save() - - site = get_current_site(self.request) - - mail_status = send_mail( - "Inivtation to {site} from {user}".format( - site=site.name, user=self.request.user.username - ), - "You have been invited by {user} to join {site} community.".format( - user=self.request.user.username, site=site.name - ), - settings.DEFAULT_FROM_EMAIL, - [instance.recipient], - ) - - if mail_status and InviteFriend.objects.filter(sender=self.request.user).count() == 2: - Points.objects.create(user=self.request.user, score=1) - InviteFriend.objects.filter(sender=self.request.user).delete() - - messages.success( - self.request, - "An email has been sent to your friend. Keep inviting your friends and get points!", - ) - return HttpResponseRedirect(self.success_url) - - @login_required(login_url="/accounts/login") def follow_user(request, user): if request.method == "GET": @@ -3701,6 +3664,54 @@ def get_context_data(self, **kwargs): return context +@receiver(user_signed_up) +def handle_user_signup(request, user, **kwargs): + referral_token = request.session.get("ref") + if referral_token: + try: + invite = InviteFriend.objects.get(referral_code=referral_token) + invite.recipients.add(user) + invite.point_by_referral += 2 + invite.save() + reward_sender_with_points(invite.sender) + del request.session["ref"] + except InviteFriend.DoesNotExist: + pass + + +def reward_sender_with_points(sender): + # Create or update points for the sender + points, created = Points.objects.get_or_create(user=sender, defaults={"score": 0}) + points.score += 2 # Reward 2 points for each successful referral signup + points.save() + + +def referral_signup(request): + referral_token = request.GET.get("ref") + # check the referral token is present on invitefriend model or not and if present then set the referral token in the session + if referral_token: + try: + invite = InviteFriend.objects.get(referral_code=referral_token) + request.session["ref"] = referral_token + except InviteFriend.DoesNotExist: + messages.error(request, "Invalid referral token") + return redirect("account_signup") + return redirect("account_signup") + + +def invite_friend(request): + # check if the user is authenticated or not + if not request.user.is_authenticated: + return redirect("account_login") + current_site = get_current_site(request) + referral_code, created = InviteFriend.objects.get_or_create(sender=request.user) + referral_link = f"https://{current_site.domain}/referral/?ref={referral_code.referral_code}" + context = { + "referral_link": referral_link, + } + return render(request, "invite_friend.html", context) + + # class CreateIssue(CronJobBase): # RUN_EVERY_MINS = 1