File size: 8,037 Bytes
0a515cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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())
    
    # Relationships
    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())
    
    # Relationships
    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())
    
    # Relationships
    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())
    
    # Relationships
    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())
    
    # Relationships
    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())
    
    # Relationships
    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())
    
    # Relationships
    project = relationship("Project", back_populates="staff_allocations")
    milestone = relationship("Milestone", back_populates="staff_allocations")
    employee = relationship("Employee", back_populates="staff_allocations")