import logging from datetime import datetime from django.contrib import messages from django.contrib.auth import authenticate, login, logout from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.views import (LoginView, LogoutView, PasswordResetCompleteView, PasswordResetConfirmView, PasswordResetDoneView, PasswordResetView) from django.db.models import Prefetch, Q from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.views import generic from django_datatables_view.base_datatable_view import BaseDatatableView from module_activity.models import (Bowel, ChronicCondition, Intolerance, MealRecord, MealSymptomRecord, Medication, PastTreatment, PrincipalHealthData, Symptoms) from module_iam import iam_constant, permission from module_iam.models import IAmPrincipal, IAmPrincipalType from module_project import constants from module_project.mixins import ActionMixin from module_project.utils import JsonResponseUtil from .forms import LoginForm, UserForm logger = logging.getLogger(__name__) class AdminLoginView(generic.View): template_name = "module_auth/login.html" form_class = LoginForm success_url = reverse_lazy("module_iam:dashboard") error_url = reverse_lazy("module_auth:login") success_message = constants.LOGIN_SUCCESS error_message = constants.INVALID_EMAIL_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) context = {"form": form} if not form.is_valid(): messages.error(request, constants.INVALID_EMAIL_PASSWORD) return render(request, self.template_name, context=context) email = form.cleaned_data['email'] password = form.cleaned_data['password'] user = authenticate(request, email=email, password=password) if user is None: messages.error(request, constants.INVALID_EMAIL_PASSWORD) return render(request, self.template_name, context=context) login(request, user) messages.success(request, constants.LOGIN_SUCCESS) logging.info(f"User {user.email} logged in.") return redirect(self.success_url) class AdminLogoutView(LogoutView): next_page = reverse_lazy("module_auth:login") class CustomPasswordResetView(PasswordResetView): form_class = PasswordResetForm template_name = "module_auth/password_reset_form.html" email_template_name = "module_auth/password_reset_email_template.html" success_url = reverse_lazy("module_auth:password_reset_done") class CustomPasswordResetDoneView(PasswordResetDoneView): template_name = "module_auth/password_reset_done.html" class UserDashView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.TemplateView): page_name = iam_constant.RESOURCE_MANAGE_USER resource = iam_constant.RESOURCE_MANAGE_USER action = None template_name = "module_auth/users_list.html" model = IAmPrincipal context_objext_name = "obj" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["page_name"] = self.page_name return context class UserCreateOrUpdateView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View): page_name = iam_constant.RESOURCE_MANAGE_USER resource = iam_constant.RESOURCE_MANAGE_USER model = IAmPrincipal form_class = UserForm template_name = "module_auth/user_add.html" success_url = reverse_lazy("module_auth:users") 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.principal_type = IAmPrincipalType.objects.filter(name=iam_constant.PRINCIPAL_TYPE_USER).first() principal.modified_by = request.user principal.modified_on = datetime.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 UserListJson(BaseDatatableView): model = IAmPrincipal columns = ["id", "first_name", "email", "phone_no", "date_of_birth", "is_active"] order_columns = ["id", "first_name", "email", "phone_no", "date_of_birth", "is_active"] FILTER_ICONTAINS = "icontains" def get_filter_method(self): """Returns preferred filter method""" return self.FILTER_ICONTAINS def get_initial_queryset(self): deleted_flag = self.request.GET.get('deleted_flag', False) return self.model.objects.filter(principal_type=IAmPrincipalType.get_principal_user(), deleted=deleted_flag) def filter_queryset(self, qs): print(f"request is {self.request.GET}") search_value = self.request.GET.get("search[value]", None) if search_value: qs = super().filter_queryset(qs) # Call the built-in filtering first for column in self.columns: print(f" columen index pattern {self.request.GET.get(f'columns[{self.columns.index(column)+2}][search][value]', None)}") search_value = self.request.GET.get(f'columns[{self.columns.index(column)+2}][search][value]', None) if search_value: column_data = self.request.GET.get(f'columns[{self.columns.index(column)+2}][data]') if column_data == "is_active": qs = qs.filter(**{f"{column}": search_value}) else: qs = qs.filter(**{f"{column}__icontains": search_value}) return qs def ordering(self, qs): order = self.request.GET.get('order[0][dir]', None) if order: column_index = int(self.request.GET.get('order[0][column]', None)) - 2 order_column = self.order_columns[column_index] if order == "asc": qs = qs.order_by(order_column) elif order == "desc": qs = qs.order_by("-" + order_column) return qs class UserActionView(ActionMixin): model = IAmPrincipal def post(self, request, *args, **kwargs): action = request.POST.get('action') # 'archive', 'active', or 'unarchive' ids = request.POST.getlist('ids[]') # List of IDs to perform action on active = request.POST.get('active') print(f"arhive action {action} and id is {ids} and active data is {active}") if action == 'archive': # Update 'deleted' field to True for the selected users self.model.objects.filter(id__in=ids).update(deleted=True, is_active=False) message = 'Record archived successfully.' elif action == 'active': # Update 'active' field to True for the selected users self.model.objects.filter(id__in=ids).update(is_active=active.capitalize()) message = 'Record updated successfully.' elif action == 'unarchive': # Update 'deleted' field to False for the selected users self.model.objects.filter(id__in=ids).update(deleted=False) message = 'Record unarchived successfully.' else: return JsonResponseUtil.error(message="Invalid Action") return JsonResponseUtil.success(message=message) class UserRecordView(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.View): page_name = iam_constant.RESOURCE_MANAGE_USER resource = iam_constant.RESOURCE_MANAGE_USER action = None model = IAmPrincipal template_name = "module_auth/user_view.html" def get_recent_meal(self, id): recent_meal_records = MealRecord.objects.filter( principal=id ).order_by('-id')[:5] return recent_meal_records def get_recent_medication(self, id): recent_medication_records = Medication.objects.filter( principal=id ).order_by('-id')[:5] return recent_medication_records def get_recent_bowel(self, id): recent_bowel_records = Bowel.objects.filter( principal=id ).order_by('-id')[:5] return recent_bowel_records def get_recent_meal_symptom(self, id): recent_meal_symptom_records = MealSymptomRecord.objects.filter( principal=id ).order_by('-id')[:5] return recent_meal_symptom_records def get(self, request, id): # Retrieve the IAmPrincipal instance principal_instance = get_object_or_404(IAmPrincipal, id=id) # Prefetch related Intolerance objects for the principal intolerance_prefetch = Prefetch( "intolerance_principal", queryset=Intolerance.objects.filter(principal=principal_instance), to_attr="intolerance_data", ) symptom_prefetch = Prefetch( "symptoms_principal", queryset=Symptoms.objects.filter(principal=principal_instance), to_attr="symptoms_data", ) pasttreatment_prefetch = Prefetch( "pasttreatment_principal", queryset=PastTreatment.objects.filter(principal=principal_instance), to_attr="pasttreatment_data", ) chronic_prefetch = Prefetch( "chronic_principal", queryset=ChronicCondition.objects.filter(principal=principal_instance), to_attr="chronic_data", ) # Now fetch the principal instance with prefetches obj = IAmPrincipal.objects.prefetch_related( intolerance_prefetch, symptom_prefetch, pasttreatment_prefetch, chronic_prefetch ).get(id=id) for data in obj.chronic_data: print(f"data is {data.name, data.duration}") context = { 'page_name': self.page_name, 'obj': obj, "recent_meal": self.get_recent_meal(id), "recent_medication": self.get_recent_medication(id), "recent_bowel": self.get_recent_bowel(id), "recent_meal_symptom": self.get_recent_meal_symptom(id), } # Render the template with the principal instance and related data return render(request, self.template_name, context=context) class UserArchiveList(permission.ResourcePermissionRequiredMixin, LoginRequiredMixin, generic.TemplateView): page_name = iam_constant.RESOURCE_MANAGE_USER resource = iam_constant.RESOURCE_MANAGE_USER action = None template_name = "module_auth/users_archive_list.html" model = IAmPrincipal def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["page_name"] = self.page_name return context class CustomPasswordResetConfirmView(PasswordResetConfirmView): template_name = "module_auth/password_reset_confirm.html" success_url = reverse_lazy("module_auth:password_reset_complete") class CustomPasswordResetCompleteView(PasswordResetCompleteView): template_name = "module_auth/password_reset_complete.html" class UsersCountView(generic.View): def get(self, request): current_year = int(self.request.GET.get("year")) user_counts = [] # Iterate over each month from January to December for month in range(1, 13): # Calculate the start and end dates for the current month start_date = datetime(current_year, month, 1) end_date = datetime(current_year, month + 1, 1) if month < 12 else datetime(current_year + 1, 1, 1) # Query the User model to count users created within the current month user_count = IAmPrincipal.objects.filter(date_joined__range=(start_date, end_date)).count() # Append the count to the list user_counts.append(user_count) return JsonResponseUtil.success(message=constants.SUCCESS, data=user_counts)