Fix multiple permission and role-related issues:
1. Gantt chart access: Replace is_admin check with view_projects permission
- Users with custom roles having view_projects permission can now access
Gantt charts, not just admins
- Updated app/routes/gantt.py to check permissions properly
2. Task view filtering: Replace is_admin check with view_all_tasks permission
- Users with custom roles having view_all_tasks permission can now see
all tasks in the Tasks view, not just admins
- Updated app/services/task_service.py to accept has_view_all_tasks parameter
- Updated app/routes/tasks.py list_tasks and export_tasks to use permission check
3. Role assignment security: Prevent privilege escalation
- Added is_super_admin property to User model
- Only super_admins can assign super_admin role to users
- Only super_admins can remove admin role from themselves or others
- Prevents admins from escalating privileges or removing admin access
- Updated app/routes/permissions.py manage_user_roles with validation
4. Version display consistency: Ensure consistent version display
- Added APP_VERSION environment variable to docker-compose.example.yml
- Ensures version is displayed consistently when using pre-built images
All changes maintain backward compatibility and follow the existing
permission system architecture.
Implement comprehensive enhancements to the Report Builder system with support
for iterative report generation, flexible email distribution, and improved
error handling.
Features:
- Add iterative report generation: generate one report per custom field value
- Add email distribution modes: mapping, template, and single recipient modes
- Add recipient email templates with {value} placeholder support
- Enhance scheduled reports with better error handling and validation
- Add fix endpoint for invalid scheduled reports
- Improve report builder UI with iterative generation options
- Add comprehensive management views for report schemes
Fixes:
- Fix template errors in iterative report view (dict access issues)
- Fix empty report builder when editing saved reports
- Fix PWA install toast notification handling
- Fix migration revision ID length issue (shortened to fit 32 char limit)
- Add idempotent migration checks to prevent duplicate column errors
- Improve error handling in scheduled reports list view
Database Changes:
- Add iterative_report_generation and iterative_custom_field_name to saved_report_views
- Add email_distribution_mode and recipient_email_template to report_email_schedules
- Migration 090_report_builder_iteration (idempotent)
UI/UX Improvements:
- Display iterative generation status in saved views list
- Show distribution mode and template in scheduled reports
- Add error badges and fix buttons for invalid schedules
- Improve report builder form loading for saved configurations
Technical:
- Enhance ScheduledReportService with recipient resolution logic
- Add validation for report configurations
- Improve error handling and logging throughout
- Update templates to use safe dictionary access patterns
- Add session state clearing (expunge_all) after rollbacks in custom field
definition error handlers to prevent stale session state
- Add graceful error handling for missing link_templates table with proper
rollback and session cleanup, preventing app crashes when migrations
haven't been run
- Add detailed performance logging to TaskService.list_tasks method to track
timing of each query step for performance monitoring
- Improve PWA install prompt UI with better toast integration, dismiss button,
and proper DOM manipulation using requestAnimationFrame
- Bump version to 4.5.0
- Add edit functionality for saved report views in custom reports builder
- Implement saved views list page with management capabilities
- Enhance scheduled reports service with improved error handling and email support
- Add email template for scheduled report delivery
- Update report templates with improved UI and functionality
- Fix PostgreSQL sequences for roles and permissions tables
- Update permission system migration with additional changes
- Improve base template with enhanced navigation and styling
- Updated CustomFieldDefinition model methods to catch ProgrammingError
when table doesn't exist (migration not run yet)
- Methods now return empty list/None instead of raising 500 errors
- Added transaction rollback to prevent subsequent query failures
- Prevents database errors when visiting Time Entries, Projects, or Clients
pages before migration 084_add_custom_field_definitions is applied
The fix ensures the application continues to work even if the migration
hasn't been run, with appropriate warning logs suggesting to run
'flask db upgrade'.
- Add cache invalidation to update_entry API endpoint
- Add cache invalidation to edit_timer route
- Add cache invalidation to delete_entry API endpoint
- Add cache invalidation to delete_timer route
- Add cache invalidation to create_entry API endpoint
The dashboard caches data for 5 minutes, but the cache was not being
invalidated when time entries were modified. This caused the 'Recent
Entries' table to show stale duration values until the cache expired
or the browser tab was refreshed.
Now the dashboard cache is immediately invalidated whenever a time
entry is created, updated, or deleted, ensuring users see the latest
data without waiting for cache expiration.
- Add cache invalidation to update_entry API endpoint
- Add cache invalidation to edit_timer route
- Add cache invalidation to delete_entry API endpoint
- Add cache invalidation to delete_timer route
- Add cache invalidation to create_entry API endpoint
The dashboard caches data for 5 minutes, but the cache was not being
invalidated when time entries were modified. This caused the 'Recent
Entries' table to show stale duration values until the cache expired
or the browser tab was refreshed.
Now the dashboard cache is immediately invalidated whenever a time
entry is created, updated, or deleted, ensuring users see the latest
data without waiting for cache expiration.
This commit introduces two major features:
1. Project Custom Fields: Add custom_fields JSON column to projects table (migration 085), support for flexible custom data storage, display and edit in project views
2. File Attachments System: Add project_attachments and client_attachments tables (migration 086), new ProjectAttachment and ClientAttachment models, full CRUD operations, file upload/download/delete, client-visible attachments support
Additional improvements: Enhanced data tables, updated project/client/invoice/timer views, improved UI for attachments and custom fields management
This commit includes multiple performance optimizations, error handling
improvements, and bug fixes across the application.
Performance Improvements:
- Add caching for task status_display property to avoid N+1 queries
- Pre-calculate task counts by status in route handler instead of template
- Pre-load kanban columns in TaskService to eliminate N+1 queries
- Remove unnecessary db.session.expire_all() call in tasks route
- Always use pagination for task lists to improve performance
Error Handling & Robustness:
- Add graceful handling for missing time_entry_approvals table in timer deletion
- Improve safe_commit to handle ProgrammingError for optional relationships
- Add VAPID key validation and error handling in PWA push notifications
- Make custom_field_definitions migration idempotent
Bug Fixes:
- Fix IndexedDB boolean query issues in offline-sync.js by using cursor iteration
- Fix app context handling in scheduled reports processing
- Improve error messages for push notification subscription failures
- Add comprehensive offline sync improvements with enhanced IndexedDB support
- Optimize task model with cached total_hours calculation for better performance
- Improve task service query optimization and eager loading strategies
- Update CSP policy to allow CDN connections for improved resource loading
- Enhance service worker with better background sync capabilities
- Improve error handling and offline queue processing
- Update base template and comment templates for better UX
- Bump version to 4.3.2
- Extend client list table to display custom field columns
- Add custom field columns dynamically based on active CustomFieldDefinition entries
- Support link templates for clickable custom field values
- Enable column visibility toggle for custom field columns
- Update search functionality to include custom fields (PostgreSQL JSONB and SQLite fallback)
- Add custom field filtering to Projects list
- Extend ProjectService.list_projects() to filter by client custom fields
- Add custom field filter inputs to projects list template
- Support filtering by client custom field values (e.g., debtor_number, ERP IDs)
- Handle both PostgreSQL (JSONB) and SQLite (Python fallback) filtering
- Add custom field filtering to Time Entries list
- Extend time entries route to filter by client custom fields
- Add custom field filter inputs to time entries overview template
- Enable filtering time entries by client custom field values
- Support distinguishing clients with same name but different custom field values
- Database compatibility
- PostgreSQL: Use efficient JSONB operators for database-level filtering
- SQLite: Fallback to Python-based filtering after initial query
- Both approaches ensure accurate results across database backends
This enhancement allows users to filter and search by custom field values,
making it easier to distinguish between clients with identical names but
different identifiers (e.g., debtor numbers, ERP IDs).
- Add count_clients_with_value() method to CustomFieldDefinition model to track how many clients have values for each custom field
- Display client count in custom field definitions list view
- Automatically remove custom field values from all clients when a custom field definition is deleted
- Show user-friendly confirmation message indicating how many clients were affected when deleting a field definition
- Update client view to use custom field definitions for friendly field names instead of raw field keys
- Add comprehensive test suite for custom field definitions including model creation, client count functionality, deletion cleanup, and edge cases
- Update templates to display client counts and improve delete confirmation dialogs
- Move Docker healthcheck from Dockerfile to docker-compose files for better
environment-specific configuration
- Add silent flag to healthcheck curl commands to reduce log noise
- Add error handling for missing link_templates table in client view
- Improve offline sync date formatting with ISO 8601 conversion helper
- Enhance error handlers and profile edit template
This improves robustness when migrations haven't been run and provides
better date handling in offline sync scenarios.
- Add new unpaid hours report route showing unpaid hours per client
- Implement Ajax-based filtering for real-time updates without page reload
- Add expandable client rows to view detailed time entries
- Create Excel export functionality organized by project
- Summary sheet with all projects and totals
- Individual sheets per project with detailed time entries
- Filter unpaid hours by excluding entries in fully paid invoices
- Support filtering by date range and client
- Add link to unpaid hours report in reports index page
The report helps sales teams identify which hours need to be invoiced
by showing only billable time entries that haven't been fully paid.
- Add duplicate_detection_fields parameter to import_csv_clients function
- Allow users to specify which fields to use for duplicate detection (name, custom fields, or both)
- Update API route to accept duplicate_detection_fields query parameter
- Add UI controls for selecting duplicate detection fields:
- Checkbox to include/exclude client name
- Text input for custom field names (comma-separated)
- Default behavior remains backward compatible (checks name + all custom fields if not specified)
- Enables use cases like detecting duplicates by debtor_number only, allowing multiple clients with same name but different debtor numbers
- Add new /time-entries route with comprehensive filtering
- Filter by user (admin only), project, client, date range
- Filter by paid/unpaid status and billable status
- Search in notes and tags
- Pagination support (50 entries per page)
- Implement bulk mark as paid/unpaid functionality
- Select multiple entries with checkboxes
- Bulk actions menu to mark selected entries as paid or unpaid
- Preserves filters after bulk operations
- Activity logging for bulk changes
- Add AJAX filtering similar to projects/tasks pages
- Auto-apply filters on dropdown/date changes (100ms debounce)
- Auto-apply search as you type (500ms debounce)
- Updates URL without page reload
- Partial template rendering for AJAX requests
- Add navigation menu link in sidebar under Work section
- Extend bulk entries API to support set_paid action
- Add summary cards showing total hours, billable hours, paid hours, and entry count
- Permission-based access: admins see all entries, regular users see only their own
- Improve audit logging error messages to distinguish table missing errors from other failures
- Add warning-level logging for audit_logs table missing scenarios with migration guidance
- Update audit event listener with better error detection and logging
- Add comprehensive diagnostic script for checking audit logging setup
- Update UI templates (base.html, admin forms, user settings, profile pages)
- Extend audit logging support across routes (admin, api, permissions, reports, timer, user)
- Add extensive test coverage for admin user management functionality
- Update time tracking service and user model with audit logging integration
- Fix AUTH_METHOD=none: Read from Flask app config instead of Config class
- Add comprehensive schema verification: Verify all SQLAlchemy models against
database and auto-fix missing columns
- Improve startup logging: Unified format with timestamps and log levels
- Enhanced migration flow: Automatic schema verification after migrations
Fixes authentication issue where password field showed even with AUTH_METHOD=none.
Ensures all database columns from models exist, preventing missing column errors.
Improves startup logging for better debugging and monitoring.
Add comprehensive CSV import and export functionality for clients, supporting
custom fields and multiple contacts per client. This enables bulk client
management and integration with external ERP systems.
Features:
- CSV import for clients with support for:
* All standard client fields (name, description, contact info, rates, etc.)
* Custom fields via custom_field_<name> columns
* Multiple contacts per client via contact_N_* columns (contact_1_first_name, etc.)
* Duplicate detection by client name or custom field values
* Option to skip duplicates during import
- Enhanced CSV export for clients including:
* All custom fields as separate columns
* All contacts with full contact details (name, email, phone, title, role, etc.)
* Dynamic column generation based on available custom fields and contact count
- New API endpoints:
* POST /api/import/csv/clients - Import clients from CSV
* GET /api/import/template/csv/clients - Download CSV template
- UI integration in Import/Export page:
* Client import section with file upload and duplicate skip option
* Client export button with direct download
* Template download link
* Improved error handling with detailed error messages
Technical improvements:
- Added import_csv_clients() function in app/utils/data_import.py
- Enhanced export_clients() route to include custom fields and contacts
- Fixed CSRF token handling for multipart/form-data requests
- Added comprehensive error handling for non-JSON responses
- Improved file encoding support (UTF-8 and Latin-1)
Use case: Enables exporting all clients from TimeTracker, comparing with ERP
system exports, removing duplicates, and importing the cleaned data back.
Closes: Client import/export feature request
Implement a global custom field system that allows defining fields once
and reusing them across all clients. Fields can be marked as mandatory
or optional, and values become clickable links when link templates are
assigned.
- Add CustomFieldDefinition model and admin interface
- Support mandatory/optional flags with validation
- Update client forms to use global definitions
- Enhance link templates to support {value} and %value% placeholders
- Make custom field values clickable in client view
- Add migration 084 for custom_field_definitions table
Breaking: Client custom fields now require global definitions. Existing
custom fields continue to work, but new fields must be defined globally.
Add ability to mark time entries as paid and link them to internal invoice
numbers. Automatically mark time entries as paid when invoices are sent.
Database Changes:
- Add migration 083 to add `paid` boolean and `invoice_number` string columns
to time_entries table
- Add index on `paid` field for faster queries
Model Updates:
- Add `paid` (default: False) and `invoice_number` (nullable) fields to TimeEntry
- Add `set_paid()` helper method to TimeEntry model
- Update `to_dict()` to include paid status and invoice number
API & Service Layer:
- Update TimeEntrySchema (all variants) to include paid/invoice_number fields
- Update API endpoints (/api/entry, /api/v1/time-entries) to accept these fields
- Update TimeTrackingService and TimeEntryRepository to handle paid status
- Add InvoiceService.mark_time_entries_as_paid() to automatically mark entries
- Update InvoiceService.mark_as_sent() to auto-mark time entries as paid
UI Updates:
- Add "Paid" checkbox and "Invoice Number" input field to time entry edit forms
- Update both admin and regular user edit forms
- Fields appear in timer edit page after tags section
Invoice Integration:
- Automatically mark time entries as paid when invoice status changes to "sent"
- Mark entries when time is added to already-sent invoices
- Store invoice number reference on time entries for tracking
- Enhanced create_invoice_from_time_entries() to properly link time entries
This enables proper tracking of which hours have been invoiced and paid
through the internal invoicing system, separate from the external ERP system.
The Integration OAuth Credentials section now uses a dropdown selector
instead of displaying all 11 integrations at once. Users can select an
integration from the dropdown to view and configure only that specific
integration's credentials.
This change improves the user experience by:
- Making the settings page more compact and easier to navigate
- Reducing visual clutter from the long list of integrations
- Allowing focused configuration of one integration at a time
All integration forms remain functional and are included in the form
submission; they are simply hidden until selected via the dropdown.
- Change "Project" column header to "Source" in Recent Entries table to
reflect that entries can be associated with either a project or a client
- Make source entries clickable: project names link to project detail page,
client names (direct entries) link to client detail page
- Add hover styling (underline) to source links for better UX
This improves navigation by allowing users to quickly access project or
client details directly from the dashboard's recent entries table.
Add a "Recent Hours History" section to the client view page that displays
the last 20 time entries for the client. This provides users with quick
visibility into recent work performed for each client.
Changes:
- Update view_client route to fetch recent time entries (directly linked
to client and through client's projects)
- Add eager loading for user, project, and task relationships to optimize
query performance
- Display time entries in a table format with date, project, task, user,
duration, and notes
- Include summary showing total entries and total hours
- Filter to only show completed entries (exclude active timers)
The history section appears below the projects list on the client detail
page, maintaining consistency with the existing UI design and providing
immediate context about recent work activity.
- Add transaction error handling to load_user function
- Create safe_query utility for safe database query execution
- Update test authentication helper to use safe query pattern
- Add comprehensive troubleshooting guide for transaction errors
Fixes issue where failed database transactions would cause
'current transaction is aborted' errors when loading users.
The fix automatically rolls back failed transactions and retries
queries, preventing application crashes.
Changes:
- Add step to convert image names to lowercase in CD workflow
- Update docker-compose.production.yml generation to use lowercase image names
- Enhance production deployment with nginx reverse proxy and certgen service
- Update CSRF configuration documentation with IP access guidance
- Improve deployment manifest generation with better service orchestration
- Update admin_authenticated_client fixture to use actual login endpoint
instead of direct login_user call for proper CSRF handling
- Improve test authentication consistency across test files
- Update tests in test_client_portal, test_routes, and test_uploads_persistence
to align with new authentication approach
This commit implements a comprehensive refactoring of the integration system to support both global (shared) and per-user integrations, adds new integrations, and improves the overall architecture.
Key changes:
- Add global integrations support: most integrations are now shared across all users (Jira, Slack, GitHub, Asana, Trello, GitLab, Microsoft Teams, Outlook Calendar, Xero)
- Add new integrations: GitLab, Microsoft Teams, Outlook Calendar, and Xero
- Database migrations:
* Migration 081: Add OAuth credential columns for all integrations to Settings model
* Migration 082: Add is_global flag to Integration model and make user_id nullable
- Update Integration model to support global integrations with nullable user_id
- Refactor IntegrationService to handle both global and per-user integrations
- Create dedicated admin setup pages for each integration
- Update Trello connector to use API key setup instead of OAuth flow
- Enhance all existing integrations (Jira, Slack, GitHub, Google Calendar, Asana, Trello) with global support
- Update routes, templates, and services to support the new global/per-user distinction
- Improve integration management UI with better separation of global vs per-user integrations
- Update scheduled tasks to work with the new integration architecture
Add client custom fields (JSON) for flexible data storage
Implement link templates system for dynamic URL generation from custom fields
Add client_id support to time entries for direct client billing (project_id now nullable)
Implement user-level UI feature flags for customizable navigation visibility
Add system-wide UI feature flags in settings for admin control
Fix metadata column naming (user_badges.achievement_metadata, leaderboard_entries.entry_metadata)
Update templates and routes to support new features
Add comprehensive UI feature flag management in admin and user settings
Enhance client views with custom fields and link template integration
Update time entry forms to support client billing
Add tests for system UI flags
Migrations: 075-080 for custom fields, link templates, UI flags, client billing, and metadata fixes
- Change CONFIG_DIR from relative 'data' to absolute '/data' path in installation.py
This fixes PermissionError when trying to create /app/data instead of using
the mounted volume at /data
- Update telemetry marker file paths to use absolute /data path for consistency
- Add ensure_data_directory() function to entrypoint_fixed.sh to:
- Create /data directory if it doesn't exist
- Set proper permissions (755) on /data
- Attempt to set ownership to current user
- Create /data/uploads subdirectory
This resolves the 'Permission denied: data' errors when accessing /admin/settings
and ensures the data volume is properly initialized at container startup.
- Updated user creation to assign roles from Role system instead of legacy role field
- Added password_change_required field to User model with migration
- Added default password input and force password change option in user creation form
- Updated login route to check password_change_required and redirect to change password page
- Created change_password route and template for forced password changes
- Updated all user creation points (admin, self-registration, OIDC, default admin) to use new Role system
- Updated user form template to show roles from Role system instead of hardcoded options
Fixes issue where newly created users were still using legacy roles instead of the new role-based permission system.
Major Features:
- Integration framework with implementations for Asana, Google Calendar, QuickBooks, and Trello
- Workflow automation system with workflow engine service
- Time entry approval system with client approval capabilities
- Recurring tasks functionality
- Client portal customization and team chat features
- AI-powered categorization and suggestion services
- GPS tracking for expenses
- Gamification system with service layer
- Custom reporting with service and model support
- Enhanced OCR service for expense processing
- Pomodoro timer service
- Currency service for multi-currency support
- PowerPoint export utility
Frontend Enhancements:
- Activity feed JavaScript module
- Mentions system for team chat
- Offline sync capabilities
- New templates for approvals, chat, and recurring tasks
Database Migrations:
- Updated integration framework migrations (066-068)
- Added workflow automation migration (069)
- Added time entry approvals migration (070)
- Added recurring tasks migration (071)
- Added client portal and team chat migration (072)
- Added AI features and GPS tracking migration (073)
Documentation:
- Updated implementation documentation
- Removed obsolete feature gap analysis docs
- Added comprehensive implementation status reports
- Create app/utils/decorators.py with admin_required decorator to fix missing module error
- Fix incorrect babel imports in 6 route files: change from 'babel' to 'flask_babel' for gettext
- app/routes/workflows.py
- app/routes/time_approvals.py
- app/routes/activity_feed.py
- app/routes/recurring_tasks.py
- app/routes/team_chat.py
- app/routes/client_portal_customization.py
- Fix UnboundLocalError in app/routes/client_portal.py by removing redundant local import of Client
- Fix undefined service variable in app/routes/time_approvals.py view_approval function
These fixes resolve the blueprint registration warnings and the client portal login error.
Major refactoring to improve code organization and maintainability:
- Refactor API routes (api_v1.py) to delegate business logic to service layer
- Add new QuoteService for quote management operations
- Enhance existing services: ExpenseService, InvoiceService, PaymentService, ProjectService, TimeTrackingService
- Improve caching utilities with enhanced cache management
- Enhance API authentication utilities
- Add comprehensive test suite covering routes, services, and utilities
- Update routes to use service layer pattern (kiosk, main, projects, quotes, timer, time_entry_templates)
- Update time entry template model with additional functionality
- Update Docker configuration and startup scripts
- Update dependencies and setup configuration
This refactoring improves separation of concerns, testability, and code maintainability while preserving existing functionality.
- Normalize line endings from CRLF to LF across all files to match .editorconfig
- Standardize quote style from single quotes to double quotes
- Normalize whitespace and formatting throughout codebase
- Apply consistent code style across 372 files including:
* Application code (models, routes, services, utils)
* Test files
* Configuration files
* CI/CD workflows
This ensures consistency with the project's .editorconfig settings and
improves code maintainability.