# Bill Tracker - Backend Refactoring Learnings ## 2026-05-11 - Phase 1 Business Logic Extraction ### Task Extract business logic from `routes/bills.js` into a dedicated service layer (`services/billsService.js`). ### Functions Extracted to `services/billsService.js` - `getDefaultCycleDay(cycleType)` - Returns default cycle day based on cycle type - `validateCycleDay(cycleType, cycleDay)` - Validates cycle_day based on cycle_type rules - `parseDueDay(value)` - Parses and validates due_day (must be 1-31 integer) - `parseInterestRate(value)` - Parses and validates interest_rate (0-100 range) - `getValidCycleTypes()` - Returns array of valid cycle types - `validateBillData(data, existingBill)` - Comprehensive validation and normalization for bill create/update - `validateCycleDayOnly(cycleType, cycleDay)` - Convenience wrapper for cycle_day validation ### Functions Remaining in `routes/bills.js` - Route handlers only - parse request, call service, send response - DB queries remain in routes (tightly coupled to HTTP flow, not pure business logic) - Error formatting with `standardizeError` (HTTP-layer concern) ### Design Decisions 1. **`validateBillData`** - Centralized validation function that handles both create and update scenarios - Takes optional `existingBill` parameter to support partial updates - Returns `{ errors, normalized }` structure - Validates all bill fields including category_id, history_visibility, cycle_type/cycle_day 2. **`getValidCycleTypes()`** - Exported constant array for consistency across files 3. **`VALID_VISIBILITY`** - Exported from service for reuse in other files if needed ### Benefits - Business logic is now testable in isolation without mocking Express request/response - Route handlers are thinner and easier to read - Validation rules are centralized in one place - Easier to add new bill-related operations without touching routes ### Files Modified - `routes/bills.js` - Removed ~80 lines of business logic, replaced with service imports and calls - `services/billsService.js` - New file created with extracted business logic ### No Breaking Changes - All API endpoints maintain exact same behavior - Same validation rules applied - Same error messages returned