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.
9.1 KiB
Advanced Report Builder Implementation Summary
Overview
This document summarizes the implementation of the Advanced Report Builder enhancements, including iterative report generation, custom field filtering, and improved scheduled report distribution.
Features Implemented
1. Iterative Report Generation
What it does:
- Generates one report per unique value of a specified custom field (e.g., one report per salesman)
- Automatically extracts all unique values from clients and generates separate reports
- Perfect for scenarios where you need separate reports for each salesman, region, or other custom field value
How to use:
- In Report Builder, create or edit a report
- In the Save modal, enable "Iterative Report Generation"
- Select the custom field to iterate over (e.g., "salesman")
- When viewing the report, you'll see separate sections for each unique value
Technical Details:
- New fields in
SavedReportViewmodel:iterative_report_generation(Boolean)iterative_custom_field_name(String)
- Route:
/reports/builder/<view_id>automatically detects iterative mode - Template:
reports/iterative_view.htmldisplays all reports grouped by field value
2. Custom Field-Based Filtering
What it does:
- Filter reports by any custom field on clients
- Works in both Report Builder and Scheduled Reports
- Supports filtering for unpaid hours reports
How to use:
- In Report Builder filters, select a custom field (e.g., "salesman")
- Enter the value to filter by (e.g., "MM")
- The report will only show data for clients matching that custom field value
Technical Details:
- Enhanced
generate_report_data()function incustom_reports.py - Supports filtering in
UnpaidHoursService - Works with both direct client custom fields and project->client relationships
3. Enhanced Scheduled Report Distribution
What it does:
- Supports three email distribution modes:
- Mapping: Uses
SalesmanEmailMappingtable to map custom field values to email addresses - Template: Uses dynamic email templates (e.g.,
{value}@test.de) - Single: Sends all reports to the same recipients (fallback)
- Mapping: Uses
How to use:
- Create a scheduled report with "Split by Custom Field" enabled
- Choose email distribution mode:
- Mapping: Set up mappings in Salesman Email Mapping (if available)
- Template: Enter template like
{value}@test.de - Single: Use default recipients field
Technical Details:
- New fields in
ReportEmailSchedulemodel:email_distribution_mode(String: 'mapping', 'template', 'single')recipient_email_template(String: e.g., '{value}@test.de')
- Enhanced
_get_recipients_for_field_value()method inScheduledReportService - Automatically resolves email addresses based on distribution mode
4. Improved Unpaid Hours Workflow
What it does:
- Clear checkbox option for "Unpaid Hours Only" in Report Builder
- Better integration with custom field filtering
- Clearer UI with helpful tooltips
How to use:
- In Report Builder, select "Time Entries" as data source
- Check "Unpaid Hours Only" checkbox
- Optionally add custom field filter to segment by salesman
- Preview or save the report
Technical Details:
- Uses
UnpaidHoursServicefor accurate unpaid hours calculation - Filters out entries that are:
- Already in invoices (via
InvoiceItem.time_entry_ids) - Marked as paid
- Not billable
- Already in invoices (via
5. Enhanced Management Views
What it does:
- Comprehensive list of saved report views with edit/delete options
- Shows iterative generation status
- Better error handling in scheduled reports view
- Ability to fix or remove invalid scheduled reports
How to use:
- Navigate to "Saved Views" from Report Builder
- View all your saved reports with their features
- Edit, view, or delete reports as needed
- In Scheduled Reports, use the "Fix" button to resolve invalid schedules
Technical Details:
- Enhanced
list_saved_views()route - New
fix_scheduled()route to handle invalid schedules - Improved error handling in
list_scheduled()route - Validates saved views and filters out invalid ones
6. Better Error Handling
What it does:
- Prevents errors from breaking the Scheduled Reports view
- Validates report configurations before displaying
- Provides clear error messages and fix options
Technical Details:
- Enhanced error handling in
scheduled_reports.py - Validates JSON configs before processing
- Gracefully handles missing saved views
- Provides fix/remove options for invalid schedules
Database Changes
Migration: 090_enhance_report_builder_iteration
New Columns:
-
saved_report_views table:
iterative_report_generation(Boolean, default: false)iterative_custom_field_name(String, nullable)
-
report_email_schedules table:
email_distribution_mode(String, nullable) - Values: 'mapping', 'template', 'single'recipient_email_template(String, nullable) - Template like '{value}@test.de'
API Endpoints
New/Enhanced Routes
-
GET
/reports/builder/<view_id>- Now supports iterative report generation
- Automatically detects if iterative mode is enabled
-
GET
/api/reports/builder/custom-field-values- Returns unique values for a custom field
- Query parameter:
field_name
-
POST
/reports/scheduled/<schedule_id>/fix- Fixes or removes invalid scheduled reports
- Validates saved view and config
-
POST
/reports/builder/save- Enhanced to accept iterative report generation settings
- New fields:
iterative_report_generation,iterative_custom_field_name
Files Modified
Backend
app/models/reporting.py- Added new model fieldsapp/routes/custom_reports.py- Enhanced with iterative generationapp/routes/scheduled_reports.py- Improved error handling, added fix routeapp/services/scheduled_report_service.py- Enhanced email distributionmigrations/versions/090_enhance_report_builder_iteration.py- New migration
Frontend
app/templates/reports/builder.html- Added iterative generation UIapp/templates/reports/saved_views_list.html- Shows iterative statusapp/templates/reports/scheduled.html- Enhanced with distribution info and fix buttonapp/templates/reports/iterative_view.html- New template for iterative reports
Usage Examples
Example 1: Unpaid Hours Report by Salesman
- Create a new report in Report Builder
- Select "Time Entries" as data source
- Enable "Unpaid Hours Only"
- Enable "Iterative Report Generation"
- Select "salesman" as the custom field
- Save the report
- View the report to see separate sections for each salesman
Example 2: Scheduled Reports with Email Mapping
- Create a scheduled report
- Enable "Split by Custom Field" and select "salesman"
- Set email distribution mode to "mapping"
- Ensure
SalesmanEmailMappingentries exist (MM -> mm@test.de, PB -> pb@test.de) - Schedule will automatically send reports to the correct email for each salesman
Example 3: Scheduled Reports with Email Template
- Create a scheduled report
- Enable "Split by Custom Field" and select "salesman"
- Set email distribution mode to "template"
- Enter template:
{value}@test.de - Reports will be sent to MM@test.de, PB@test.de, etc.
Testing Recommendations
-
Unit Tests:
- Test iterative report generation logic
- Test email distribution modes
- Test custom field filtering
-
Integration Tests:
- Test full workflow: create report → enable iterative → view report
- Test scheduled reports with different distribution modes
- Test error handling for invalid schedules
-
Smoke Tests:
- Create unpaid hours report with custom field filter
- Create iterative report and verify all values are shown
- Create scheduled report and verify email distribution
Known Limitations
-
Email Mapping:
- Requires
SalesmanEmailMappingentries to be set up manually - Falls back to default recipients if mapping not found
- Requires
-
Custom Field Values:
- Only extracts values from active clients
- Values must be present in client custom_fields JSON
-
Iterative Reports:
- Currently only works for time entries data source
- Other data sources will need similar implementation
Future Enhancements
- Support iterative generation for other data sources (projects, invoices, etc.)
- Add UI for managing email mappings directly in scheduled reports
- Add preview for iterative reports before saving
- Support multiple custom fields for iteration
- Add export functionality for iterative reports
Migration Instructions
-
Run the migration:
flask db upgrade -
Verify the migration:
flask db current -
Test the new features:
- Create a test report with iterative generation
- Create a test scheduled report with email distribution
- Verify error handling works correctly
Support
For issues or questions:
- Check the error logs in
logs/timetracker.log - Verify custom field values exist in client records
- Check that email mappings are set up correctly (if using mapping mode)
- Ensure saved report views have valid JSON configurations