Data Layer low complexity mobile
1
Dependencies
0
Dependents
1
Entities
0
Integrations

Description

Manages persistence of expense type selections as part of an expense record in the travel and expense registration flow. Reads and writes the selected expense type set to the local draft store and to Supabase when the expense is submitted. Validates that the stored combination passes mutual exclusion rules before persisting.

Feature: Expense Type Selection with Mutual Exclusion

expense-type-repository

Summaries

The Expense Type Repository ensures that employee expense selections are never lost during the submission process, protecting against data loss from app backgrounding, network interruptions, or accidental navigation. Draft persistence means employees can start an expense claim, switch tasks, and return without re-entering data — a significant usability improvement that reduces submission abandonment rates. Reliable synchronisation to Supabase on submission provides the finance system with an accurate, validated record of expense types, supporting audit trails and policy compliance reporting. This reliability directly supports employee trust in the tool and reduces support ticket volume.

Low complexity component, but it carries integration dependencies on both local draft storage and the Supabase backend, making it one of the components most exposed to environment-related delays. Confirm Supabase schema and RLS policies for expense type fields before development begins to avoid late-stage blockers. Local draft storage implementation must be agreed upon (Hive, SharedPreferences, or SQLite) early, as this decision affects other draft-related components. Testing must cover offline draft save and restore, online submission, and the edit-flow read-back scenario.

Integration tests against a Supabase staging environment are required. Plan for additional time if Supabase schema changes are needed.

Implements the repository pattern over two storage backends: a local draft store (implementation-agnostic, injected via interface) and Supabase for submitted records. saveDraft serialises the Set to a JSON-encodable list keyed by expenseId. submitExpenseTypes runs mutual exclusion validation via the rule engine before writing to Supabase — reject with a typed error if validation fails. loadDraft and getExpenseTypes both return empty sets (not null) when no record exists to simplify caller logic.

Use async/await throughout with typed exceptions for network and storage failures. The repository must not hold mutable state — each call operates on the provided expenseId. Supabase writes should use upsert semantics to handle re-submissions of draft records cleanly.

Responsibilities

  • Persist selected expense types to local draft storage
  • Sync confirmed expense type selections to Supabase
  • Read back saved expense type selections for edit flows
  • Validate persisted combinations against exclusion rules before save

Interfaces

saveDraft(String expenseId, Set<ExpenseType> types) → Future<void>
loadDraft(String expenseId) → Future<Set<ExpenseType>>
submitExpenseTypes(String expenseId, Set<ExpenseType> types) → Future<void>
getExpenseTypes(String expenseId) → Future<Set<ExpenseType>>

Relationships

Dependencies (1)

Components this component depends on

Related Data Entities (1)

Data entities managed by this component

API Contract

View full contract →
REST /api/v1/expense-type-drafts 5 endpoints
GET /api/v1/expense-type-drafts List all expense type draft records
GET /api/v1/expense-type-drafts/:id Load the draft expense types for a specific expense
POST /api/v1/expense-type-drafts Save a new expense type draft
PUT /api/v1/expense-type-drafts/:id Update draft or submit expense types for an expense
DELETE /api/v1/expense-type-drafts/:id Delete a draft expense type record