Skip to content

Commit

Permalink
Project complated : fix invite and referrals (#1830)
Browse files Browse the repository at this point in the history
* fix invite

* fix invite

* fix invite

* fix invite

* fix invite

* fix invite

* fix invite

* fix invite
  • Loading branch information
JisanAR03 authored Feb 26, 2024
1 parent 2f03606 commit 7482fd3
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 86 deletions.
8 changes: 2 additions & 6 deletions blt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
AllIssuesView,
CompanySettings,
CreateHunt,
CreateInviteFriend,
CustomObtainAuthToken,
DomainDetailView,
DomainList,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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")),
Expand Down
9 changes: 1 addition & 8 deletions website/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
55 changes: 55 additions & 0 deletions website/migrations/0083_alter_invitefriend_options_and_more.py
Original file line number Diff line number Diff line change
@@ -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,
),
),
]
13 changes: 6 additions & 7 deletions website/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
52 changes: 28 additions & 24 deletions website/templates/invite_friend.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
{% extends "base.html" %}
{% block title %} invite friend {% endblock title %}
{% block content %}
<form action="{% url 'invite_friend' %}" method="post" class="form-inline">
{% csrf_token %}
<div class="row">
{% for error in form.non_field_errors %}
<div class="col-lg-6">{{ error }}</div>
{% endfor %}
</div>
<div class="row">
<div class="col-lg-10">
{% if form.recipient.errors %}
<div class="alert alert-danger">{{ form.recipient.errors }}</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-lg-10">
<h3 class="page-header">Invite 2 friends and get 1 point!</h3>
<label>Email:</label>
{{ form.recipient }}
<button type="submit" class="btn btn-danger text-black">Invite</button>
</div>
</div>
</form>
{% endblock %}
{% include "includes/sidenav.html" %}
<div class="mx-auto my-12 p-6 rounded-lg shadow-xl max-w-3xl">

<div class="mb-4">
<label for="recipient" class="block text-gray-700 text-2xl font-bold mb-2">Share & Earn</label>
<input class="form-control" type="text" value="{{ referral_link }}" id="referralLink" readonly>
<button onclick="copyReferralLink()" class="mt-2 bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Copy</button> <span> or </span>
<a href="mailto:?subject=Join Me on BLT to Discover and Report Bugs!&body=Hi there!%0D%0A%0D%0AI've been using BLT, a platform where we can discover and report bugs across various applications and websites. It's been an exciting journey, and I believe you too can contribute significantly and benefit from it.%0D%0A%0D%0ABLT allows us to:%0D%0A- Explore and report bugs.%0D%0A- Earn rewards and recognition for our contributions.%0D%0A- Join a community of like-minded individuals passionate about improving software quality.%0D%0A%0D%0AI thought it would be something you're interested in exploring. You can sign up using the link below and start your journey with BLT today!%0D%0A%0D%0A{{ referral_link|urlencode }}%0D%0A%0D%0ALooking forward to seeing you on BLT and tackling challenges together.%0D%0A%0D%0ABest,%0D%0A{{ user.username|urlencode }}"><button class="inline-block bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-lg shadow-lg focus:outline-none focus:shadow-outline transition duration-150 ease-in-out"><i class="fas fa-envelope mr-2"></i>Send Mail</button></a>
</div>
<div class="flex items-center justify-between">
<p class="inline-block align-baseline font-bold text-base text-red-500 hover:text-red-800">
Invite a friend to join the site and earn 2 points!
</p>
</div>
</div>
{% endblock content %}
{% block after_js %}
<script>
function copyReferralLink() {
var copyText = document.getElementById("referralLink");
copyText.select();
copyText.setSelectionRange(0, 99999);
navigator.clipboard.writeText(copyText.value);
alert("Copied to clipboard: " + copyText.value);
}
</script>
{% endblock %}
93 changes: 52 additions & 41 deletions website/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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":
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit 7482fd3

Please sign in to comment.