mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-19 12:50:11 -05:00
b4486a627f
- Webhook models: remove duplicate index definitions so db.create_all() no longer raises 'index already exists' (columns already have index=True) - ImportService: fix circular import by late-importing ClientService, ProjectService, TimeTrackingService in __init__ - reports: fix F823 by renaming unpack variable _ to _entry_count to avoid shadowing gettext _ in export_task_excel() - Code quality: add .flake8 with extend-ignore so flake8 CI passes; simplify pyproject.toml isort config (drop unsupported options) - Format: run black and isort on app/ - tests: restore minimal app fixture in test_import_export_models
62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
"""
|
|
Shared validation for time entry requirements (task, description).
|
|
|
|
Used when creating/updating time entries and when starting timers.
|
|
"""
|
|
|
|
from typing import TYPE_CHECKING, Any, Dict, Optional
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.settings import Settings
|
|
|
|
|
|
def validate_time_entry_requirements(
|
|
settings: "Settings",
|
|
project_id: Optional[int],
|
|
client_id: Optional[int],
|
|
task_id: Optional[int],
|
|
notes: Optional[str],
|
|
) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Validate time entry requirements based on admin settings.
|
|
|
|
Returns error dict with keys: success=False, message, error; or None if valid.
|
|
|
|
Rules:
|
|
- time_entry_require_task: Only when project_id is set; task_id must be non-null.
|
|
- time_entry_require_description: notes must be non-empty and meet min length.
|
|
- Client-only entries (client_id set, no project_id): task requirement does not apply.
|
|
"""
|
|
require_task = getattr(settings, "time_entry_require_task", False)
|
|
require_description = getattr(settings, "time_entry_require_description", False)
|
|
min_length = getattr(settings, "time_entry_description_min_length", 20)
|
|
|
|
if not require_task and not require_description:
|
|
return None
|
|
|
|
# Task requirement: only when project_id is set (not client-only)
|
|
if require_task and project_id and not task_id:
|
|
return {
|
|
"success": False,
|
|
"message": "A task must be selected when logging time for a project",
|
|
"error": "task_required",
|
|
}
|
|
|
|
# Description requirement
|
|
if require_description:
|
|
notes_stripped = (notes or "").strip()
|
|
if not notes_stripped:
|
|
return {
|
|
"success": False,
|
|
"message": "A description is required when logging time",
|
|
"error": "description_required",
|
|
}
|
|
if len(notes_stripped) < min_length:
|
|
return {
|
|
"success": False,
|
|
"message": f"Description must be at least {min_length} characters",
|
|
"error": "description_too_short",
|
|
}
|
|
|
|
return None
|