# Unified Product Types - Solution to Type Duplication

## Problem Statement

Previously, we had multiple type definitions trying to represent the same underlying Salesforce `Product2` data:

- `CatalogItem` - for catalog display
- `CatalogOrderItem` - for order items in checkout
- `InternetPlan`, `SimPlan`, `VpnPlan` - for specific product types
- Various interfaces in Salesforce order types

This led to:

- **Type duplication** across the codebase
- **Inconsistent field names** between contexts
- **Maintenance overhead** when Salesforce fields change
- **Confusion** about which type to use when

## Solution: Unified Product Types

### Core Principle

**One Salesforce Product2 = One TypeScript Type**

Since order items get their data from Salesforce `Product2` objects (via `PricebookEntry.Product2`), and catalog items are also representing the same `Product2` objects, we should have unified types that directly map to the Salesforce structure.

### New Type Hierarchy

```typescript
// Base product interface mapping directly to Salesforce Product2
interface BaseProduct {
  // Standard Salesforce fields
  id: string; // Product2.Id
  name: string; // Product2.Name
  sku: string; // Product2.StockKeepingUnit

  // Custom fields for portal
  category: ProductCategory; // Product2Categories1__c
  itemClass: ItemClass; // Item_Class__c
  billingCycle: BillingCycle; // Billing_Cycle__c
  portalCatalog: boolean; // Portal_Catalog__c
  portalAccessible: boolean; // Portal_Accessible__c

  // WHMCS integration
  whmcsProductId: number; // WH_Product_ID__c
  whmcsProductName: string; // WH_Product_Name__c

  // Pricing from PricebookEntry
  monthlyPrice?: number;
  oneTimePrice?: number;
}

// Specialized types for each product category
interface InternetProduct extends BaseProduct {
  category: "Internet";
  internetPlanTier?: "Silver" | "Gold" | "Platinum";
  internetOfferingType?: string;
  // ... other Internet-specific fields
}

interface SimProduct extends BaseProduct {
  category: "SIM";
  simDataSize?: string;
  simPlanType?: "DataOnly" | "DataSmsVoice" | "VoiceOnly";
  simHasFamilyDiscount?: boolean;
  // ... other SIM-specific fields
}

// Union type for all products
type Product = InternetProduct | SimProduct | VpnProduct | BaseProduct;

// Order item with quantity
interface ProductOrderItem extends BaseProduct {
  quantity: number;
  unitPrice: number;
  totalPrice: number;
  autoAdded?: boolean;
}
```

### Benefits

1. **Single Source of Truth**: All types map directly to Salesforce Product2 structure
2. **No Duplication**: Same type used in catalog, orders, and business logic
3. **Type Safety**: Proper TypeScript discrimination based on `category` field
4. **Maintainability**: Changes to Salesforce fields only need updates in one place
5. **Consistency**: Same field names and structure across all contexts

### Usage Examples

```typescript
// Transform Salesforce data to unified type
const product = fromSalesforceProduct2(salesforceProduct, pricebookEntry);

// Use in catalog context
if (isCatalogVisible(product)) {
  displayInCatalog(product);
}

// Use in order context
const orderItem: ProductOrderItem = {
  ...product,
  quantity: 1,
  unitPrice: product.monthlyPrice || 0,
  totalPrice: product.monthlyPrice || 0,
};

// Type-safe access to specific fields
if (isInternetProduct(product)) {
  console.log(product.internetPlanTier); // TypeScript knows this exists
}
```

### Migration Strategy

1. **Backward Compatibility**: Legacy type aliases maintained

   ```typescript
   export type InternetPlan = InternetProduct; // For existing code
   export type CatalogItem = Product; // Unified representation
   ```

2. **Gradual Migration**: Existing code continues to work while new code uses unified types

3. **Field Mapping**: The `fromSalesforceProduct2()` function handles transformation from Salesforce API responses

### Implementation Files

- `packages/domain/src/entities/product.ts` - Core unified types
- `packages/domain/src/entities/catalog.ts` - Re-exports with legacy aliases
- `packages/domain/src/entities/order.ts` - Updated order types
- `packages/domain/src/entities/examples/unified-product-usage.ts` - Usage examples

### Key Functions

- `fromSalesforceProduct2()` - Transform Salesforce data to unified types
- `isInternetProduct()`, `isSimProduct()`, `isVpnProduct()` - Type guards
- `isCatalogVisible()`, `isOrderable()` - Business logic helpers
- `isServiceProduct()`, `isAddonProduct()` - Classification helpers

This unified approach eliminates the confusion about which type to use and ensures consistency across the entire application while maintaining direct mapping to the underlying Salesforce data structure.
