Implemented financial tracking

This commit is contained in:
2026-03-20 13:07:28 -05:00
parent 6fa4fc1f7c
commit c88e344198
22 changed files with 1058 additions and 270 deletions
+32 -7
View File
@@ -6,25 +6,36 @@ from django_enum import EnumField
from django.utils.text import slugify
import datetime
def user_str(self):
if self.first_name and self.last_name:
return f"{self.first_name} {self.last_name}"
if self.username:
return self.username
if self.email:
return self.email
return str(self.id)
User.__str__ = user_str
# Abstract Model Classes
class TimeMixin(models.Model):
created = models.DateTimeField(default=timezone.now)
last_modified = models.DateTimeField(default=timezone.now)
created_by = models.ForeignKey
last_modified_BY = models.ForeignKey
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='+')
last_modified_BY = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='+')
class Meta:
abstract = True
class IdMixin(models.Model):
slug = models.SlugField()
slug = models.SlugField(blank=True, unique=True, null=True)
class Meta:
abstract = True
def save(self, *args, **kwargs):
if self.slug is None:
if not self.slug:
self.slug = slugify(datetime.datetime.now().time())
super(IdMixin, self).save(*args, **kwargs)
@@ -32,6 +43,7 @@ class IdMixin(models.Model):
class Contract(IdMixin, TimeMixin):
class ContractTypeEnum(models.TextChoices):
FIRM_FIX_PRICED = "FFP", "FIRM_FIX_PRICED"
COST_PLUS_FIXED_FEE = "CPFF", "COST_PLUS_FIXED_FEE"
MAX_NUM_CONRACT_TYPES = "MAX", "MAX_NUM_CONTRACT_TYPES"
contract_type = EnumField(ContractTypeEnum)
@@ -40,11 +52,16 @@ class Contract(IdMixin, TimeMixin):
proposed_amount = models.FloatField(default=0.0)
baseline_amount = models.FloatField(default=0.0)
funded_amount = models.FloatField(default=0.0)
award_amount = models.FloatField(default=0.0)
budget_hours = models.FloatField(default=0.0)
baseline_start = models.DateField(null=True, blank=True, default=None)
baseline_end = models.DateField(null=True, blank=True, default=None)
linkedContracts = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return f"{self.name} - {self.contract_type}"
# TODO: make calc ev func
class ChargeNumber(IdMixin, TimeMixin):
@@ -73,14 +90,19 @@ class AddressModel(models.Model):
zip_code = models.CharField(max_length=5)
class Employee(IdMixin, TimeMixin):
manager = models.ForeignKey("self", on_delete=models.CASCADE, related_name="manager_employee")
manager = models.ForeignKey("self", on_delete=models.CASCADE, related_name="manager_employee", null=True, blank=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
primaryAddress = models.ForeignKey(AddressModel, on_delete=models.CASCADE, related_name="primary_address_employee")
workAddress = models.ForeignKey(AddressModel, on_delete=models.CASCADE, related_name="work_address_employee")
phoneNumber = PhoneNumberField(null=False, blank=False, unique=True)
phoneNumber = PhoneNumberField(null=True, blank=True, unique=True)
slary= models.FloatField(default=0.0)
# TODO: get hourly salary
def __str__(self):
return str(self.user)
@property
def hourly_salary(self):
return (self.slary or 0.0) / 2080.0
# TODO: roles, jpbTitles
@@ -97,7 +119,10 @@ class TimeCard(IdMixin, TimeMixin):
class TimeCardCell(IdMixin, TimeMixin):
timeCard = models.ForeignKey(TimeCard, on_delete=models.CASCADE)
date = models.DateField(null=True, default = None)
start_time = models.TimeField(null=True, blank=True)
end_time = models.TimeField(null=True, blank=True)
hour = models.FloatField(default = 0.0)
contract = models.ForeignKey(Contract, on_delete=models.CASCADE, null=True, blank=True)