85 lines
3.4 KiB
Python
85 lines
3.4 KiB
Python
"""
|
|
Database models for employee workstation activity tracking.
|
|
|
|
This module defines the SQLAlchemy models used for storing activity events.
|
|
"""
|
|
from app import db
|
|
|
|
|
|
class WorkEvent(db.Model):
|
|
"""
|
|
Represents a user activity event with state transitions (working/stopped).
|
|
|
|
Attributes:
|
|
id (int): Primary key for the event
|
|
user (str): Username of the person whose activity is being tracked
|
|
state (str): Current activity state ('working' or 'stopped')
|
|
ts (datetime): Timestamp when the event occurred
|
|
"""
|
|
|
|
__tablename__ = "work_events"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
user = db.Column(db.String(100), nullable=False, index=True)
|
|
state = db.Column(db.String(10), nullable=False) # 'working' or 'stopped'
|
|
ts = db.Column(
|
|
db.DateTime,
|
|
nullable=False,
|
|
server_default=db.func.current_timestamp(),
|
|
index=True,
|
|
)
|
|
|
|
def __repr__(self):
|
|
"""Return a string representation of the model."""
|
|
return f"<WorkEvent(user='{self.user}', state='{self.state}', ts='{self.ts}')>"
|
|
|
|
def to_dict(self):
|
|
"""Convert model to dictionary for API responses."""
|
|
return {
|
|
"id": self.id,
|
|
"user": self.user,
|
|
"state": self.state,
|
|
"ts": self.ts.isoformat() if self.ts else None,
|
|
}
|
|
|
|
|
|
class UserRealWorkSummary(db.Model):
|
|
"""
|
|
Represents aggregated "real work hours" for a user on a specific date.
|
|
A "real work hour" is defined as 40 consecutive minutes of 'working' state.
|
|
|
|
Attributes:
|
|
id (int): Primary key for the summary record.
|
|
username (str): Username of the person (links to WorkEvent.user).
|
|
work_date (Date): The date for which the hours are summarized.
|
|
real_hours_counted (int): Number of 40-minute work blocks counted for this user on this date.
|
|
last_processed_event_id (int): The ID of the last WorkEvent processed to update this summary.
|
|
last_event_completed_block (bool): Indicates whether the last processed event completed a 40-minute block.
|
|
"""
|
|
|
|
__tablename__ = "user_real_work_summary"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
username = db.Column(db.String(255), nullable=False, index=True)
|
|
work_date = db.Column(db.Date, nullable=False, index=True)
|
|
real_hours_counted = db.Column(db.Integer, nullable=False, default=0)
|
|
last_processed_event_id = db.Column(db.Integer, db.ForeignKey('work_events.id'), nullable=True)
|
|
last_event_completed_block = db.Column(db.Boolean, nullable=False, default=False)
|
|
|
|
__table_args__ = (db.UniqueConstraint("username", "work_date", name="uq_user_work_date"),)
|
|
|
|
def __repr__(self):
|
|
"""Return a string representation of the model."""
|
|
return f"<UserRealWorkSummary(username='{self.username}', work_date='{self.work_date}', hours='{self.real_hours_counted}', last_event_id='{self.last_processed_event_id}', completed_block='{self.last_event_completed_block}')>"
|
|
|
|
def to_dict(self):
|
|
"""Convert model to dictionary for API responses."""
|
|
return {
|
|
"id": self.id,
|
|
"username": self.username,
|
|
"work_date": self.work_date.isoformat() if self.work_date else None,
|
|
"real_hours_counted": self.real_hours_counted,
|
|
"last_processed_event_id": self.last_processed_event_id,
|
|
"last_event_completed_block": self.last_event_completed_block,
|
|
}
|