Approvals¶
Purpose¶
The approvals app provides a generic, extensible approval workflow system.
It enables:
- requesting approvals for arbitrary objects (via generic relations)
- assigning approvers (direct + delegated)
- managing approval decisions (approve / reject)
- forwarding approvals between users
- tracking delegation of approval responsibility
It acts as the central decision engine for business workflows such as:
- timesheet submissions
- (future) expense approvals
- (future) PTO requests
- (future) inventory or operational approvals
Key concepts¶
Approval¶
A single approval request tied to a target object.
- generic relation (
content_type,object_id) - has a lifecycle (
pending → approved/rejected) - stores decision metadata and payload
ApprovalAssignee¶
Represents who can act on an approval.
- direct assignment (e.g. manager)
- forwarded assignment
- computed via services
ApprovalDelegation¶
Allows one user to delegate approval responsibility to another.
- time-bound (
starts_at,ends_at) - kind-aware (global or per approval type)
- used in:
- inbox visibility
- permission checks
- decision authority
ApprovalKind¶
Defines what type of approval flow is being executed.
Examples:
timesheet_submit
Used to:
- drive assignee computation
- scope delegations
- apply side effects
Inbox¶
A filtered view of approvals visible to a user.
Includes:
- direct assignments
- delegated approvals
- forwarded approvals
Decision workflow¶
The process of:
- validating permissions
- applying approval decision
- triggering side effects
- notifying relevant users
Entry points¶
API endpoints¶
Defined in views.py:
GET /approvals/GET /approvals/inbox/GET /approvals/{id}/POST /approvals/{id}/decide/POST /approvals/{id}/forward/POST /approvals/{id}/unforward/
Delegations:
GET /approval-delegations/GET /approval-delegations/me/POST /approval-delegations/POST /approval-delegations/{id}/disable/DELETE /approval-delegations/{id}/
Admin¶
- Django admin for:
ApprovalApprovalDelegationApprovalAssignee
Tasks¶
Currently:
- no dedicated Celery tasks
Future potential:
- approval reminders
- escalation workflows
- SLA enforcement
Signals¶
Currently:
- no Django signals used
Side effects are handled explicitly in:
handlers.py
Dependencies¶
Depends on¶
orgs- org scoping
- membership and roles
teams- manager resolution (
effective_manager) timesheets- approval targets
- side effects
notifications- user notifications
core- audit logging
- Django:
ContentType(generic relations)
Used by¶
timesheets- triggers approval creation
- consumes approval decisions
Future:
- any app needing approval workflows
Operational notes¶
Known pitfalls¶
- Generic relations
- no DB-level FK enforcement → validate carefully
- Duplicate approvals
- guarded by unique constraint, but still needs care in services
- Delegation complexity
- time + kind + assignment interactions can be subtle
- Forwarding vs assignment
- forwarding overrides visibility rules
- Payload growth
- audit and forwarding history stored in JSON field
Performance considerations¶
- Inbox queries use:
Existssubqueries- annotations
- Prefetching is critical:
assignees- related users
- Serializer context avoids N+1 queries:
- timesheet meta map
- delegation info map
- Bulk operations used for:
- assignee refresh
Design characteristics¶
The approvals system is:
- generic → works for any model
- org-scoped → multi-tenant safe
- delegation-aware → supports real-world org structures
- extensible → new approval kinds easily added
- service-driven → business logic centralized outside views
Summary¶
The approvals app provides a flexible and extensible approval workflow engine.
It supports:
- assignment-based approvals
- delegation-aware decision making
- forwarding workflows
- side-effect handling
- notification integration
This makes it a core building block for controlled, auditable decision flows across the system.