Commit Graph

275 Commits

Author SHA1 Message Date
Dries Peeters
ff19b67046 Fix PDF layout designer logo issues and dropdown menu behavior
- Fix logo becoming invisible after resize in designer by reloading images from URL when loading saved designs

- Fix logo size not being preserved by converting scale changes to width/height during resize

- Fix logo resizing for invoice PDF layouts with proper transformend event handling

- Fix PDF templates dropdown closing parent admin menu by keeping ancestor dropdowns open

- Fix JavaScript syntax error with Jinja2 template in logo rendering

- Fix logo display in preview with proper URL embedding
2025-12-29 14:05:52 +01:00
Dries Peeters
89717dc089 Fix log_event() calls in inventory routes to use keyword arguments
Fixed all log_event() calls in app/routes/inventory.py that were incorrectly
passing dictionaries as positional arguments. The log_event() function signature
requires the event name as the first positional argument and all other data as
keyword arguments (via **kwargs).

Changed 19 calls from:
  log_event('event_name', {'key': value})  # Wrong

To:
  log_event('event_name', key=value)  # Correct

This resolves the error 'log_event() takes 1 positional argument but 2 were
given' that occurred when creating or editing stock items and other inventory
operations.

Affected operations:
- Stock item create/update/delete
- Warehouse create/update/delete
- Stock movements, transfers, and adjustments
- Stock reservations
- Supplier create/update/delete
- Purchase order operations
2025-12-29 12:57:05 +01:00
Dries Peeters
e2d7e21447 feat(api): implement and enhance search API endpoints
- Fix syntax error in existing /api/search endpoint (missing parenthesis in tasks query)
- Enhance /api/search endpoint with types filter, improved error handling, and response metadata
- Add new /api/v1/search endpoint with token-based authentication
  - Requires read:projects scope
  - Respects user permissions (non-admin users see only their own time entries)
  - Supports filtering by entity type (project, task, client, entry)
  - Includes OpenAPI documentation
- Add comprehensive test suite for both endpoints
  - Tests for legacy /api/search (session-based auth)
  - Tests for /api/v1/search (token-based auth)
  - Covers authentication, authorization, filtering, and search functionality
- Update API documentation in docs/api/REST_API.md
  - Add search endpoint documentation with examples
  - Include parameter descriptions and response formats
- Add search endpoint to /api/v1/info endpoint listing

This addresses the HIGH PRIORITY requirement to implement the search API
endpoint that was referenced but may not have been fully functional.

Resolves: Search API endpoint (/api/search) referenced but may not exist
2025-12-29 12:40:38 +01:00
Dries Peeters
95a35d2cd0 fix: Complete integration implementations and improve error handling
HIGH PRIORITY FIXES:
- GitHub: Fix webhook signature verification to use raw request body bytes
  * GitHub signs the raw body, not parsed JSON, so signature verification was failing
  * Added security checks to reject webhooks when secret configured but signature missing
  * Updated route handler to pass raw body for proper signature verification

- QuickBooks: Complete customer/account mapping implementation
  * Implemented automatic customer lookup by DisplayName in QuickBooks
  * Implemented automatic item lookup by Name for invoice items
  * Implemented automatic expense account discovery with fallback
  * Auto-saves discovered mappings for future use
  * Added validation to ensure required mappings exist before creating invoices
  * Improved API request handling with proper error messages and timeout handling

IMPROVEMENTS:
- CalDAV: Enhance bidirectional sync functionality
  * Improved update handling to use existing event hrefs correctly
  * Better error handling for HTTP errors (404, etc.)
  * Enhanced event creation vs update logic

- Integrations: Add comprehensive error handling across all integrations
  * GitHub: Network errors, authentication failures, database errors, timeout handling
  * QuickBooks: API errors, validation errors, timeout handling, connection errors
  * CalDAV: HTTP errors, connection errors, timeout handling
  * Jira & Slack: Improved error handling in webhook handlers
  * All integrations now properly handle timeouts, connection errors, auth failures
  * Detailed error messages and appropriate logging levels
  * Proper database transaction rollback on errors

