Files
leocrm/app/plugins/builtins/tasks/contracts.py
T

120 lines
3.2 KiB
Python
Raw Normal View History

"""Public contract for the tasks plugin.
Exposes only the symbols that other builtins plugins need.
Importers should use::
from app.plugins.builtins.contracts import get_contract
tasks = get_contract("tasks")
if tasks:
await tasks.create_task(db, tenant_id, user_id, data)
instead of importing from internal modules directly.
"""
from __future__ import annotations
from typing import Any
from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.plugins.builtins.contracts import get_contract_registry
from app.plugins.builtins.tasks.models import Task
from app.plugins.builtins.tasks.services import (
assign_task,
create_task,
delete_task,
get_due_tasks,
get_task,
list_tasks,
update_task,
update_task_status,
)
class TasksContract:
"""Public API surface for the tasks plugin."""
contract_name = "tasks"
# ─── services ───
list_tasks = staticmethod(list_tasks)
get_task = staticmethod(get_task)
create_task = staticmethod(create_task)
update_task = staticmethod(update_task)
delete_task = staticmethod(delete_task)
assign_task = staticmethod(assign_task)
update_task_status = staticmethod(update_task_status)
get_due_tasks = staticmethod(get_due_tasks)
# ─── Workspace Scopes contribution (Phase N4) ───
@staticmethod
def workspace_scopes() -> list[dict]:
"""Scope-Dimensionen des tasks-Moduls: „nur meine" (Roadmap N4)."""
return [
{
"module_key": "tasks",
"dimensions": [
{
"key": "only_mine",
"label": "Nur meine Aufgaben",
"control": "toggle",
"options": [],
"value_source": None,
"default": False,
},
],
}
]
# ─── models (read-only for queries) ───
Task = Task
@staticmethod
async def dsar_collect(
db: AsyncSession, tenant_id: Any, user_id: Any
) -> dict[str, Any]:
"""GDPR Art. 15: collect tasks owned by or assigned to the user."""
tasks = (
await db.execute(
select(Task).where(
or_(Task.owner_id == user_id, Task.assigned_to == user_id),
Task.tenant_id == tenant_id,
Task.deleted_at.is_(None),
).limit(1000)
)
).scalars().all()
return {
"tasks": [
{
"id": str(t.id),
"title": t.title,
"status": t.status,
"priority": t.priority,
"due_date": t.due_date.isoformat() if t.due_date else None,
}
for t in tasks
]
}
# ─── self-registration ───
_contract = TasksContract()
get_contract_registry().register("tasks", _contract)
__all__ = [
"TasksContract",
"Task",
"list_tasks",
"get_task",
"create_task",
"update_task",
"delete_task",
"assign_task",
"update_task_status",
"get_due_tasks",
]