Admins can hide whole app modules (Analytics, Finance & Expenses, CRM, etc.)
per role so users in that role neither see them in the nav nor access them
by URL/API.
- Add Role.hidden_module_ids (JSON denylist) and migration
- Extend ModuleRegistry.is_enabled() with role-based hide check; module is
hidden only if ALL of the user's roles hide it (super admins bypass)
- Add Module visibility section to role create/edit form with checkboxes
by category; persist via hidden_modules form field
- Add tests for registry hide/allow semantics and route decorator 403
Closes#484
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add POST /api/v1/auth/login (rate-limited) returning API token for mobile
- Fix time entry duration when DB returns timezone-aware datetimes (_naive_dt)
- Add _parse_date_range helper; expose timezone in API info
- Extend time entries API tests
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add User preferences: calendar_color_events, calendar_color_tasks,
calendar_color_time_entries (nullable hex)
- Calendar API: attach color to each event/task/time_entry and return
typeColors; view_calendar passes type_colors to template
- PATCH /api/preferences: accept and validate calendar color fields
- Migration 117: add the three user columns
Events, tasks, and time entries can now be distinguished by user-chosen
colors (defaults: blue, amber, green). Frontend color pickers and
legend are on the calendar page (already in previous commit).
Co-authored-by: Cursor <cursoragent@cursor.com>
- Show Project and Task instead of Stock Item and Warehouse for items from time entries
- Make quantity read-only for time-based items (billed hours) to prevent accidental edits
- Preserve time_entry_ids when saving invoice edits (fixes lost linkage)
- Enforce quantity from time entries on save for defense in depth
- Add task_name_from_time_entries property to InvoiceItem
- Add translations for new UI strings
Fixes#458 - Time entries now properly align with their start and end
timestamps in both FullCalendar and custom calendar weekly views.
FullCalendar (timer calendar):
- Add explicit timeZone: 'local' to ensure consistent date interpretation
- Normalize time entry ISO format to YYYY-MM-DDTHH:mm:ss (no microseconds)
Custom calendar week view:
- Fix data loading: merge events, tasks, and time_entries from separate
API arrays into unified structure with extendedProps.item_type
- Implement proper spanning: entries now span across multiple hour cells
based on their actual start/end times
- Add precise positioning: entries align with minute-level accuracy using
percentage-based top/height calculations
- Apply same spanning logic to calendar events with duration
- Add hour labels column (00:00-23:00) for better visual reference
Time entries and events now correctly display their full duration and
align with both start and end timestamps in the weekly grid view.
- Make InstallationConfig config dir overridable via INSTALLATION_CONFIG_DIR
so tests and CI use a writable path instead of /data (fixes PermissionError
on redirect to /admin/settings after logo upload).
- Set INSTALLATION_CONFIG_DIR in conftest before app import and in
ci-comprehensive.yml for integration-tests and full-test-suite jobs.
- In Settings.get_settings(), add _session_in_flush() and a re-entrancy
guard to skip add+commit when called during another commit's flush,
fixing ResourceClosedError in currency_display test setup.
- Update test_installation_config fixture to set INSTALLATION_CONFIG_DIR
so it continues to use its temp dir with the new env-based behavior.
- Client: call flag_modified() after mutating custom_fields in
set_custom_field() and remove_custom_field() so SQLAlchemy persists
JSON changes (in-place dict updates are not tracked by default).
Fixes test_count_clients_with_value_ignores_empty and
test_count_clients_with_value_ignores_other_fields.
- ClientNote: add ondelete=CASCADE to client_id FK so schema from
db.create_all() matches migration 024 and notes are deleted when
client is deleted. Fixes test_client_note_cascade_delete.
- Add cascade='all, delete-orphan' to the notes backref so client notes
are removed when a client is deleted.
- In test_client_has_notes_relationship use client.notes.count() instead
of len(client.notes) since the backref uses lazy='dynamic'.
- Add user status tracking (online/offline/away) based on last_login
- Implement is_online() and get_status() methods in User model
- Include status in user.to_dict() for API responses
- Create persistent chat widget that remains open across page navigation
- Floating chat button in bottom-right corner (always visible)
- Expandable chat panel with channels, direct messages, and message input
- State persistence using localStorage (remembers open/closed and active channel)
- Auto-refreshes channels and messages periodically
- Integrates with user selector for starting new chats
- Add chat user selection popup component
- Searchable user list with avatars and status indicators
- Color-coded status badges (green=online, yellow=away, gray=offline)
- Creates or finds existing direct message channels
- Add API endpoints for chat functionality
- GET /api/chat/users: List all active users with status
- POST /api/chat/direct-message/<user_id>: Create or find direct message channel
- Add chat button to header navigation
- Opens persistent chat widget or user selector
- Only visible when team_chat module is enabled
- Add status indicators throughout chat interface
- Show user status in direct messages list
- Display status badges in channel member lists
- Status visible in user selection popup
- Fix z-index and positioning issues
- Chat widget positioned above other floating elements (z-[60])
- Adjusted position to avoid overlap with quick actions button
- Fix CSRF token handling
- Use FormData for message submission to properly handle CSRF
- Include CSRF token in user selector requests
- Fix file_size variable in upload_attachment endpoint
Add exclude_weekends feature to allow users to set weekly goals for
Monday-Friday (5-day work week) instead of Monday-Sunday (7-day week).
This addresses client feedback requesting the ability to exclude weekends
when setting weekly goals, making it more realistic for standard work
schedules.
Changes:
- Add exclude_weekends boolean column to weekly_time_goals table
- Update WeeklyTimeGoal model to calculate week_end_date as Friday when
exclude_weekends is True
- Filter weekend hours from actual_hours calculation when enabled
- Update days_remaining to count only weekdays for 5-day goals
- Add checkbox option in create/edit forms with helpful tooltips
- Update view template to show 5-day work week badge and exclude weekends
from daily breakdown
- Update tips section to mention the 5-day option
The feature is backward compatible - existing goals default to 7-day weeks.
All calculations (hours, days remaining, averages) correctly account for
the selected work week type.
- Add @module_enabled decorator to all module routes (30+ route files)
- Protects routes for inventory, mileage, per_diem, project_templates,
gantt, kanban, weekly_goals, issues, time_entry_templates, reports,
custom_reports, scheduled_reports, invoice_approvals, recurring_invoices,
payments, payment_gateways, budget_alerts, analytics, integrations,
import_export, saved_filters, workflows, time_approvals, activity_feed,
recurring_tasks, team_chat, client_portal, kiosk, and more
- Ensures disabled modules are not accessible to users
- Fix indentation errors in route files
- Remove duplicate module_enabled imports incorrectly placed inside
function bodies in 8 files (import_export, client_portal, custom_reports,
integrations, kiosk, payment_gateways, scheduled_reports, team_chat)
- Move all imports to top of files for proper scope
- Fix Jinja2 template error in admin/settings.html
- Replace invalid loop.parent.loop.last with namespace-based approach
- Use Jinja2 namespace feature to track first item for comma placement
- Fixes UndefinedError when rendering module dependencies and names
- Fix JavaScript syntax error in admin/settings.html
- Remove orphaned closing braces causing parse errors
- Restores toggleCategory function availability
- Update task templates to include module visibility checks
- Add module_enabled checks to task creation and editing templates
This commit completes the module management system, allowing administrators
to globally enable/disable modules, with all routes properly protected and
UI elements conditionally rendered based on module status.
Add comprehensive audit logging for TimeEntry operations including:
- Client/project context and creation timestamps
- Full entity state before/after changes
- User-provided reasons for deletions and modifications
- Enhanced UI for entering reasons in delete/edit dialogs
Database Changes:
- Add migration 114: reason, entity_metadata, full_old_state, full_new_state columns
- Use JSON column type for entity_metadata for better type handling
Model Updates:
- Extend AuditLog model with new fields and helper methods
- Update log_change() to accept reason, metadata, and full states
- Add get_entity_metadata(), get_full_old_state(), get_full_new_state() methods
- Use JSON column for entity_metadata (returns dict/list directly)
Service Layer:
- Update TimeTrackingService to capture full TimeEntry state and metadata
- Accept reason parameter in delete_entry() and update_entry()
- Create comprehensive audit logs with all context
API Routes:
- Update api.py, api_v1.py, and timer.py routes to accept reason parameter
- Refactor routes to use service layer for consistent audit logging
- Add reason support to bulk delete operations
UI Enhancements:
- Add reason textarea to bulk delete confirmation dialog
- Add reason textarea to time entry edit forms (admin and regular users)
- Update JavaScript to handle reason submission
Audit Log Display:
- Show client/project information and creation timestamp in list view
- Display full old/new states, reason, and metadata in detail view
- Format JSON states for better readability
Bug Fixes:
- Fix duration_seconds reference in timer stop route
- Improve error handling in timer operations with proper exception handling
- Add dashboard cache invalidation after manual entry creation
Scheduled reports (per-salesman, unpaid-only)
- Schedule form: add email distribution (single / SalesmanEmailMapping /
template) and recipient template when "Split by custom field" is on.
- Support {value} and {value_lower} in recipient_email_template
(e.g. {value_lower}@test.de).
- Add use_last_month_dates on ReportEmailSchedule: optional "Use previous
calendar month" for monthly runs; migration 111.
- Override report date range in ScheduledReportService when
cadence=monthly and use_last_month_dates=true.
- Wire use_last_month_dates through schedule form, API, and
create_schedule.
Report Builder
- Add "Unpaid time entries" quick-start (Time Entries + unpaid only +
last 30 days) and applyUnpaidPreset().
- Clarify "Unpaid only" help: "Unpaid = billable, not yet on any invoice."
- Define canvas at top of script so edit-mode IIFE and addDataSourceToCanvas
can use it; fix applyUnpaidPreset/onclick when script failed to parse.
- Click-to-add for Data Sources and Components (in addition to drag-and-drop).
- Set dataTransfer.effectAllowed = 'copy' in dragstart for drop compatibility.
- Fix save-form handler: remove orphan try { with no catch that caused
SyntaxError and prevented applyUnpaidPreset (and rest of script) from loading.
Documentation
- Add docs/reports/UNPAID_BY_SALESMAN_AND_SCHEDULED_REPORTS.md (unpaid
definition, unpaid-by-salesman setup, SalesmanEmailMapping, template use).
- Add settings.disabled_module_ids (JSON) to store admin-disabled module IDs
- Migration 110: add disabled_module_ids column to settings
- ModuleRegistry.is_enabled() respects settings.disabled_module_ids
- Admin > System Settings: new 'Module visibility' section with toggles
for all non-core modules; disabled modules are hidden from all users.
- Core modules stay always on; default empty list keeps current behavior.
Audit logs were not recording any changes because after_flush runs
after SQL is emitted; by then session.new, session.dirty, and
session.deleted can be cleared and attribute history for updates is
often consumed, so the handler saw nothing to log.
Changes:
- Add receive_before_flush: process session.dirty (updates) and
session.deleted (deletes) while history is still valid; stash
session.new (creates) in session.info for after_flush.
- Simplify receive_after_flush: only handle pending creates from
session.info (instances now have ids), then session.flush() so
audit rows are in the same transaction.
- Register receive_before_flush for before_flush on Session,
sessionmaker class, and SignallingSession.
- Make receive_before_flush accept (session, flush_context, instances)
to match SQLAlchemy's before_flush signature.
- Remove db.session.flush() from AuditLog.log_change to avoid
nested flush; rely on main flush or explicit flush in after_flush.
- check_audit_logging.py: use entity_type='TimeEntry' to match
get_entity_type (model __class__.__name__).
- test_audit_logging: assert at least one AuditLog for create/update/
delete; use test_client for create; fix update to merge then mutate.
- Add Project.color (hex) and migration for projects.color
- Projects create/edit: Gantt color field with Pickr (swatch + hex input),
Pickr theme CSS and gantt-color-picker.js for init and sync
- Gantt API: include color in JSON for projects and tasks (tasks use project color)
- Gantt view: set custom_class from color, inject CSS for .bar and .bar-progress,
fix selectors for .gantt .bar-wrapper and :hover/.active overrides; add
fallback styles for gantt-project and gantt-task
InventoryReportService: use moved_at and reference_type/reference_id instead of non-existent movement_date and reference to avoid AttributeError in get_inventory_turnover, _get_stock_at_date, get_movement_history.
_ensure_legacy_lot: run only for outflows (movement_qty < 0) or record_devaluation (movement_qty None). For outflows use pre-movement total (updated_stock + abs(qty)) so FIFO consumption stays in sync with WarehouseStock. Skip for inbound to prevent double-count of new lots.
record_movement: stop swallowing exceptions from _apply_lot_changes; re-raise so callers can roll back and avoid inconsistent WarehouseStock vs StockLot state.
Movement form: dynamic quantity hint by type (return/waste/devaluation/default), required devaluation fields when shown, client-side sign checks for return (positive) and waste (negative).
Tests: test_first_inbound_with_no_lots_matches_warehouse_stock, test_first_outbound_with_no_lots_matches_warehouse_stock.
- Add date_format column to invoice_pdf_templates and quote_pdf_templates tables
- Default date format set to DD.MM.YYYY (%d.%m.%Y)
- Update PDF generators to use template-specific date format
- Add date format configuration in admin PDF template editor
- Replace Babel date formatting with strftime for consistent formatting
- Update template filters to use DD.MM.YYYY format by default
This allows users to customize date formatting per PDF template while
maintaining backward compatibility with existing templates.
- Add decorative image element to PDF Layout Designer for both invoice and quote templates
- Implement template-level decorative image upload and management
- Add backend routes for template image upload and serving
- Update PDF generation (HTML preview and ReportLab) to handle template images with transparency preservation
- Sync all decorative image functionality between invoice and quote PDF layout editors
Fixes:
- Fix upload button not opening file picker in invoice template (use fresh DOM references)
- Fix element name matching to handle 'decorative-image element-overlap' format (use .includes() instead of strict equality)
- Fix image restoration after page reload with enhanced JSON searching and position matching
- Fix image persistence in Konva.js serialization/deserialization
Improvements:
- Enhanced image restoration logic with fallback mechanisms
- Improved error handling and console logging for debugging
- Better handling of transparent backgrounds in PDF export
- Consistent behavior between invoice and quote template editors
- Add 'devaluation' to stock movement types
- Add validation to ensure trackable items for devaluation
- Improve error handling for devaluation operations
- Improve invoice model with enhanced prefix handling and validation
- Enhance expense routes with better error handling and validation
- Refactor PDF generator with improved template support and formatting
- Update Google Calendar integration with improved error handling
- Enhance scheduled tasks with better logging and reliability
- Update admin routes with improved permission checks
- Improve email utility with better template handling
- Improve invoice model with additional fields and methods
- Enhance quote model with better validation and relationships
- Add invoice repository for data access layer abstraction
- Update invoice and quote routes with improved functionality
- Add quote service for business logic separation
- Improve quote view and edit templates with better UX
- Add ReportLab template renderer with JSON-based template system
- Implement template schema validation and helper functions
- Add database migration for template_json columns
- Update visual editor to generate ReportLab JSON alongside HTML/CSS
- Maintain backward compatibility with legacy templates
- Add comprehensive migration documentation
BREAKING CHANGE: Existing PDF templates need to be saved again through
the visual editor to generate the new template_json format. Templates
will continue to work using the legacy fallback generator until saved.
- Improve expenses route with additional functionality
- Enhance admin route with new features
- Update auth route with improved authentication handling
- Extend user model with new capabilities
- Update expenses view template
- Improve config manager utility
- Add migration to update check constraint allowing NULL project_id and client_id for source='auto' entries
- Update TimeEntry model validation to allow entries without project/client when source='auto'
- Update TimeEntryCreateSchema to allow entries without project/client when source='auto'
- Enables calendar integrations to import entries that don't have project/client mapping yet
Replace bare except clauses with specific exception types and add
appropriate logging throughout the codebase. This improves:
- Debugging capabilities with proper error messages
- Code maintainability by catching specific exceptions
- Error tracking through structured logging
Changes include:
- Replace bare except: with specific exception types (JSONDecodeError,
TypeError, ValueError, OSError, AttributeError, RuntimeError)
- Add logging for error conditions that were previously silently ignored
- Improve error messages with context information
- Add upload_comment_attachment route with file validation
- Add download_attachment route for file downloads
- Add delete_attachment route with permission checks
- Enhance Comment.to_dict() to include attachments array
- Support file size limits (10 MB) and type validation
- Proper error handling and file cleanup on errors
Routes follow existing attachment patterns from projects/clients.
- Create CommentAttachment model following ProjectAttachment pattern
- Add database migration for comment_attachments table
- Register CommentAttachment in models __init__.py
- Support file uploads (images, PDFs, documents, archives)
- Include file metadata (size, type, uploader, timestamp)
- Cascade delete attachments when comments are deleted
Enables file attachments to comments for better team collaboration.
- Update stock movement model with improved functionality
- Enhance inventory routes and API endpoints
- Improve inventory templates for movements, reports, and stock items
- Add better history tracking and valuation reporting
Add Peppol BIS Billing 3.0 (UBL) invoice sending via a configurable access point, including admin-configurable settings, per-invoice send history, and documentation/README updates.
Also introduce stock lots/allocations (valuation layers) with supporting inventory route/report/UI updates and hardened startup migration handling.
Add new client portal pages (dashboard, approvals, notifications, documents, reports) and extend API/routes/services to support client approvals, invoices/quotes views, and related notifications.
Update email templates and docs; add/adjust tests for new models/routes.
- Rename 'metadata' column to 'extra_data' in ClientNotification model
to avoid SQLAlchemy Declarative API reserved word conflict
- Update ClientNotificationService to use 'extra_data' instead of 'metadata'
- Maintain API compatibility by returning 'metadata' key in to_dict() method
- Update migration to create 'extra_data' column instead of 'metadata'
- Improve migration idempotency and SQLite compatibility with proper checks
- Enhance backup directory handling with configurable BACKUP_FOLDER support
- Update admin routes to use centralized backup directory function
This fixes the application startup error:
sqlalchemy.exc.InvalidRequestError: Attribute name 'metadata' is reserved
when using the Declarative API.
The migration is now idempotent and handles both PostgreSQL and SQLite
databases safely.
- Refactor migrations with idempotency checks and better error handling
* Add SQLAlchemy inspector checks for table/column existence
* Improve error messages and handling for schema operations
* Make migrations safe to run multiple times
* Update 27 migration files with enhanced error handling patterns
- Add missing schema columns via new migrations
* Migration 095: Add ui_show_issues column to users table
* Migration 096: Add portal_issues_enabled column to clients table
- Enhance Settings model error handling
* Improve detection of schema errors (table/column missing)
* Better handling of SQLAlchemy exceptions during migrations
* More comprehensive error checking for OperationalErrors
- Fix database auto-switching logic in app initialization
* Respect explicit DATABASE_URL setting to prevent unwanted switches
* Only auto-switch to PostgreSQL when not explicitly configured
- Update docker entrypoint script with migration improvements
- Add dedicated donation page (/donate) explaining why donations matter
- Implement DonationInteraction model to track user engagement and interactions
- Add smart banner logic with contextual messaging based on user milestones
- Improve donation accessibility with links in sidebar, footer, dashboard, and all major pages
- Add UTM tracking to all Buy Me a Coffee links for analytics
- Fix CSRF token issues in donation tracking JavaScript
- Enhance dashboard widget with user stats and dual action buttons
- Add donation information section to About page
- Update support banner with 'Learn More' and 'Donate' options
- Create database migration for donation_interactions table
The donation system now provides:
- Smart prompts that show after user milestones (7+ days, 50+ entries, 100+ hours)
- Banner dismissal tracking with 30-day cooldown
- Multiple access points throughout the application
- Better visibility of donation impact and importance
- Comprehensive tracking for analytics and optimization
Remove both system-wide and per-user UI feature enable/disable settings
in favor of the centralized ModuleRegistry system for module management.
Changes:
- Remove ui_allow_* columns from Settings model and database (migration 093)
- Remove ui_show_* preference assignments from user settings route
- Remove UI Customization section from user settings template
- Remove UI Features section from admin settings template
- Update admin modules template to use ModuleRegistry instead of settings flags
- Remove settings_flag and user_flag attributes from ModuleDefinition
- Update ModuleRegistry.is_enabled() to only check dependencies and default_enabled
- Update dashboard template to use is_module_enabled() helper
- Update admin route docstring to reflect module management changes
Module visibility is now controlled exclusively via the admin module
management interface (/admin/modules), eliminating the need for separate
system-wide and per-user UI preference systems.
- Add centralized module registry system (ModuleRegistry) for managing
module metadata, dependencies, and visibility across the application
- Create module helper utilities with decorators (@module_enabled) and
helper functions for route protection and template access
- Add database migration (092) to add missing module visibility flags
to settings and users tables for granular control
- Extend Settings and User models with additional module visibility
flags for CRM, Finance, Tools, and Advanced features
- Implement admin module management UI for system-wide module
enable/disable controls
- Add module checks to routes (calendar, contacts, deals, expenses,
invoices, leads, custom_reports) to enforce visibility rules
- Update scheduled report service and report templates to respect
module visibility settings
- Bump version to 4.8.0 in setup.py
- Add comprehensive documentation for module integration planning
and implementation analysis
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.
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.
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
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
- 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'.
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