TECHNICAL CHANGES:
- Updated BaseConnector.handle_webhook() to accept optional raw_body parameter
- Updated all webhook handlers (GitHub, Jira, Slack) for consistency
- Improved QuickBooks API request method with better error handling
- Enhanced CalDAV client create_or_update_event() to handle existing hrefs
2025-12-29 12:40:27 +01:00
Dries Peeters
33ad9a0c26 feat: Complete offline sync, form auto-save, browser fallbacks, and smart notifications
- Offline sync: Implement task and project sync functionality
  * Add syncTasks() and syncProjects() methods with full CRUD support
  * Implement saveTaskOffline(), saveProjectOffline() helper methods
  * Add createTaskOffline() and createProjectOffline() public API methods
  * Update markAsSynced() to handle tasks and projects correctly
  * Support both create and update operations for offline entities

- Enhanced UI: Complete form auto-save initialization
  * Add comprehensive error handling and validation
  * Implement storage quota error handling with fallback
  * Improve indicator with error states and better visual feedback
  * Add beforeunload handler to save state on page unload
  * Prevent duplicate initialization with proper tracking
  * Add CSRF token handling and form method detection
  * Use passive event listeners for better performance

- Error handling: Implement browser fallbacks for older browsers
  * Add polyfillFetch() using XMLHttpRequest for fetch API fallback
  * Implement polyfillLocalStorage() with in-memory storage
  * Add sessionStorage fallback support
  * Initialize fallbacks early in error handler setup

- Smart notifications: Complete check methods with error handling
  * Enhance checkIdleTime() with duplicate prevention and better event handling
  * Improve checkDeadlines() with validation, rate limiting, and error handling
  * Enhance checkDailySummary() with once-per-day sending and better formatting
  * Add comprehensive error handling to startBackgroundTasks()
  * Implement proper network error handling and response validation

All implementations include proper error handling, edge case coverage,
performance optimizations, and browser compatibility considerations.
2025-12-29 12:32:09 +01:00
Dries Peeters
92893b188d fix: complete backend implementations and integration improvements
This commit addresses multiple incomplete implementations identified in the
codebase analysis, focusing on security, functionality, and error handling.

Backend Fixes:
- Issues module: Implement proper permission filtering for non-admin users
  - Users can only see issues for projects they have access to
  - Added permission checks to view_issue and edit_issue routes
  - Statistics now respect user permissions

- Push notifications: Implement proper subscription storage
  - Created PushSubscription model for browser push notification subscriptions
  - Updated routes to use new model with proper CRUD operations
  - Added support for multiple subscriptions per user
  - Added endpoint to list user subscriptions

Integration Improvements:
- GitHub: Implement webhook signature verification
  - Added HMAC SHA-256 signature verification using webhook secret
  - Uses constant-time comparison to prevent timing attacks
  - Added webhook_secret field to config schema

- QuickBooks: Implement customer and account mapping
  - Added support for customer mappings (client → QuickBooks customer)
  - Added support for item mappings (invoice items → QuickBooks items)
  - Added support for account mappings (expense categories → accounts)
  - Added default expense account configuration
  - Improved error handling and logging

- Xero: Add customer and account mapping support
  - Added contact mappings (client → Xero Contact ID)
  - Added item mappings (invoice items → Xero item codes)
  - Added account mappings (expense categories → Xero account codes)
  - Added default expense account configuration

- CalDAV: Implement bidirectional sync
  - Added TimeTracker to Calendar sync direction
  - Implemented iCalendar event generation from time entries
  - Added create_or_update_event method to CalDAVClient
  - Supports bidirectional sync (both directions simultaneously)
  - Improved error handling for event creation/updates

- Trello: Implement bidirectional sync
  - Added TimeTracker to Trello sync direction
  - Implemented task to card creation and updates
  - Automatic board creation for projects if needed
  - Maps task status to Trello lists
  - Supports bidirectional sync

