Need to create Models in django for a task management app. The columns for planned_task are
- Task Area
- Task Type
- Task Assigned Date
- Assigned to
- Supporting member
This is the model for task plan(tasks will be followed according to this schedule)
class PlanTask(models.Model):
id = models.AutoField(primary_key=True)
task_area = models.CharField(max_length=255, null=False)
task_type = models.CharField(max_length=255, null=False)
task_assigned_date = models.DateField(null=False)
assigned_to = models.ForeignKey(User, null=True, blank=True,on_delete=models.DO_NOTHING)
supporting_member = models.ForeignKey(User, null=True, blank=True, on_delete=models.DO_NOTHING)
planned_start_date = models.DateField(null=True, blank=True)
planned_planning_start = models.DateField(null=True, blank=True)
planned_planning_end = models.DateField(null=True, blank=True)
planned_field_work_start = models.DateField(null=True, blank=True)
planned_field_work_end = models.DateField(null=True, blank=True)
planned_reporting_start = models.DateField(null=True, blank=True)
planned_reporting_end = models.DateField(null=True, blank=True)
planned_approval_start = models.DateField(null=True, blank=True)
planned_approval_end = models.DateField(null=True, blank=True)
planned_end_date = models.DateField(null=True, blank=True)
This is the model for Actual task
class ActualTask(models.Model):
id = models.AutoField(primary_key=True)
task_area = models.ForeignKey(Plan, null=True, blank=True, on_delete=models.CASCADE)
STATUS_CHOICES = [
('Assigned', 'Assigned'),
('WIP', 'WIP'),
('Completed', 'Completed'),
]
status = models.CharField(max_length=50, choices=STATUS_CHOICES, default='Assigned', null=False)
planning_stage = models.CharField(max_length=255, null=True, blank=True)
research_planning = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
task_plan = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
initial_task_meeting = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
process_walkover = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
@property
def planning_progress(self):
return (self.research_planning or 0) + (self.task_plan or 0) + (self.initial_task_meeting or 0) + (
self.process_walkover or 0)
field_work_stage = models.CharField(max_length=255, null=True, blank=True)
documents_verification = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
research_work_data_analysis = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
research_work_field = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
query_clarification = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
@property
def field_work_progress(self):
return (self.documents_verification or 0) + (self.research_work_data_analysis or 0) + (
self.research_work_field or 0) + (self.query_clarification or 0)
reporting_stage = models.CharField(max_length=255, null=True, blank=True)
drafting_report = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
task_presentation = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
taskee_feedback_pending = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
final_presentation = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
@property
def reporting_progress(self):
return (self.drafting_report or 0) + (self.task_presentation or 0) + (self.taskee_feedback_pending or 0) + (
self.final_presentation or 0)
approval_stage = models.CharField(max_length=255, null=True, blank=True)
mgmt_approval = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
ic_to_taskee = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
gr_to_taskee = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
completed = models.DecimalField(max_digits=5, decimal_places=2,
choices=[(0, '0'), (10, '10'), (20, '20'), (25, '25')],
validators=[MaxValueValidator(25)], null=True, blank=True)
@property
def approval_progress(self):
return (self.mgmt_approval or 0) + (self.ic_to_taskee or 0) + (self.gr_to_taskee or 0) + (self.completed or 0)
@property
def overall_progress(self):
return (self.planning_progress * 0.15) + (self.field_work_progress * 0.5) + (self.reporting_progress * 0.25) + (
self.approval_progress * 0.1)
actual_start_date = models.DateField(null=True, blank=True)
actual_planning_start = models.DateField(null=True, blank=True)
actual_planning_end = models.DateField(null=True, blank=True)
delay_planning = models.IntegerField(default=0)
actual_field_work_start = models.DateField(null=True, blank=True)
actual_field_work_end = models.DateField(null=True, blank=True)
delay_field_work = models.IntegerField(default=0)
actual_reporting_start = models.DateField(null=True, blank=True)
actual_reporting_end = models.DateField(null=True, blank=True)
delay_reporting = models.IntegerField(default=0)
actual_approval_start = models.DateField(null=True, blank=True)
actual_approval_end = models.DateField(null=True, blank=True)
delay_approval = models.IntegerField(default=0)
actual_end_date = models.DateField(null=True, blank=True)
delay = models.IntegerField(default=0)
def save(self, *args, **kwargs):
# Update actual dates and delays
if self.status == 'WIP' and not self.actual_start_date:
self.actual_start_date = timezone.now().date()
if self.planning_progress > 0 and not self.actual_planning_start:
self.actual_planning_start = timezone.now().date()
if self.planning_progress == 100 and not self.actual_planning_end:
self.actual_planning_end = timezone.now().date()
if self.field_work_progress > 0 and not self.actual_field_work_start:
self.actual_field_work_start = timezone.now().date()
if self.field_work_progress == 100 and not self.actual_field_work_end:
self.actual_field_work_end = timezone.now().date()
if self.reporting_progress > 0 and not self.actual_reporting_start:
self.actual_reporting_start = timezone.now().date()
if self.reporting_progress == 100 and not self.actual_reporting_end:
self.actual_reporting_end = timezone.now().date()
if self.approval_progress > 0 and not self.actual_approval_start:
self.actual_approval_start = timezone.now().date()
if self.approval_progress == 100 and not self.actual_approval_end:
self.actual_approval_end = timezone.now().date()
if self.status == 'Completed' and not self.actual_end_date:
self.actual_end_date = timezone.now().date()
# Calculate delays
# Assuming planned_* fields are provided and should be datetime.date objects
today = timezone.now().date()
if hasattr(self, 'planned_planning_end') and self.planned_planning_end:
self.delay_planning = max((today - self.planned_planning_end).days,
0) if self.actual_planning_end is None else max(
(self.actual_planning_end - self.planned_planning_end).days, 0)
if hasattr(self, 'planned_field_work_end') and self.planned_field_work_end:
self.delay_field_work = max((today - self.planned_field_work_end).days,
0) if self.actual_field_work_end is None else max(
(self.actual_field_work_end - self.planned_field_work_end).days, 0)
if hasattr(self, 'planned_reporting_end') and self.planned_reporting_end:
self.delay_reporting = max((today - self.planned_reporting_end).days,
0) if self.actual_reporting_end is None else max(
(self.actual_reporting_end - self.planned_reporting_end).days, 0)
if hasattr(self, 'planned_approval_end') and self.planned_approval_end:
self.delay_approval = max((today - self.planned_approval_end).days,
0) if self.actual_approval_end is None else max(
(self.actual_approval_end - self.planned_approval_end).days, 0)
self.delay = self.delay_planning + self.delay_field_work + self.delay_reporting + self.delay_approval
super().save(*args, **kwargs)
def __str__(self):
return f"task {self.id}: {self.task_area}"
My idea is that when the team leader assigns a task it goes to the assigned list for the particular team member. Then they can add the task to their work-in-progress list. If they completed it then it will go to their completed list.(and I also want to archive the tasks once the year is completed.)
PlanTask will be a reference for ActualTasks, and I have to link PlanTask model with ActualTasks model so that we can track delay in the progress.
The “Assigned to” and “Supporting member” are foreign keys taken from Users model. But when I gave these two, I got a error
Reverse accessor ‘User.plan_set’ for ‘task_management.Plan.assigned_to’ clashes with reverse accessor for ‘task_management.Plan.supporting_member’ HINT: Add or change a related_name argument to the definition
Is this linking PlanTask with ActualTasks possible? or is there any easy way to do this?