Files
TimeTracker/docs/development/MODULE_INTEGRATION_PLAN.md
Dries Peeters 083dd9f1f2 feat: Implement comprehensive module system with visibility controls
- 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
2025-12-29 14:13:32 +01:00

554 lines
17 KiB
Markdown

# Module Integration & Visibility Control Plan
**Date:** 2025-01-27
**Status:** Planning Phase
## Executive Summary
This document outlines a comprehensive plan to improve module integration in TimeTracker and implement a centralized system for enabling/disabling modules and menu items from admin settings. The goal is to create a more maintainable, flexible architecture that allows administrators to customize the application based on their needs.
---
## Current State Analysis
### Module Inventory
TimeTracker currently has **50+ modules/features** organized into the following categories:
#### Core Modules (Always Enabled)
- **Authentication** (`auth`) - Login, logout, profile
- **Dashboard** (`main`) - Main dashboard
- **Projects** (`projects`) - Project management
- **Time Tracking** (`timer`) - Time entry, timers
- **Tasks** (`tasks`) - Task management
- **Clients** (`clients`) - Client management
#### Optional Modules (Can Be Disabled)
1. **Calendar** (`calendar`) - Calendar view, integrations
2. **Project Templates** (`project_templates`) - Template system
3. **Gantt Chart** (`gantt`) - Gantt visualization
4. **Kanban Board** (`kanban`) - Kanban task board
5. **Weekly Goals** (`weekly_goals`) - Goal tracking
6. **Issues** (`issues`) - Issue/bug tracking
7. **CRM Features:**
- **Quotes** (`quotes`) - Quote management
- **Contacts** (`contacts`) - Contact management
- **Deals** (`deals`) - Deal pipeline
- **Leads** (`leads`) - Lead management
8. **Finance & Expenses:**
- **Reports** (`reports`) - Standard reports
- **Report Builder** (`custom_reports`) - Custom report builder
- **Scheduled Reports** (`scheduled_reports`) - Automated reports
- **Invoices** (`invoices`) - Invoice management
- **Invoice Approvals** (`invoice_approvals`) - Approval workflow
- **Recurring Invoices** (`recurring_invoices`) - Recurring billing
- **Payments** (`payments`) - Payment tracking
- **Payment Gateways** (`payment_gateways`) - Gateway integration
- **Expenses** (`expenses`) - Expense tracking
- **Mileage** (`mileage`) - Mileage tracking
- **Per Diem** (`per_diem`) - Per diem expenses
- **Budget Alerts** (`budget_alerts`) - Budget monitoring
9. **Inventory** (`inventory`) - Inventory management
10. **Analytics** (`analytics`) - Analytics dashboard
11. **Tools & Data:**
- **Integrations** (`integrations`) - External integrations
- **Import/Export** (`import_export`) - Data import/export
- **Saved Filters** (`saved_filters`) - Filter management
12. **Admin Features:**
- **User Management** (`admin`) - User administration
- **Permissions** (`permissions`) - RBAC system
- **Settings** (`settings`) - System settings
- **Audit Logs** (`audit_logs`) - Activity logging
- **Webhooks** (`webhooks`) - Webhook management
- **Custom Fields** (`custom_field_definitions`) - Field definitions
- **Link Templates** (`link_templates`) - Link templates
- **Time Entry Templates** (`time_entry_templates`) - Time templates
13. **Advanced Features:**
- **Workflows** (`workflows`) - Automation workflows
- **Time Approvals** (`time_approvals`) - Time approval workflow
- **Activity Feed** (`activity_feed`) - Activity stream
- **Recurring Tasks** (`recurring_tasks`) - Automated tasks
- **Team Chat** (`team_chat`) - Team messaging
- **Client Portal** (`client_portal`) - Client-facing portal
- **Kiosk Mode** (`kiosk`) - Kiosk interface
### Current Architecture Issues
1. **No Centralized Module Registry**
- Blueprints registered directly in `app/__init__.py`
- No single source of truth for module metadata
- Hard to track module dependencies
2. **Inconsistent Visibility Control**
- Some modules have `ui_allow_*` flags in Settings
- Some modules have `ui_show_*` flags in User
- Many modules have no flags at all
- No route-level protection
3. **Complex Navigation Logic**
- Navigation menu has hardcoded endpoint checks
- Conditional rendering scattered throughout templates
- Difficult to add/remove menu items
4. **Missing Module Flags**
- CRM features (deals, leads, contacts) have no flags
- Many admin features have no flags
- Advanced features have no flags
5. **No Module Dependencies**
- No way to express that one module depends on another
- No validation when disabling modules
---
## Proposed Solution
### Phase 1: Module Registry System
Create a centralized module registry that defines:
- Module metadata (name, description, category)
- Dependencies between modules
- Default visibility settings
- Route associations
**File:** `app/utils/module_registry.py`
```python
from dataclasses import dataclass
from typing import List, Optional, Dict
from enum import Enum
class ModuleCategory(Enum):
CORE = "core"
TIME_TRACKING = "time_tracking"
PROJECT_MANAGEMENT = "project_management"
CRM = "crm"
FINANCE = "finance"
INVENTORY = "inventory"
ANALYTICS = "analytics"
TOOLS = "tools"
ADMIN = "admin"
ADVANCED = "advanced"
@dataclass
class ModuleDefinition:
id: str
name: str
description: str
category: ModuleCategory
blueprint_name: str
default_enabled: bool = True
requires_admin: bool = False
dependencies: List[str] = None # Module IDs this depends on
settings_flag: Optional[str] = None # Settings.ui_allow_* field name
user_flag: Optional[str] = None # User.ui_show_* field name
routes: List[str] = None # Route endpoints
def __post_init__(self):
if self.dependencies is None:
self.dependencies = []
if self.routes is None:
self.routes = []
class ModuleRegistry:
_modules: Dict[str, ModuleDefinition] = {}
@classmethod
def register(cls, module: ModuleDefinition):
cls._modules[module.id] = module
@classmethod
def get(cls, module_id: str) -> Optional[ModuleDefinition]:
return cls._modules.get(module_id)
@classmethod
def get_all(cls) -> Dict[str, ModuleDefinition]:
return cls._modules.copy()
@classmethod
def get_by_category(cls, category: ModuleCategory) -> List[ModuleDefinition]:
return [m for m in cls._modules.values() if m.category == category]
@classmethod
def is_enabled(cls, module_id: str, settings, user) -> bool:
"""Check if a module is enabled for a user"""
module = cls.get(module_id)
if not module:
return False
# Check system-wide setting
if module.settings_flag:
if not getattr(settings, module.settings_flag, True):
return False
# Check user-specific setting
if module.user_flag:
if not getattr(user, module.user_flag, True):
return False
# Check dependencies
for dep_id in module.dependencies:
if not cls.is_enabled(dep_id, settings, user):
return False
return True
```
### Phase 2: Add Missing UI Flags
Add missing `ui_allow_*` flags to Settings model and `ui_show_*` flags to User model for all modules.
**Settings Model Additions:**
```python
# CRM section (missing)
ui_allow_contacts = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_deals = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_leads = db.Column(db.Boolean, default=True, nullable=False)
# Admin section (missing)
ui_allow_workflows = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_time_approvals = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_activity_feed = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_recurring_tasks = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_team_chat = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_client_portal = db.Column(db.Boolean, default=True, nullable=False)
ui_allow_kiosk = db.Column(db.Boolean, default=True, nullable=False)
```
**User Model Additions:**
```python
# CRM section (missing)
ui_show_contacts = db.Column(db.Boolean, default=True, nullable=False)
ui_show_deals = db.Column(db.Boolean, default=True, nullable=False)
ui_show_leads = db.Column(db.Boolean, default=True, nullable=False)
# Admin section (missing)
ui_show_workflows = db.Column(db.Boolean, default=True, nullable=False)
ui_show_time_approvals = db.Column(db.Boolean, default=True, nullable=False)
ui_show_activity_feed = db.Column(db.Boolean, default=True, nullable=False)
ui_show_recurring_tasks = db.Column(db.Boolean, default=True, nullable=False)
ui_show_team_chat = db.Column(db.Boolean, default=True, nullable=False)
ui_show_client_portal = db.Column(db.Boolean, default=True, nullable=False)
ui_show_kiosk = db.Column(db.Boolean, default=True, nullable=False)
```
### Phase 3: Module Checking Utilities
Create utilities for checking module availability in routes and templates.
**File:** `app/utils/module_helpers.py`
```python
from functools import wraps
from flask import abort, redirect, url_for, current_app
from flask_login import current_user
from app.models import Settings
from app.utils.module_registry import ModuleRegistry
def module_enabled(module_id: str):
"""Decorator to require a module to be enabled"""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
settings = Settings.get_settings()
if not ModuleRegistry.is_enabled(module_id, settings, current_user):
if current_user.is_admin:
flash(f"Module '{module_id}' is disabled. Enable it in Settings.", "warning")
return redirect(url_for('admin.settings'))
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
def is_module_enabled(module_id: str) -> bool:
"""Check if a module is enabled for current user"""
if not current_user.is_authenticated:
return False
settings = Settings.get_settings()
return ModuleRegistry.is_enabled(module_id, settings, current_user)
# Template helper
def init_module_helpers(app):
@app.context_processor
def inject_module_helpers():
return {
"is_module_enabled": is_module_enabled,
"get_modules_by_category": lambda cat: ModuleRegistry.get_by_category(cat),
}
```
### Phase 4: Route Protection
Add route decorators to protect routes based on module flags.
**Example:**
```python
@calendar_bp.route("/calendar")
@login_required
@module_enabled("calendar")
def view_calendar():
# Route implementation
pass
```
### Phase 5: Navigation Refactoring
Refactor navigation menu to use module registry instead of hardcoded checks.
**Benefits:**
- Centralized menu structure
- Automatic menu item visibility
- Easier to add/remove items
- Consistent behavior
**File:** `app/utils/navigation.py`
```python
from app.utils.module_registry import ModuleRegistry, ModuleCategory
from app.models import Settings
from flask_login import current_user
def build_navigation_menu(settings, user):
"""Build navigation menu structure from module registry"""
menu = {
"dashboard": {"enabled": True, "items": []},
"calendar": {"enabled": False, "items": []},
"time_tracking": {"enabled": True, "items": []},
"crm": {"enabled": False, "items": []},
"finance": {"enabled": False, "items": []},
"inventory": {"enabled": False, "items": []},
"analytics": {"enabled": False, "items": []},
"tools": {"enabled": False, "items": []},
"admin": {"enabled": False, "items": []},
}
# Populate menu from module registry
for module in ModuleRegistry.get_all().values():
if ModuleRegistry.is_enabled(module.id, settings, user):
category_key = module.category.value
if category_key in menu:
menu[category_key]["enabled"] = True
menu[category_key]["items"].append({
"id": module.id,
"name": module.name,
"url": url_for(f"{module.blueprint_name}.index") if hasattr(module, "index_route") else None,
})
return menu
```
### Phase 6: Admin UI for Module Management
Create admin interface to manage module visibility.
**Route:** `app/routes/admin.py`
```python
@admin_bp.route("/admin/modules", methods=["GET", "POST"])
@login_required
@admin_required
def manage_modules():
"""Manage module visibility settings"""
settings = Settings.get_settings()
if request.method == "POST":
# Update module flags
for module_id in ModuleRegistry.get_all().keys():
flag_name = f"ui_allow_{module_id}"
if hasattr(settings, flag_name):
setattr(settings, flag_name, request.form.get(flag_name) == "on")
db.session.commit()
flash("Module settings updated successfully", "success")
return redirect(url_for("admin.manage_modules"))
# Group modules by category
modules_by_category = {}
for category in ModuleCategory:
modules_by_category[category] = ModuleRegistry.get_by_category(category)
return render_template("admin/modules.html",
modules_by_category=modules_by_category,
settings=settings)
```
**Template:** `app/templates/admin/modules.html`
- Checkboxes for each module
- Category grouping
- Dependency warnings
- Save button
### Phase 7: Database Migration
Create Alembic migration to add missing columns.
**File:** `migrations/versions/XXXX_add_module_visibility_flags.py`
```python
def upgrade():
# Add Settings columns
op.add_column('settings', sa.Column('ui_allow_contacts', sa.Boolean(), nullable=False, server_default='true'))
op.add_column('settings', sa.Column('ui_allow_deals', sa.Boolean(), nullable=False, server_default='true'))
# ... etc
# Add User columns
op.add_column('users', sa.Column('ui_show_contacts', sa.Boolean(), nullable=False, server_default='true'))
op.add_column('users', sa.Column('ui_show_deals', sa.Boolean(), nullable=False, server_default='true'))
# ... etc
```
---
## Implementation Phases
### Phase 1: Foundation (Week 1)
- [ ] Create module registry system
- [ ] Define all module definitions
- [ ] Create module checking utilities
- [ ] Add route decorators
### Phase 2: Database & Models (Week 1-2)
- [ ] Create Alembic migration for missing flags
- [ ] Update Settings model
- [ ] Update User model
- [ ] Test migration
### Phase 3: Route Protection (Week 2)
- [ ] Add `@module_enabled` decorator to all optional routes
- [ ] Test route protection
- [ ] Handle edge cases
### Phase 4: Navigation Refactoring (Week 2-3)
- [ ] Create navigation builder utility
- [ ] Refactor base.html to use module registry
- [ ] Test navigation visibility
### Phase 5: Admin UI (Week 3)
- [ ] Create admin module management page
- [ ] Add dependency validation
- [ ] Test admin interface
### Phase 6: Testing & Documentation (Week 3-4)
- [ ] Write unit tests
- [ ] Write integration tests
- [ ] Update documentation
- [ ] Create migration guide
---
## Module Dependencies
### Critical Dependencies
- **Invoices** → **Projects** (required)
- **Payments** → **Invoices** (required)
- **Expenses** → **Projects** (optional, but recommended)
- **Tasks** → **Projects** (optional, but recommended)
- **Time Entries** → **Projects** (required)
### Feature Dependencies
- **Invoice Approvals** → **Invoices**
- **Recurring Invoices** → **Invoices**
- **Payment Gateways** → **Payments**
- **Budget Alerts** → **Projects**
- **Kanban Board** → **Tasks**
- **Gantt Chart** → **Tasks**
- **Deals** → **Clients**
- **Leads** → **Clients**
- **Contacts** → **Clients**
---
## Benefits
1. **Centralized Management**
- Single source of truth for module metadata
- Easy to add/remove modules
- Clear dependency tracking
2. **Better User Experience**
- Admins can customize application
- Users see only relevant features
- Cleaner navigation
3. **Maintainability**
- Less code duplication
- Easier to test
- Clearer architecture
4. **Flexibility**
- Easy to add new modules
- Easy to change module behavior
- Support for module plugins (future)
---
## Risks & Mitigation
### Risk 1: Breaking Existing Functionality
**Mitigation:**
- Comprehensive testing
- Gradual rollout
- Feature flags for new system
### Risk 2: Performance Impact
**Mitigation:**
- Cache module registry
- Optimize database queries
- Lazy loading where possible
### Risk 3: Migration Complexity
**Mitigation:**
- Thorough migration testing
- Rollback plan
- Data validation
---
## Success Criteria
1. ✅ All modules have visibility flags
2. ✅ Admin can disable any module from settings
3. ✅ Routes are protected by module flags
4. ✅ Navigation automatically reflects module state
5. ✅ Module dependencies are enforced
6. ✅ All tests pass
7. ✅ Documentation is updated
---
## Future Enhancements
1. **Module Plugins**
- Support for third-party modules
- Module marketplace
2. **Module Permissions**
- Fine-grained permissions per module
- Role-based module access
3. **Module Analytics**
- Track module usage
- Identify unused modules
4. **Module Templates**
- Pre-configured module sets
- Industry-specific configurations
---
## References
- Current Settings Model: `app/models/settings.py`
- Current User Model: `app/models/user.py`
- Navigation Template: `app/templates/base.html`
- Blueprint Registration: `app/__init__.py`
---
**Next Steps:**
1. Review and approve this plan
2. Create module registry implementation
3. Begin Phase 1 implementation