- Exception handling: Improve error logging in integrations
  - Replaced silent pass statements with proper error logging
  - Added debug logging for non-critical failures (user info fetch)
  - Improved error visibility for debugging
  - Affected: Google Calendar, Outlook Calendar, Microsoft Teams, Asana, GitLab

All changes include proper error handling, logging, and follow existing code
patterns. Database migration required for push_subscriptions table.
2025-12-29 12:31:52 +01:00
Dries Peeters
d3f7fb8998 docs: Add troubleshooting for PostgreSQL init and ADMIN_USERNAMES behavior
Addresses user deployment issues:
1. PostgreSQL database tables not being created automatically
2. Authentication issues when using multiple admin usernames

Documentation improvements:
- Added comprehensive troubleshooting sections for PostgreSQL database initialization
- Clarified that only the first username in ADMIN_USERNAMES is auto-created during initialization
- Documented that additional admin usernames must self-register or be created manually
- Added step-by-step solutions for both issues

Code improvements:
- Fixed whitespace handling in ADMIN_USERNAMES parsing (strip whitespace from all usernames)
- Fixed whitespace handling in all database initialization scripts to properly strip the first admin username
- Ensured consistent behavior across all initialization paths

Files updated:
- All Docker setup documentation files
- Configuration documentation
- README and env.example
- Database initialization scripts
- Config parsing logic
2025-12-29 08:00:26 +01:00
Dries Peeters
df9b06c228 fix: Improve CalDAV integration error handling and feature completeness
Fix multiple issues with CalDAV calendar integration:

Error Handling & User Experience:
- Fix 'Integration not found' error after saving CalDAV configuration
- Improve error handling in view_integration route to gracefully handle missing/invalid credentials
- Add connector error display in integration view template with helpful links
- Fix 'Test Connection' button always showing errors by improving credential validation
- Add better error messages for SSL, timeout, and connection errors with actionable guidance

Sync Improvements:
- Fix sync returning 0 items with no feedback - now provides detailed messages
- Add support for DURATION-based events (not just DTEND)
- Improve sync result messages to distinguish between 'no events found' vs 'all events already imported'
- Add synced_items field for compatibility with scheduled sync tasks
- Better handling of duplicate UID race conditions during import

CalDAV Client Enhancements:
- Improve XML parsing error handling with clear error messages
- Handle empty responses gracefully (return empty multistatus for no events)
- Add time range validation in fetch_events
- Better error handling in calendar discovery with step-by-step error messages
- Improve iCalendar parsing with better error logging

Configuration & Setup:
- Add auto_sync configuration option in CalDAV setup form
- Add URL validation for server_url and calendar_url
- Ensure credentials are properly saved and integration marked as active
- Improve CalDAV setup route to handle missing credentials during initial setup

Logging & Debugging:
- Add comprehensive logging throughout sync process
- Log calendar discovery steps and event fetch operations
- Better error context in logs for troubleshooting

This addresses user-reported issues where:
- Users couldn't click on integration after saving
- Test Connection always failed with generic errors
- Sync showed 0 items with no explanation
- Credentials weren't being saved properly
2025-12-29 08:00:08 +01:00
Dries Peeters
443a797e2d feat: Add CalDAV calendar integration for Zimbra and other CalDAV servers
Implement comprehensive CalDAV calendar integration to import calendar events
as time entries from CalDAV-compatible servers (Zimbra, Nextcloud, ownCloud).

Features:
- CalDAV client with calendar discovery and event fetching
- Automatic calendar discovery from server URL
- Import calendar events (VEVENT) as time entries
- Project matching from event titles with fallback to default project
- Idempotent sync using IntegrationExternalEventLink to prevent duplicates
- Per-user integration setup (similar to Google Calendar)
- Support for both server URL (with discovery) and direct calendar URL
- SSL certificate verification toggle for self-signed certificates
- Configurable lookback period for event import

