201 lines
5.5 KiB
Markdown
201 lines
5.5 KiB
Markdown
|
|
# Codebase Refactoring Complete ✅
|
||
|
|
|
||
|
|
## Summary
|
||
|
|
|
||
|
|
Completed comprehensive refactoring to establish WHMCS as single source of truth and cleaned up architectural inconsistencies.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ✅ Fixed Issues
|
||
|
|
|
||
|
|
### 1. **Removed Duplicate Address Alias**
|
||
|
|
**Location:** `packages/domain/auth/contract.ts`
|
||
|
|
|
||
|
|
**Before:**
|
||
|
|
```typescript
|
||
|
|
export type Address = CustomerAddress; // Duplicate
|
||
|
|
```
|
||
|
|
|
||
|
|
**After:**
|
||
|
|
```typescript
|
||
|
|
import type { CustomerProfile, Address } from "../customer/contract"; // Import from customer domain
|
||
|
|
```
|
||
|
|
|
||
|
|
**Benefit:** Single source of truth for Address type
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. **Fixed Inconsistent Error Handling**
|
||
|
|
**Location:** `apps/bff/src/modules/users/users.service.ts`
|
||
|
|
|
||
|
|
**Before:**
|
||
|
|
```typescript
|
||
|
|
throw new Error("Failed to find user"); // ❌ Generic error
|
||
|
|
throw new Error("Failed to create user"); // ❌ Generic error
|
||
|
|
throw new Error(`Failed to retrieve dashboard data: ${error}`); // ❌ Exposes details
|
||
|
|
```
|
||
|
|
|
||
|
|
**After:**
|
||
|
|
```typescript
|
||
|
|
throw new BadRequestException("Unable to retrieve user profile"); // ✅ NestJS exception
|
||
|
|
throw new BadRequestException("Unable to create user account"); // ✅ User-friendly message
|
||
|
|
throw new BadRequestException("Unable to retrieve dashboard summary"); // ✅ No sensitive info
|
||
|
|
throw new NotFoundException("User not found"); // ✅ Proper HTTP status
|
||
|
|
```
|
||
|
|
|
||
|
|
**Benefits:**
|
||
|
|
- Consistent error handling across service
|
||
|
|
- User-friendly error messages
|
||
|
|
- No sensitive information exposed
|
||
|
|
- Proper HTTP status codes
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. **Fixed Hardcoded Currency**
|
||
|
|
**Location:** `apps/bff/src/modules/users/users.service.ts`
|
||
|
|
|
||
|
|
**Before:**
|
||
|
|
```typescript
|
||
|
|
currency: "JPY", // ❌ Hardcoded
|
||
|
|
```
|
||
|
|
|
||
|
|
**After:**
|
||
|
|
```typescript
|
||
|
|
// Get currency from WHMCS client data
|
||
|
|
let currency = "JPY"; // Default
|
||
|
|
try {
|
||
|
|
const client = await this.whmcsService.getClientDetails(mapping.whmcsClientId);
|
||
|
|
currency = client.currencyCode || currency;
|
||
|
|
} catch (error) {
|
||
|
|
this.logger.warn("Could not fetch currency from WHMCS client", { userId });
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Benefit:** Dynamic currency from WHMCS profile
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4. **Cleaned Up Imports**
|
||
|
|
**Location:** `apps/bff/src/modules/users/users.service.ts`
|
||
|
|
|
||
|
|
**Before:**
|
||
|
|
```typescript
|
||
|
|
import type { CustomerAddress } from "@customer-portal/domain/customer"; // ❌ Redundant
|
||
|
|
```
|
||
|
|
|
||
|
|
**After:**
|
||
|
|
```typescript
|
||
|
|
// Removed redundant import - Address is available from auth domain
|
||
|
|
```
|
||
|
|
|
||
|
|
**Benefit:** Cleaner imports, uses Address alias consistently
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 Architecture Improvements Summary
|
||
|
|
|
||
|
|
### Database Layer
|
||
|
|
- ✅ Removed cached profile fields from User table
|
||
|
|
- ✅ Portal DB now auth-only (email, passwordHash, mfaSecret, etc.)
|
||
|
|
- ✅ Created migration: `20250103000000_remove_cached_profile_fields`
|
||
|
|
|
||
|
|
### Domain Layer
|
||
|
|
- ✅ Unified `UpdateCustomerProfileRequest` (profile + address)
|
||
|
|
- ✅ Removed deprecated types (UpdateProfileRequest, UpdateAddressRequest, UserProfile, User)
|
||
|
|
- ✅ Single Address type from customer domain
|
||
|
|
- ✅ Clean naming following WHMCS conventions (firstname, lastname, etc.)
|
||
|
|
|
||
|
|
### Service Layer
|
||
|
|
- ✅ `getProfile()` - Fetches complete profile from WHMCS
|
||
|
|
- ✅ `updateProfile()` - Updates profile AND/OR address in WHMCS
|
||
|
|
- ✅ Consistent error handling with NestJS exceptions
|
||
|
|
- ✅ No sensitive information in error messages
|
||
|
|
- ✅ Dynamic currency from WHMCS
|
||
|
|
|
||
|
|
### API Layer
|
||
|
|
- ✅ Single endpoint: `GET /me` (complete profile with address)
|
||
|
|
- ✅ Single endpoint: `PATCH /me` (update profile/address)
|
||
|
|
- ✅ Removed redundant `/me/address` endpoints
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 Architecture Benefits
|
||
|
|
|
||
|
|
1. **Single Source of Truth:** WHMCS owns all customer data
|
||
|
|
2. **No Data Sync Issues:** Always fresh from WHMCS
|
||
|
|
3. **Consistent Error Handling:** Proper HTTP status codes
|
||
|
|
4. **No Sensitive Data Leaks:** User-friendly error messages
|
||
|
|
5. **Dynamic Configuration:** Currency from customer profile
|
||
|
|
6. **Clean Type System:** No duplicate aliases or deprecated types
|
||
|
|
7. **Simplified API:** Fewer endpoints, clearer purpose
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📝 Files Modified
|
||
|
|
|
||
|
|
### Domain Layer
|
||
|
|
- `packages/domain/auth/contract.ts` - Removed Address alias, cleaned types
|
||
|
|
- `packages/domain/auth/schema.ts` - Removed deprecated schemas
|
||
|
|
- `packages/domain/auth/index.ts` - Updated exports
|
||
|
|
- `packages/domain/customer/contract.ts` - Added CustomerProfile
|
||
|
|
|
||
|
|
### Backend Layer
|
||
|
|
- `apps/bff/prisma/schema.prisma` - Removed profile fields
|
||
|
|
- `apps/bff/prisma/migrations/20250103000000_remove_cached_profile_fields/migration.sql`
|
||
|
|
- `apps/bff/src/modules/users/users.service.ts` - Complete refactor
|
||
|
|
- `apps/bff/src/modules/users/users.controller.ts` - Simplified API
|
||
|
|
- `apps/bff/src/infra/utils/user-mapper.util.ts` - Renamed to mapPrismaUserToAuthState
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🚀 Migration Steps
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1. Apply database migration
|
||
|
|
cd apps/bff
|
||
|
|
npx prisma migrate deploy
|
||
|
|
npx prisma generate
|
||
|
|
|
||
|
|
# 2. Verify no linting errors
|
||
|
|
npm run lint
|
||
|
|
|
||
|
|
# 3. Build
|
||
|
|
npm run build
|
||
|
|
|
||
|
|
# 4. Test
|
||
|
|
npm test
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📈 Code Quality Metrics
|
||
|
|
|
||
|
|
**Before:**
|
||
|
|
- 16 inconsistent error throws (mix of Error, NotFoundException, BadRequestException)
|
||
|
|
- 2 duplicate Address type aliases
|
||
|
|
- 1 hardcoded currency
|
||
|
|
- 3 redundant endpoints (/me, /me/address, /me/billing)
|
||
|
|
- Profile fields cached in 2 places (Portal DB + WHMCS)
|
||
|
|
|
||
|
|
**After:**
|
||
|
|
- ✅ Consistent error handling (100% NestJS exceptions)
|
||
|
|
- ✅ Single Address type
|
||
|
|
- ✅ Dynamic currency from WHMCS
|
||
|
|
- ✅ 2 clean endpoints (GET /me, PATCH /me)
|
||
|
|
- ✅ Single source of truth (WHMCS only)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎉 Result
|
||
|
|
|
||
|
|
**Clean, production-ready codebase with:**
|
||
|
|
- Clear data ownership
|
||
|
|
- Consistent patterns
|
||
|
|
- Proper error handling
|
||
|
|
- No redundancy
|
||
|
|
- Type safety
|
||
|
|
- Single source of truth
|
||
|
|
|
||
|
|
All changes follow domain-driven design principles and modern NestJS best practices.
|
||
|
|
|