-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodels.py
More file actions
277 lines (240 loc) · 9.02 KB
/
models.py
File metadata and controls
277 lines (240 loc) · 9.02 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
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
import json
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
# These classes represent database entities without using an ORM
# They'll be populated using data from direct database queries
class User:
def __init__(self, user_id=None, username=None, password_hash=None, email=None,
first_name=None, last_name=None, is_active=True, last_login=None):
self.UserID = user_id
self.Username = username
self.PasswordHash = password_hash
self.Email = email
self.FirstName = first_name
self.LastName = last_name
self.IsActive = is_active
self.LastLogin = last_login
self.CreatedAt = datetime.now()
self.UpdatedAt = datetime.now()
self.roles = []
@property
def password(self):
raise AttributeError('password is not a readable attribute')
@password.setter
def password(self, password):
self.PasswordHash = generate_password_hash(password)
def verify_password(self, password):
return check_password_hash(self.PasswordHash, password)
@property
def FullName(self):
return f"{self.FirstName} {self.LastName}" if self.FirstName and self.LastName else self.Username
def has_role(self, role_name):
return role_name in [role.RoleName for role in self.roles]
def __repr__(self):
return f'<User {self.Username}>'
@classmethod
def from_row(cls, row):
"""Create a User object from a database row"""
if not row:
return None
# Map column names to object properties
user = cls(
user_id=row.UserID,
username=row.Username,
password_hash=row.PasswordHash,
email=row.Email,
first_name=row.FirstName,
last_name=row.LastName,
is_active=bool(row.IsActive),
last_login=row.LastLogin
)
return user
class Role:
def __init__(self, role_id=None, role_name=None, description=None):
self.RoleID = role_id
self.RoleName = role_name
self.Description = description
self.CreatedAt = datetime.now()
self.UpdatedAt = datetime.now()
@property
def Name(self):
return self.RoleName
def __repr__(self):
return f'<Role {self.RoleName}>'
@classmethod
def from_row(cls, row):
"""Create a Role object from a database row"""
if not row:
return None
role = cls(
role_id=row.RoleID,
role_name=row.RoleName,
description=row.Description
)
return role
class Book:
def __init__(self, book_id=None, title=None, author=None, isbn=None,
publication_year=None, publisher=None, category_id=None,
status='Available', description=None, cover_image=None):
self.BookID = book_id
self.Title = title
self.Author = author
self.ISBN = isbn
self.PublicationYear = publication_year
self.Publisher = publisher
self.CategoryID = category_id
self.Status = status
self.Description = description
self.CoverImage = cover_image
self.CreatedAt = datetime.now()
self.UpdatedAt = datetime.now()
self.CategoryName = None # Will be populated when joined with Category
self.loans = [] # For storing related loan records
@classmethod
def from_row(cls, row):
"""Create a Book object from a database row"""
if not row:
return None
book = cls(
book_id=row.BookID,
title=row.Title,
author=row.Author,
isbn=row.ISBN,
publication_year=row.PublicationYear,
publisher=row.Publisher,
category_id=row.CategoryID,
status=row.Status,
description=row.Description,
cover_image=row.CoverImage
)
# Check if CategoryName exists in the row (for joined queries)
if hasattr(row, 'CategoryName'):
book.CategoryName = row.CategoryName
return book
class Category:
def __init__(self, category_id=None, category_name=None, description=None):
self.CategoryID = category_id
self.CategoryName = category_name
self.Description = description
self.CreatedAt = datetime.now()
self.UpdatedAt = datetime.now()
@classmethod
def from_row(cls, row):
"""Create a Category object from a database row"""
if not row:
return None
category = cls(
category_id=row.CategoryID,
category_name=row.CategoryName,
description=row.Description
)
return category
class Member:
def __init__(self, member_id=None, first_name=None, last_name=None, email=None,
phone=None, address=None, membership_date=None, membership_expiry=None,
status='Active', user_id=None):
self.MemberID = member_id
self.FirstName = first_name
self.LastName = last_name
self.Email = email
self.Phone = phone
self.Address = address
self.MembershipDate = membership_date or datetime.now()
self.MembershipExpiry = membership_expiry
self.Status = status
self.UserID = user_id
self.CreatedAt = datetime.now()
self.UpdatedAt = datetime.now()
@property
def FullName(self):
return f"{self.FirstName} {self.LastName}"
@classmethod
def from_row(cls, row):
"""Create a Member object from a database row"""
if not row:
return None
member = cls(
member_id=row.MemberID,
first_name=row.FirstName,
last_name=row.LastName,
email=row.Email,
phone=row.Phone,
address=row.Address,
membership_date=row.MembershipDate,
membership_expiry=row.MembershipExpiry,
status=row.Status,
user_id=row.UserID
)
return member
class Loan:
def __init__(self, loan_id=None, book_id=None, member_id=None, loan_date=None,
due_date=None, return_date=None, status='Borrowed', fine_amount=0.0, notes=None):
self.LoanID = loan_id
self.BookID = book_id
self.MemberID = member_id
self.LoanDate = loan_date or datetime.now()
self.DueDate = due_date
self.ReturnDate = return_date
self.Status = status
self.FineAmount = fine_amount
self.Notes = notes
self.CreatedAt = datetime.now()
self.UpdatedAt = datetime.now()
self.book = None # Will be populated with Book object
self.member = None # Will be populated with Member object
@classmethod
def from_row(cls, row):
"""Create a Loan object from a database row"""
if not row:
return None
loan = cls(
loan_id=row.LoanID,
book_id=row.BookID,
member_id=row.MemberID,
loan_date=row.LoanDate,
due_date=row.DueDate,
return_date=row.ReturnDate,
status=row.Status,
fine_amount=row.FineAmount,
notes=row.Notes
)
return loan
class ActivityLog:
def __init__(self, log_id=None, user_id=None, action=None, table_name=None,
record_id=None, old_values=None, new_values=None, ip_address=None):
self.LogID = log_id
self.UserID = user_id
self.Action = action
self.TableName = table_name
self.RecordID = record_id
self.OldValues = old_values
self.NewValues = new_values
self.IPAddress = ip_address
self.ChangedAt = datetime.now()
self.Username = None # Will be populated when joined with User
@classmethod
def from_row(cls, row):
"""Create an ActivityLog object from a database row"""
if not row:
return None
# Parse JSON strings if they exist
old_values = json.loads(row.OldValues) if row.OldValues else None
new_values = json.loads(row.NewValues) if row.NewValues else None
log = cls(
log_id=row.LogID,
user_id=row.UserID,
action=row.Action,
table_name=row.TableName,
record_id=row.RecordID,
old_values=old_values,
new_values=new_values,
ip_address=row.IPAddress
)
# Check if Username exists in the row (for joined queries)
if hasattr(row, 'Username'):
log.Username = row.Username
return log
# Helper function to log activity - will be used directly by the app with database connection
def log_activity(user_id, action, table_name=None, record_id=None, old_values=None, new_values=None, ip_address=None):
# This function implementation is now in app.py with direct database access
pass