Expense Type Selection with Mutual Exclusion
Feature Detail
Description
A structured expense type picker that presents fixed categories — kilometers driven, tolls, parking, and public transit — as discrete choices rather than free-text fields. The system enforces mutual exclusion rules so that logically incompatible combinations (e.g., mileage reimbursement and a bus ticket for the same trip leg) cannot be selected simultaneously, preventing erroneous claims before submission. The fixed-choice model reduces cognitive load for peer mentors, eliminates manual review overhead for coordinators, and produces clean structured data suitable for downstream accounting integration. Each choice maps to a known reimbursement formula, enabling automatic calculation of the expected payout without manual interpretation.
Analysis
Eliminates the most common class of reimbursement errors (incompatible expense combinations) at the point of entry rather than during auditing, reducing coordinator review time and rejected claims. Structured data also unblocks reliable API export to accounting systems.
Model expense types as an enum with a compatibility matrix. Use a stateful multi-select widget that disables incompatible options reactively when a selection is made. BLoC or Riverpod state for the selection set; validation rule checked on each toggle. Map each type to its calculation logic (per-km rate, flat receipt amount, etc.).
Components (206)
Shared Components
These components are reused across multiple features
User Interface (59)
Service Layer (52)
Data Layer (33)
Infrastructure (54)
User Stories (10)
As a As a Peer Mentor (Likeperson)
I want my expense type selections and any mutual exclusion conflicts I encounter to be tracked anonymously
So that the organisation can identify which expense types are most used, which combinations are attempted incorrectly, and whether the exclusion rules are configured appropriately
- Given a peer mentor selects an expense type, when the selection is confirmed, then an analytics event is recorded with the expense type ID, organisation ID, and a session token (no user ID)
- Given a mutual exclusion conflict is triggered, when the conflicting type is disabled, then an analytics event records the pair of conflicting type IDs and the triggering type
- Given a peer mentor abandons the expense flow after a mutual exclusion conflict, when the session ends, then an abandonment event is recorded linked to the conflict event
- +2 more
As a As a Coordinator
I want my expense type selections and any mutual exclusion conflicts I encounter to be tracked anonymously
So that the organisation can identify which expense types are most used, which combinations are attempted incorrectly, and whether the exclusion rules are configured appropriately
- Given a peer mentor selects an expense type, when the selection is confirmed, then an analytics event is recorded with the expense type ID, organisation ID, and a session token (no user ID)
- Given a mutual exclusion conflict is triggered, when the conflicting type is disabled, then an analytics event records the pair of conflicting type IDs and the triggering type
- Given a peer mentor abandons the expense flow after a mutual exclusion conflict, when the session ends, then an abandonment event is recorded linked to the conflict event
- +2 more
As a As a Peer Mentor (Likeperson)
I want to see a live calculation of my estimated reimbursement amount as I select expense types and enter details
So that I can verify the claim is correct before submitting and understand exactly how the reimbursement is calculated
- Given the peer mentor selects 'mileage' and enters a distance, when the distance field updates, then the preview panel recalculates and displays the reimbursement amount within 300 ms without a full page reload
- Given the calculated amount is below the auto-approval threshold, when the preview renders, then a green indicator and label 'Auto-approved' are shown
- Given the calculated amount exceeds the auto-approval threshold, when the preview renders, then an amber indicator and label 'Requires coordinator approval' are shown
- +3 more
As a As a Peer Mentor (Likeperson)
I want the expense type picker to be fully operable with a screen reader, keyboard navigation, and large touch targets
So that I can register expenses accurately regardless of whether I have visual, motor, or cognitive accessibility needs
- Given VoiceOver or TalkBack is active, when the expense type picker renders, then each card's accessibility label reads '[Type Name], [selected/not selected], [unavailable: reason if applicable]'
- Given the peer mentor navigates with VoiceOver swipe gestures, when focus moves between expense type cards, then focus order follows visual top-to-bottom, left-to-right order
- Given a mutual exclusion is triggered, when the state changes, then a live region announcement notifies the user without moving focus away from the current element
- +3 more
As a As a Coordinator
I want to see a live calculation of my estimated reimbursement amount as I select expense types and enter details
So that I can verify the claim is correct before submitting and understand exactly how the reimbursement is calculated
- Given the peer mentor selects 'mileage' and enters a distance, when the distance field updates, then the preview panel recalculates and displays the reimbursement amount within 300 ms without a full page reload
- Given the calculated amount is below the auto-approval threshold, when the preview renders, then a green indicator and label 'Auto-approved' are shown
- Given the calculated amount exceeds the auto-approval threshold, when the preview renders, then an amber indicator and label 'Requires coordinator approval' are shown
- +3 more
As a As a Coordinator
I want the expense type picker to be fully operable with a screen reader, keyboard navigation, and large touch targets
So that I can register expenses accurately regardless of whether I have visual, motor, or cognitive accessibility needs
- Given VoiceOver or TalkBack is active, when the expense type picker renders, then each card's accessibility label reads '[Type Name], [selected/not selected], [unavailable: reason if applicable]'
- Given the peer mentor navigates with VoiceOver swipe gestures, when focus moves between expense type cards, then focus order follows visual top-to-bottom, left-to-right order
- Given a mutual exclusion is triggered, when the state changes, then a live region announcement notifies the user without moving focus away from the current element
- +3 more
As a As a Peer Mentor (Likeperson)
I want to select my expense type from a fixed list of options rather than entering free text
So that I can quickly register the correct expense category without making errors or using inconsistent terminology
- Given the peer mentor opens the expense registration flow, when the expense type picker renders, then only expense types enabled in the organisation's configuration are displayed
- Given the expense type picker is visible, when the peer mentor taps an expense type card, then that card is visually highlighted and all other cards are deselected
- Given an expense type is selected, when the form continues, then the subsequent fields shown are specific to that expense type (e.g., distance fields for mileage, amount field for parking)
- +2 more
As a As a Peer Mentor (Likeperson)
I want the app to prevent me from selecting expense types that cannot be claimed together (such as mileage and public transport for the same journey)
So that I cannot accidentally submit an invalid combination that would be rejected during attestation or cause accounting errors
- Given the peer mentor has selected 'mileage' as an expense type, when the expense type picker is still visible, then 'public transport' is visually disabled and labelled with a reason such as 'Cannot be combined with mileage'
- Given a conflicting type is disabled, when the peer mentor taps it, then a tooltip or inline message explains why it cannot be selected without dismissing the picker
- Given the peer mentor deselects 'mileage', when the picker updates, then 'public transport' becomes enabled again
- +3 more
As a As a Coordinator
I want to select my expense type from a fixed list of options rather than entering free text
So that I can quickly register the correct expense category without making errors or using inconsistent terminology
- Given the peer mentor opens the expense registration flow, when the expense type picker renders, then only expense types enabled in the organisation's configuration are displayed
- Given the expense type picker is visible, when the peer mentor taps an expense type card, then that card is visually highlighted and all other cards are deselected
- Given an expense type is selected, when the form continues, then the subsequent fields shown are specific to that expense type (e.g., distance fields for mileage, amount field for parking)
- +2 more
As a As a Coordinator
I want the app to prevent me from selecting expense types that cannot be claimed together (such as mileage and public transport for the same journey)
So that I cannot accidentally submit an invalid combination that would be rejected during attestation or cause accounting errors
- Given the peer mentor has selected 'mileage' as an expense type, when the expense type picker is still visible, then 'public transport' is visually disabled and labelled with a reason such as 'Cannot be combined with mileage'
- Given a conflicting type is disabled, when the peer mentor taps it, then a tooltip or inline message explains why it cannot be selected without dismissing the picker
- Given the peer mentor deselects 'mileage', when the picker updates, then 'public transport' becomes enabled again
- +3 more