Assist_Design/docs/_archive/PRIORITY-2-PLAN.md

5.1 KiB

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

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

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

// 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

// 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