Components:
- CalDAVCalendarConnector: Main integration connector with sync logic
- CalDAVClient: Low-level CalDAV client using PROPFIND/REPORT requests
- IntegrationExternalEventLink: Model for tracking imported events (idempotency)
- Setup UI: User-friendly form for configuration
- Comprehensive validation and error handling
- Full test coverage (unit, integration, route tests)
- Documentation: Setup guide and troubleshooting

Technical details:
- Uses icalendar library for parsing VEVENT components
- Handles timezone conversion (CalDAV UTC to app local timezone)
- Skips all-day events (only imports timed events)
- Stores credentials securely (password in access_token, username in extra_data)
- Automatic calendar discovery on first sync if only server URL provided

Migration:
- Adds integration_external_event_links table for sync tracking
- Unique constraint on (integration_id, external_uid) prevents duplicates

Documentation:
- CALDAV_INTEGRATION.md: Complete feature documentation
- CALDAV_QUICK_SETUP.md: Step-by-step setup guide with examples

Closes feature request for CalDAV/Zimbra integration.
2025-12-20 17:28:48 +01:00
Dries Peeters
00f467843b feat: add project time entries overview + day-group invoice selection
- Add per-project time entries overview page with date range filter and chronological grouping.

- Add navigation links from project view/dashboard.

- Group unbilled invoice time entry selection by day and sort chronologically.
2025-12-20 08:54:45 +01:00
Dries Peeters
a89ecd4b31 Fix project creation 500 when logging client name
Project.client is a backward-compat property that returns a string, so accessing project.client.name raised AttributeError during /projects/create activity logging.

- Use Project.client_obj.name (fallback to Project.client) when building activity/audit-style descriptions
- Fix similar usages in reports/exports/invoice/unpaid-hours flows
- Add regression test covering POST /projects/create
2025-12-20 08:35:10 +01:00
Dries Peeters
29f7186ee8 docs: Reorganize documentation structure for better navigation
Complete reorganization of project documentation to improve discoverability,
navigation, and maintainability. All documentation has been restructured into
a clear, role-based hierarchy.

## Major Changes

### New Directory Structure
- Created `docs/api/` for API documentation
- Created `docs/admin/` with subdirectories:
  - `admin/configuration/` - Configuration guides
  - `admin/deployment/` - Deployment guides
  - `admin/security/` - Security documentation
  - `admin/monitoring/` - Monitoring and analytics
- Created `docs/development/` for developer documentation
- Created `docs/guides/` for user-facing guides
- Created `docs/reports/` for analysis reports and summaries
- Created `docs/changelog/` for detailed changelog entries (ready for future use)

### File Organization

#### Moved from Root Directory (40+ files)
- Implementation notes → `docs/implementation-notes/`
- Test reports → `docs/testing/`
- Analysis reports → `docs/reports/`
- User guides → `docs/guides/`

#### Reorganized within docs/
- API documentation → `docs/api/`
- Administrator documentation → `docs/admin/` (with subdirectories)
- Developer documentation → `docs/development/`
- Security documentation → `docs/admin/security/`
- Telemetry documentation → `docs/admin/monitoring/`

### Documentation Updates

#### docs/README.md
- Complete rewrite with improved navigation
- Added visual documentation map
- Organized by role (Users, Administrators, Developers)
- Better categorization and quick links
- Updated all internal links to new structure

#### README.md (root)
- Updated all documentation links to reflect new structure
- Fixed 8 broken links

#### app/templates/main/help.html
- Enhanced "Where can I get additional help?" section
- Added links to new documentation structure
- Added documentation index link
- Added admin documentation link for administrators
- Improved footer with organized documentation links
- Added "Complete Documentation" section with role-based links

### New Index Files
- Created README.md files for all new directories:
  - `docs/api/README.md`
  - `docs/guides/README.md`
  - `docs/reports/README.md`
  - `docs/development/README.md`
  - `docs/admin/README.md`

### Cleanup
- Removed empty `docs/security/` directory (moved to `admin/security/`)
- Removed empty `docs/telemetry/` directory (moved to `admin/monitoring/`)
- Root directory now only contains: README.md, CHANGELOG.md, LICENSE

