core PK: id 7 required 2 unique

Description

Records the review and approval lifecycle for a submitted activity registration. Each activity has exactly one approval record tracking whether it has been approved, rejected, or flagged by a coordinator or org admin. Approved activities are the authoritative source of truth for Bufdir grant reporting, reimbursement processing, and organizational KPIs.

19
Attributes
7
Indexes
7
Validation Rules
27
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key uniquely identifying the approval record
PKrequiredunique
activity_id uuid Foreign key to the activity under review; enforces the one-to-one relationship — each activity has exactly one approval record created at submission time
requiredunique
org_id uuid Organization the activity belongs to; denormalized onto this table to enable org-scoped approval queue queries without joining activities
required
local_association_id uuid Local association the submitting peer mentor belongs to; enables coordinator-scoped queue filtering without joining users or user_local_associations
-
status enum Current approval lifecycle state. pending_review is the initial state on activity submission; approved and rejected are terminal states set by a reviewer; flagged marks suspected duplicates or policy violations pending investigation
required
reviewer_id uuid User ID of the coordinator or org admin who made the approval or rejection decision; null while status is pending_review or flagged
-
reviewed_at datetime Timestamp when the approval or rejection decision was recorded; null until the reviewer acts
-
rejection_reason text Mandatory human-readable explanation when status transitions to rejected; surfaced to the submitting peer mentor as feedback. Must be non-empty when status is rejected.
-
approval_comment text Optional internal reviewer comment attached to an approval decision; not shown to the peer mentor but visible in audit log and admin portal
-
corrections json JSONB map of field corrections applied by the reviewer before approving (e.g. {"activity_type": "phone_call", "duration_minutes": 45}). Populated by the correctAndApprove workflow and stored for audit trail purposes.
-
version integer Optimistic concurrency control counter, incremented on every status mutation. The optimistic-lock-adapter checks that the client-supplied version matches the current DB value before writing to prevent concurrent approval conflicts.
required
flagged_by uuid User ID of the coordinator or admin who raised the flag; null when the record has never been flagged
-
flagged_at datetime Timestamp when the activity was flagged; null when not flagged
-
flag_reason text Reason supplied by the flagger explaining why the activity is suspicious (e.g. suspected duplicate, implausible duration, wrong contact); null when not flagged
-
flag_resolved_at datetime Timestamp when the flag investigation was closed; null when the flag is still open
-
flag_resolved_by uuid User ID of the coordinator or org admin who resolved the flag; null when unresolved
-
flag_resolution_action enum Action taken when closing a flag investigation; null when no flag has been resolved
-
created_at datetime Timestamp when the approval record was created, which coincides with the activity submission event
required
updated_at datetime Timestamp of the most recent write to this record; maintained by an updated_at trigger or ORM hook on every mutation
required

Database Indexes

idx_activity_approval_activity_id
btree unique

Columns: activity_id

idx_activity_approval_org_status
btree

Columns: org_id, status

idx_activity_approval_local_assoc_status
btree

Columns: local_association_id, status

idx_activity_approval_reviewer_id
btree

Columns: reviewer_id

idx_activity_approval_reviewed_at
btree

Columns: reviewed_at

idx_activity_approval_flagged_org
btree

Columns: org_id, flagged_at

idx_activity_approval_created_at
btree

Columns: created_at

Validation Rules

valid_status_transition error

Validation failed

rejection_reason_non_empty error

Validation failed

corrections_json_schema error

Validation failed

version_match_on_write error

Validation failed

flag_reason_required_on_flag error

Validation failed

org_id_matches_activity error

Validation failed

reviewed_at_set_on_decision error

Validation failed

Business Rules

one_approval_per_activity
on_create

Each activity has exactly one approval record. The UNIQUE constraint on activity_id at the database level enforces this. The approval record is created atomically with or immediately after activity submission.

rejection_requires_reason
on_update

A reviewer must supply a non-empty rejection_reason when transitioning status to rejected. This ensures submitting peer mentors receive actionable feedback.

reviewer_must_have_coordinator_or_admin_role
on_update

Only users with Coordinator or Organization Admin roles may set status to approved or rejected. The permission-validation-middleware enforces this at the API boundary; activity-approval-service enforces it at the service layer.

coordinator_scoped_to_local_association
always

Coordinators may only approve or reject activities from peer mentors within their own local association(s). The review-queue-service and approval-store apply local_association_id scoping to all queries.

optimistic_locking_required
on_update

Any status update must include the current version value. If the client-supplied version does not match the DB row, the write is rejected with a conflict error to prevent concurrent approvals from overwriting each other.

flagged_activities_excluded_from_bufdir
always

Activities with status=flagged must not be included in Bufdir report aggregations until the flag is resolved. The bufdir-report-service and report-data-aggregator filter by status=approved only.

corrections_audit_trail
on_update

When a reviewer corrects fields before approving (correctAndApprove), the original activity fields must remain unchanged and the corrections JSONB column must capture all modified fields and their new values for audit purposes.

flag_resolution_closes_flag
on_update

Resolving a flag must set flag_resolved_at, flag_resolved_by, and flag_resolution_action atomically. If the resolution action is reject or correct_and_approve, the status field must be updated in the same transaction.

all_decisions_written_to_audit_log
on_update

Every status transition (approve, reject, flag, resolve flag) must produce an immutable audit_log entry within the same database transaction capturing actor_id, action type, entity reference, and timestamp.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage

Components Managing This Entity

service Permission Validation Middleware ["backend"] infrastructure Bulk Transaction Handler ["backend"] service Bulk Processing Service ["mobile"] service Bulk Processing Service ["backend"] service Bufdir Report Service ["backend"] service Bufdir Report Service ["backend","mobile"] service Report Data Aggregator ["backend"] service Dashboard Service ["mobile"] service Dashboard Service ["mobile"] data Analytics Store ["backend"] data Analytics Store ["backend"] service KPI Aggregation Service ["backend"] service KPI Aggregation Service ["backend"] data Activity Feed Query Builder ["backend"] service Activity Feed Service ["backend"] service Activity Feed Service ["backend"] data Approval Store ["backend"] data Approval Store ["backend"] infrastructure Optimistic Lock Adapter ["backend"] service Activity Approval Service ["backend"] service Activity Approval Service ["backend"] service Audit Log Service ["backend"] service Review Queue Service ["backend"] ui Activity Detail Panel ["frontend"] ui Activity Review Page ["frontend"] ui Activity Review Page ["frontend"] ui Approval Status Indicator ["frontend"] data Flag Store ["backend"] service Activity Flagging Service ["backend"] service Activity Flagging Service ["backend"] ui Flag Management Component ["frontend"] ui Flag Management Component ["frontend"] data Expense Approval Store ["backend"] data Expense Approval Store ["backend"] service Audit Log Service ["backend"] service Reimbursement Service ["backend"] service Reimbursement Service ["backend"] service Audit Log Service ["backend"] service Audit Log Service ["backend"]