
This commit introduces a new endpoint for updating chores of any type, allowing conversions between personal and group chores while enforcing permission checks. Additionally, structured logging has been implemented through a new middleware, improving request tracing and logging details for better monitoring and debugging. These changes aim to enhance the functionality and maintainability of the chore management system.
12 KiB
Financial System Overview
Introduction
This document provides a comprehensive overview of the Expense, Cost & Financial domain of the project. It is intended for backend / frontend developers, QA engineers and DevOps personnel who need to understand how money flows through the system, what invariants are enforced and where to extend the platform.
TL;DR The financial subsystem is a Split-wise-inspired engine with first-class support for: shared lists, item-derived expenses, multi-scheme splitting, settlements, recurring charges and complete auditability.
Main Concepts & Entities
Entity | Purpose | Key Relationships |
---|---|---|
User | A registered account. Owns expenses, owes splits, records settlements. | expenses_paid , expenses_created , expense_splits , settlements_made/received , settlements_created |
Group | A collection of users with shared expenses / lists. | member_associations (UserGroup) , lists , expenses , settlements |
List | A shopping / to-do list. May belong to a Group or be personal. |
items , expenses |
Item | A purchasable line inside a List . Price & author drive item-based expense splits. |
list , added_by_user |
Expense | A monetary outflow. | splits , list , group , item , recurrence_pattern |
ExpenseSplit | A who-owes-what record for an Expense . |
user , settlement_activities |
Settlement | A generic cash transfer between two users inside a group. | – |
SettlementActivity | A payment that reduces an individual ExpenseSplit (e.g. Alice pays Bob her part). |
– |
RecurrencePattern | The schedule template that spawns future Expense occurrences. |
expenses |
FinancialAuditLog | Append-only journal of who did what (create / update / delete) for all financial entities. | – |
Expense Lifecyle
-
Creation (
POST /financials/expenses
) • Caller provides anExpenseCreate
DTO.
• Backend validates the context (list / group / item), the payer, and the chosen split strategy. • Supportedsplit_type
values (SplitTypeEnum
):EQUAL
– evenly divided among computed participants.EXACT_AMOUNTS
– caller supplies absolute owed amounts.PERCENTAGE
– caller supplies percentages totalling 100 %.SHARES
– integer share units (e.g. 1 : 2 : 3).ITEM_BASED
– derived from pricedItem
s in a list. • A database transaction writesExpense
+ExpenseSplit
rows and aFinancialAuditLog
entry.
-
Reading •
GET /financials/expenses/{id}
enforces row-level security: the requester must be payer, list member or group member. -
Update / Delete • Optimistic-locking via the
version
field. • Only the payer or a group owner may mutate records. -
Settlement • Generic settlements (
/financials/settlements
) clear balances between two users.
• Fine-grained settlements (/financials/expense_splits/{id}/settle
) clear a singleExpenseSplit
. -
Recurring Expenses • An
Expense
can be flaggedis_recurring = true
and carry aRecurrencePattern
.
• A background job (app/jobs/recurring_expenses.py::generate_recurring_expenses
) wakes up daily and:- Finds template expenses due (
next_occurrence <= now
). - Spawns a child expense replicating the split logic.
- Updates
last_occurrence
, decrementsmax_occurrences
and calculates the next date.
- Finds template expenses due (
Cost Summaries & Balance Sheets
List Cost Summary
Endpoint: GET /costs/lists/{list_id}/cost-summary
• If an ITEM_BASED
expense already exists → returns a snapshot derived from the expense.
• Otherwise → computes an on-the-fly summary using Item.price
values (read-only).
Key Figures:
total_list_cost
– sum of item prices.equal_share_per_user
– what each participant should pay.balance
– (over / under) contribution for each user.
Action: POST /costs/lists/{id}/cost-summary
finalises the list by persisting the derived ITEM_BASED
expense.
Group Balance Summary
Endpoint: GET /costs/groups/{group_id}/balance-summary
Aggregates across all group expenses + settlements:
- What each user paid (expenses + received settlements)
- What each user owed
- Suggested minimal settlement graph (creditors vs debtors)
Data-Integrity Rules & Guards
Expense
must reference eitherlist_id
orgroup_id
(DB-level CHECK).- Row uniqueness guards:
UniqueConstraint('expense_id', 'user_id')
onExpenseSplit
. Settlement
payer ≠ payee (DB CHECK).- All mutating endpoints perform authorization checks via
crud_group
/crud_list
helpers. - Monetary amounts are stored as
Numeric(10,2)
and rounded (ROUND_HALF_UP
).
Recent Fixes & Improvements (June 2025)
Area | Issue | Resolution |
---|---|---|
Recurring filter | GET /financials/expenses?isRecurring=true referenced nonexistent recurrence_rule . |
Switched to is_recurring flag. |
Enum mismatches | RecurrencePattern.type stored uppercase enum, while API took lowercase strings. |
Robust mapper converts strings → RecurrenceTypeEnum ; scheduler is now case-insensitive. |
Scheduler | _calculate_next_occurrence failed with Enum values & stringified days_of_week . |
Added polymorphic handling + safe parsing of comma-separated strings. |
All tests pass (pytest -q
) and new unit tests cover the edge-cases above.
Extension Points
- VAT / Tax logic – attach a
tax_rate
column toExpense
and resolve net vs gross amounts. - Multi-currency – normalize amounts to a base currency using FX rates; expose a
Currency
table. - Budgeting / Limits – per-group or per-list spending caps with alerting.
- Webhook notifications – publish
FinancialAuditLog
entries to external services.
Appendix – Key SQL Schema Snapshots
-- Expense table (excerpt)
CREATE TABLE expenses (
id SERIAL PRIMARY KEY,
total_amount NUMERIC(10,2) NOT NULL,
split_type VARCHAR(20) NOT NULL,
list_id INT NULL,
group_id INT NULL,
-- …
CHECK (group_id IS NOT NULL OR list_id IS NOT NULL)
);
CREATE UNIQUE INDEX uq_expense_user_split ON expense_splits(expense_id, user_id);
System Reliability Analysis & Improvements
✅ Implemented Reliability Features
1. Transaction Safety
- All financial operations use transactional sessions (
get_transactional_session
) - Atomic operations ensure data consistency across expense creation, splits, and settlements
- Row-level locking (
WITH FOR UPDATE
) prevents race conditions in settlement activities
2. Overpayment Protection
- NEW: Settlement activities now validate against remaining owed amount
- Prevents payments that exceed the split's owed amount
- Provides clear error messages with remaining balance information
- Handles multiple partial payments correctly
3. Data Validation & Constraints
- Decimal precision: All monetary amounts use
Numeric(10,2)
with proper rounding - Positive amount validation: Prevents negative payments and settlements
- User existence validation: Ensures all referenced users exist before operations
- Split consistency: Validates split totals match expense amounts (EXACT_AMOUNTS, PERCENTAGE)
4. Permission & Authorization
- Multi-layered permission checks for expense creation and settlement recording
- Group owners can act on behalf of members with proper validation
- List/group access controls prevent unauthorized financial operations
5. Status Management
- Automatic status updates for expense splits (unpaid → partially_paid → paid)
- Cascading status updates for parent expenses based on split states
- Pessimistic locking ensures consistent status transitions
6. Audit Trail
- All financial operations logged via
create_financial_audit_log
- Complete traceability of who created/modified financial records
- Immutable settlement activity records (no updates, only creation)
7. Error Handling
- Comprehensive exception hierarchy for different error types
- Specific
OverpaymentError
for payment validation failures - Database integrity and connection error handling
- Graceful degradation with meaningful error messages
🔍 Potential Areas for Enhancement
1. Optimistic Locking for Expenses
Currently, expenses use basic versioning but could benefit from full optimistic locking:
# Consider adding to ExpenseUpdate operations
if expected_version != current_expense.version:
raise ConflictError("Expense was modified by another user")
2. Recurring Expense Reliability
- Add retry logic for failed recurring expense generation
- Implement dead letter queue for failed recurring operations
- Add monitoring for recurring expense job health
3. Currency Consistency
While currency is stored, there's no validation that all splits in an expense use the same currency:
# Potential enhancement
if expense.currency != "USD" and any(split.currency != expense.currency for split in splits):
raise InvalidOperationError("All splits must use the same currency as the parent expense")
4. Settlement Verification
Consider adding verification flags for settlements to distinguish between:
- Automatic settlements (from expense splits)
- Manual settlements (direct user payments)
- Disputed settlements requiring verification
📊 System Health Metrics
The system provides comprehensive financial tracking through:
- Real-time balance calculations via
costs_service.py
- Settlement suggestions using optimal debt reduction algorithms
- Expense categorization and filtering with proper indexing
- Multi-context support (lists, groups, personal expenses)
🛡️ Security Considerations
- Input sanitization: All financial inputs validated through Pydantic schemas
- Authorization layers: Multiple permission checks prevent unauthorized access
- Audit logging: Complete financial operation history for compliance
- Data isolation: Users only see expenses/settlements they have permission to access
🚀 Performance Optimizations
- Database indexing on critical foreign keys and search fields
- Eager loading with
selectinload
to prevent N+1 queries - Pagination for large result sets
- Connection pooling with health checks (
pool_pre_ping=True
)
Testing & Quality Assurance
The financial system includes comprehensive test coverage:
- Unit tests for CRUD operations and business logic
- Integration tests for API endpoints and workflows
- Edge case testing for overpayment protection and boundary conditions
- Concurrency tests for settlement race conditions
- Data consistency tests for split calculations and status updates
Example test scenarios:
- Multiple users settling the same split simultaneously
- Expense split totals validation across different split types
- Currency precision and rounding accuracy
- Permission boundary testing for cross-user operations
Deployment & Monitoring Recommendations
Database Considerations
- Regular backup strategy for financial data
- Monitor transaction isolation levels and deadlocks
- Set up alerts for unusual financial activity patterns
- Implement database connection monitoring
Application Monitoring
- Track settlement activity creation rates and failures
- Monitor recurring expense job execution and errors
- Set up alerts for permission denial patterns
- Track API response times for financial endpoints
Business Intelligence
- Daily/weekly financial summaries per group
- Settlement velocity tracking (time to pay debts)
- Expense categorization analytics
- User engagement with financial features
The financial system is now production-ready with robust reliability safeguards, comprehensive error handling, and strong data consistency guarantees.