Service Layer high complexity mobilebackend
4
Dependencies
4
Dependents
3
Entities
0
Integrations

Description

Core service implementing the claim finite state machine (draft → submitted → approved | rejected → exported). Evaluates threshold rules on submission to determine the approval path, persists state transitions with timestamps, and triggers downstream notifications. Acts as the single authoritative orchestrator for all status changes.

Feature: Threshold-Based Expense Approval Workflow

approval-workflow-service

Summaries

The Approval Workflow Service is the engine that governs how every expense claim moves through the organisation's review process — from initial submission through automatic or manual approval to final export. By automating approval decisions for claims that fall below configured thresholds, it eliminates unnecessary manual review work for coordinators, freeing them to focus on higher-value tasks. The service also enforces consistent policy application across all claims, reducing the risk of errors or preferential treatment. Bulk approval capability allows coordinators to clear large backlogs efficiently, directly reducing administrative bottlenecks and improving the speed at which peer mentors receive reimbursement.

This is the highest-complexity component in the batch and sits at the critical path for the entire approval feature. It has four dependencies — threshold-evaluation-service, claim-events-repository, expense-claim-status-repository, and approval-notification-service — all of which must be delivered before integration testing can begin. The finite state machine logic must be thoroughly tested for all valid and invalid transition combinations. Bulk approval adds another dimension of test coverage: partial failure scenarios, rollback behaviour, and result aggregation.

Deployment must account for the backend Edge Function execution context in addition to mobile. Any delay in dependent services directly impacts delivery of this component.

This service implements a claim finite state machine with transitions: draft → submitted → approved | rejected → exported. On submitClaim(), it calls threshold-evaluation-service.evaluateClaim() to determine whether to invoke autoApprove() or leave the claim in submitted state for coordinator review. coordinatorApprove() and coordinatorReject() persist decisions via claim-events-repository and expense-claim-status-repository, recording actor identity, timestamp, and optional comment. bulkApprove() delegates to individual transitions with per-record error isolation and aggregates results.

State change events trigger approval-notification-service for downstream notifications. getValidTransitions() and validateTransition() enforce FSM integrity before any state mutation. Runs on both mobile and backend (Supabase Edge Function) contexts, requiring stateless, side-effect-isolated design.

Responsibilities

  • Evaluate combined expense line totals against configured thresholds on submission
  • Transition claim to approved (auto) or submitted (pending review) based on threshold result
  • Persist coordinator approve/reject decisions with actor identity and timestamp
  • Emit state change events for notification and audit pipelines
  • Orchestrate bulk approval by iterating individual transitions with per-record error handling

Interfaces

submitClaim(claimId, userId)
autoApprove(claimId)
coordinatorApprove(claimId, coordinatorId, comment)
coordinatorReject(claimId, coordinatorId, comment)
bulkApprove(claimIds, coordinatorId)
getClaimStatus(claimId)
getValidTransitions(currentStatus)
validateTransition(fromStatus, toStatus)

Related Data Entities (3)

Data entities managed by this component

API Contract

View full contract →
REST /api/v1/claims 9 endpoints
GET /api/v1/claims List claims across the workflow
GET /api/v1/claims/:claim_id Get full claim with current workflow status
POST /api/v1/claims Create and optionally submit a new claim
PUT /api/v1/claims/:claim_id Update a draft claim before submission
DELETE /api/v1/claims/:claim_id Delete a draft claim
POST /api/v1/claims/:claim_id/submit Submit a claim into the approval workflow (submitClaim)
+3 more