|
|
from sqlalchemy import Column, String, Numeric, Date, Integer, Boolean, Text, DateTime, ForeignKey, CheckConstraint
|
|
|
from sqlalchemy.sql import func
|
|
|
from sqlalchemy.orm import relationship
|
|
|
from database import Base
|
|
|
|
|
|
class Project(Base):
|
|
|
__tablename__ = "projects"
|
|
|
|
|
|
project_id = Column(String(20), primary_key=True, index=True)
|
|
|
project_name = Column(String(255), nullable=False)
|
|
|
client_name = Column(String(255), nullable=False, index=True)
|
|
|
contract_value_aed = Column(Numeric(15, 2), nullable=False)
|
|
|
planned_cost_aed = Column(Numeric(15, 2), nullable=False)
|
|
|
project_start_date = Column(Date, nullable=False)
|
|
|
project_end_date = Column(Date, nullable=False)
|
|
|
project_type = Column(String(50), nullable=False, index=True)
|
|
|
project_status = Column(String(50), nullable=False, index=True)
|
|
|
current_phase = Column(String(100))
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
|
|
|
timesheets = relationship("Timesheet", back_populates="project")
|
|
|
milestones = relationship("Milestone", back_populates="project", cascade="all, delete-orphan")
|
|
|
invoices = relationship("Invoice", back_populates="project")
|
|
|
subcontractors = relationship("Subcontractor", back_populates="project", cascade="all, delete-orphan")
|
|
|
staff_allocations = relationship("StaffAllocation", back_populates="project", cascade="all, delete-orphan")
|
|
|
|
|
|
|
|
|
class Employee(Base):
|
|
|
__tablename__ = "employees"
|
|
|
|
|
|
employee_id = Column(String(20), primary_key=True, index=True)
|
|
|
employee_name = Column(String(255), nullable=False)
|
|
|
department = Column(String(100), nullable=False, index=True)
|
|
|
role = Column(String(100), nullable=False, index=True)
|
|
|
hourly_rate_aed = Column(Numeric(10, 2), nullable=False)
|
|
|
employment_type = Column(String(50), nullable=False)
|
|
|
start_date = Column(Date, nullable=False)
|
|
|
end_date = Column(Date)
|
|
|
cost_category = Column(String(100), nullable=False, index=True)
|
|
|
is_active = Column(Boolean, default=True, index=True)
|
|
|
email = Column(String(255))
|
|
|
phone = Column(String(50))
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
|
|
|
timesheets = relationship("Timesheet", back_populates="employee")
|
|
|
staff_allocations = relationship("StaffAllocation", back_populates="employee")
|
|
|
|
|
|
|
|
|
class Timesheet(Base):
|
|
|
__tablename__ = "timesheets"
|
|
|
|
|
|
record_id = Column(String(20), primary_key=True, index=True)
|
|
|
date = Column(Date, nullable=False, index=True)
|
|
|
employee_id = Column(String(20), ForeignKey("employees.employee_id"), nullable=False, index=True)
|
|
|
project_id = Column(String(20), ForeignKey("projects.project_id"), nullable=False, index=True)
|
|
|
hours_worked = Column(Numeric(5, 2), nullable=False)
|
|
|
billable_hours = Column(Numeric(5, 2), nullable=False)
|
|
|
work_category = Column(String(100), nullable=False)
|
|
|
task_description = Column(String(500))
|
|
|
is_approved = Column(Boolean, default=False, index=True)
|
|
|
approved_by = Column(String(20))
|
|
|
approved_at = Column(DateTime)
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
|
|
|
employee = relationship("Employee", back_populates="timesheets")
|
|
|
project = relationship("Project", back_populates="timesheets")
|
|
|
|
|
|
|
|
|
class Milestone(Base):
|
|
|
__tablename__ = "milestones"
|
|
|
|
|
|
milestone_id = Column(Integer, primary_key=True, autoincrement=True)
|
|
|
project_id = Column(String(20), ForeignKey("projects.project_id", ondelete="CASCADE"), nullable=False, index=True)
|
|
|
milestone_name = Column(String(255), nullable=False)
|
|
|
milestone_order = Column(Integer, nullable=False)
|
|
|
planned_date = Column(Date, nullable=False, index=True)
|
|
|
actual_date = Column(Date)
|
|
|
status = Column(String(50), nullable=False, index=True)
|
|
|
completion_percentage = Column(Integer, default=0)
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
|
|
|
project = relationship("Project", back_populates="milestones")
|
|
|
staff_allocations = relationship("StaffAllocation", back_populates="milestone")
|
|
|
|
|
|
|
|
|
class Invoice(Base):
|
|
|
__tablename__ = "invoices"
|
|
|
|
|
|
invoice_id = Column(String(20), primary_key=True, index=True)
|
|
|
project_id = Column(String(20), ForeignKey("projects.project_id"), nullable=False, index=True)
|
|
|
invoice_date = Column(Date, nullable=False)
|
|
|
invoice_amount_aed = Column(Numeric(15, 2), nullable=False)
|
|
|
due_date = Column(Date, nullable=False, index=True)
|
|
|
payment_date = Column(Date, index=True)
|
|
|
payment_status = Column(String(50), nullable=False, index=True)
|
|
|
days_outstanding = Column(Integer)
|
|
|
milestone_reference = Column(String(255))
|
|
|
paid_amount_aed = Column(Numeric(15, 2), default=0)
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
|
|
|
project = relationship("Project", back_populates="invoices")
|
|
|
|
|
|
|
|
|
class Subcontractor(Base):
|
|
|
__tablename__ = "subcontractors"
|
|
|
|
|
|
subcontractor_id = Column(Integer, primary_key=True, autoincrement=True)
|
|
|
project_id = Column(String(20), ForeignKey("projects.project_id", ondelete="CASCADE"), nullable=False, index=True)
|
|
|
subcontractor_name = Column(String(255), nullable=False, index=True)
|
|
|
service_type = Column(String(100), nullable=False, index=True)
|
|
|
contract_amount_aed = Column(Numeric(15, 2), nullable=False)
|
|
|
amount_invoiced_aed = Column(Numeric(15, 2), default=0)
|
|
|
payment_status = Column(String(50), nullable=False, index=True)
|
|
|
work_category = Column(String(100), nullable=False)
|
|
|
contract_start_date = Column(Date)
|
|
|
contract_end_date = Column(Date)
|
|
|
contact_person = Column(String(255))
|
|
|
contact_email = Column(String(255))
|
|
|
contact_phone = Column(String(50))
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
|
|
|
project = relationship("Project", back_populates="subcontractors")
|
|
|
|
|
|
|
|
|
class StaffAllocation(Base):
|
|
|
__tablename__ = "staff_allocation"
|
|
|
|
|
|
allocation_id = Column(Integer, primary_key=True, autoincrement=True)
|
|
|
project_id = Column(String(20), ForeignKey("projects.project_id", ondelete="CASCADE"), nullable=False, index=True)
|
|
|
milestone_id = Column(Integer, ForeignKey("milestones.milestone_id", ondelete="SET NULL"), index=True)
|
|
|
milestone_name = Column(String(255))
|
|
|
employee_id = Column(String(20), ForeignKey("employees.employee_id"), nullable=False, index=True)
|
|
|
employee_name = Column(String(255), nullable=False)
|
|
|
role = Column(String(100), nullable=False)
|
|
|
category = Column(String(100))
|
|
|
hours_allocated = Column(Numeric(10, 2), nullable=False)
|
|
|
hours_worked = Column(Numeric(10, 2), default=0)
|
|
|
hourly_rate_aed = Column(Numeric(10, 2), nullable=False)
|
|
|
skill_match_score = Column(Integer)
|
|
|
availability_status = Column(String(50))
|
|
|
performance_rating = Column(String(50))
|
|
|
start_date = Column(Date, nullable=False, index=True)
|
|
|
end_date = Column(Date)
|
|
|
notes = Column(Text)
|
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
|
|
|
project = relationship("Project", back_populates="staff_allocations")
|
|
|
milestone = relationship("Milestone", back_populates="staff_allocations")
|
|
|
employee = relationship("Employee", back_populates="staff_allocations") |