## Results

**Before:**
- 45+ markdown files cluttering root directory
- Documentation scattered across root and docs/
- Difficult to find relevant documentation
- No clear organization structure

**After:**
- 3 files in root directory (README, CHANGELOG, LICENSE)
- Clear directory structure organized by purpose and audience
- Easy navigation with role-based organization
- All documentation properly categorized
- Improved discoverability

## Benefits

1. Better Organization - Documentation grouped by purpose and audience
2. Easier Navigation - Role-based sections (Users, Admins, Developers)
3. Improved Discoverability - Clear structure with README files in each directory
4. Cleaner Root - Only essential files at project root
5. Maintainability - Easier to add and organize new documentation

## Files Changed

- 40+ files moved from root to appropriate docs/ subdirectories
- 15+ files reorganized within docs/
- 3 major documentation files updated (docs/README.md, README.md, help.html)
- 5 new README index files created
- 2 empty directories removed

All internal links have been updated to reflect the new structure.
2025-12-14 07:56:07 +01:00
Dries Peeters
7791e6ada0 feat: Add comprehensive issue/bug tracking system
Implement a complete issue management system with client portal integration
and internal admin interface for tracking and resolving client-reported issues.

Features:
- New Issue model with full lifecycle management (open, in_progress, resolved, closed, cancelled)
- Priority levels (low, medium, high, urgent) with visual indicators
- Issue linking to projects and tasks
- Create tasks directly from issues
- Client portal integration for issue reporting and viewing
- Internal admin routes for issue management, filtering, and assignment
- Comprehensive templates for both client and admin views
- Status filtering and search functionality
- Issue assignment to internal users
- Automatic timestamp tracking (created, updated, resolved, closed)

Client Portal:
- Clients can report new issues with project association
- View all issues with status filtering
- View individual issue details
- Submit issues with optional submitter name/email

Admin Interface:
- List all issues with advanced filtering (status, priority, client, project, assignee, search)
- View, edit, and delete issues
- Link issues to existing tasks
- Create tasks from issues
- Update issue status, priority, and assignment
- Issue statistics dashboard

Technical:
- Added Issue model with relationships to Client, Project, Task, and User
- New issues blueprint for internal management
- Extended client_portal routes with issue endpoints
- Updated model imports and relationships
- Added navigation links in base templates
- Version bump to 4.6.0
- Code cleanup in docker scripts and schema verification
2025-12-14 07:25:42 +01:00
Dries Peeters
8324636e2b perf: optimize task listing and improve version management
- Bump version to 4.5.1
- Refactor version retrieval: make get_version_from_setup() public and add multiple path fallbacks for better reliability in production and development environments
- Optimize task listing performance:
  * Replace joinedload with selectinload to avoid cartesian product issues
  * Implement optimized pagination that avoids expensive count queries when possible
  * Move AJAX request check earlier to skip unnecessary filter data loading
  * Add query limits to filter dropdowns (projects: 500, users: 200)
  * Optimize permission checks by checking is_admin first (no DB query)
- Update API info endpoint and context processor to use centralized version retrieval
- Maintain backward compatibility with _get_version_from_setup alias
2025-12-13 19:06:19 +01:00
Dries Peeters
2230d5b909 feat: Add quick task creation from Start Timer modal
Add ability to create tasks directly from the Start Timer UI without
navigating through deep menus or loading all tasks upfront.

Features:
- Convert task dropdown to combobox (input + datalist) for autocomplete
- Allow free-text input to create new tasks on-the-fly
- Auto-create tasks with sensible defaults when timer is started:
  * Assigned to current user
  * Medium priority
  * No due date
  * Todo status
- New AJAX endpoint /api/tasks/create for inline task creation
- Preserve task selection when reloading task list after creation

Implementation details:
- Task combobox shows existing tasks as suggestions via datalist
- When user types a new task name, it's automatically created before
  starting the timer
