You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

437 lines
17 KiB
Python

from django.db import models
from django.contrib.auth.models import User
from colorfield.fields import ColorField
from datetime import datetime
from django.db.models import Max
from django.utils import timezone
from django.db.models import Sum, F
from datetime import timedelta
# Create your models here.
class Reference(models.Model):
name = models.CharField(max_length=50)
date = models.DateField()
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class BusinessType(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class CustomerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True)
mobile_number = models.CharField(max_length=50, blank=True)
personal_website = models.URLField(null=True, blank=True)
STATUS_CHOICES = (
('Pending', 'Pending'),
('Active', 'Active'),
('Suspended', 'Suspended'),
('Terminated', 'Terminated'),
)
status = models.CharField(max_length=200, choices=STATUS_CHOICES, default='Active', blank=True)
reference = models.ForeignKey(Reference, on_delete=models.CASCADE, null=True, blank=True)
customer_id = models.CharField(max_length=20, null=True, blank=True)
def __str__(self):
return self.user.username
def save(self, *args, **kwargs):
if not self.customer_id:
# Get the last two digits of the current year
current_year = str(datetime.now().year)[-2:]
# Find the maximum project ID in the database and increment it
max_id = CustomerProfile.objects.aggregate(models.Max('customer_id'))['customer_id__max']
new_id = str(int(max_id[-4:]) + 1).zfill(4) if max_id else '0001' # If no existing records, start with '0001'
self.customer_id = current_year + new_id # Add 'p' prefix
super(CustomerProfile, self).save(*args, **kwargs)
@property
def get_last_seen(self):
connection = Connection.objects.filter(user=self.user).last()
if not connection:
return "Not seen yet"
if connection.online:
return "Online"
last_seen_time = connection.last_seen
now = timezone.now()
time_diff = now - last_seen_time
if time_diff < timedelta(days=1):
if last_seen_time.date() == now.date():
return f"last seen today at {last_seen_time.strftime('%I:%M %p')}"
else:
return f"last seen yesterday at {last_seen_time.strftime('%I:%M %p')}"
else:
return f"last seen on {last_seen_time.strftime('%b %d at %I:%M %p')}"
class Business(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField(unique=True)
financial_number = models.CharField(max_length=50)
vat = models.BooleanField(default=False)
commercial_registration = models.CharField(max_length=50)
phone_number = models.CharField(max_length=50)
website = models.URLField(null=True)
customer = models.ForeignKey(CustomerProfile, on_delete=models.CASCADE, null=True, blank=True)
type = models.ForeignKey(BusinessType, on_delete=models.CASCADE, null=True, blank=True)
logo = models.ImageField(upload_to='uploaded_images')
business_id = models.CharField(max_length=20, null=True, blank=True)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = u'Businesses'
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.business_id:
# Get the last two digits of the current year
current_year = str(datetime.now().year)[-2:]
# Find the maximum project ID in the database and increment it
max_id = Business.objects.aggregate(models.Max('business_id'))['business_id__max']
new_id = str(int(max_id[-4:]) + 1).zfill(4) if max_id else '0001' # If no existing records, start with '0001'
self.business_id = 'B' + current_year + new_id # Add 'p' prefix
super(Business, self).save(*args, **kwargs)
class Department(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
def get_staff(self):
# Retrieve all staff profiles associated with positions in this department
staff_profiles = StaffProfile.objects.filter(staffposition__position__department=self)
return staff_profiles
class JobPosition(models.Model):
name = models.CharField(max_length=100)
department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.name
class StaffProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(upload_to='uploaded_images', null=True, blank=True)
mobile_number = models.CharField(max_length=50)
intern = models.BooleanField(default=False)
active = models.BooleanField(default=True)
staff_id = models.CharField(max_length=20, null=True, blank=True) # Allow null and blank for initial creation
def __str__(self):
return self.user.username
def save(self, *args, **kwargs):
if not self.staff_id:
# Get the last two digits of the current year
current_year = str(datetime.now().year)[-2:]
# Find the maximum project ID in the database and increment it
max_id = StaffProfile.objects.aggregate(models.Max('staff_id'))['staff_id__max']
new_id = str(int(max_id[-4:]) + 1).zfill(4) if max_id else '0001' # If no existing records, start with '0001'
self.staff_id = 'O' + current_year + new_id # Add 'p' prefix
super(StaffProfile, self).save(*args, **kwargs)
@property
def get_last_seen(self):
connection = Connection.objects.filter(user=self.user).last()
if not connection:
return "Not seen yet"
if connection.online:
return "Online"
last_seen_time = connection.last_seen
now = timezone.now()
time_diff = now - last_seen_time
if time_diff < timedelta(days=1):
if last_seen_time.date() == now.date():
return f"last seen today at {last_seen_time.strftime('%I:%M %p')}"
else:
return f"last seen yesterday at {last_seen_time.strftime('%I:%M %p')}"
else:
return f"last seen on {last_seen_time.strftime('%b %d at %I:%M %p')}"
class StaffPosition(models.Model):
staff = models.ForeignKey(StaffProfile, on_delete=models.CASCADE)
position = models.ForeignKey(JobPosition, null=True, on_delete=models.SET_NULL)
start_date = models.DateField()
end_date = models.DateField(null=True, blank=True)
class ProjectType(models.Model):
name = models.CharField(max_length=50)
department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.name
class Project(models.Model):
name = models.CharField(max_length=50)
logo = models.ImageField(null=True, blank=True)
customer = models.ForeignKey(CustomerProfile, on_delete=models.CASCADE, null=True)
manager = models.ForeignKey(StaffProfile, on_delete=models.CASCADE, null=True)
project_type = models.ManyToManyField('ProjectType', default='', related_name='manager_project')
details = models.TextField()
members = models.ManyToManyField('StaffProfile', default='', related_name='members_project')
start_date = models.DateField()
end_date = models.DateField()
active = models.BooleanField(default=True, null=True)
project_id = models.CharField(max_length=20, null=True, blank=True)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.project_id:
# Get the last two digits of the current year
current_year = str(datetime.now().year)[-2:]
# Find the maximum project ID in the database and increment it
max_id = Project.objects.aggregate(models.Max('project_id'))['project_id__max']
new_id = str(int(max_id[-4:]) + 1).zfill(4) if max_id else '0001' # If no existing records, start with '0001'
self.project_id = 'P' + current_year + new_id # Add 'p' prefix
super(Project, self).save(*args, **kwargs)
def is_pinned(self, user):
return PinnedProject.objects.filter(user=user, project=self).exists()
def total_time_worked(self, user):
total_time_seconds = 0
tasks = self.task_set.all() if user.is_superuser else self.task_set.filter(assigned_to=user.staffprofile)
for task in tasks:
total_time_hours, total_time_minutes, total_time_seconds_task = task.total_task_time()
total_time_seconds += (total_time_hours * 3600) + (total_time_minutes * 60) + total_time_seconds_task
total_time_hours = total_time_seconds // 3600
total_time_minutes = (total_time_seconds % 3600) // 60
total_time_seconds = total_time_seconds % 60
return {
'hours': total_time_hours,
'minutes': total_time_minutes,
'seconds': total_time_seconds
}
def open_tasks_count(self, user):
if user.is_superuser:
return Task.objects.filter(project=self).exclude(status='Closed').count()
else:
return Task.objects.filter(project=self, assigned_to=user.staffprofile).exclude(status='Closed').count()
class ProjectStatus(models.Model):
STATUS_CHOICES = (
('In Progress', 'In Progress'),
('Completed', 'Completed'),
('Pending', 'Pending'),
('Cancelled', 'Cancelled'),
)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
status = models.CharField(max_length=200, choices=STATUS_CHOICES)
date = models.DateTimeField()
class PinnedProject(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
class Milestone(models.Model):
title = models.CharField(max_length=150)
description = models.TextField()
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True)
start_date = models.DateField()
end_date = models.DateField()
def __str__(self):
return self.title
class Epic(models.Model):
title = models.CharField(max_length=150)
STATUS_CHOICES = (
('Open', 'Open'),
('Closed', 'Closed')
)
status = models.CharField(max_length=200, choices=STATUS_CHOICES, null=True)
description = models.TextField()
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True)
start_date = models.CharField(max_length=200)
end_date = models.CharField(max_length=200)
def __str__(self):
return self.title
class ProjectRequirement(models.Model):
content = models.CharField(max_length=350)
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True)
date = models.DateField(null=True, auto_now=True)
added_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.content
class ProjectFile(models.Model):
name = models.CharField(max_length=350)
file = models.FileField(upload_to='uploaded_images', blank=True)
date = models.DateField()
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True)
class ProjectCredential(models.Model):
emailorusername = models.CharField(max_length=350)
password = models.CharField(max_length=350)
usedfor = models.CharField(max_length=350)
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True)
class Note(models.Model):
text = models.TextField(blank=True)
date = models.DateTimeField(null=True,blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True,blank=True)
color = ColorField(default='#FF0000',blank=True)
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True, blank=True)
class Task(models.Model):
name = models.CharField(max_length=250)
project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True)
epic = models.ForeignKey(Epic, on_delete=models.CASCADE, null=True)
STATUS_CHOICES = (
('Open', 'Open'),
('Working On', 'Working On'),
('Closed', 'Closed')
)
status = models.CharField(max_length=200, choices=STATUS_CHOICES, null=True)
status_date = models.DateTimeField(default=timezone.now)
extra = models.BooleanField(default=False)
description = models.TextField()
start_date = models.DateField(null=True)
end_date = models.DateField(null=True)
assigned_to = models.ForeignKey(StaffProfile, on_delete=models.CASCADE, null=True)
requirement = models.ForeignKey(ProjectRequirement, on_delete=models.SET_NULL, null=True, blank=True)
task_id = models.CharField(max_length=20, null=True, blank=True)
def save(self, *args, **kwargs):
if not self.task_id:
# Get the last two digits of the current year
current_year = str(datetime.now().year)[-2:]
# Find the maximum project ID in the database and increment it
max_id = Task.objects.aggregate(models.Max('task_id'))['task_id__max']
new_id = str(int(max_id[-4:]) + 1).zfill(4) if max_id else '0001' # If no existing records, start with '0001'
self.task_id = 'T' + current_year + new_id # Add 'p' prefix
if self.pk is not None:
original_task = Task.objects.get(pk=self.pk)
if original_task.status != self.status:
self.status_date = timezone.now()
super(Task, self).save(*args, **kwargs)
def total_task_time(self):
total_time_seconds = 0
for point in self.point_set.all():
if point:
point_hours, point_minutes, point_seconds = point.total_activity_time()
total_time_seconds += (point_hours * 3600) + (point_minutes * 60) + point_seconds
total_time_hours = total_time_seconds // 3600
total_time_minutes = (total_time_seconds % 3600) // 60
total_time_seconds = total_time_seconds % 60
return total_time_hours, total_time_minutes, total_time_seconds
class Point(models.Model):
text = models.TextField(blank=True)
STATUS_CHOICES = (
('Not Completed', 'Not Completed'),
('Working On', 'Working On'),
('Paused', 'Paused'),
('Completed', 'Completed')
)
status = models.CharField(max_length=200, choices=STATUS_CHOICES, null=True)
task = models.ForeignKey(Task, on_delete=models.CASCADE, null=True)
def total_activity_time(self):
total_time_seconds = 0
for activity in self.pointactivity_set.all():
if activity.total_time:
total_time_seconds += activity.total_time.total_seconds()
total_time_hours = int(total_time_seconds // 3600)
total_time_minutes = int((total_time_seconds % 3600) // 60)
total_time_seconds = int(total_time_seconds % 60)
return total_time_hours, total_time_minutes, total_time_seconds
class PointActivity(models.Model):
point = models.ForeignKey(Point, on_delete=models.CASCADE, null=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField(null=True, blank=True)
total_time = models.DurationField(null=True, blank=True)
def save(self, *args, **kwargs):
if self.start_time and not self.end_time:
self.total_time = datetime.now() - self.start_time
elif self.start_time and self.end_time:
self.total_time = self.end_time - self.start_time
super(PointActivity, self).save(*args, **kwargs)
def total_time_in_hours_minutes_seconds(self):
if self.total_time:
total_seconds = self.total_time.total_seconds()
hours = int(total_seconds // 3600)
minutes = int((total_seconds % 3600) // 60)
seconds = int(total_seconds % 60)
return hours, minutes, seconds
return 0, 0, 0
class Status(models.Model):
text = models.TextField(blank=True)
date = models.CharField(max_length=40)
time = models.CharField(max_length=40)
staff = models.ForeignKey(StaffProfile, on_delete=models.CASCADE, null=True,blank=True, related_name='staff')
task = models.ForeignKey(Task, on_delete=models.SET_NULL ,null=True, blank=True, related_name='reference_task')
def __str__(self):
return self.text
class Reaction(models.Model):
status = models.ForeignKey(Status, on_delete=models.CASCADE)
emoji = models.CharField(max_length=15)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class DailyReport(models.Model):
text = models.TextField(blank=True)
date = models.CharField(max_length=40)
time = models.CharField(max_length=40)
staff = models.ForeignKey(StaffProfile, on_delete=models.CASCADE, null=True,blank=True, related_name='dailyreport_staff')
class Connection(models.Model):
date = models.DateTimeField(null=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
online = models.BooleanField(default=True)
last_seen = models.DateTimeField(null=True, blank=True)
disconnected = models.BooleanField(default=False)