2.2 KiB
2.2 KiB
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 typevalidateCycleDay(cycleType, cycleDay)- Validates cycle_day based on cycle_type rulesparseDueDay(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 typesvalidateBillData(data, existingBill)- Comprehensive validation and normalization for bill create/updatevalidateCycleDayOnly(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
-
validateBillData- Centralized validation function that handles both create and update scenarios- Takes optional
existingBillparameter to support partial updates - Returns
{ errors, normalized }structure - Validates all bill fields including category_id, history_visibility, cycle_type/cycle_day
- Takes optional
-
getValidCycleTypes()- Exported constant array for consistency across files -
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 callsservices/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