Todos & Tasks
Todos & Tasks
The Todo & Task system lets you create, assign, and track tasks against tenancies and tenancy terms. Tasks can be scoped to a specific role (agent, tenant, or landlord), categorised by type, prioritised, and tracked through completion — with a portfolio-wide view for outstanding work.
Concepts
Task Types
Every todo has a taskType that categorises it:
| Value | Description |
|---|---|
cost_breakdown_sign | Tenant or landlord needs to sign a cost breakdown |
holding_deposit_pay | Tenant needs to pay the holding deposit |
tenancy_agreement_sign | Tenancy agreement needs to be signed |
compliance_doc | A compliance document needs to be uploaded |
custom | A freeform task not covered by the above types |
The default task type is custom.
Role Assignment (assignedTo)
Each todo is assigned to a role:
agent— an internal team member (default)tenant— the tenant partylandlord— the landlord party
Optionally, a specific user ID (assignedUserId) can be set to target an individual agent.
Status & Completion
Todos have a status field (pending | complete) and a boolean isComplete flag. When a todo is marked complete, the platform records:
completedAt— the timestampcompletedByUserId— the user who performed the action
Completion can be reversed using the reopenTodo procedure.
Priority
Four priority levels are supported: low, normal (default), high, urgent.
Scoping
A todo must be scoped to at least one of:
tenancyId— links the task to a tenancytenancyTermId— links the task to a specific tenancy term
Both can be provided simultaneously. The platform validates that the referenced tenancy or term belongs to your organisation before creating the todo.
tRPC Procedures
All procedures are accessed via the todo router and require an authenticated org session.
todo.createTodo
Create a new todo.
Input:
{
tenancyId?: string; // Required if tenancyTermId not provided
tenancyTermId?: string; // Required if tenancyId not provided
title: string; // 1–500 characters
description?: string; // Up to 2,000 characters
taskType?: TaskType; // Default: "custom"
assignedTo?: Role; // Default: "agent"
assignedUserId?: string; // Specific agent user ID (optional)
priority?: Priority; // Default: "normal"
dueDate?: string; // ISO 8601 datetime string
propertyAddress?: string; // Up to 500 characters
tenantName?: string; // Up to 200 characters
}
Returns: The created todo record.
Audit event: todo.created
todo.markTodoComplete
Mark a todo as complete. Throws if the todo is already complete.
Input:
{ todoId: string }
Returns: The updated todo record.
Audit event: todo.completed
todo.reopenTodo
Undo completion of a todo. Resets isComplete, completedAt, and completedByUserId. Throws if the todo is not complete.
Input:
{ todoId: string }
Returns: The updated todo record.
Audit event: todo.reopened
todo.getById
Fetch a single todo by ID.
Input:
{ todoId: string }
Returns: The todo record, or a NOT_FOUND error.
todo.listByTenancy
List todos scoped to a tenancy or tenancy term. Results are ordered: incomplete items first (ascending due date), then complete items.
Input:
{
tenancyId?: string;
tenancyTermId?: string;
includeComplete?: boolean; // Default: false
}
Returns: Array of todo records.
todo.listOutstandingAcrossPortfolio
Paginated list of all incomplete todos across the entire portfolio, sorted by due date (most urgent first). Supports filtering by role, task type, and assigned user.
Input:
{
// Pagination
page?: number;
limit?: number;
// Filters
assignedTo?: Role; // "agent" | "tenant" | "landlord"
taskType?: TaskType;
assignedUserId?: string;
}
Returns: Paginated result with todo records.
Note:
propertyAddressandtenantNameare denormalised onto each todo record to support efficient display in this portfolio-wide view without joins.
todo.applyDefaultTemplates
Reads the company's default todo templates from companySettings.defaultTodoTemplates (JSONB) and bulk-creates todos for a given tenancy. Use this when creating a new tenancy term to bootstrap the standard task list.
Input:
{
tenancyId: string;
tenancyTermId?: string;
propertyAddress?: string;
tenantName?: string;
}
Returns: Array of created todo records.
todo.updateTodo
Update todo details. Only the fields you provide will be changed.
Updatable fields: title, description, priority, assignedTo, assignedUserId, dueDate, taskType
Input:
{
todoId: string;
title?: string;
description?: string;
priority?: Priority;
assignedTo?: Role;
assignedUserId?: string;
dueDate?: string;
taskType?: TaskType;
}
Returns: The updated todo record.
todo.deleteTodo
Permanently delete a todo. Only incomplete todos can be deleted.
Input:
{ todoId: string }
Returns: Confirmation of deletion.
Default Todo Templates
You can define a standard set of tasks to be created automatically when a new tenancy term is set up. Templates are stored in companySettings.defaultTodoTemplates as a JSONB array. Call todo.applyDefaultTemplates with the new tenancy's IDs to instantiate the template list.
This is useful for enforcing a consistent pre-tenancy pipeline (e.g. always creating tasks for cost breakdown sign-off, holding deposit payment, and compliance document upload).
Audit Logging
All state-changing operations are recorded in the audit trail:
| Action | Trigger |
|---|---|
todo.created | createTodo |
todo.completed | markTodoComplete |
todo.reopened | reopenTodo |
Each audit event captures the acting user, the todo ID, task type, and associated tenancy identifiers.
Type Reference
type TaskType =
| "cost_breakdown_sign"
| "holding_deposit_pay"
| "tenancy_agreement_sign"
| "compliance_doc"
| "custom";
type Role = "agent" | "tenant" | "landlord";
type Priority = "low" | "normal" | "high" | "urgent";
type Status = "pending" | "complete";