from django.contrib.auth import get_user_model from django.db import models from apps.logs.services import build_workspace_log_metadata from apps.logs.services.constants import SECTION_PROJECTS from core.models.base import BaseModel from apps.workspaces.models import Workspace User = get_user_model() class Project(BaseModel): workspace = models.ForeignKey( Workspace, on_delete=models.CASCADE, related_name="projects", ) name = models.CharField(max_length=255) client = models.ForeignKey( "clients.Client", on_delete=models.SET_NULL, null=True, blank=True, related_name="projects", ) description = models.TextField(blank=True) thumbnail = models.ImageField(upload_to="profile/projects/", blank=True, null=True) is_archived = models.BooleanField(default=False) color = models.CharField(max_length=7, blank=True) class Meta: db_table = "project" ordering = ("-updated_at", "-created_at") indexes = [ models.Index(fields=["workspace"], name="project_workspace_idx"), models.Index(fields=["workspace", "is_archived", "updated_at"], name="project_ws_arch_upd_idx"), ] constraints = [ models.UniqueConstraint( fields=["workspace", "name"], name="unique_project_name_per_workspace", condition=models.Q(is_deleted=False), ) ] def __str__(self): return self.name def get_additional_data(self): return build_workspace_log_metadata( section=SECTION_PROJECTS, workspace_id=self.workspace_id, target_id=self.id, target_label=self.name, extra={"client_id": str(self.client_id) if self.client_id else None}, ) class ProjectRate(BaseModel): project = models.ForeignKey( Project, on_delete=models.CASCADE, related_name="rates", ) hourly_rate = models.DecimalField( max_digits=10, decimal_places=2, ) currency = models.CharField( max_length=3, default="USD", ) effective_from = models.DateTimeField() is_active = models.BooleanField(default=True) class Meta: db_table = "project_rate" ordering = ("-effective_from",) indexes = [ models.Index(fields=["project"], name="project_rate_project_idx"), ] class ProjectUserRate(BaseModel): project = models.ForeignKey( Project, on_delete=models.CASCADE, related_name="user_rates", ) user = models.ForeignKey( User, on_delete=models.CASCADE, related_name="project_rates", ) hourly_rate = models.DecimalField( max_digits=10, decimal_places=2, ) currency = models.CharField( max_length=3, default="USD", ) effective_from = models.DateTimeField() is_active = models.BooleanField(default=True) class Meta: db_table = "project_user_rate" ordering = ("-effective_from",) constraints = [ models.UniqueConstraint( fields=["project", "user", "effective_from"], name="unique_project_user_rate_time", condition=models.Q(is_deleted=False), ) ] indexes = [ models.Index(fields=["project"], name="pur_project_idx"), models.Index(fields=["user"], name="pur_user_idx"), ] class ProjectAccess(BaseModel): project = models.ForeignKey( Project, on_delete=models.CASCADE, related_name="access_memberships", ) user = models.ForeignKey( User, on_delete=models.CASCADE, related_name="project_accesses", ) class Meta: db_table = "project_access" ordering = ("-created_at",) constraints = [ models.UniqueConstraint( fields=["project", "user"], name="unique_project_access", condition=models.Q(is_deleted=False), ) ] indexes = [ models.Index(fields=["project"], name="project_access_project_idx"), models.Index(fields=["user"], name="project_access_user_idx"), ]