Files
goodtimes/accounts/views.py

1179 lines
46 KiB
Python

import logging
from django.conf import settings
from django.db.models import Count, Q
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.views import LogoutView
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.hashers import make_password
from django.contrib.auth.views import (
LoginView,
PasswordResetCompleteView,
PasswordResetConfirmView,
PasswordResetDoneView,
PasswordResetView,
)
from django.core.exceptions import ValidationError
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse_lazy
from django.views import generic
from django.db import models, transaction, IntegrityError
from django.utils import timezone
from accounts import permission
from goodtimes import constants
from goodtimes.services import EmailService
from goodtimes.utils import JsonResponseUtil
from manage_events.models import EventCategory, PrincipalPreference
from manage_referrals.models import ReferralCode
from manage_subscriptions.models import PrincipalSubscription, Subscription
from . import resource_action
from .forms import (
CreateCustomerForm,
CustomAuthenticationForm,
IAmPrincipalForm,
IAmPrincipalGroupRoleLinkForm,
IAmPrincipalResourceLinkForm,
IAmPrincipalRoleAppResourceActionLinkForm,
IAmPrincipalGroupLinkForm,
ProfileEditForm,
UpdateCustomerForm,
UploadExcelForm,
)
from .models import (
IAmPrincipal,
IAmPrincipalExtendedData,
IAmPrincipalType,
IAmAppResourceActionLink,
IAmPrincipalGroup,
IAmRole,
)
logger = logging.getLogger(__name__)
class AdminLoginView(generic.View):
form_class = CustomAuthenticationForm
template_name = "accounts/authentication/login.html"
success_url = reverse_lazy("dashboard:main_dashboard")
error_url = reverse_lazy("accounts:login")
success_message = constants.LOGIN_SUCCESS
error_message = "Login failed, Invalid email or password!"
def get(self, request):
form = self.form_class()
return render(request, self.template_name, context={"form": form})
def post(self, request):
form = self.form_class(data=request.POST)
if not form.is_valid():
error_message = form.errors.get("__all__") or ["Invalid email or password."]
messages.error(
request, error_message[0]
) # Display the form-level error or fallback message
return redirect(self.error_url)
# Uncomment this block if you implement the first-time login logic
# if not user.last_login:
# messages.info(request, "Welcome! Since this is your first login, please change your password.")
# return redirect(reverse_lazy('accounts:change_password'))
login(request, form.user)
return redirect(self.success_url)
class AdminLogoutView(LogoutView):
next_page = reverse_lazy("accounts:login")
class CustomPasswordResetView(PasswordResetView):
form_class = PasswordResetForm
template_name = "accounts/authentication/password_reset_form.html"
email_template_name = "accounts/authentication/password_reset_email_template.html"
success_url = reverse_lazy("accounts:password_reset_done")
class CustomPasswordResetDoneView(PasswordResetDoneView):
template_name = "accounts/authentication/password_reset_done.html"
class CustomPasswordResetConfirmView(PasswordResetConfirmView):
template_name = "accounts/authentication/password_reset_confirm.html"
success_url = reverse_lazy("accounts:password_reset_complete")
class CustomPasswordResetCompleteView(PasswordResetCompleteView):
template_name = "accounts/authentication/password_reset_complete.html"
# class PrinicpalCreateView(generic.View):
# model = IAmPrincipal
# form_class = RegistrationForm
# template_name = "registration/form.html"
# title = "Add Sub admin"
# success_message = constants.RECORD_CREATED
# error_message = constants.ERROR_OCCURR
# success_url = reverse_lazy("accounts:register")
# def get_context_data(self, **kwargs):
# context = {"title": self.title, "operation": "Add"}
# context.update(kwargs)
# return context
# def get(self, *args, **kwargs):
# form = self.form_class()
# context = self.get_context_data(form=form)
# return render(self.request, self.template_name, context=context)
# def post(self, *args, **kwargs):
# form = self.form_class(self.request.POST)
# if not form.is_valid():
# messages.error(self.request, self.error_message)
# context = self.get_context_data(form=form)
# return render(self.request, self.template_name, context=context)
# form.save()
# messages.success(self.request, self.success_message)
# return redirect(self.success_url)
# template_name = "registration/password_reset_complete.html"
class AdminDashboard(generic.View):
template_name = "dashboard/index.html"
def get(self, request):
return render(request, self.template_name)
"""I Am Principal"""
class PrincipalListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL
# resource = resource_action.RESOURCE_IAM_PRINCIPAL
# action = resource_action.ACTION_READ
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("principal_type", "principal_source")
.exclude(
models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_USER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_FREE_USER
)
)
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
import datetime
class PrincipalCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL
model = IAmPrincipal
form_class = IAmPrincipalForm
template_name = "accounts/iam_module/iam_principal_add.html"
success_url = reverse_lazy("accounts:principal_list")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Edit" if self.object else "Add",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
@transaction.atomic
def post(self, request, *args, **kwargs):
print(request.POST)
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
try:
if form.is_valid():
principal = form.save(commit=False)
# Check if it's a new object (create action) or an existing one (update action)
if not principal.pk: # pk is None for new objects
principal.created_by = request.user
principal.modified_by = request.user
principal.modified_on = timezone.now()
# Save the object
principal.save()
messages.success(request, "Form submitted successfully")
return redirect(self.success_url)
except Exception as e:
self.error_message = constants.ERROR_OCCURR.format(str(e))
print(self.error_message)
messages.error(request, self.error_message)
context = self.get_context_data(form=form)
return render(request, template_name=self.template_name, context=context)
class PrincipalResourcePermissionEditView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL
resource = resource_action.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_resource_permission_edit.html"
form_class = IAmPrincipalResourceLinkForm
success_url = reverse_lazy("accounts:principal_group_link_list")
success_message = "Record Updated Successfully"
error_message = "An error occurred while saving the data"
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(request, self.success_message)
return redirect(self.success_url)
"""Principal Group Link"""
class PrincipalGroupLinkListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_group_link_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("principal_type", "principal_source")
.prefetch_related("principal_group")
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
context["admin_principal"] = self.get_queryset().filter(
principal_type__name=resource_action.PRINCIPAL_TYPE_ADMIN, is_active=True
)
context["subadmin_principal"] = self.get_queryset().filter(
principal_type__name=resource_action.PRINCIPAL_TYPE_SUBADMIN, is_active=True
)
print(context["subadmin_principal"])
return context
class PrincipalGroupLinkEditView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_PRINCIPAL_GROUP
model = IAmPrincipal
template_name = "accounts/iam_module/iam_principal_group_link_edit.html"
form_class = IAmPrincipalGroupLinkForm
success_url = reverse_lazy("accounts:principal_group_link_list")
success_message = "Record Updated Successfully"
error_message = "An error occurred while saving the data"
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(request, self.success_message)
return redirect(self.success_url)
"""Principal Group"""
class PrincipalGroupListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_GROUP
model = IAmPrincipalGroup
template_name = "accounts/iam_module/iam_group_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return super().get_queryset().prefetch_related("role").filter(deleted=False)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class PrincipalGroupCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_GROUP
page_title = "Principal Group"
model = IAmPrincipalGroup
template_name = "accounts/iam_module/iam_group_add.html"
form_class = IAmPrincipalGroupRoleLinkForm
success_url = reverse_lazy("accounts:principal_group_list")
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
constants.RECORD_CREATED if not self.object else constants.RECORD_UPDATED
)
return self.success_message
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Add" if not self.object else "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)
class PrincipalGroupDeleteView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_GROUP
model = IAmPrincipalGroup
success_url = reverse_lazy("accounts:principal_group_list")
success_message = constants.RECORD_DELETED
error_message = constants.RECORD_NOT_FOUND
def get(self, request, pk):
try:
type_obj = self.model.objects.get(id=pk)
principal = IAmPrincipal.objects.filter(principal_group=type_obj).exists()
if principal:
messages.success(
request,
"You can't delete this record as it's assigned to principals.",
)
else:
type_obj.deleted = True
type_obj.save()
messages.success(request, self.success_message)
except self.model.DoesNotExist:
messages.success(request, self.error_message)
return redirect(self.success_url)
""" Role"""
class AppRoleListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "accounts/iam_module/iam_role_list.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.prefetch_related(
"app_resource_action",
"app_resource_action__app_resource",
"app_resource_action__app_action",
)
.filter(deleted=False)
)
def generate_role_data(self):
roles = self.get_queryset()
role_data = []
for role in roles:
role_info = {
"id": role.id,
"name": role.name,
"active": role.active,
"resources": {},
}
for link in role.app_resource_action.all():
resource = link.app_resource.name
action = link.app_action.name
if resource in role_info["resources"]:
role_info["resources"][resource].append(action)
else:
role_info["resources"][resource] = [action]
role_data.append(role_info)
return role_data
def get_context_data(self, **kwargs):
context = {"page_name": self.page_name, "roles": self.generate_role_data()}
context.update(kwargs)
return context
class AppRoleCreateOrUpdateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_ROLE
model = IAmRole
template_name = "accounts/iam_module/iam_role_add.html"
form_class = IAmPrincipalRoleAppResourceActionLinkForm
success_url = reverse_lazy("accounts:role_list")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
f"Record {'Created' if not self.object else 'Updated'} Successfully"
)
return self.success_message
def get_object(self):
pk = self.kwargs.get("pk")
return get_object_or_404(self.model, pk=pk) if pk else None
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Add" if not self.object else "Edit",
"app_resource_action": IAmAppResourceActionLink.objects.generate_app_resource_action_data(),
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
try:
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
except Exception as e:
messages.error(request, str(e))
return redirect(self.success_url)
def post(self, request, *args, **kwargs):
try:
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)
except Exception as e:
messages.error(self.request, str(e))
return redirect(self.success_url)
class AppRoleDeleteView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_IAM_ROLE
model = IAmRole
success_url = reverse_lazy("accounts:role_list")
success_message = constants.RECORD_DELETED
error_message = constants.RECORD_NOT_FOUND
def get(self, request, pk):
try:
type_obj = self.model.objects.get(id=pk)
principal = IAmPrincipalGroup.objects.filter(role=type_obj).exists()
if principal:
messages.success(
request, "You can't delete this record as it's assigned to groups."
)
else:
type_obj.deleted = True
type_obj.save()
messages.success(request, self.success_message)
except self.model.DoesNotExist:
messages.success(request, self.error_message)
return redirect(self.success_url)
"""Customer"""
class CustomerCheckEmail(generic.View):
model = IAmPrincipal
def post(self, request, *args, **kwargs):
email = request.POST.get('email')
print("check email is cllaed ", email)
if self.model.objects.filter(email=email).exists():
print("exist called")
return JsonResponse({'message': 'This email address is already in use.'}, status=400)
else:
print("email is valid")
return JsonResponse({'message': 'Email is available.'}, status=200)
class CustomerCreateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_MANAGE_CUSTOMER
resource = resource_action.RESOURCE_MANAGE_CUSTOMER
model = IAmPrincipal
form_class = CreateCustomerForm
template_name = "accounts/customer/customer_add.html"
success_url = reverse_lazy("accounts:customer_list")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Add",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
form = self.form_class()
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
print(request.POST)
# return redirect(self.success_url)
form = self.form_class(request.POST)
if not form.is_valid():
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
try:
with transaction.atomic():
# save principal data
principal_obj = IAmPrincipal.objects.create(
email=form.cleaned_data.get('email'),
first_name=form.cleaned_data.get('first_name'),
last_name=form.cleaned_data.get('last_name'),
password=make_password("goodtimes#2024"),
username=form.cleaned_data.get("email"),
email_verified=True,
register_complete=True,
principal_type=IAmPrincipalType.objects.get(name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER),
)
# generate referralcode of manager
ReferralCode.create_referral_code_for_user_manager(
principal=principal_obj, principal_type=principal_obj.principal_type
)
IAmPrincipalExtendedData.objects.create(
principal=principal_obj,
is_onboarded=True,
)
# save principal preferences record
principal_preference = PrincipalPreference.objects.create(principal=principal_obj)
principal_preference.preferred_categories.set(form.cleaned_data.get("preferences"))
principal_subscription= PrincipalSubscription.objects.create(
start_date=form.cleaned_data.get("free_start_date"),
end_date=form.cleaned_data.get("free_end_date"),
principal=principal_obj,
grace_period_end_date=PrincipalSubscription.generate_grace_period_end_date(form.cleaned_data.get("free_end_date")),
is_paid=True,
subscription=Subscription.objects.filter(is_free=True, active=True).first()
)
messages.success(self.request, constants.REGISTRATION_SUCCESS)
return redirect(self.success_url)
except Exception as e:
messages.error(self.request, str(e))
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
class CustomerUpdateView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_MANAGE_CUSTOMER
resource = resource_action.RESOURCE_MANAGE_CUSTOMER
model = IAmPrincipal
form_class = UpdateCustomerForm
template_name = "accounts/customer/customer_edit.html"
success_url = reverse_lazy("accounts:customer_list")
success_message = "Updated Successfully"
error_message = "An error occurred while saving the data."
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
"operation": "Edit",
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
principal_id = kwargs.get("pk")
principal_obj = IAmPrincipal.objects.get(pk=principal_id)
initial_data = {
"first_name": principal_obj.first_name,
"last_name": principal_obj.last_name,
"email": principal_obj.email,
"active": principal_obj.is_active
}
try:
principal_preference = PrincipalPreference.objects.get(principal=principal_obj)
initial_data["preferences"] = list(principal_preference.preferred_categories.all().values_list("id", flat=True))
except PrincipalPreference.DoesNotExist:
initial_data["preferences"] = []
try:
subscription = PrincipalSubscription.objects.filter(principal=principal_obj).latest("created_on")
initial_data["free_start_date"] = subscription.start_date
initial_data["free_end_date"] = subscription.end_date
except PrincipalSubscription.DoesNotExist:
initial_data["free_start_date"] = None
initial_data["free_end_date"] = None
form = self.form_class(initial=initial_data)
context = self.get_context_data(form=form, principal_obj=principal_obj)
print("context dta is ", context)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
customer_id = kwargs.get("pk")
principal_obj = IAmPrincipal.objects.get(pk=customer_id)
form = self.form_class(request.POST)
if not form.is_valid():
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
try:
with transaction.atomic():
# update principal data
principal_obj.first_name = form.cleaned_data.get('first_name')
principal_obj.last_name = form.cleaned_data.get('last_name')
principal_obj.save()
# update principal preferences record
principal_preference, _ = PrincipalPreference.objects.get_or_create(principal=principal_obj)
principal_preference.preferred_categories.set(form.cleaned_data.get("preferences"))
# update principal subscription record
principal_subscription = PrincipalSubscription.objects.filter(principal=principal_obj).order_by('-end_date').first()
if principal_subscription:
principal_subscription.start_date = form.cleaned_data.get("free_start_date")
principal_subscription.end_date = form.cleaned_data.get("free_end_date")
principal_subscription.grace_period_end_date = form.cleaned_data.get("free_end_date") + datetime.timedelta(days=15)
principal_subscription.save()
else:
PrincipalSubscription.objects.create(
principal=principal_obj,
start_date=form.cleaned_data.get("free_start_date"),
end_date=form.cleaned_data.get("free_end_date"),
grace_period_end_date=PrincipalSubscription.generate_grace_period_end_date(form.cleaned_data.get("free_end_date")),
is_paid=True,
subscription=Subscription.objects.filter().first() # Assuming you want to link a default subscription
)
messages.success(self.request, self.success_message)
return redirect(self.success_url)
except Exception as e:
messages.error(self.request, str(e))
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
class CustomerDetailView(LoginRequiredMixin, generic.DetailView):
template_name = 'accounts/customer/customer_detail.html'
def get(self, request, *args, **kwargs):
principal_obj = IAmPrincipal.objects.get(pk=kwargs.get("pk"))
principal_preference = PrincipalPreference.objects.get(principal_id=principal_obj.id)
principal_subscription = PrincipalSubscription.objects.filter(principal=principal_obj).order_by("-start_date").first()
return render(request, self.template_name, locals())
class CustomerListView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_MANAGE_CUSTOMER
resource = resource_action.RESOURCE_MANAGE_CUSTOMER
action = resource_action.ACTION_READ
model = IAmPrincipal
template_name = "accounts/customer/customer_list.html"
context_object_name = "data_objs"
def get_queryset(self):
queryset = (
super()
.get_queryset()
.select_related("principal_type", "principal_source", "extended_data")
.filter(
models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_USER
)
| models.Q(
principal_type__name=resource_action.PRINCIPAL_TYPE_FREE_USER
),
)
)
# Annotate the queryset with the count of referrals for each principal
queryset = queryset.annotate(
referral_count=Count(
"referrals_by_referrer",
filter=Q(
referrals_by_referrer__is_completed=True
), # Assuming you only want to count completed referrals
distinct=True, # Ensures referrals are not double-counted if there are multiple conditions or joins
)
)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
import pandas as pd
from openpyxl import Workbook, load_workbook
from openpyxl.worksheet.datavalidation import DataValidation
from openpyxl.styles import Font
from django.http import HttpResponse
# def export_excel_template(request):
# # Define the columns and create an empty DataFrame
# columns = ['First Name', 'Last Name', 'Email', 'Preferences', 'Free period start date', 'Free period end date']
# df = pd.DataFrame(columns=columns)
# # Create a workbook and select the active worksheet
# wb = Workbook()
# ws = wb.active
# ws.title = 'Customer Registration'
# # # Write the column headers
# # for col_num, column_title in enumerate(df.columns, 1):
# # cell = ws.cell(row=1, column=col_num, value=column_title)
# # cell.font = Font(bold=True)
# # # Create a hidden sheet for preferences
# # ws_prefs = wb.create_sheet(title="Preferences")
# # ws_prefs.sheet_state = 'hidden'
# # # Fetch preferences options from the EventCategory model
# # preferences_options = EventCategory.objects.values_list('title', flat=True)
# # # Write preferences to the hidden sheet
# # for row_num, preference in enumerate(preferences_options, 1):
# # ws_prefs.cell(row=row_num, column=1, value=preference)
# # # Define the range for preferences in the hidden sheet
# # preferences_range = f"Preferences!$A$1:$A${len(preferences_options)}"
# # # Add Data Validation for preferences (drop-down list)
# # dv_preferences = DataValidation(
# # type="list",
# # formula1=preferences_range,
# # allow_blank=True,
# # showDropDown=True
# # )
# # ws.add_data_validation(dv_preferences)
# # dv_preferences.add(f'D2:D1048576') # Apply to the whole column
# # # Add Data Validation for date comparison
# # dv_start_date = DataValidation(
# # type="date",
# # operator="greaterThan",
# # formula1='"1900-01-01"',
# # showErrorMessage=True
# # )
# # dv_end_date = DataValidation(
# # type="custom",
# # formula1="=AND(ISNUMBER(F2), F2>E2)",
# # showErrorMessage=True,
# # errorTitle="Invalid Date",
# # error="End date must be greater than start date."
# # )
# # ws.add_data_validation(dv_start_date)
# # ws.add_data_validation(dv_end_date)
# # dv_start_date.add(f'E2:E1048576')
# # dv_end_date.add(f'F2:F1048576')
# # Save the workbook to a bytes buffer
# response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
# response['Content-Disposition'] = 'attachment; filename=customer_registration_template.xlsx'
# wb.save(response)
# return response
def export_excel_template(request):
# Define the columns and create an empty DataFrame
columns = ['First Name', 'Last Name', 'Email', 'Preferences(should be seperated by comma)', 'Free period start date(YYYY-MM-DD)', 'Free period end date(YYYY-MM-DD)']
df = pd.DataFrame(columns=columns)
# Create a workbook and select the active worksheet
wb = Workbook()
ws = wb.active
ws.title = 'Customer Registration'
# Write the column headers
for col_num, column_title in enumerate(df.columns, 1):
cell = ws.cell(row=1, column=col_num, value=column_title)
cell.font = Font(bold=True)
# Save the workbook to a bytes buffer
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=customer_registration_template.xlsx'
wb.save(response)
return response
class CustomerTransferView(LoginRequiredMixin, generic.View):
model = IAmPrincipal
def get(self, request, *args, **kwargs):
try:
principal_obj = self.model.objects.get(pk=kwargs.get("pk"))
except self.model.DoesNotExist:
messages.error(request, "Something went wrong")
return redirect(reverse_lazy("accounts:customer_detail"))
email_service = EmailService(
subject="Your Exclusive Account Access Details with Good Times!",
to=principal_obj.email,
from_email=settings.EMAIL_HOST_USER,
)
# Send the email
try:
temp_password="goodtimes#2024"
principal_obj.password = make_password(temp_password)
principal_obj.save()
email_service.load_template(
"accounts/customer/account_transfer_email_template.html", locals()
)
email_service.send()
principal_preference = IAmPrincipalExtendedData.objects.get(principal=principal_obj)
principal_preference.is_transferred = True
principal_preference.save()
messages.success(request, "Account Transfer mail send successfully")
except Exception as e:
messages.error(request, f"{str(e)}")
return redirect(reverse_lazy("accounts:customer_detail", kwargs={"pk": kwargs.get("pk")}))
class CustomerImportView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_MANAGE_CUSTOMER
resource = resource_action.RESOURCE_MANAGE_CUSTOMER
action = resource_action.ACTION_READ
template_name = "accounts/customer/customer_bulk_template.html"
form_class = UploadExcelForm
def get_context_data(self, **kwargs):
context = {
"page_name": self.page_name,
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
form = self.form_class()
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request.FILES)
context = self.get_context_data(form=form)
if not form.is_valid():
print(form.errors)
return render(request, self.template_name, context=context)
excel_file = request.FILES['file']
wb = load_workbook(filename=excel_file)
ws = wb.active
error_log = []
principals = []
preferences_l = []
subscriptions = []
principal_type = IAmPrincipalType.objects.get(name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER)
free_subscription = Subscription.objects.filter(is_free=True, active=True).first()
for idx, row in enumerate(ws.iter_rows(min_row=2, values_only=True), start=2):
first_name, last_name, email, preferences, start_date, end_date = row
print(f"{first_name}, {last_name, email, preferences, start_date, end_date}")
# validate all data
if not first_name or not last_name or not email or not preferences or not start_date or not end_date:
error_log.append(f"Row {idx}: Missing data.")
continue
# validate email existence
if IAmPrincipal.objects.filter(email=email).exists():
error_log.append(f"Row {idx}: Email {email} already exists.")
continue
# validate date rnage
if end_date < start_date:
error_log.append(f"Row {idx}: End date {end_date} must greater then start date {start_date}.")
continue
# validate preferences
preference_list = [pref.strip() for pref in preferences.split(',')]
event_categories = EventCategory.objects.filter(title__in=preference_list)
if len(event_categories) != len(preference_list):
error_log.append(f"Row {idx}: One or more preferences are invalid.")
continue
# collect the principals
principal = IAmPrincipal(
first_name=first_name.strip().capitalize(),
last_name=last_name.strip().capitalize(),
email=email.strip(),
password=make_password("goodtimes#2024"),
username=email.strip(),
email_verified=True,
register_complete=True,
principal_type=principal_type
)
principals.append(principal)
# Collect preferences to be set later
preferences_l.append((principal, event_categories, start_date, end_date))
if error_log:
context = self.get_context_data(form=form, error_log=error_log)
messages.error(request, "No recore is created check error log and fix the error in the file ")
return render(request, self.template_name, context=context)
# Use transaction.atomic to ensure all-or-nothing
with transaction.atomic():
# Bulk create principals
for principal in principals:
principal.save()
# Now we need to refresh principals from the DB to get their IDs
principals = IAmPrincipal.objects.filter(email__in=[p.email for p in principals])
# Create subscriptions and preferences
for principal, event_categories, start_date, end_date in preferences_l:
principal = principals.get(email=principal.email)
# Generate referral code for the manager
ReferralCode.create_referral_code_for_user_manager(principal=principal, principal_type=principal_type)
# Create IAmPrincipalExtendedData record
IAmPrincipalExtendedData.objects.create(principal=principal, is_onboarded=True)
# Create PrincipalSubscription record
subscription = PrincipalSubscription(
principal=principal,
start_date=start_date,
end_date=end_date,
grace_period_end_date=PrincipalSubscription.generate_grace_period_end_date(end_date),
is_paid=True,
subscription=free_subscription
)
subscriptions.append(subscription)
# Create PrincipalPreferences record
preference = PrincipalPreference(principal=principal)
preference.save()
preference.preferred_categories.set(event_categories)
# Bulk create subscriptions
PrincipalSubscription.objects.bulk_create(subscriptions)
messages.success(request, "Data imported successfully")
return render(request, self.template_name, context=context)
class CustomerExportView(LoginRequiredMixin, generic.View):
model = IAmPrincipal
def get(self, request, *args, **kwargs):
princiapls = IAmPrincipal.objects.select_related("extended_data").filter(principal_type__name=resource_action.PRINCIPAL_TYPE_EVENT_MANAGER)
# prepare data for excel file
data = []
for principal in princiapls:
data.append([
principal.email,
principal.first_name,
principal.last_name,
str(principal.phone_no) if principal.phone_no else "N/A",
principal.email_verified,
principal.is_active,
# principal.extended_data.is_onboarded if principal.extended_data else 'N/A',
# principal.extended_data.is_transferred if principal.extended_data else 'N/A',
# principal.created_on.replace(tzinfo=None) if principal.created_on else 'N/A'
])
# Define the columns for the Excel file
columns = ["Email", "First Name", "Last Name", "Phone Number", "Email Verified", "Active"]
# Create a workbook and select the active worksheet
wb = Workbook()
ws = wb.active
ws.title = "Event Managers List"
# Write the column headers
for col_num, column_title in enumerate(columns, 1):
cell = ws.cell(row=1, column=col_num, value=column_title)
cell.font = Font(bold=True)
# write the data rows
for row_num, row_data in enumerate(data, 2):
for col_num, cell_value in enumerate(row_data, 1):
ws.cell(row=row_num, column=col_num, value=cell_value)
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=event_managers.xlsx'
wb.save(response)
return response
class DatatableListView(LoginRequiredMixin, generic.ListView):
pass
class PrincipalProfileView(LoginRequiredMixin, generic.ListView):
page_name = resource_action.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "accounts/iam_module/profile_details.html"
context_object_name = "data_obj"
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("principal_type", "principal_source")
.get(id=self.request.user.id)
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_name"] = self.page_name
return context
class PrincipalProfileEditView(LoginRequiredMixin, generic.View):
page_name = resource_action.RESOURCE_MANAGE_DASHBOARD
model = IAmPrincipal
template_name = "accounts/iam_module/profile_details_edit.html"
form_class = ProfileEditForm
success_url = reverse_lazy("accounts:profile_details")
success_message = "Saved Successfully"
error_message = "An error occurred while saving the data."
def get_success_message(self):
self.success_message = (
f"Record {'Created' if not self.object else 'Updated'} Successfully"
)
return self.success_message
def get_object(self):
return self.request.user
def get_context_data(self, **kwargs):
context = {
# "page_name": self.page_name,
"operation": "Edit",
"page_name": self.page_name,
}
context.update(kwargs) # Include any additional context data passed to the view
return context
def get(self, request, *args, **kwargs):
# try:
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
# except Exception as e:
# print("error in project ", str)
# messages.error(request, str(e))
# return redirect(self.success_url)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, request.FILES, instance=self.object)
if not form.is_valid():
print(form.errors)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
form.save()
messages.success(self.request, self.get_success_message())
return redirect(self.success_url)