mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-28 23:49:30 -06:00
This commit introduces several high-impact features to improve user experience and productivity: New Features: - Activity Logging: Comprehensive audit trail tracking user actions across the system with Activity model, including IP address and user agent tracking - Time Entry Templates: Reusable templates for frequently logged activities with usage tracking and quick-start functionality - Saved Filters: Save and reuse common search/filter combinations across different views (projects, tasks, reports) - User Preferences: Enhanced user settings including email notifications, timezone, date/time formats, week start day, and theme preferences - Excel Export: Generate formatted Excel exports for time entries and reports with styling and proper formatting - Email Notifications: Complete email system for task assignments, overdue invoices, comments, and weekly summaries with HTML templates - Scheduled Tasks: Background task scheduler for periodic operations Models Added: - Activity: Tracks all user actions with detailed context and metadata - TimeEntryTemplate: Stores reusable time entry configurations - SavedFilter: Manages user-saved filter configurations Routes Added: - user.py: User profile and settings management - saved_filters.py: CRUD operations for saved filters - time_entry_templates.py: Template management endpoints UI Enhancements: - Bulk actions widget component - Keyboard shortcuts help modal with advanced shortcuts - Save filter widget component - Email notification templates - User profile and settings pages - Saved filters management interface - Time entry templates interface Database Changes: - Migration 022: Creates activities and time_entry_templates tables - Adds user preference columns (notifications, timezone, date/time formats) - Proper indexes for query optimization Backend Updates: - Enhanced keyboard shortcuts system (commands.js, keyboard-shortcuts-advanced.js) - Updated projects, reports, and tasks routes with activity logging - Safe database commit utilities integration - Event tracking for analytics Dependencies: - Added openpyxl for Excel generation - Added Flask-Mail dependencies - Updated requirements.txt All new features include proper error handling, activity logging integration, and maintain existing functionality while adding new capabilities.
89 lines
3.6 KiB
Python
89 lines
3.6 KiB
Python
from datetime import datetime
|
|
from app import db
|
|
|
|
|
|
class TimeEntryTemplate(db.Model):
|
|
"""Quick-start templates for common time entries
|
|
|
|
Allows users to create reusable templates for frequently
|
|
logged activities, saving time and ensuring consistency.
|
|
"""
|
|
|
|
__tablename__ = 'time_entry_templates'
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True)
|
|
name = db.Column(db.String(200), nullable=False)
|
|
description = db.Column(db.Text, nullable=True)
|
|
|
|
# Default values for time entries
|
|
project_id = db.Column(db.Integer, db.ForeignKey('projects.id'), nullable=True, index=True)
|
|
task_id = db.Column(db.Integer, db.ForeignKey('tasks.id'), nullable=True, index=True)
|
|
default_duration_minutes = db.Column(db.Integer, nullable=True) # Optional default duration
|
|
default_notes = db.Column(db.Text, nullable=True)
|
|
tags = db.Column(db.String(500), nullable=True) # Comma-separated tags
|
|
billable = db.Column(db.Boolean, default=True, nullable=False)
|
|
|
|
# Metadata
|
|
usage_count = db.Column(db.Integer, default=0, nullable=False) # Track how often used
|
|
last_used_at = db.Column(db.DateTime, nullable=True)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
|
|
|
|
# Relationships
|
|
user = db.relationship('User', backref='time_entry_templates')
|
|
project = db.relationship('Project', backref='time_entry_templates')
|
|
task = db.relationship('Task', backref='time_entry_templates')
|
|
|
|
def __repr__(self):
|
|
return f'<TimeEntryTemplate {self.name}>'
|
|
|
|
@property
|
|
def default_duration(self):
|
|
"""Get duration in hours"""
|
|
if self.default_duration_minutes is None:
|
|
return None
|
|
return self.default_duration_minutes / 60.0
|
|
|
|
@default_duration.setter
|
|
def default_duration(self, hours):
|
|
"""Set duration from hours"""
|
|
if hours is None:
|
|
self.default_duration_minutes = None
|
|
else:
|
|
self.default_duration_minutes = int(hours * 60)
|
|
|
|
def record_usage(self):
|
|
"""Record that this template was used"""
|
|
self.usage_count += 1
|
|
self.last_used_at = datetime.utcnow()
|
|
|
|
def increment_usage(self):
|
|
"""Increment usage count and update last used timestamp"""
|
|
self.usage_count += 1
|
|
self.last_used_at = datetime.utcnow()
|
|
db.session.commit()
|
|
|
|
def to_dict(self):
|
|
"""Convert to dictionary for API responses"""
|
|
return {
|
|
'id': self.id,
|
|
'user_id': self.user_id,
|
|
'name': self.name,
|
|
'description': self.description,
|
|
'project_id': self.project_id,
|
|
'project_name': self.project.name if self.project else None,
|
|
'task_id': self.task_id,
|
|
'task_name': self.task.name if self.task else None,
|
|
'default_duration': self.default_duration, # In hours for API
|
|
'default_duration_minutes': self.default_duration_minutes, # Keep for compatibility
|
|
'default_notes': self.default_notes,
|
|
'tags': self.tags,
|
|
'billable': self.billable,
|
|
'usage_count': self.usage_count,
|
|
'last_used_at': self.last_used_at.isoformat() if self.last_used_at else None,
|
|
'created_at': self.created_at.isoformat() if self.created_at else None,
|
|
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
|
|
}
|
|
|