197 lines
5.1 KiB
Markdown
197 lines
5.1 KiB
Markdown
# Priority 2: Business Validation Consolidation Plan
|
|
|
|
**Objective**: Move business validation logic from service layers to domain schemas where appropriate.
|
|
|
|
---
|
|
|
|
## 🎯 Analysis Summary
|
|
|
|
### Current State
|
|
|
|
**Validation logic is scattered across multiple layers:**
|
|
|
|
1. **✅ Already in Domain** (Good)
|
|
- Basic schema validation (format, required fields)
|
|
- Some business rules in `orderBusinessValidationSchema`
|
|
- Type validation
|
|
|
|
2. **⚠️ In BFF Services** (Should be moved)
|
|
- Order SKU business rules (`validateBusinessRules`)
|
|
- Invoice status validation
|
|
- Pagination limits
|
|
- SIM validation logic
|
|
|
|
3. **✅ Should Stay in Services** (Infrastructure concerns)
|
|
- External API calls (WHMCS, Salesforce)
|
|
- Database lookups
|
|
- Payment method verification
|
|
- User mapping validation
|
|
- Duplicate order checks
|
|
|
|
---
|
|
|
|
## 📋 What Should Move to Domain
|
|
|
|
### 1. **Order Business Rules** (High Priority)
|
|
|
|
**Current**: `apps/bff/src/modules/orders/services/order-validator.service.ts:176-228`
|
|
|
|
```typescript
|
|
validateBusinessRules(orderType: string, skus: string[]): void {
|
|
switch (orderType) {
|
|
case "SIM": {
|
|
// Check for SIM service plan
|
|
const hasSimService = skus.some(...);
|
|
// Check for activation fee
|
|
const hasActivation = skus.some(...);
|
|
}
|
|
case "VPN": {
|
|
// VPN activation check
|
|
}
|
|
case "Internet": {
|
|
// Internet service check
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Should be**: Extended validation in `packages/domain/orders/schema.ts`
|
|
|
|
### 2. **Invoice Validation Constants** (Medium Priority)
|
|
|
|
**Current**: `apps/bff/src/modules/invoices/validators/invoice-validator.service.ts:14-23`
|
|
|
|
```typescript
|
|
private readonly validStatuses: readonly InvoiceStatus[] = [
|
|
"Paid", "Unpaid", "Cancelled", "Overdue", "Collections"
|
|
] as const;
|
|
private readonly maxLimit = 100;
|
|
private readonly minLimit = 1;
|
|
```
|
|
|
|
**Should be**: In `packages/domain/billing/schema.ts`
|
|
|
|
### 3. **Common Validation Utilities**
|
|
|
|
- ID validation helpers
|
|
- Pagination limits
|
|
- Status validation
|
|
|
|
---
|
|
|
|
## ❌ What Should NOT Move to Domain
|
|
|
|
### Infrastructure/External Dependencies:
|
|
|
|
1. **User Mapping Validation** - requires DB lookup
|
|
2. **Payment Method Validation** - requires WHMCS API call
|
|
3. **Internet Duplication Check** - requires WHMCS API call
|
|
4. **SKU Existence Check** - requires Salesforce API call
|
|
5. **SIM Account Extraction** - complex WHMCS integration logic
|
|
|
|
These involve:
|
|
- External API calls
|
|
- Database queries
|
|
- Caching
|
|
- Rate limiting
|
|
- Retry logic
|
|
- Logging infrastructure
|
|
|
|
---
|
|
|
|
## 🔄 Implementation Plan
|
|
|
|
### Phase 1: Order Validation (High Priority)
|
|
1. Create advanced order validation schemas in domain
|
|
2. Move SKU business rules to domain
|
|
3. Update OrderValidator service to use domain schemas
|
|
4. Remove duplicate validation logic
|
|
|
|
### Phase 2: Invoice Validation (Medium Priority)
|
|
1. Move invoice constants to domain
|
|
2. Enhance invoice query schemas
|
|
3. Update InvoiceValidator to use domain constants
|
|
|
|
### Phase 3: Common Patterns (Low Priority)
|
|
1. Create shared validation helpers in domain/toolkit
|
|
2. Standardize pagination schemas
|
|
3. Create reusable validation utilities
|
|
|
|
---
|
|
|
|
## 📊 Expected Benefits
|
|
|
|
1. **Reusability**: Frontend can use same validation logic
|
|
2. **Consistency**: Same rules enforced everywhere
|
|
3. **Testability**: Pure validation logic easy to unit test
|
|
4. **Maintainability**: Single place to update business rules
|
|
5. **Type Safety**: TypeScript infers from schema
|
|
|
|
---
|
|
|
|
## 🚦 Decision Matrix
|
|
|
|
| Validation Type | Move to Domain? | Reason |
|
|
|----------------|-----------------|---------|
|
|
| SKU format rules | ✅ Yes | Pure business logic |
|
|
| Order type rules | ✅ Yes | Domain constraint |
|
|
| Invoice status list | ✅ Yes | Domain constant |
|
|
| Pagination limits | ✅ Yes | Application constant |
|
|
| User exists check | ❌ No | Database query |
|
|
| Payment method exists | ❌ No | External API |
|
|
| SKU exists in SF | ❌ No | External API |
|
|
| Internet duplication | ❌ No | External API |
|
|
| SIM account extraction | ❌ No | Complex integration |
|
|
|
|
---
|
|
|
|
## 📝 Implementation Notes
|
|
|
|
### Pattern: Domain Schema with Complex Validation
|
|
|
|
```typescript
|
|
// packages/domain/orders/validation.ts (NEW FILE)
|
|
import { z } from "zod";
|
|
import { orderBusinessValidationSchema } from "./schema";
|
|
|
|
/**
|
|
* Extended order validation with SKU business rules
|
|
*/
|
|
export const orderWithSkuValidationSchema = orderBusinessValidationSchema.refine(
|
|
(data) => {
|
|
if (data.orderType === "SIM") {
|
|
const hasSimService = data.skus.some(/* logic */);
|
|
return hasSimService;
|
|
}
|
|
return true;
|
|
},
|
|
{ message: "SIM orders must include a service plan", path: ["skus"] }
|
|
);
|
|
```
|
|
|
|
### Pattern: Domain Constants
|
|
|
|
```typescript
|
|
// packages/domain/billing/constants.ts (NEW FILE)
|
|
export const INVOICE_VALIDATION = {
|
|
PAGINATION: {
|
|
MIN_LIMIT: 1,
|
|
MAX_LIMIT: 100,
|
|
DEFAULT_LIMIT: 10,
|
|
},
|
|
VALID_STATUSES: ["Paid", "Unpaid", "Cancelled", "Overdue", "Collections"] as const,
|
|
} as const;
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Success Criteria
|
|
|
|
- [ ] Order SKU validation rules in domain
|
|
- [ ] Invoice constants in domain
|
|
- [ ] Frontend can reuse validation schemas
|
|
- [ ] Services delegate to domain schemas
|
|
- [ ] No duplication of business rules
|
|
- [ ] All tests pass
|
|
|