- Updated pnpm-lock.yaml to include new dependencies and ensure consistent package versions. - Refactored order handling in OrderOrchestrator to utilize centralized field mapping for Salesforce queries. - Modified SalesforceOrder interface to replace Order_Type__c with Type for clarity. - Improved error handling in UsersService during WHMCS updates to provide user-friendly messages. - Enhanced BillingPage and ProfilePage components to streamline address management and improve user experience. - Updated documentation to reflect changes in address handling and system architecture.
351 lines
9.9 KiB
Markdown
351 lines
9.9 KiB
Markdown
# Address System Documentation
|
|
|
|
## Overview
|
|
|
|
Our address system follows a **clean, logical flow** where address is **required at signup** and managed throughout the user lifecycle. This eliminates surprises during checkout and ensures data integrity.
|
|
|
|
## 🎯 Core Logic
|
|
|
|
```
|
|
Registration → Required Address → WHMCS Storage → Order Snapshots
|
|
```
|
|
|
|
## Architecture
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[User Registration] --> B[Required Address Validation]
|
|
B --> C[WHMCS Client Creation]
|
|
C --> D[Complete Profile]
|
|
|
|
D --> E[Checkout Flow]
|
|
E --> F{Order Type?}
|
|
F -->|Internet| G[Explicit Address Verification]
|
|
F -->|Other| H[Auto-Confirm Address]
|
|
|
|
G --> I[Address Snapshot]
|
|
H --> I
|
|
I --> J[Salesforce Order]
|
|
|
|
D --> K[Profile Management]
|
|
K --> L[Address Updates]
|
|
L --> M[WHMCS Sync]
|
|
```
|
|
|
|
## Key Components
|
|
|
|
### Backend
|
|
- `SignupDto` - Address required at registration
|
|
- `UsersService.updateBillingInfo()` - WHMCS sync
|
|
- `OrderBuilder.addAddressSnapshot()` - Salesforce snapshots
|
|
|
|
### Frontend
|
|
- `AddressConfirmation` - Checkout verification
|
|
- `ProfileCompletionGuard` - Handles incomplete profiles
|
|
- `/account/billing` - Address management
|
|
|
|
## Order Type Flows
|
|
|
|
| Order Type | Address Behavior |
|
|
|------------|------------------|
|
|
| **Internet** | ✅ Explicit verification required (technician visit) |
|
|
| **SIM/VPN/Other** | ✅ Auto-confirm (exists from signup) |
|
|
|
|
## Implementation
|
|
|
|
### 1. Signup Flow (Required Address)
|
|
|
|
#### Backend Validation
|
|
```typescript
|
|
// apps/bff/src/auth/dto/signup.dto.ts
|
|
export class AddressDto {
|
|
@IsNotEmpty() line1: string; // Required
|
|
@IsOptional() line2?: string; // Optional
|
|
@IsNotEmpty() city: string; // Required
|
|
@IsNotEmpty() state: string; // Required
|
|
@IsNotEmpty() postalCode: string; // Required
|
|
@IsNotEmpty() country: string; // Required
|
|
}
|
|
|
|
export class SignupDto {
|
|
@ValidateNested()
|
|
@Type(() => AddressDto)
|
|
address: AddressDto; // ✅ REQUIRED - not optional
|
|
}
|
|
```
|
|
|
|
#### WHMCS Client Creation
|
|
```typescript
|
|
// apps/bff/src/auth/auth.service.ts
|
|
await this.whmcsService.addClient({
|
|
address1: address.line1, // Required field
|
|
address2: address.line2 || "", // Optional field
|
|
city: address.city, // Required field
|
|
state: address.state, // Required field
|
|
postcode: address.postalCode, // Required field
|
|
country: address.country, // Required field
|
|
});
|
|
```
|
|
|
|
### 2. Checkout Flow
|
|
|
|
#### Address Confirmation Logic
|
|
```typescript
|
|
// apps/portal/src/components/checkout/address-confirmation.tsx
|
|
// Since address is required at signup, it should always be complete
|
|
if (requiresAddressVerification) {
|
|
// Internet orders: require explicit verification
|
|
setAddressConfirmed(false);
|
|
onAddressIncomplete(); // Keep disabled until confirmed
|
|
} else {
|
|
// Other orders: auto-confirm since address exists from signup
|
|
onAddressConfirmed(data.address);
|
|
setAddressConfirmed(true);
|
|
}
|
|
```
|
|
|
|
#### Internet Order Verification
|
|
```typescript
|
|
{isInternetOrder && !addressConfirmed && (
|
|
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
|
|
<p className="text-sm text-blue-800">
|
|
<strong>Internet Installation Address Verification Required</strong>
|
|
</p>
|
|
<p className="text-sm text-blue-700 mt-1">
|
|
Please verify this is the correct address for your internet installation.
|
|
A technician will visit this location for setup.
|
|
</p>
|
|
</div>
|
|
)}
|
|
```
|
|
|
|
### 3. Address Updates & WHMCS Sync
|
|
|
|
```typescript
|
|
// apps/bff/src/users/users.service.ts
|
|
async updateBillingInfo(userId: string, billingData: UpdateBillingDto): Promise<void> {
|
|
const mapping = await this.mappingsService.findByUserId(userId);
|
|
|
|
// Prepare WHMCS update data
|
|
const whmcsUpdateData = {
|
|
address1: billingData.street,
|
|
address2: billingData.streetLine2,
|
|
city: billingData.city,
|
|
state: billingData.state,
|
|
postcode: billingData.postalCode,
|
|
country: billingData.country,
|
|
};
|
|
|
|
// Update in WHMCS (authoritative source)
|
|
await this.whmcsService.updateClient(mapping.whmcsClientId, whmcsUpdateData);
|
|
}
|
|
```
|
|
|
|
### 4. Order Address Snapshots
|
|
|
|
```typescript
|
|
// apps/bff/src/orders/services/order-builder.service.ts
|
|
private async addAddressSnapshot(orderFields: Record<string, unknown>, userId: string, body: CreateOrderBody): Promise<void> {
|
|
const billingInfo = await this.usersService.getBillingInfo(userId);
|
|
const orderAddress = (body.configurations as any)?.address;
|
|
const addressChanged = !!(orderAddress);
|
|
const addressToUse = orderAddress || billingInfo.address;
|
|
|
|
// Combine street lines for Salesforce
|
|
const fullStreet = [addressToUse?.street, addressToUse?.streetLine2]
|
|
.filter(Boolean)
|
|
.join(", ");
|
|
|
|
// Always populate billing address fields
|
|
orderFields["BillToStreet"] = fullStreet || "";
|
|
orderFields["BillToCity"] = addressToUse?.city || "";
|
|
orderFields["BillToState"] = addressToUse?.state || "";
|
|
orderFields["BillToPostalCode"] = addressToUse?.postalCode || "";
|
|
orderFields["BillToCountry"] = addressToUse?.country || "";
|
|
|
|
// Set change flag
|
|
orderFields["Address_Changed__c"] = addressChanged;
|
|
}
|
|
```
|
|
|
|
## Field Mapping
|
|
|
|
### WHMCS ↔ Internal ↔ Salesforce
|
|
```
|
|
WHMCS → Internal → Salesforce Order
|
|
address1 → street → BillToStreet (combined)
|
|
address2 → streetLine2 → BillToStreet (combined)
|
|
city → city → BillToCity
|
|
state → state → BillToState
|
|
postcode → postalCode → BillToPostalCode
|
|
country → country → BillToCountry
|
|
|
|
// Change detection
|
|
N/A → addressChanged → Address_Changed__c (boolean)
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### Address Management
|
|
```typescript
|
|
// Get current address
|
|
GET /api/users/billing
|
|
Response: {
|
|
address: {
|
|
street: string | null;
|
|
streetLine2: string | null;
|
|
city: string | null;
|
|
state: string | null;
|
|
postalCode: string | null;
|
|
country: string | null;
|
|
};
|
|
isComplete: boolean;
|
|
}
|
|
|
|
// Update address
|
|
PATCH /api/users/billing
|
|
Body: {
|
|
street?: string;
|
|
streetLine2?: string;
|
|
city?: string;
|
|
state?: string;
|
|
postalCode?: string;
|
|
country?: string;
|
|
}
|
|
```
|
|
|
|
## Quick Patterns
|
|
|
|
### Protect Route with Profile Completion
|
|
```tsx
|
|
<ProfileCompletionGuard requireComplete={true}>
|
|
<YourComponent />
|
|
</ProfileCompletionGuard>
|
|
```
|
|
|
|
### Handle Address in Checkout
|
|
```tsx
|
|
<AddressConfirmation
|
|
onAddressConfirmed={handleConfirmed}
|
|
onAddressIncomplete={handleIncomplete}
|
|
orderType={orderType}
|
|
/>
|
|
```
|
|
|
|
### Check Profile Completion
|
|
```tsx
|
|
const { isComplete, loading, redirectToCompletion } = useProfileCompletion();
|
|
```
|
|
|
|
## User Flows
|
|
|
|
### 1. New User Registration
|
|
1. User fills registration form with **required address**
|
|
2. Backend validates all address fields
|
|
3. WHMCS client created with complete address
|
|
4. User can immediately access all features
|
|
|
|
### 2. Internet Order Checkout
|
|
1. User selects Internet service
|
|
2. Address confirmation component loads
|
|
3. Shows current address with verification requirement
|
|
4. User must explicitly confirm installation address
|
|
5. Order created with address snapshot
|
|
|
|
### 3. Other Order Checkout
|
|
1. User selects SIM/VPN/Other service
|
|
2. Address confirmation component loads
|
|
3. Auto-confirms address (exists from signup)
|
|
4. Order created with address snapshot
|
|
|
|
### 4. Address Updates
|
|
1. User goes to `/account/billing`
|
|
2. Can edit and save address changes
|
|
3. Changes sync to WHMCS immediately
|
|
4. Future orders use updated address
|
|
|
|
## Testing
|
|
|
|
### Quick Commands
|
|
```bash
|
|
# Test required address validation
|
|
curl -X POST /api/auth/signup -d '{"address": {...}}'
|
|
|
|
# Get user address
|
|
curl -X GET /api/users/billing
|
|
|
|
# Update address
|
|
curl -X PATCH /api/users/billing -d '{"street": "New St"}'
|
|
```
|
|
|
|
### Test Scenarios
|
|
1. **New User Signup**: Verify address is required and validated
|
|
2. **Internet Order**: Verify explicit address confirmation required
|
|
3. **SIM Order**: Verify address auto-confirmed
|
|
4. **Address Update**: Verify WHMCS sync works
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
#### "Address not found during checkout"
|
|
- **Cause**: User somehow has incomplete profile
|
|
- **Solution**: `ProfileCompletionGuard` will redirect to completion
|
|
|
|
#### "Internet order won't submit"
|
|
- **Cause**: Address not explicitly confirmed
|
|
- **Solution**: User must click "Confirm Installation Address"
|
|
|
|
#### "Address changes not saving"
|
|
- **Cause**: WHMCS API connection issue
|
|
- **Solution**: Check WHMCS credentials and API access
|
|
|
|
### Quick Debug
|
|
1. **Address not required?** → Check `SignupDto.address` is not `@IsOptional()`
|
|
2. **Internet order auto-confirms?** → Check `orderType === "Internet"` logic
|
|
3. **Address not in Salesforce?** → Check `addAddressSnapshot()` call
|
|
4. **WHMCS not updating?** → Check API credentials and `updateClient()` method
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
```bash
|
|
# WHMCS API
|
|
WHMCS_API_URL=https://your-whmcs.com/includes/api.php
|
|
WHMCS_API_IDENTIFIER=your_api_identifier
|
|
WHMCS_API_SECRET=your_api_secret
|
|
|
|
# Salesforce Field Mapping (optional overrides)
|
|
ORDER_ADDRESS_CHANGED_FIELD=Address_Changed__c
|
|
ORDER_BILL_TO_STREET_FIELD=BillToStreet
|
|
ORDER_BILL_TO_CITY_FIELD=BillToCity
|
|
ORDER_BILL_TO_STATE_FIELD=BillToState
|
|
ORDER_BILL_TO_POSTAL_CODE_FIELD=BillToPostalCode
|
|
ORDER_BILL_TO_COUNTRY_FIELD=BillToCountry
|
|
```
|
|
|
|
## Benefits
|
|
|
|
### ✅ **User Experience**
|
|
- No surprise address requirements during checkout
|
|
- Clear completion flows for edge cases
|
|
- Order-type specific verification (Internet vs Others)
|
|
|
|
### ✅ **Data Integrity**
|
|
- Address required at source (signup)
|
|
- Single source of truth (WHMCS)
|
|
- Point-in-time snapshots (Salesforce orders)
|
|
|
|
### ✅ **Performance**
|
|
- No unnecessary dashboard banners
|
|
- Simplified checkout validation
|
|
- Efficient profile completion checks
|
|
|
|
### ✅ **Maintainability**
|
|
- Logical flow from signup to order
|
|
- Reusable profile completion components
|
|
- Clean separation of concerns
|
|
|
|
---
|
|
|
|
*This address system provides a clean, logical, and modern approach to address management with required addresses at signup and intelligent order-type specific flows.* |