6.2 KiB
6.2 KiB
Phase 4: Service Layer Refactor - Checklist
✅ Completed Tasks
Customer Service Refactor
- Analyze existing customer service structure
- Update customer service with branch context integration
- Implement contact visibility logic (private-by-default)
- Add
BranchContextparameter to all customer operations - Implement contact sharing/unsharing functionality
- Add business rule validation for quotation creation
- Create
generateCrmCustomerCodeutility function - Add soft delete support for customers
- Implement CRUD operations with branch scoping
Quotation Service Refactor
- Analyze existing quotation service structure
- Add multi-currency support (THB, USD, EUR, JPY, CNY)
- Implement exchange rate capture at quotation creation
- Add base currency amount calculation
- Implement quotation revision system
- Add
parentQuotationIdandrevisionNotracking - Create
createQuotationRevisionfunction with cloning logic - Implement quotation item management
- Add quotation customer relationship management
- Create multi-currency calculation utilities
- Add quotation validation rules (editable, sendable status checks)
- Implement
generateQuotationCodeutility function
📁 Created Files
-
src/modules/customers/service.refactored.ts- Customer operations with branch scoping
- Contact visibility enforcement
- Contact sharing functionality
- Business rule validations
-
src/modules/quotations/service.refactored.ts- Quotation CRUD with branch context
- Multi-currency support
- Revision system implementation
- Currency conversion utilities
- Validation helpers
🔑 Key Features Implemented
Branch Scoping
- All operations automatically scoped by
currentBranchId - Cross-branch access prevented at service layer
- Automatic branch ID injection on create/update operations
Contact Visibility Logic
Visibility Rule: User can see contact IF:
- createdBy == currentUser
OR
- isPublic == true
Multi-Currency Support
- Currency code stored with each quotation
- Exchange rate captured at creation time (immutable)
- Base currency (THB) amount calculated and stored
- Same quotation code can have multiple currency versions
Revision System
Quotation Status Flow:
DRAFT → SENT (locked)
SENT → Create REVISION (new draft)
REVISION → SENT (locked)
SENT → ACCEPTED | REJECTED
Business Rules
- ✅ User must have visible contacts to create quotation
- ✅ Only creator can update/delete their contacts
- ✅ Sent quotations cannot be edited directly (must create revision)
- ✅ Draft quotations are editable
📊 Database Integration
Customer Service
- Uses Drizzle ORM with PostgreSQL
- Implements proper foreign key relationships
- Supports soft deletes with
deletedAttimestamp - Indexes: branchId, customerStatus, crmCustomerCode, erpCustomerCode
Quotation Service
- Full Drizzle ORM integration
- Multi-table transactions (quotations, items, customers)
- Proper cascade deletes
- Indexes: branchId, code, status, quotationDate, parentQuotationId
🔄 Migration Notes
From Old Service to New Service
Old Pattern:
export function getAllCustomers(branch: string): Customer[] {
return getCustomersByBranch(branch);
}
New Pattern:
export async function getCustomersByBranch(
context: BranchContext,
status?: string,
): Promise<Customer[]> {
const { currentBranchId } = context;
return await db
.select()
.from(customers)
.where(eq(customers.branchId, currentBranchId));
}
Breaking Changes
- All functions now require
BranchContextparameter - Functions are now async (return Promises)
- Contact visibility is enforced by default
- Multi-currency fields are required for quotations
🧪 Testing Recommendations
Unit Tests Needed
- Test branch scoping enforcement
- Test contact visibility rules
- Test contact sharing/unsharing
- Test multi-currency calculations
- Test revision creation logic
- Test quotation validation rules
- Test soft delete functionality
Integration Tests Needed
- Test full quotation creation flow
- Test quotation revision flow
- Test customer + contact creation flow
- Test cross-branch access prevention
- Test currency conversion accuracy
📋 Next Steps
Phase 5: Controllers Update
- Update customer controllers to use refactored service
- Update quotation controllers to use refactored service
- Add BranchContext injection from middleware
- Update API request/response types
- Add error handling for validation failures
Phase 6: Models (TypeScript)
- Update customer model types for new fields
- Add quotation model types with multi-currency
- Create contact model types
- Add revision-related types
- Update ElysiaJS validation schemas
Phase 7: Testing
- Write unit tests for customer service
- Write unit tests for quotation service
- Write integration tests for API endpoints
- Test multi-tenant scenarios
- Test multi-currency scenarios
🎯 Success Criteria
Phase 4 is complete when:
- All service functions use BranchContext
- Contact visibility is enforced
- Multi-currency is fully supported
- Revision system works correctly
- Controllers are updated (Phase 5)
- Models are updated (Phase 6)
- Tests pass (Phase 7)
📝 Notes
Contact Visibility Implementation
- The contact visibility is implemented at the service layer using
isPublicflag - Future enhancement: Add
contact_sharestable for more granular sharing (specific users) - Current implementation: Public/Private binary flag
Multi-Currency Implementation
- Exchange rates are captured at quotation creation time
- Historical rates are preserved (no dynamic recalculation)
- Base currency (THB) is used for reporting and comparisons
Revision System
- Each revision creates a new quotation record
- Parent relationship tracked via
parentQuotationId - Same quotation code shared across revisions
- Status resets to "draft" for new revisions
Phase 4 Status: ✅ CORE IMPLEMENTATION COMPLETE
Next Phase: Phase 5 - Controllers Update