|
| 1 | +# Expense System UI Specification |
| 2 | + |
| 3 | +## Overview |
| 4 | +The Expense System UI is a FastAPI-based web application that provides both a web interface and REST API for managing expense requests. It integrates with Temporal workflows through callback mechanisms. |
| 5 | + |
| 6 | +## System Components |
| 7 | + |
| 8 | +### Data Model |
| 9 | +- **ExpenseState Enum**: Defines expense lifecycle states |
| 10 | + - `CREATED`: Initial state when expense is first created |
| 11 | + - `APPROVED`: Expense has been approved for payment |
| 12 | + - `REJECTED`: Expense has been denied |
| 13 | + - `COMPLETED`: Payment has been processed |
| 14 | + |
| 15 | +### Storage |
| 16 | +- **all_expenses**: In-memory dictionary mapping expense IDs to their current state |
| 17 | +- **token_map**: Maps expense IDs to Temporal activity task tokens for workflow callbacks |
| 18 | + |
| 19 | +## API Endpoints |
| 20 | + |
| 21 | +### 1. Home/List View (`GET /` or `GET /list`) |
| 22 | +**Purpose**: Display all expenses in an HTML table format |
| 23 | + |
| 24 | +**Response**: HTML page containing: |
| 25 | +- Page title "SAMPLE EXPENSE SYSTEM" |
| 26 | +- Navigation link to HOME |
| 27 | +- Table with columns: Expense ID, Status, Action |
| 28 | +- Action buttons for CREATED expenses (APPROVE/REJECT) |
| 29 | +- Sorted expense display by ID |
| 30 | + |
| 31 | +**Business Rules**: |
| 32 | +- Only CREATED expenses show action buttons |
| 33 | +- Expenses are displayed in sorted order by ID |
| 34 | + |
| 35 | +### 2. Action Handler (`GET /action`) |
| 36 | +**Purpose**: Process expense state changes (approve/reject/payment) |
| 37 | + |
| 38 | +**Parameters**: |
| 39 | +- `type` (required): Action type - "approve", "reject", or "payment" |
| 40 | +- `id` (required): Expense ID |
| 41 | +- `is_api_call` (optional): "true" for API calls, "false" for UI calls |
| 42 | + |
| 43 | +**Business Rules**: |
| 44 | +- `approve`: Changes CREATED → APPROVED |
| 45 | +- `reject`: Changes CREATED → REJECTED |
| 46 | +- `payment`: Changes APPROVED → COMPLETED |
| 47 | +- Invalid IDs return 400 error |
| 48 | +- Invalid action types return 400 error |
| 49 | +- State changes from CREATED to APPROVED/REJECTED trigger workflow notifications |
| 50 | +- API calls return "SUCCEED" on success |
| 51 | +- UI calls redirect to list view after success |
| 52 | + |
| 53 | +**Error Handling**: |
| 54 | +- API calls return "ERROR:INVALID_ID" or "ERROR:INVALID_TYPE" |
| 55 | +- UI calls return HTTP 400 with descriptive messages |
| 56 | + |
| 57 | +### 3. Create Expense (`GET /create`) |
| 58 | +**Purpose**: Create a new expense entry |
| 59 | + |
| 60 | +**Parameters**: |
| 61 | +- `id` (required): Unique expense ID |
| 62 | +- `is_api_call` (optional): "true" for API calls, "false" for UI calls |
| 63 | + |
| 64 | +**Business Rules**: |
| 65 | +- Expense ID must be unique |
| 66 | +- New expenses start in CREATED state |
| 67 | +- Duplicate IDs return 400 error |
| 68 | + |
| 69 | +**Error Handling**: |
| 70 | +- API calls return "ERROR:ID_ALREADY_EXISTS" |
| 71 | +- UI calls return HTTP 400 with descriptive message |
| 72 | + |
| 73 | +### 4. Status Check (`GET /status`) |
| 74 | +**Purpose**: Retrieve current expense state |
| 75 | + |
| 76 | +**Parameters**: |
| 77 | +- `id` (required): Expense ID |
| 78 | + |
| 79 | +**Response**: Current expense state as string |
| 80 | +**Error Handling**: Returns "ERROR:INVALID_ID" for unknown IDs |
| 81 | + |
| 82 | +### 5. Callback Registration (`POST /registerCallback`) |
| 83 | +**Purpose**: Register Temporal workflow callback for expense state changes |
| 84 | + |
| 85 | +**Parameters**: |
| 86 | +- `id` (query): Expense ID |
| 87 | +- `task_token` (form): Hex-encoded Temporal task token |
| 88 | + |
| 89 | +**Business Rules**: |
| 90 | +- Expense must exist and be in CREATED state |
| 91 | +- Task token must be valid hex format |
| 92 | +- Enables workflow notification on state changes |
| 93 | + |
| 94 | +**Error Handling**: |
| 95 | +- "ERROR:INVALID_ID" for unknown expenses |
| 96 | +- "ERROR:INVALID_STATE" for non-CREATED expenses |
| 97 | +- "ERROR:INVALID_FORM_DATA" for invalid tokens |
| 98 | + |
| 99 | +## Workflow Integration |
| 100 | + |
| 101 | +### Callback Mechanism |
| 102 | +- When expenses transition from CREATED to APPROVED/REJECTED, registered callbacks are triggered |
| 103 | +- Uses Temporal's async activity completion mechanism |
| 104 | +- Task tokens are stored and used to complete workflow activities |
| 105 | + |
| 106 | +### Error Handling |
| 107 | +- Failed callback completions are logged but don't affect UI operations |
| 108 | +- Invalid or expired tokens are handled gracefully |
| 109 | + |
| 110 | +## User Interface |
| 111 | + |
| 112 | +### Web Interface Features |
| 113 | +- Clean HTML table display |
| 114 | +- Color-coded action buttons (green for APPROVE, red for REJECT) |
| 115 | +- Real-time state display |
| 116 | +- Navigation between views |
| 117 | + |
| 118 | +### API Interface Features |
| 119 | +- RESTful endpoints for programmatic access |
| 120 | +- Consistent error response format |
| 121 | +- Support for both sync and async operations |
| 122 | + |
| 123 | +## Non-Functional Requirements |
| 124 | + |
| 125 | +### Concurrency |
| 126 | +- Thread-safe in-memory storage operations |
| 127 | +- Handles concurrent API and UI requests |
| 128 | + |
| 129 | +### Error Recovery |
| 130 | +- Graceful handling of workflow callback failures |
| 131 | +- Input validation on all endpoints |
| 132 | +- Descriptive error messages |
| 133 | + |
| 134 | +### Logging |
| 135 | +- State change operations are logged |
| 136 | +- Callback registration and completion logged |
| 137 | +- Error conditions logged for debugging |
| 138 | + |
| 139 | +## Security Considerations |
| 140 | +- Input validation on all parameters |
| 141 | +- Protection against duplicate ID creation |
| 142 | +- Secure handling of Temporal task tokens |
| 143 | + |
| 144 | +## Scalability Notes |
| 145 | +- Current implementation uses in-memory storage |
| 146 | +- Designed for demonstration/development use |
| 147 | +- Production deployment would require persistent storage |
0 commit comments