-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodels.py
More file actions
128 lines (105 loc) · 5.07 KB
/
models.py
File metadata and controls
128 lines (105 loc) · 5.07 KB
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
"""
Database models for Simple Project Management System
"""
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from datetime import datetime
# Initialize db here - it will be set by the main app
db = SQLAlchemy()
# User model
class User(UserMixin, db.Model):
"""User model for authentication and role management"""
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(255), nullable=False)
role = db.Column(db.String(20), nullable=False, default='team_member') # admin, project_manager, team_member
created_at = db.Column(db.DateTime, default=datetime.utcnow)
is_active = db.Column(db.Boolean, default=True)
# Relationships
created_projects = db.relationship('Project', backref='creator', lazy=True)
assigned_tasks = db.relationship('Task', backref='assignee', lazy=True)
def __repr__(self):
return f'<User {self.username}>'
def has_permission(self, permission):
"""Check if user has specific permission based on role"""
permissions = {
'admin': ['create_project', 'delete_project', 'assign_users', 'view_all', 'manage_users'],
'project_manager': ['create_project', 'assign_tasks', 'view_team_projects'],
'team_member': ['view_assigned_tasks', 'update_task_status']
}
return permission in permissions.get(self.role, [])
# Project model
class Project(db.Model):
"""Project model for managing projects"""
__tablename__ = 'projects'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(200), nullable=False)
description = db.Column(db.Text)
start_date = db.Column(db.Date, nullable=False)
end_date = db.Column(db.Date, nullable=False)
status = db.Column(db.String(20), default='active') # active, completed, on_hold, cancelled
created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
tasks = db.relationship('Task', backref='project', lazy=True, cascade='all, delete-orphan')
def __repr__(self):
return f'<Project {self.name}>'
@property
def progress_percentage(self):
"""Calculate project progress based on completed tasks"""
if not self.tasks:
return 0
completed_tasks = len([t for t in self.tasks if t.status == 'Done'])
return round((completed_tasks / len(self.tasks)) * 100, 2)
@property
def is_overdue(self):
"""Check if project is overdue"""
return datetime.now().date() > self.end_date and self.status != 'completed'
# Task model
class Task(db.Model):
"""Task model for managing individual tasks within projects"""
__tablename__ = 'tasks'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
description = db.Column(db.Text)
status = db.Column(db.String(20), default='To Do') # To Do, In Progress, Done
priority = db.Column(db.String(10), default='medium') # low, medium, high, urgent
due_date = db.Column(db.Date)
project_id = db.Column(db.Integer, db.ForeignKey('projects.id'), nullable=False)
assigned_to = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
activities = db.relationship('ActivityLog', backref='task', lazy=True, cascade='all, delete-orphan')
def __repr__(self):
return f'<Task {self.title}>'
@property
def is_overdue(self):
"""Check if task is overdue"""
if not self.due_date:
return False
return datetime.now().date() > self.due_date and self.status != 'Done'
@property
def days_until_due(self):
"""Calculate days until due date"""
if not self.due_date:
return None
delta = self.due_date - datetime.now().date()
return delta.days
# Activity Log model
class ActivityLog(db.Model):
"""Activity log for tracking changes and comments"""
__tablename__ = 'activity_logs'
id = db.Column(db.Integer, primary_key=True)
task_id = db.Column(db.Integer, db.ForeignKey('tasks.id'), nullable=True) # Made nullable for project activities
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
action = db.Column(db.String(50), nullable=False) # created, updated, commented, status_changed
message = db.Column(db.Text, nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
# Relationships
user = db.relationship('User', backref='activities')
def __repr__(self):
return f'<ActivityLog {self.action} by {self.user.username}>'