From c4de53b568d095e25d514566c9d1d68cfe73558e Mon Sep 17 00:00:00 2001 From: Horilla Date: Sat, 9 Sep 2023 14:10:09 +0530 Subject: [PATCH] [UPDT]Pylint fixes --- pms/admin.py | 35 +-- pms/apps.py | 12 +- pms/filters.py | 141 +++++++--- pms/forms.py | 55 +++- pms/models.py | 264 +++++++++++++----- .../question_template_update.html | 2 +- .../question_template_view.html | 8 +- .../okr/objective_detailed_view.html | 4 +- pms/templates/okr/objective_list.html | 4 +- pms/templates/okr/objective_update.html | 2 +- pms/templates/period/period_update.html | 2 +- pms/templates/period/period_view.html | 4 +- pms/urls.py | 220 +++++++++++---- pms/views.py | 66 ++--- 14 files changed, 574 insertions(+), 245 deletions(-) diff --git a/pms/admin.py b/pms/admin.py index 9eea64589..ab00def42 100644 --- a/pms/admin.py +++ b/pms/admin.py @@ -1,25 +1,28 @@ +""" +admin.py + +This page is used to register PMS models with admins site. +""" from django.contrib import admin -from . models import Comment,EmployeeKeyResult,Period,EmployeeObjective -from . models import Question,QuestionTemplate,Feedback,Answer,KeyresultFeedback, QuestionOptions -from .models import EmployeeObjective from simple_history.admin import SimpleHistoryAdmin +from .models import Comment, EmployeeKeyResult, Period, EmployeeObjective +from .models import ( + Question, + QuestionTemplate, + Feedback, + Answer, + KeyResultFeedback, + QuestionOptions, +) # Register your models here. objective = [Period] -feedback = [ Question,QuestionTemplate,Feedback,Answer, QuestionOptions] -admin.site.register(EmployeeObjective,SimpleHistoryAdmin) -admin.site.register(EmployeeKeyResult,SimpleHistoryAdmin) +feedback = [Question, QuestionTemplate, Feedback, Answer, QuestionOptions] +admin.site.register(EmployeeObjective, SimpleHistoryAdmin) +admin.site.register(EmployeeKeyResult, SimpleHistoryAdmin) admin.site.register(objective) admin.site.register(feedback) -admin.site.register(KeyresultFeedback) -admin.site.register(Comment,SimpleHistoryAdmin) - - - - - - - - +admin.site.register(KeyResultFeedback) +admin.site.register(Comment, SimpleHistoryAdmin) diff --git a/pms/apps.py b/pms/apps.py index 76503b0aa..61d042235 100644 --- a/pms/apps.py +++ b/pms/apps.py @@ -1,6 +1,14 @@ +""" +Django application configuration for the PMS (Performance Management System) app. +""" from django.apps import AppConfig class PmsConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'pms' + """ + This class provides configuration settings for the PMS app, such as the default + database field type and the app's name. + """ + + default_auto_field = "django.db.models.BigAutoField" + name = "pms" diff --git a/pms/filters.py b/pms/filters.py index 532941f8f..f964104c1 100644 --- a/pms/filters.py +++ b/pms/filters.py @@ -1,24 +1,39 @@ +""" +Module: filters.py + +This module contains custom Django filters and filter sets for +the PMS (Performance Management System) app. +""" import datetime import django_filters -from pms.models import EmployeeObjective, Feedback -from django_filters import DateFilter from django import forms +from django_filters import DateFilter +from pms.models import EmployeeObjective, Feedback + + class DateRangeFilter(django_filters.Filter): + """ + A custom Django filter for filtering querysets based on date ranges. + + This filter allows you to filter a queryset based on date ranges such as 'today', + 'yesterday', 'week', or 'month' in the 'created_at' field of model. + """ + def filter(self, qs, value): if value: - if value == 'today': + if value == "today": today = datetime.date.today() - qs = qs.filter(created_at=today) - if value == 'yesterday': + qs = qs.filter(created_at=today) + if value == "yesterday": today = datetime.date.today() yesterday = today - datetime.timedelta(days=1) - qs = qs.filter(created_at=yesterday) - if value == 'week': + qs = qs.filter(created_at=yesterday) + if value == "week": today = datetime.date.today() start_of_week = today - datetime.timedelta(days=today.weekday()) end_of_week = start_of_week + datetime.timedelta(days=6) qs = qs.filter(created_at__range=[start_of_week, end_of_week]) - elif value == 'month': + elif value == "month": today = datetime.date.today() start_of_month = datetime.date(today.year, today.month, 1) end_of_month = start_of_month + datetime.timedelta(days=31) @@ -32,65 +47,109 @@ class CustomFilterSet(django_filters.FilterSet): for field_name, field in self.filters.items(): filter_widget = self.filters[field_name] widget = filter_widget.field.widget - if isinstance(widget, (forms.NumberInput, forms.EmailInput, forms.TextInput)): - filter_widget.field.widget.attrs.update( - {'class': 'oh-input w-100'}) + if isinstance( + widget, (forms.NumberInput, forms.EmailInput, forms.TextInput) + ): + filter_widget.field.widget.attrs.update({"class": "oh-input w-100"}) elif isinstance(widget, (forms.Select,)): filter_widget.field.widget.attrs.update( - {'class': 'oh-select oh-select-2 select2-hidden-accessible', }) + { + "class": "oh-select oh-select-2 select2-hidden-accessible", + } + ) elif isinstance(widget, (forms.Textarea)): + filter_widget.field.widget.attrs.update({"class": "oh-input w-100"}) + elif isinstance( + widget, + ( + forms.CheckboxInput, + forms.CheckboxSelectMultiple, + ), + ): filter_widget.field.widget.attrs.update( - {'class': 'oh-input w-100'}) - elif isinstance(widget, (forms.CheckboxInput, forms.CheckboxSelectMultiple,)): - filter_widget.field.widget.attrs.update( - {'class': 'oh-switch__checkbox'}) + {"class": "oh-switch__checkbox"} + ) elif isinstance(widget, (forms.ModelChoiceField)): filter_widget.field.widget.attrs.update( - {'class': 'oh-select oh-select-2 select2-hidden-accessible', }) + { + "class": "oh-select oh-select-2 select2-hidden-accessible", + } + ) if isinstance(field, django_filters.CharFilter): - field.lookup_expr='icontains' + field.lookup_expr = "icontains" + - class ObjectiveFilter(CustomFilterSet): - - # objective = django_filters.CharFilter(lookup_expr='icontains') - created_at_date_range = DateRangeFilter(field_name='created_at') + """ + Custom filter set for EmployeeObjective records. + + This filter set allows to filter EmployeeObjective records based on various criteria. + """ + + created_at_date_range = DateRangeFilter(field_name="created_at") created_at = DateFilter( - widget=forms.DateInput(attrs={'type': 'date','class':'oh-input w-100'}), - # add lookup expression here + widget=forms.DateInput(attrs={"type": "date", "class": "oh-input w-100"}), + # add lookup expression here ) updated_at = DateFilter( - widget=forms.DateInput(attrs={'type': 'date','class':'oh-input w-100'}), - # add lookup expression here + widget=forms.DateInput(attrs={"type": "date", "class": "oh-input w-100"}), + # add lookup expression here ) start_date = DateFilter( - widget=forms.DateInput(attrs={'type': 'date','class':'oh-input w-100'}), - # add lookup expression here + widget=forms.DateInput(attrs={"type": "date", "class": "oh-input w-100"}), + # add lookup expression here ) end_date = DateFilter( - widget=forms.DateInput(attrs={'type': 'date','class':'oh-input w-100'}), - # add lookup expression here + widget=forms.DateInput(attrs={"type": "date", "class": "oh-input w-100"}), + # add lookup expression here ) class Meta: + """ + A nested class that specifies the model and fields for the filter. + """ + model = EmployeeObjective - fields = ['objective','status','employee_id','created_at','start_date','updated_at','end_date','archive','emp_obj_id'] - + fields = [ + "objective", + "status", + "employee_id", + "created_at", + "start_date", + "updated_at", + "end_date", + "archive", + "emp_obj_id", + ] + class FeedbackFilter(CustomFilterSet): - review_cycle = django_filters.CharFilter(lookup_expr='icontains') - created_at_date_range = DateRangeFilter(field_name='created_at') + """ + Custom filter set for Feedback records. + + This filter set allows to filter Feedback records based on various criteria. + """ + + review_cycle = django_filters.CharFilter(lookup_expr="icontains") + created_at_date_range = DateRangeFilter(field_name="created_at") start_date = DateFilter( - widget=forms.DateInput(attrs={'type': 'date','class':'oh-input w-100'}), - # add lookup expression here + widget=forms.DateInput(attrs={"type": "date", "class": "oh-input w-100"}), + # add lookup expression here ) end_date = DateFilter( - widget=forms.DateInput(attrs={'type': 'date','class':'oh-input w-100'}), + widget=forms.DateInput(attrs={"type": "date", "class": "oh-input w-100"}), + # add lookup expression here + ) - # add lookup expression here - ) class Meta: + """ + A nested class that specifies the model and fields for the filter. + """ + model = Feedback - fields = '__all__' + fields = "__all__" + def __init__(self, data=None, queryset=None, *, request=None, prefix=None): - super(FeedbackFilter, self).__init__(data=data, queryset=queryset, request=request, prefix=prefix) + super(FeedbackFilter, self).__init__( + data=data, queryset=queryset, request=request, prefix=prefix + ) diff --git a/pms/forms.py b/pms/forms.py index 132ecd507..45e70baa7 100644 --- a/pms/forms.py +++ b/pms/forms.py @@ -4,10 +4,9 @@ forms.py This module is used to register the forms for pms models """ import uuid +from django import forms from django.core.exceptions import ValidationError -from django import forms from django.utils.translation import gettext_lazy as _ -from django import forms from employee.models import Department, JobPosition from pms.models import ( Question, @@ -23,6 +22,9 @@ from pms.models import ( def validate_date(start_date, end_date): + """ + Validates that the start date is before or equal to the end date. + """ if start_date and end_date and start_date > end_date: raise forms.ValidationError("The start date must be before the end date.") @@ -102,11 +104,18 @@ class ObjectiveForm(forms.ModelForm): ) class Meta: + """ + A nested class that specifies the model,fields and style of fields for the form. + """ + model = EmployeeObjective exclude = ["status"] widgets = { "objective": forms.TextInput( - attrs={"class": "oh-input oh-input--block", "placeholder": _("Objective")} + attrs={ + "class": "oh-input oh-input--block", + "placeholder": _("Objective"), + } ), "objective_description": forms.Textarea( attrs={ @@ -215,6 +224,10 @@ class KeyResultForm(forms.ModelForm): ) class Meta: + """ + A nested class that specifies the model,fields and exclude fields for the form. + """ + model = EmployeeKeyResult fields = "__all__" exclude = [ @@ -287,6 +300,9 @@ class KeyResultForm(forms.ModelForm): self.fields["employee_id"].widget.attrs.update({"id": str(uuid.uuid4())}) def clean_value(self, value_type): + """ + Validate the 'current_value' and 'target_value' field of model EmployeeKeyResult. + """ value = self.cleaned_data.get(value_type) other_value = self.cleaned_data.get( "current_value" if value_type == "target_value" else "target_value" @@ -348,8 +364,11 @@ class FeedbackForm(forms.ModelForm): required=False, ) - # employee_key_results_id = forms.ModelChoiceField(queryset=EmployeeKeyResult.objects.filter(id=-8451257845215),widget=forms.SelectMultiple(attrs={"class":"oh-select oh-select-2 w-100 oh-select-2--large","multiple":"multiple"}),required=False) class Meta: + """ + A nested class that specifies the model,fields and exclude fields for the form. + """ + model = Feedback fields = "__all__" exclude = ["status", "archive"] @@ -376,7 +395,6 @@ class FeedbackForm(forms.ModelForm): "class": "oh-select oh-select-2 ", "style": "width:100%; display:none;", "required": "false", - }, ), "colleague_id": forms.SelectMultiple( @@ -398,7 +416,6 @@ class FeedbackForm(forms.ModelForm): "class": "oh-select oh-select--lg oh-select-no-search", "style": "width:100%; display:none;", "required": "false", - } ), } @@ -466,6 +483,10 @@ class QuestionTemplateForm(forms.ModelForm): ) class Meta: + """ + A nested class that specifies the model and fields for the form. + """ + model = QuestionTemplate fields = "__all__" @@ -517,8 +538,11 @@ class QuestionForm(forms.ModelForm): ) class Meta: - model = Question + """ + A nested class that specifies the model,exclude fields and style of fields for the form. + """ + model = Question exclude = ["question_option_id", "template_id"] widgets = { "question_type": forms.Select( @@ -559,6 +583,10 @@ class ObjectiveCommentForm(forms.ModelForm): """ class Meta: + """ + A nested class that specifies the model,exclude fields and style of fields for the form. + """ + model = Comment exclude = ["employee_id", "employee_objective_id"] widgets = { @@ -578,6 +606,10 @@ class PeriodForm(forms.ModelForm): """ class Meta: + """ + A nested class that specifies the model,fields and style of fields for the form. + """ + model = Period fields = "__all__" widgets = { @@ -593,12 +625,11 @@ class PeriodForm(forms.ModelForm): } def __init__(self, *args, **kwargs): + """ + django forms not showing value inside the date, time html element. + so here overriding default forms instance method to set initial value + """ if instance := kwargs.get("instance"): - """ - django forms not showing value inside the date, time html element. - so here overriding default forms instance method to set initial value - """ - kwargs["initial"] = set_date_field_initial(instance) super(PeriodForm, self).__init__(*args, **kwargs) diff --git a/pms/models.py b/pms/models.py index e1370a633..9eee99cee 100644 --- a/pms/models.py +++ b/pms/models.py @@ -1,84 +1,129 @@ from django.db import models -from employee.models import Employee +from django.utils.translation import gettext_lazy as _ + # importing simple history from simple_history.models import HistoricalRecords -from django.utils.translation import gettext_lazy as _ +from employee.models import Employee """Objectives and key result section""" class Period(models.Model): - """ this is a period model used for creating period """ + """this is a period model used for creating period""" - period_name = models.CharField(max_length=150,unique=True) + period_name = models.CharField(max_length=150, unique=True) start_date = models.DateField(null=True, blank=True) end_date = models.DateField(null=True, blank=True) + objects = models.Manager() def __str__(self): return self.period_name + class EmployeeObjective(models.Model): - """ this is a EmployObjective model used for creating Employee objectives """ + """this is a EmployObjective model used for creating Employee objectives""" STATUS_CHOICES = ( - ('On Track', _('On Track')), - ('Behind', _('Behind')), - ('Closed', _('Closed')), - ('At Risk', _('At Risk')), - ('Not Started', _('Not Started')), + ("On Track", _("On Track")), + ("Behind", _("Behind")), + ("Closed", _("Closed")), + ("At Risk", _("At Risk")), + ("Not Started", _("Not Started")), ) objective = models.CharField(null=False, blank=False, max_length=100) objective_description = models.TextField(blank=False, null=False) created_at = models.DateField(auto_now_add=True) - employee_id = models.ForeignKey(Employee, on_delete=models.DO_NOTHING, related_name='employee_objective', null=True, blank=True) + employee_id = models.ForeignKey( + Employee, + on_delete=models.DO_NOTHING, + related_name="employee_objective", + null=True, + blank=True, + ) updated_at = models.DateField(auto_now=True) start_date = models.DateField(null=False, blank=False) end_date = models.DateField(null=False, blank=False) - status = models.CharField(max_length=20,choices=STATUS_CHOICES,null=False, blank=False, default='Not Started') + status = models.CharField( + max_length=20, + choices=STATUS_CHOICES, + null=False, + blank=False, + default="Not Started", + ) history = HistoricalRecords() - archive =models.BooleanField(default=False,null=True,blank=True) + archive = models.BooleanField(default=False, null=True, blank=True) + objects = models.Manager() def __str__(self): - return f'{self.employee_id.employee_first_name} -{self.objective}' - + return f"{self.employee_id.employee_first_name} -{self.objective}" class Comment(models.Model): """comments for objectives""" comment = models.CharField(max_length=150) - employee_id = models.ForeignKey(Employee, on_delete=models.DO_NOTHING, related_name='comment', null=True, blank=True) - employee_objective_id = models.ForeignKey(EmployeeObjective, on_delete=models.CASCADE, related_name='emp_objective', null=True, blank=True) + employee_id = models.ForeignKey( + Employee, + on_delete=models.DO_NOTHING, + related_name="comment", + null=True, + blank=True, + ) + employee_objective_id = models.ForeignKey( + EmployeeObjective, + on_delete=models.CASCADE, + related_name="emp_objective", + null=True, + blank=True, + ) created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) - history = HistoricalRecords(excluded_fields=['comment']) + history = HistoricalRecords(excluded_fields=["comment"]) + objects = models.Manager() def __str__(self): - return f'{self.employee_id.employee_first_name} -{self.comment} ' + return f"{self.employee_id.employee_first_name} -{self.comment} " class EmployeeKeyResult(models.Model): - """employee key result creation """ + """employee key result creation""" + PROGRESS_CHOICES = ( - ('%', _('Percentage')), - ('#', _('Number')), - ('Currency', (('$', 'USD$'), ('₹', 'INR'), ('€', 'EUR'))) + ("%", _("Percentage")), + ("#", _("Number")), + ("Currency", (("$", "USD$"), ("₹", "INR"), ("€", "EUR"))), ) STATUS_CHOICES = ( - ('On Track', _('On Track')), - ('Behind', _('Behind')), - ('Closed', _('Closed')), - ('At Risk', _('At Risk')), - ('Not Started', _('Not Started')) + ("On Track", _("On Track")), + ("Behind", _("Behind")), + ("Closed", _("Closed")), + ("At Risk", _("At Risk")), + ("Not Started", _("Not Started")), ) key_result = models.CharField(max_length=60, null=True, blank=False) key_result_description = models.TextField(blank=False, null=True) - employee_objective_id = models.ForeignKey(EmployeeObjective, on_delete=models.CASCADE, related_name='emp_obj_id') - employee_id = models.ForeignKey(Employee, on_delete=models.DO_NOTHING, related_name='emp_kpi', null=True, blank=True) - progress_type = models.CharField(max_length=60, null=True, blank=True, choices=PROGRESS_CHOICES) - status = models.CharField(max_length=20,choices=STATUS_CHOICES,null=True, blank=True, default='Not Started') + employee_objective_id = models.ForeignKey( + EmployeeObjective, on_delete=models.CASCADE, related_name="emp_obj_id" + ) + employee_id = models.ForeignKey( + Employee, + on_delete=models.DO_NOTHING, + related_name="emp_kpi", + null=True, + blank=True, + ) + progress_type = models.CharField( + max_length=60, null=True, blank=True, choices=PROGRESS_CHOICES + ) + status = models.CharField( + max_length=20, + choices=STATUS_CHOICES, + null=True, + blank=True, + default="Not Started", + ) created_at = models.DateField(auto_now_add=True, blank=True, null=True) updated_at = models.DateField(auto_now=True, null=True, blank=True) start_value = models.IntegerField(null=True, blank=True, default=0) @@ -87,11 +132,10 @@ class EmployeeKeyResult(models.Model): start_date = models.DateField(null=True, blank=True) end_date = models.DateField(null=True, blank=True) history = HistoricalRecords() + objects = models.Manager() def __str__(self): - return f'{self.key_result} ' - - + return f"{self.key_result} " """360degree feedback section""" @@ -99,7 +143,11 @@ class EmployeeKeyResult(models.Model): class QuestionTemplate(models.Model): """question template creation""" - question_template = models.CharField(max_length=100, null=False, blank=False , unique=True) + + question_template = models.CharField( + max_length=100, null=False, blank=False, unique=True + ) + objects = models.Manager() def __str__(self): return self.question_template @@ -107,67 +155,147 @@ class QuestionTemplate(models.Model): class Question(models.Model): """question creation""" + QUESTION_TYPE_CHOICE = ( - ('1', _('Text')), - ('2', _('Rating')), - ('3', _('Boolean')), - ('4', _('Multi-choices')), - ('5', _('Likert')) + ("1", _("Text")), + ("2", _("Rating")), + ("3", _("Boolean")), + ("4", _("Multi-choices")), + ("5", _("Likert")), ) question = models.CharField(max_length=250, null=False, blank=False) - question_type = models.CharField(choices=QUESTION_TYPE_CHOICE, max_length=100, null=True, blank=True) - template_id = models.ForeignKey(QuestionTemplate, on_delete=models.CASCADE, related_name='question', null=True, blank=True) + question_type = models.CharField( + choices=QUESTION_TYPE_CHOICE, max_length=100, null=True, blank=True + ) + template_id = models.ForeignKey( + QuestionTemplate, + on_delete=models.CASCADE, + related_name="question", + null=True, + blank=True, + ) + objects = models.Manager() def __str__(self): return self.question class QuestionOptions(models.Model): - """options for question """ - question_id = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='question_options', null=True, blank=True) + """options for question""" + + question_id = models.ForeignKey( + Question, + on_delete=models.CASCADE, + related_name="question_options", + null=True, + blank=True, + ) option_a = models.CharField(max_length=250, null=True, blank=True) option_b = models.CharField(max_length=250, null=True, blank=True) option_c = models.CharField(max_length=250, null=True, blank=True) option_d = models.CharField(max_length=250, null=True, blank=True) + objects = models.Manager() class Feedback(models.Model): - """feedback model for creating feedback """ + """feedback model for creating feedback""" + STATUS_CHOICES = ( - ('On Track', _('On Track')), - ('Behind', _('Behind') ), - ('Closed', _('Closed') ), - ('At Risk', _('At Risk') ), - ('Not Started', _('Not Started')) + ("On Track", _("On Track")), + ("Behind", _("Behind")), + ("Closed", _("Closed")), + ("At Risk", _("At Risk")), + ("Not Started", _("Not Started")), ) review_cycle = models.CharField(max_length=100, null=False, blank=False) - manager_id = models.ForeignKey(Employee, related_name='feedback_manager', on_delete=models.DO_NOTHING, null=True, blank=False) - employee_id = models.ForeignKey(Employee, on_delete=models.DO_NOTHING, related_name='feedback_employee',null=False,blank=False) - colleague_id = models.ManyToManyField(Employee, related_name='feedback_colleague',blank=True) - subordinate_id = models.ManyToManyField(Employee, related_name='feedback_subordinate',blank=True) - question_template_id = models.ForeignKey(QuestionTemplate, on_delete=models.DO_NOTHING, related_name='feedback_question_template',null=False,blank=False) - status = models.CharField(max_length=50,choices=STATUS_CHOICES,default='Not Started') + manager_id = models.ForeignKey( + Employee, + related_name="feedback_manager", + on_delete=models.DO_NOTHING, + null=True, + blank=False, + ) + employee_id = models.ForeignKey( + Employee, + on_delete=models.DO_NOTHING, + related_name="feedback_employee", + null=False, + blank=False, + ) + colleague_id = models.ManyToManyField( + Employee, related_name="feedback_colleague", blank=True + ) + subordinate_id = models.ManyToManyField( + Employee, related_name="feedback_subordinate", blank=True + ) + question_template_id = models.ForeignKey( + QuestionTemplate, + on_delete=models.DO_NOTHING, + related_name="feedback_question_template", + null=False, + blank=False, + ) + status = models.CharField( + max_length=50, choices=STATUS_CHOICES, default="Not Started" + ) created_at = models.DateField(auto_now_add=True) archive = models.BooleanField(null=True, blank=True, default=False) start_date = models.DateField(null=False, blank=False) end_date = models.DateField(null=True, blank=False) - employee_key_results_id = models.ManyToManyField(EmployeeKeyResult, blank=True,) + employee_key_results_id = models.ManyToManyField( + EmployeeKeyResult, + blank=True, + ) + objects = models.Manager() def __str__(self): - return f'{self.employee_id.employee_first_name} - {self.review_cycle}' + return f"{self.employee_id.employee_first_name} - {self.review_cycle}" class Answer(models.Model): - """feedback answer model """ + """feedback answer model""" + answer = models.JSONField(max_length=200, null=True, blank=True) - question_id = models.ForeignKey(Question, on_delete=models.DO_NOTHING, related_name='answer_question_id',null=True,blank=True) - employee_id = models.ForeignKey(Employee, on_delete=models.DO_NOTHING, related_name='employee_answer',null=True,blank=True) - feedback_id = models.ForeignKey(Feedback, on_delete=models.CASCADE, related_name='feedback_answer') + question_id = models.ForeignKey( + Question, + on_delete=models.DO_NOTHING, + related_name="answer_question_id", + null=True, + blank=True, + ) + employee_id = models.ForeignKey( + Employee, + on_delete=models.DO_NOTHING, + related_name="employee_answer", + null=True, + blank=True, + ) + feedback_id = models.ForeignKey( + Feedback, on_delete=models.CASCADE, related_name="feedback_answer" + ) + objects = models.Manager() def __str__(self): - return f'{self.employee_id.employee_first_name} -{self.answer}' -class KeyresultFeedback(models.Model): - feedback_id = models.ForeignKey(Feedback, on_delete=models.CASCADE, related_name='feedback_key_result', null=True,blank=True) - employee_id = models.ForeignKey(Employee, on_delete=models.DO_NOTHING, related_name='employee_key_result') + return f"{self.employee_id.employee_first_name} -{self.answer}" + + +class KeyResultFeedback(models.Model): + feedback_id = models.ForeignKey( + Feedback, + on_delete=models.CASCADE, + related_name="feedback_key_result", + null=True, + blank=True, + ) + employee_id = models.ForeignKey( + Employee, on_delete=models.DO_NOTHING, related_name="employee_key_result" + ) answer = models.JSONField(max_length=200, null=True, blank=True) - key_result_id = models.ForeignKey(EmployeeKeyResult,related_name='key_result_feedback',null=True,blank=True,on_delete=models.DO_NOTHING) \ No newline at end of file + key_result_id = models.ForeignKey( + EmployeeKeyResult, + related_name="key_result_feedback", + null=True, + blank=True, + on_delete=models.DO_NOTHING, + ) + objects = models.Manager() diff --git a/pms/templates/feedback/question_template/question_template_update.html b/pms/templates/feedback/question_template/question_template_update.html index ff7939226..6cc661271 100644 --- a/pms/templates/feedback/question_template/question_template_update.html +++ b/pms/templates/feedback/question_template/question_template_update.html @@ -1,5 +1,5 @@ {% load i18n %} -
+ {% csrf_token %}
diff --git a/pms/templates/feedback/question_template/question_template_view.html b/pms/templates/feedback/question_template/question_template_view.html index e956bd7fb..c37ec25b0 100644 --- a/pms/templates/feedback/question_template/question_template_view.html +++ b/pms/templates/feedback/question_template/question_template_view.html @@ -56,7 +56,7 @@ {% for question_template in question_templates %}
+ href="{% url 'question-template-detailed-view' template_id=question_template.id %}" class="oh-sticky-table__sd">
{{question_template.question.count}}
diff --git a/pms/templates/okr/objective_detailed_view.html b/pms/templates/okr/objective_detailed_view.html index f8e1cf828..b463caee8 100644 --- a/pms/templates/okr/objective_detailed_view.html +++ b/pms/templates/okr/objective_detailed_view.html @@ -18,7 +18,7 @@ {% if perms.pms.delete_employeeobjective %} -
+ {% csrf_token %} diff --git a/pms/templates/okr/objective_list.html b/pms/templates/okr/objective_list.html index 27f26c5d2..23fd0557b 100644 --- a/pms/templates/okr/objective_list.html +++ b/pms/templates/okr/objective_list.html @@ -107,7 +107,7 @@
{% endif %} {% if perms.pms.delete_employeeobjective %}
{% endif %} {% if perms.pms.delete_employeeobjective %}
diff --git a/pms/templates/period/period_update.html b/pms/templates/period/period_update.html index ba0646471..6ee9fef1d 100644 --- a/pms/templates/period/period_update.html +++ b/pms/templates/period/period_update.html @@ -12,7 +12,7 @@
{% endif %} {% trans "Update Period" %} - + {% csrf_token %}
diff --git a/pms/templates/period/period_view.html b/pms/templates/period/period_view.html index 7ed106f7c..0a76668c1 100644 --- a/pms/templates/period/period_view.html +++ b/pms/templates/period/period_view.html @@ -60,9 +60,9 @@
{{period.end_date}}
- -
diff --git a/pms/urls.py b/pms/urls.py index 5f7ed1ec8..50386e91f 100644 --- a/pms/urls.py +++ b/pms/urls.py @@ -1,65 +1,165 @@ - from django.urls import path -from pms import views +from . import views urlpatterns = [ - - path('objective-creation', views.objective_creation,name='objective-creation'), - path('objective-list-search', views.objective_list_search,name='objective-list-search'), - path('objective-list-view', views.objective_list_view,name='objective-list-view'), - path('objective-update/', views.objective_update,name='objective-update'), - path('objective-delete/', views.objective_delete,name='objective-delete'), - path('objective-archive/', views.objective_archive,name='objective-archive'), - - path('objective-detailed-view/',views.objective_detailed_view,name='objective-detailed-view'), - path('objective-detailed-view-objective-status/',views.objective_detailed_view_objective_status,name='objective-detailed-view-objective-status'), - path('objective-detailed-view-key-result-status//',views.objective_detailed_view_key_result_status,name='objective-detailed-view-key-result-status'), - path('objective-detailed-view-current-value/',views.objective_detailed_view_current_value,name='objective-detailed-view-current-value'), - path('objective-detailed-view-activity/',views.objective_detailed_view_activity,name='objective-detailed-view-activity'), - path('objective-detailed-view-comment/',views.objective_detailed_view_comment,name='objective-detailed-view-comment'), - - path('key-result-creation//',views.key_result_creation,name='key-result-creation'), - path('key-result-creation-htmx/',views.key_result_creation_htmx,name='key-result-creation-htmx'), - path('key-result-update/', views.key_result_update,name='key-result-update'), - - path('feedback-view',views.feedback_list_view,name='feedback-view'), - path('feedback-list-search',views.feedback_list_search,name='feedback-list-search'), - path('feedback-creation',views.feedback_creation,name='feedback-creation'), - path('feedback-creation-ajax',views.feedback_creation_ajax,name="feedback-creation-ajax"), - path('feedback-update/',views.feedback_update,name='feedback-update'), - path('feedback-delete/',views.feedback_delete,name='feedback-delete'), - path('feedback-archive/',views.feedback_archive,name='feedback-archive'), - - path('feedback-answer-get/',views.feedback_answer_get,name='feedback-answer-get'), - path('feedback-answer-post/',views.feedback_answer_post,name='feedback-answer-post'), - path('feedback-answer-view/',views.feedback_answer_view,name='feedback-answer-view'), - path('feedback-detailed-view/',views.feedback_detailed_view,name="feedback-detailed-view"), - path('feedback-detailed-view-answer//',views.feedback_detailed_view_answer,name="feedback-detailed-view-answer"), - path('feedback-detailed-view-status/',views.feedback_detailed_view_status,name="feedback-detailed-view-status"), - path('feedback-status',views.feedback_status,name="feedback-status"), - - - path('question-creation/',views.question_creation,name='question-creation'), - path('question-view/',views.question_view,name='question-view'), - path('question-update//',views.question_update,name='question-update'), - path('question-delete/',views.question_delete,name='question-delete'), - - path('question-template-creation',views.question_template_creation,name='question-template-creation'), - path('question-template-view',views.question_template_view,name='question-template-view'), - path('question-template-detailed-view/',views.question_template_detailed_view,name='question-template-detailed-view'), - path('question-template-update//',views.question_template_update,name='question-template-update'), - path('question-template-delete/',views.question_template_delete,name='question-template-delete'), - - path('period-create',views.period_create,name='period-create'), - path('period-view',views.period_view,name='period-view'), - path('period-delete/',views.period_delete,name='period-delete'), - path('period-update/',views.period_update,name='period-update'), - path('period-change',views.period_change,name='period-change'), - - path('dashboard-view',views.dashboard_view,name='dashboard-view'), - path('dashboard-objective-status',views.dashboard_objective_status,name='dashboard-objective-status'), - path('dashbord-key-result-status',views.dashboard_key_result_status,name='dashbord-key-result-status'), - path('dashboard-feedback-status',views.dashboard_feedback_status,name='dashboard-feedback-status'), - + path("objective-creation", views.objective_creation, name="objective-creation"), + path( + "objective-list-search", + views.objective_list_search, + name="objective-list-search", + ), + path("objective-list-view", views.objective_list_view, name="objective-list-view"), + path( + "objective-update/", views.objective_update, name="objective-update" + ), + path( + "objective-delete/", views.objective_delete, name="objective-delete" + ), + path( + "objective-archive/", views.objective_archive, name="objective-archive" + ), + path( + "objective-detailed-view/", + views.objective_detailed_view, + name="objective-detailed-view", + ), + path( + "objective-detailed-view-objective-status/", + views.objective_detailed_view_objective_status, + name="objective-detailed-view-objective-status", + ), + path( + "objective-detailed-view-key-result-status//", + views.objective_detailed_view_key_result_status, + name="objective-detailed-view-key-result-status", + ), + path( + "objective-detailed-view-current-value/", + views.objective_detailed_view_current_value, + name="objective-detailed-view-current-value", + ), + path( + "objective-detailed-view-activity/", + views.objective_detailed_view_activity, + name="objective-detailed-view-activity", + ), + path( + "objective-detailed-view-comment/", + views.objective_detailed_view_comment, + name="objective-detailed-view-comment", + ), + path( + "key-result-creation//", + views.key_result_creation, + name="key-result-creation", + ), + path( + "key-result-creation-htmx/", + views.key_result_creation_htmx, + name="key-result-creation-htmx", + ), + path( + "key-result-update/", views.key_result_update, name="key-result-update" + ), + path("feedback-view", views.feedback_list_view, name="feedback-view"), + path( + "feedback-list-search", views.feedback_list_search, name="feedback-list-search" + ), + path("feedback-creation", views.feedback_creation, name="feedback-creation"), + path( + "feedback-creation-ajax", + views.feedback_creation_ajax, + name="feedback-creation-ajax", + ), + path("feedback-update/", views.feedback_update, name="feedback-update"), + path("feedback-delete/", views.feedback_delete, name="feedback-delete"), + path("feedback-archive/", views.feedback_archive, name="feedback-archive"), + path( + "feedback-answer-get/", + views.feedback_answer_get, + name="feedback-answer-get", + ), + path( + "feedback-answer-post/", + views.feedback_answer_post, + name="feedback-answer-post", + ), + path( + "feedback-answer-view/", + views.feedback_answer_view, + name="feedback-answer-view", + ), + path( + "feedback-detailed-view/", + views.feedback_detailed_view, + name="feedback-detailed-view", + ), + path( + "feedback-detailed-view-answer//", + views.feedback_detailed_view_answer, + name="feedback-detailed-view-answer", + ), + path( + "feedback-detailed-view-status/", + views.feedback_detailed_view_status, + name="feedback-detailed-view-status", + ), + path("feedback-status", views.feedback_status, name="feedback-status"), + path( + "question-creation/", views.question_creation, name="question-creation" + ), + path("question-view/", views.question_view, name="question-view"), + path( + "question-update//", + views.question_update, + name="question-update", + ), + path("question-delete/", views.question_delete, name="question-delete"), + path( + "question-template-creation", + views.question_template_creation, + name="question-template-creation", + ), + path( + "question-template-view", + views.question_template_view, + name="question-template-view", + ), + path( + "question-template-detailed-view/", + views.question_template_detailed_view, + name="question-template-detailed-view", + ), + path( + "question-template-update//", + views.question_template_update, + name="question-template-update", + ), + path( + "question-template-delete/", + views.question_template_delete, + name="question-template-delete", + ), + path("period-create", views.period_create, name="period-create"), + path("period-view", views.period_view, name="period-view"), + path("period-delete/", views.period_delete, name="period-delete"), + path("period-update/", views.period_update, name="period-update"), + path("period-change", views.period_change, name="period-change"), + path("dashboard-view", views.dashboard_view, name="dashboard-view"), + path( + "dashboard-objective-status", + views.dashboard_objective_status, + name="dashboard-objective-status", + ), + path( + "dashbord-key-result-status", + views.dashboard_key_result_status, + name="dashbord-key-result-status", + ), + path( + "dashboard-feedback-status", + views.dashboard_feedback_status, + name="dashboard-feedback-status", + ), ] diff --git a/pms/views.py b/pms/views.py index fca054244..ed842192e 100644 --- a/pms/views.py +++ b/pms/views.py @@ -1,6 +1,7 @@ import json import datetime from urllib.parse import parse_qs +from itertools import tee from django.http import HttpResponse, JsonResponse from django.db.utils import IntegrityError from django.db.models import Q @@ -11,6 +12,10 @@ from django.utils.translation import gettext_lazy as _ from django.shortcuts import get_object_or_404, render, redirect from horilla.decorators import manager_can_enter from horilla.decorators import login_required, hx_request_required +from notifications.signals import notify +from base.methods import get_key_instances +from base.models import Department, JobPosition +from employee.models import Employee, EmployeeWorkInformation from pms.filters import ObjectiveFilter, FeedbackFilter from pms.models import ( EmployeeKeyResult, @@ -22,12 +27,8 @@ from pms.models import ( Answer, Period, QuestionOptions, - KeyresultFeedback, + KeyResultFeedback, ) -from base.models import Department, JobPosition -from base.methods import get_key_instances -from employee.models import Employee, EmployeeWorkInformation -from itertools import tee from .forms import ( QuestionForm, ObjectiveForm, @@ -37,7 +38,6 @@ from .forms import ( PeriodForm, QuestionTemplateForm, ) -from notifications.signals import notify @login_required @@ -133,15 +133,15 @@ def objective_creation(request): @login_required @hx_request_required @manager_can_enter(perm="pms.change_employeeobjective") -def objective_update(request, id): +def objective_update(request, obj_id): """ This view takes one arguments, id , and returns a HttpResponse object.,using htmx Args: - id (int): Primarykey of EmployeeObjective. + id (int): Primary key of EmployeeObjective. Returns: A HttpResponse object with the content Form errors. """ - instance = EmployeeObjective.objects.get(id=id) + instance = EmployeeObjective.objects.get(id=obj_id) objective_form = ObjectiveForm(instance=instance) context = {"objective_form": objective_form} if request.method == "POST": @@ -176,7 +176,7 @@ def objective_update(request, id): @login_required @manager_can_enter(perm="pms.delete_employeeobjective") -def objective_delete(request, id): +def objective_delete(request, obj_id): """ This view takes one arguments, id and returns redirecting to a view. Args: @@ -184,7 +184,7 @@ def objective_delete(request, id): Returns: Redirect to Objective_list_view". """ - objective = EmployeeObjective.objects.get(id=id) + objective = EmployeeObjective.objects.get(id=obj_id) objective.delete() messages.success( request, @@ -436,14 +436,14 @@ def objective_detailed_view_activity(request, id): """ This view is used to show objective activity template ,using htmx Args: - id (int): Primarykey of EmployeeObjective. + id (int): Primary key of EmployeeObjective. Returns: it will return history,comment object to objective_detailed_view_activity. """ history = objective_history(id) - objecitve = EmployeeObjective.objects.get(id=id) - comments = Comment.objects.filter(employee_objective_id=objecitve) + objective = EmployeeObjective.objects.get(id=id) + comments = Comment.objects.filter(employee_objective_id=objective) context = { "historys": history, "comments": comments, @@ -457,16 +457,16 @@ def objective_detailed_view_comment(request, id): """ This view is used to create comment object for objective activity, using htmx Args: - id (int): Primarykey of EmployeeObjective. + id (int): Primary key of EmployeeObjective. Returns: it will redirect to objective_detailed_view_activity. """ comment_form = ObjectiveCommentForm(request.POST) if comment_form.is_valid(): - objecitve = EmployeeObjective.objects.get(id=id) + objective = EmployeeObjective.objects.get(id=id) form = comment_form.save(commit=False) form.employee_id = request.user.employee_get - form.employee_objective_id = objecitve + form.employee_objective_id = objective form.save() return redirect(objective_detailed_view_activity, id) @@ -557,11 +557,11 @@ def objective_archive(request, id): redirect to objective_list_view """ objective = EmployeeObjective.objects.get(id=id) - if objective.archive == True: + if objective.archive: objective.archive = False objective.save() messages.info(request, _("Objective un-archived successfully!.")) - elif objective.archive == False: + elif not objective.archive: objective.archive = True objective.save() messages.info(request, _("Objective archived successfully!.")) @@ -1143,7 +1143,7 @@ def feedback_answer_post(request, id): for key_result in feedback.employee_key_results_id.all(): if request.POST.get(f"key_result{key_result.id}"): answer = request.POST.get(f"key_result{key_result.id}") - KeyresultFeedback.objects.get_or_create( + KeyResultFeedback.objects.get_or_create( answer={"answer": answer}, key_result_id=key_result, feedback_id=feedback, @@ -1171,7 +1171,7 @@ def feedback_answer_view(request, id): employee = Employee.objects.filter(employee_user_id=user).first() feedback = Feedback.objects.get(id=id) answers = Answer.objects.filter(feedback_id=feedback, employee_id=employee) - key_result_feedback = KeyresultFeedback.objects.filter( + key_result_feedback = KeyResultFeedback.objects.filter( feedback_id=feedback, employee_id=employee ) @@ -1256,11 +1256,11 @@ def feedback_archive(request, id): """ feedback = Feedback.objects.get(id=id) - if feedback.archive == True: + if feedback.archive: feedback.archive = False feedback.save() messages.info(request, _("Feedback un-archived successfully!.")) - elif feedback.archive == False: + elif not feedback.archive: feedback.archive = True feedback.save() messages.info(request, _("Feedback archived successfully!.")) @@ -1498,7 +1498,7 @@ def question_template_view(request): @login_required @manager_can_enter(perm="pms.view_questiontemplate") -def question_template_detailed_view(request, id): +def question_template_detailed_view(request, template_id): """ This view is used to view question template object. Args: @@ -1508,7 +1508,7 @@ def question_template_detailed_view(request, id): it will redirect to question_template_detailed_view. """ - question_template = QuestionTemplate.objects.get(id=id) + question_template = QuestionTemplate.objects.get(id=template_id) questions = question_template.question.all() question_types = ["text", "ratings", "boolean", "multi-choices", "likert"] options = QuestionOptions.objects.filter(question_id__in=questions) @@ -1532,7 +1532,7 @@ def question_template_detailed_view(request, id): @login_required @manager_can_enter(perm="pms.change_questiontemplate") -def question_template_update(request, id): +def question_template_update(request, template_id): """ This view is used to update question template object. Args: @@ -1541,7 +1541,7 @@ def question_template_update(request, id): it will redirect to question_template_view. """ - question_template = QuestionTemplate.objects.filter(id=id).first() + question_template = QuestionTemplate.objects.filter(id=template_id).first() question_update_form = QuestionTemplateForm(instance=question_template) context = {"question_update_form": question_update_form} if request.method == "POST": @@ -1558,7 +1558,7 @@ def question_template_update(request, id): @login_required @manager_can_enter(perm="pms.delete_questiontemplate") -def question_template_delete(request, id): +def question_template_delete(request, template_id): """ This view is used to delete question template object. Args: @@ -1567,7 +1567,7 @@ def question_template_delete(request, id): it will redirect to question_template_view. """ - question_template = QuestionTemplate.objects.get(id=id) + question_template = QuestionTemplate.objects.get(id=template_id) if Feedback.objects.filter(question_template_id=question_template): messages.info(request, _("This template is using in a feedback")) return redirect(question_template_view) @@ -1618,7 +1618,7 @@ def period_create(request): @login_required @manager_can_enter(perm="pms.change_period") -def period_update(request, id): +def period_update(request, period_id): """ This view is used to update period objects. Args: @@ -1627,7 +1627,7 @@ def period_update(request, id): it will redirect to period_view. """ - period = Period.objects.filter(id=id).first() + period = Period.objects.filter(id=period_id).first() form = PeriodForm(instance=period) context = {"form": form} if request.method == "POST": @@ -1646,7 +1646,7 @@ def period_update(request, id): @login_required @manager_can_enter(perm="pms.delete_period") -def period_delete(request, id): +def period_delete(request, period_id): """ This view is used to delete period objects. Args: @@ -1655,7 +1655,7 @@ def period_delete(request, id): it will redirect to period_view. """ - obj_period = Period.objects.get(id=id) + obj_period = Period.objects.get(id=period_id) obj_period.delete() messages.info(request, _("Period deleted successfully.")) return redirect(period_view)