Skip to content

Async Project Tasks

AsyncTaskNamespace for the project.task model, accessed as client.tasks on AsyncOdooClient.

project_tasks

Async project task operations for Vodoo.

AsyncTaskNamespace

AsyncTaskNamespace(client: AsyncOdooClient)

Bases: GeneratedAsyncTaskNamespace

Async project task namespace.

Source code in src/vodoo/aio/_domain.py
def __init__(self, client: AsyncOdooClient) -> None:
    self._client = client

context async

context(task_id: int, fields: list[str] | None = None, *, page_size: int = 100, max_pages: int | None = None) -> dict[str, Any]

Read task context; same contract and completeness checks as sync context.

Source code in src/vodoo/aio/project_tasks.py
async def context(
    self,
    task_id: int,
    fields: list[str] | None = None,
    *,
    page_size: int = 100,
    max_pages: int | None = None,
) -> dict[str, Any]:
    """Read task context; same contract and completeness checks as sync context."""
    return await async_get_task_context(
        self._client, task_id, fields, page_size=page_size, max_pages=max_pages
    )

create async

create(name: str, project_id: int, description: str | None = None, user_ids: list[int] | None = None, tag_ids: list[int] | None = None, parent_id: int | None = None, *, stage_id: int | None = None, depend_on_ids: list[int] | None = None, **kwargs: Any) -> int

Create a task atomically; relation IDs must be positive integers.

Descriptions use Markdown by default; wrap in HTML to bypass conversion.

Source code in src/vodoo/aio/project_tasks.py
async def create(
    self,
    name: str,
    project_id: int,
    description: str | None = None,
    user_ids: list[int] | None = None,
    tag_ids: list[int] | None = None,
    parent_id: int | None = None,
    *,
    stage_id: int | None = None,
    depend_on_ids: list[int] | None = None,
    **kwargs: Any,
) -> int:
    """Create a task atomically; relation IDs must be positive integers.

    Descriptions use Markdown by default; wrap in HTML to bypass conversion.
    """
    values, context = _build_task_values(
        name,
        project_id,
        description,
        user_ids,
        tag_ids,
        parent_id,
        stage_id=stage_id,
        depend_on_ids=depend_on_ids,
        **kwargs,
    )
    return await self._client.create(self._model, values, context=context)

set_milestone async

set_milestone(task_id: int, milestone_id: int) -> bool

Assign a task to a milestone in the same project.

Source code in src/vodoo/aio/project_tasks.py
async def set_milestone(self, task_id: int, milestone_id: int) -> bool:
    """Assign a task to a milestone in the same project."""
    tasks = await self._client.read(self._model, [task_id], fields=["project_id"])
    if not tasks:
        raise RecordNotFoundError(self._model, task_id)

    milestones = await self._client.read(
        "project.milestone", [milestone_id], fields=["project_id"]
    )
    if not milestones:
        raise RecordNotFoundError("project.milestone", milestone_id)

    task_project_id = _project_id(tasks[0])
    milestone_project_id = _project_id(milestones[0])
    if task_project_id is None or milestone_project_id is None:
        raise RecordOperationError("Task and milestone must both belong to a project")
    if task_project_id != milestone_project_id:
        raise RecordOperationError(
            f"Task {task_id} and milestone {milestone_id} belong to different projects"
        )

    return await self._client.write(self._model, [task_id], {"milestone_id": milestone_id})

add_dependencies async

add_dependencies(task_id: int, dependency_ids: list[int]) -> bool

Add tasks that must be completed before this task.

Source code in src/vodoo/aio/project_tasks.py
async def add_dependencies(self, task_id: int, dependency_ids: list[int]) -> bool:
    """Add tasks that must be completed before this task."""
    commands = [Cmd.link(dependency_id) for dependency_id in dependency_ids]
    return await self.set(task_id, {"depend_on_ids": commands})

clear_dependencies async

clear_dependencies(task_id: int) -> bool

Remove all dependencies from a task.

Source code in src/vodoo/aio/project_tasks.py
async def clear_dependencies(self, task_id: int) -> bool:
    """Remove all dependencies from a task."""
    return await self.set(task_id, {"depend_on_ids": [Cmd.clear()]})

schedule async

schedule(task_id: int, start: str, end: str) -> bool

Set Gantt scheduling dates (requires Odoo Project Enterprise).

PARAMETER DESCRIPTION
task_id

Task ID.

TYPE: int

start

Planned start datetime in YYYY-MM-DD HH:MM:SS format.

TYPE: str

end

Deadline in YYYY-MM-DD format.

TYPE: str

RETURNS DESCRIPTION
bool

True if successful.

Source code in src/vodoo/aio/project_tasks.py
async def schedule(self, task_id: int, start: str, end: str) -> bool:
    """Set Gantt scheduling dates (requires Odoo Project Enterprise).

    Args:
        task_id: Task ID.
        start: Planned start datetime in ``YYYY-MM-DD HH:MM:SS`` format.
        end: Deadline in ``YYYY-MM-DD`` format.

    Returns:
        True if successful.
    """
    _validate_schedule_values(start, end)
    return await self.set(
        task_id,
        {"planned_date_begin": start, "date_deadline": end},
    )

create_tag async

create_tag(name: str, color: int | None = None) -> int

Create a new project tag.

Source code in src/vodoo/aio/project_tasks.py
async def create_tag(self, name: str, color: int | None = None) -> int:
    """Create a new project tag."""
    values: dict[str, Any] = {"name": name}
    if color is not None:
        values["color"] = color
    assert self._tag_model is not None
    return await self._client.create(self._tag_model, values)

delete_tag async

delete_tag(tag_id: int) -> bool

Delete a project tag.

Source code in src/vodoo/aio/project_tasks.py
async def delete_tag(self, tag_id: int) -> bool:
    """Delete a project tag."""
    assert self._tag_model is not None
    return await self._client.unlink(self._tag_model, [tag_id])