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.
330 lines
13 KiB
Python
330 lines
13 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.CharField(max_length=200)
|
|
def __str__(self):
|
|
return self.name
|
|
def formatted_date(self):
|
|
# Assuming start_date is stored as "day-month-year"
|
|
parts = self.date.split('-')
|
|
return f"{parts[2]}-{parts[1]}-{parts[0]}"
|
|
|
|
|
|
class Tag(models.Model):
|
|
name = models.CharField(max_length=50)
|
|
|
|
|
|
class BusinessType(models.Model):
|
|
name = models.CharField(max_length=50)
|
|
|
|
|
|
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)
|
|
type = models.ForeignKey(BusinessType, on_delete=models.CASCADE, null=True, blank=True)
|
|
logo = models.ImageField()
|
|
business_id = models.CharField(max_length=20, null=True, blank=True) # Allow null and blank for initial creation
|
|
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 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 = (
|
|
('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)
|
|
business = models.ForeignKey(Business, 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)
|
|
|
|
|
|
|
|
|
|
class StaffPosition(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
|
|
|
|
class StaffProfile(models.Model):
|
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
|
image = models.ImageField(null=True, blank=True)
|
|
mobile_number = models.CharField(max_length=50)
|
|
staff_position = models.ForeignKey(StaffPosition, on_delete=models.CASCADE, null=True, blank=True)
|
|
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)
|
|
|
|
|
|
|
|
class ProjectType(models.Model):
|
|
name = models.CharField(max_length=50)
|
|
|
|
|
|
|
|
class Project(models.Model):
|
|
name = models.CharField(max_length=50)
|
|
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')
|
|
STATUS_CHOICES = (
|
|
('Active', 'Active'),
|
|
('Completed', 'Completed'),
|
|
('Pending', 'Pending'),
|
|
('Cancelled', 'Cancelled'),
|
|
)
|
|
status = models.CharField(max_length=200, choices=STATUS_CHOICES)
|
|
start_date = models.CharField(max_length=200)
|
|
end_date = models.CharField(max_length=200)
|
|
project_id = models.CharField(max_length=20, null=True, blank=True) # Allow null and blank for initial creation
|
|
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)
|
|
|
|
|
|
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()
|
|
|
|
|
|
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)
|
|
|
|
|
|
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)
|
|
|
|
|
|
class ProjectFile(models.Model):
|
|
name = models.CharField(max_length=350)
|
|
file = models.FileField(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')
|
|
|
|
|
|
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):
|
|
STATUS_CHOICES = (
|
|
('Online', 'Online'),
|
|
('Offline', 'Offline'),
|
|
)
|
|
status = models.CharField(max_length=200, choices=STATUS_CHOICES, null=True)
|
|
date = models.DateTimeField(null=True)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE) |