[UPDT] PROJECT: Updated project app by adding verbose name for models and fields

This commit is contained in:
Horilla
2025-05-07 14:01:30 +05:30
parent 7c780f403d
commit b89ac75370
4 changed files with 97 additions and 66 deletions

View File

@@ -9,6 +9,7 @@ from django.db.models import Q
from django.http import HttpResponse
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
from django.views.generic import ListView
@@ -137,7 +138,7 @@ class ProjectsNavView(HorillaNavView):
("status", _("Status")),
("is_active", _("Is active")),
]
nav_title = _("Projects")
nav_title = Project._meta.verbose_name_plural
filter_instance = ProjectFilter()
filter_form_context_name = "form"
filter_body_template = "cbv/projects/filter.html"
@@ -170,20 +171,23 @@ class ProjectsList(HorillaListView):
if self.request.user.is_superuser:
self.action_method = "actions"
@cached_property
def columns(self):
instance = self.model()
return [
(instance._meta.get_field("title").verbose_name, "title"),
(instance._meta.get_field("managers").verbose_name, "get_managers"),
(instance._meta.get_field("members").verbose_name, "get_members"),
(instance._meta.get_field("status").verbose_name, "status_column"),
(instance._meta.get_field("start_date").verbose_name, "start_date"),
(instance._meta.get_field("end_date").verbose_name, "end_date"),
(instance._meta.get_field("document").verbose_name, "get_document_html"),
(instance._meta.get_field("description").verbose_name, "get_description"),
]
model = Project
filter_class = ProjectFilter
columns = [
(_("Project"), "title"),
(_("Project Managers"), "get_managers"),
(_("Project Members"), "get_members"),
(_("Status"), "status_column"),
(_("Start Date"), "start_date"),
(_("End Date"), "end_date"),
(_("File"), "get_document_html"),
(_("Description"), "get_description"),
]
sortby_mapping = [
("Project", "title"),
("Start Date", "start_date"),
@@ -274,7 +278,7 @@ class ProjectFormView(HorillaFormView):
form_class = ProjectForm
model = Project
new_display_title = _("Create Project")
new_display_title = _("Create") + " " + model._meta.verbose_name
def __init__(self, **kwargs):
super().__init__(**kwargs)
@@ -286,7 +290,9 @@ class ProjectFormView(HorillaFormView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.form.instance.pk:
self.form_class.verbose_name = _("Update project")
self.form_class.verbose_name = (
_("Update") + " " + self.model._meta.verbose_name
)
return context
def form_valid(self, form: ProjectForm) -> HttpResponse:

View File

@@ -1,6 +1,7 @@
import django_filters
from django import forms
from django.db.models import Q
from django.utils.translation import gettext as _
from horilla.filters import FilterSet, HorillaFilterSet, filter_by_name
@@ -27,11 +28,13 @@ class ProjectFilter(HorillaFilterSet):
field_name="start_date",
lookup_expr="gte",
widget=forms.DateInput(attrs={"type": "date"}),
label=_("Start From"),
)
end_till = django_filters.DateFilter(
field_name="end_date",
lookup_expr="lte",
widget=forms.DateInput(attrs={"type": "date"}),
label=_("End Till"),
)
def filter_by_project(self, queryset, _, value):

View File

@@ -19,6 +19,7 @@ from django.utils.translation import gettext_lazy as _
from employee.models import Employee
from horilla.horilla_middlewares import _thread_locals
from horilla.models import HorillaModel
from horilla_views.cbv_methods import render_template
# Create your models here.
@@ -43,7 +44,7 @@ def validate_time_format(value):
raise ValidationError(_("Invalid format")) from error
class Project(models.Model):
class Project(HorillaModel):
PROJECT_STATUS = [
("new", "New"),
("in_progress", "In Progress"),
@@ -52,28 +53,28 @@ class Project(models.Model):
("cancelled", "Cancelled"),
("expired", "Expired"),
]
title = models.CharField(max_length=200, unique=True, verbose_name="Name")
title = models.CharField(max_length=200, unique=True, verbose_name=_("Name"))
managers = models.ManyToManyField(
Employee,
blank=True,
related_name="project_managers",
verbose_name="Project Managers",
verbose_name=_("Project Managers"),
)
members = models.ManyToManyField(
Employee,
blank=True,
related_name="project_members",
verbose_name="Project Members",
verbose_name=_("Project Members"),
)
status = models.CharField(choices=PROJECT_STATUS, max_length=250, default="new")
start_date = models.DateField()
end_date = models.DateField(null=True, blank=True)
status = models.CharField(
choices=PROJECT_STATUS, max_length=250, default="new", verbose_name=_("Status")
)
start_date = models.DateField(verbose_name=_("Start Date"))
end_date = models.DateField(null=True, blank=True, verbose_name=_("End Date"))
document = models.FileField(
upload_to="project/files", blank=True, null=True, verbose_name="Project File"
upload_to="project/files", blank=True, null=True, verbose_name=_("Project File")
)
is_active = models.BooleanField(default=True)
description = models.TextField()
objects = models.Manager()
description = models.TextField(verbose_name=_("Description"))
def get_description(self, length=50):
"""
@@ -190,7 +191,7 @@ class Project(models.Model):
This method to get delete url
"""
url = reverse_lazy("delete-project", kwargs={"project_id": self.pk})
message = "Are you sure you want to delete this project?"
message = _("Are you sure you want to delete this project?")
return f"'{url}'" + "," + f"'{message}'"
def actions(self):
@@ -238,22 +239,31 @@ class Project(models.Model):
def status_column(self):
return dict(self.PROJECT_STATUS).get(self.status)
class Meta:
"""
Meta class to add the additional info
"""
class ProjectStage(models.Model):
verbose_name = _("Project")
verbose_name_plural = _("Projects")
class ProjectStage(HorillaModel):
"""
ProjectStage model
"""
title = models.CharField(max_length=200)
title = models.CharField(max_length=200, verbose_name=_("Title"))
project = models.ForeignKey(
Project,
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="project_stages",
verbose_name=_("Project"),
)
sequence = models.IntegerField(null=True, blank=True, editable=False)
is_end_stage = models.BooleanField(default=False)
is_end_stage = models.BooleanField(default=False, verbose_name=_("Is end stage"))
def __str__(self) -> str:
return f"{self.title}"
@@ -300,46 +310,50 @@ class ProjectStage(models.Model):
"""
unique_together = ["project", "title"]
verbose_name = _("Project Stage")
verbose_name_plural = _("Project Stages")
class Task(models.Model):
class Task(HorillaModel):
"""
Task model
"""
TASK_STATUS = [
("to_do", "To Do"),
("in_progress", "In Progress"),
("completed", "Completed"),
("expired", "Expired"),
("to_do", _("To Do")),
("in_progress", _("In Progress")),
("completed", _("Completed")),
("expired", _("Expired")),
]
title = models.CharField(max_length=200)
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=200, verbose_name=_("Title"))
project = models.ForeignKey(
Project, on_delete=models.CASCADE, null=True, verbose_name=_("Project")
)
stage = models.ForeignKey(
ProjectStage,
on_delete=models.CASCADE,
null=True,
related_name="tasks",
verbose_name="Project Stage",
verbose_name=_("Project Stage"),
)
task_managers = models.ManyToManyField(
Employee,
blank=True,
verbose_name="Task Managers",
verbose_name=_("Task Managers"),
)
task_members = models.ManyToManyField(
Employee, blank=True, related_name="tasks", verbose_name="Task Members"
Employee, blank=True, related_name="tasks", verbose_name=_("Task Members")
)
status = models.CharField(choices=TASK_STATUS, max_length=250, default="to_do")
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
status = models.CharField(
choices=TASK_STATUS, max_length=250, default="to_do", verbose_name=_("Status")
)
start_date = models.DateField(null=True, blank=True, verbose_name=_("Start Date"))
end_date = models.DateField(null=True, blank=True, verbose_name=_("End Date"))
document = models.FileField(
upload_to="task/files", blank=True, null=True, verbose_name="Task File"
upload_to="task/files", blank=True, null=True, verbose_name=_("Task File")
)
is_active = models.BooleanField(default=True)
description = models.TextField()
description = models.TextField(verbose_name=_("Description"))
sequence = models.IntegerField(default=0)
objects = models.Manager()
def clean(self) -> None:
if self.end_date is not None and self.project.end_date is not None:
@@ -363,6 +377,8 @@ class Task(models.Model):
"""
unique_together = ["project", "title"]
verbose_name = _("Task")
verbose_name_plural = _("Tasks")
def __str__(self):
return f"{self.title}"
@@ -492,37 +508,37 @@ class Task(models.Model):
url = reverse("delete-task", kwargs={"task_id": self.pk})
url_with_params = f"{url}?task_all=true"
message = "Are you sure you want to delete this task?"
message = _("Are you sure you want to delete this task?")
return f"'{url_with_params}'" + "," + f"'{message}'"
class TimeSheet(models.Model):
class TimeSheet(HorillaModel):
"""
TimeSheet model
"""
TIME_SHEET_STATUS = [
("in_Progress", "In Progress"),
("completed", "Completed"),
("in_Progress", _("In Progress")),
("completed", _("Completed")),
]
project_id = models.ForeignKey(
Project,
on_delete=models.CASCADE,
null=True,
related_name="project_timesheet",
verbose_name="Project",
verbose_name=_("Project"),
)
task_id = models.ForeignKey(
Task,
on_delete=models.CASCADE,
null=True,
related_name="task_timesheet",
verbose_name="Task",
verbose_name=_("Task"),
)
employee_id = models.ForeignKey(
Employee,
on_delete=models.CASCADE,
verbose_name="Employee",
verbose_name=_("Employee"),
)
date = models.DateField(default=timezone.now)
time_spent = models.CharField(
@@ -530,13 +546,15 @@ class TimeSheet(models.Model):
default="00:00",
max_length=10,
validators=[validate_time_format],
verbose_name="Hours Spent",
verbose_name=_("Hours Spent"),
)
status = models.CharField(
choices=TIME_SHEET_STATUS, max_length=250, default="in_Progress"
choices=TIME_SHEET_STATUS,
max_length=250,
default="in_Progress",
verbose_name=_("Status"),
)
description = models.TextField(blank=True, null=True)
objects = models.Manager()
description = models.TextField(blank=True, null=True, verbose_name=_("Description"))
class Meta:
ordering = ("-id",)
@@ -606,7 +624,7 @@ class TimeSheet(models.Model):
This method to get delete url
"""
url = reverse_lazy("delete-time-sheet", kwargs={"time_sheet_id": self.pk})
message = "Are you sure you want to delete this time sheet?"
message = _("Are you sure you want to delete this time sheet?")
return f"'{url}'" + "," + f"'{message}'"
def detail_view(self):
@@ -615,3 +633,7 @@ class TimeSheet(models.Model):
"""
url = reverse("time-sheet-detail-view", kwargs={"pk": self.pk})
return url
class Meta:
verbose_name = _("TimeSheet")
verbose_name_plural = _("TimeSheets")

View File

@@ -8,29 +8,29 @@
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6">
<div class="oh-input-group">
<label class="oh-label">{% trans "Manager" %}</label>
{{form.managers}}
<label class="oh-label" for="{{form.managers.id_for_label}}">{{form.managers.label}}</label>
{{form.managers}}
</div>
<div class="oh-input-group">
<label class="oh-label">{% trans "Status" %}</label>
{{form.status}}
<label class="oh-label" for="{{form.status.id_for_label}}">{{ form.status.label }} </label>
{{form.status}}
</div>
<div class="oh-input-group">
<label class="oh-label">{% trans "Start from" %}</label>
<label class="oh-label" for="{{form.start_from.id_for_label}}">{{ form.start_from.label }}</label>
{{form.start_from}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6">
<div class="oh-input-group">
<label class="oh-label">{% trans "Members" %}</label>
<label class="oh-label" for="{{form.members.id_for_label}}">{{ form.members.label }}</label>
{{form.members}}
</div>
<div class="oh-input-group">
<label class="oh-label">{% trans "Active" %}</label>
<label class="oh-label" for="{{form.is_active.id_for_label}}">{{ form.is_active.label }}</label>
{{form.is_active}}
</div>
<div class="oh-input-group">
<label class="oh-label">{% trans "End till" %}</label>
<label class="oh-label" for="{{form.end_till.id_for_label}}">{{ form.end_till.label }}</label>
{{form.end_till}}
</div>
</div>