- JavaScript handles task creation asynchronously with proper error handling
- Form submission includes the newly created task_id

Tests:
- Add integration test for inline task creation endpoint
- Add smoke test for full timer start flow with new task creation

This significantly improves workflow efficiency by eliminating the need
to navigate through multiple screens to create and start a timer for
a new task.
2025-12-12 22:35:38 +01:00
Dries Peeters
a83aabb006 feat: Add user filter and flexible column layout to Kanban board
- Add 'Assigned To' filter dropdown to filter tasks by assigned user
  - Enables users to view their personal todo landscape
  - Filter works in combination with existing project filter
  - Shows all active users sorted by display name

- Replace fixed grid layout with flexible flexbox layout
  - Columns now expand evenly to fill available horizontal space
  - Added min-width constraint to prevent columns from becoming too narrow
  - Maintains horizontal scrolling on smaller screens for better mobile UX

This improves the Kanban board usability by allowing users to focus on
their assigned tasks and provides a better visual layout that adapts
to the number of columns and screen size.
2025-12-12 22:24:19 +01:00
Dries Peeters
bde61c7f5d Fix permission and role management bugs
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.
2025-12-12 22:18:30 +01:00
Dries Peeters
88656c3d34 feat: Advanced Report Builder with iterative generation and email distribution
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
2025-12-12 22:11:57 +01:00
Dries Peeters
a582e2af62 feat: improve error handling, performance logging, and PWA install UI
- 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
2025-12-12 21:49:26 +01:00
Dries Peeters
8a78975497 Enhance custom reports and scheduled reports functionality
- 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
2025-12-08 21:16:06 +01:00
Dries Peeters
98fefd5ec1 fix: handle missing custom_field_definitions table gracefully (fixes #344)
- 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'.
2025-12-05 07:50:35 +01:00
Dries Peeters
3c2e144f5c Fix dashboard cache invalidation when editing timer entries (#342)
- 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.
2025-12-05 07:44:57 +01:00
Dries Peeters
5f3cd98533 Fix dashboard cache invalidation when editing timer entries (#342)
- 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.
2025-12-05 07:15:37 +01:00
Dries Peeters
4e57f08c03 Add salesman-based report splitting and email distribution
- Add SalesmanEmailMapping model to map salesman initials to email addresses
  - Support for direct email addresses, email patterns, and domain-based patterns
  - Admin interface for managing email mappings

- Add UnpaidHoursService for querying and grouping unpaid time entries
  - Filter by client custom fields (e.g., salesman)
  - Group unpaid hours by salesman for report generation

- Add salesman report routes and API endpoints
  - CRUD operations for email mappings
  - Generate and send reports split by salesman
  - Preview email addresses for salesman initials

- Enhance scheduled reports with salesman splitting
  - Add split_by_salesman and salesman_field_name to report schedules
  - Automatically split reports by salesman and send to mapped emails

- Add UI components for salesman report management
  - Admin dashboard integration
  - Report builder with salesman splitting options
  - Email mapping management interface

- Add email template for unpaid hours reports

- Add database migrations:
  - 087: Create salesman_email_mappings table
  - 088: Add salesman splitting fields to report_email_schedules
2025-12-03 08:59:48 +01:00
Dries Peeters
f3a3a40480 Add project custom fields and file attachments for projects and clients
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
2025-12-03 08:30:15 +01:00
Dries Peeters
86b3498f05 perf: optimize task queries and fix N+1 performance issues
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
2025-12-03 07:02:39 +01:00
Dries Peeters
ac19bebf2d feat: enhance offline sync and improve performance (v4.3.2)
- 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
2025-12-02 06:13:54 +01:00
Dries Peeters
b37860f582 Update enhanced-ui.js 2025-12-01 19:26:46 +01:00
Dries Peeters
f87da99781 feat: Add custom field filtering and display for clients, projects, and time entries
- 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).
2025-12-01 19:25:05 +01:00
Dries Peeters
2bd48d9e60 feat: Add client count tracking and cleanup for custom field definitions
- 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
2025-12-01 18:48:38 +01:00
Dries Peeters
c71d444756 Improve error handling, Docker healthchecks, and offline sync functionality
- 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.
2025-12-01 16:24:39 +01:00
Dries Peeters
4851ee6a40 feat: Add unpaid hours report with Ajax filtering and Excel export
- 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.
2025-12-01 15:43:14 +01:00
Dries Peeters
73b4129662 Add configurable duplicate detection fields for CSV client import
- 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
2025-12-01 14:38:33 +01:00
Dries Peeters
de266dbf7d feat: Add time entries overview page with AJAX filters and bulk mark as paid
- 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
2025-12-01 14:15:58 +01:00
Dries Peeters
9112a696dd feat: Enhance audit logging with improved error handling and diagnostic tools
- 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
2025-12-01 13:30:18 +01:00
Dries Peeters
1f6941ff43 Fix AUTH_METHOD=none and add comprehensive schema verification
- 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.
2025-12-01 08:15:30 +01:00
Dries Peeters
b2ecf11b15 feat(import-export): Add CSV import/export for clients with custom fields and contacts
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
2025-11-30 16:06:02 +01:00
Dries Peeters
3f5d253a8b feat: Add global custom field definitions with link template support
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.
2025-11-30 15:29:02 +01:00
Dries Peeters
90d8407bda feat(billing): add paid status tracking for time entries with invoice reference
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.
2025-11-30 11:31:42 +01:00
Dries Peeters
bf4b36e701 feat: Convert OAuth credentials section to dropdown in System Settings
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.
2025-11-30 11:13:07 +01:00
Dries Peeters
1bdac1efe1 Update dashboard: rename Project column to Source and make entries clickable
- 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.
2025-11-30 11:03:41 +01:00
Dries Peeters
1e7d8cf575 feat(clients): Add recent hours history to client detail page
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.
2025-11-30 11:00:03 +01:00
Dries Peeters
ac465d9612 feat: Enhance UI/UX with improved form validation and error handling
- Add comprehensive form validation system with real-time feedback
- Implement enhanced error handling with retry mechanisms and offline support
- Update route handlers for improved error responses
- Enhance list templates with better error handling and validation
- Update dashboard, timer, and report templates with enhanced UI
- Improve project service with better error handling
- Update config manager utilities
- Bump version to 4.2.0

Files updated:
- Routes: auth, clients, invoices, projects, quotes, tasks, timer, custom_reports
- Templates: base, dashboard, all list views, timer pages, reports
- Static: enhanced-ui.js, error-handling-enhanced.js, form-validation.js
- Services: project_service.py
- Utils: config_manager.py
- Version: setup.py
2025-11-30 10:51:09 +01:00
Dries Peeters
c3e3005baf Fix transaction abort error on user loading (4.1.1 update issue)
- 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.
2025-11-29 14:58:43 +01:00
Dries Peeters
ce81852d2e Fix app context handling for expiring quotes scheduled task
- Add wrapper function check_expiring_quotes_with_app() to properly handle Flask app context
- Refactor check_expiring_quotes() to remove redundant app context wrapper
- Ensure consistent pattern with other scheduled tasks (webhook retry, integration sync)
- Bump version to 4.1.1
2025-11-29 09:33:56 +01:00
Dries Peeters
149a4bb4c8 Update CI workflow, app initialization, quotes route, and test files 2025-11-29 07:39:29 +01:00
Dries Peeters
0094428b72 Update routes, services, and tests 2025-11-29 07:22:15 +01:00
Dries Peeters
583f9b6755 Format code with Black to fix code quality test 2025-11-29 07:13:23 +01:00
Dries Peeters
0ec6b8e9d6 refactor: major integration system overhaul with global integrations support
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
2025-11-29 07:03:00 +01:00
Dries Peeters
dcbdfcc288 feat: Add client custom fields, link templates, UI feature flags, and client billing support
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
2025-11-29 06:17:07 +01:00