# Customer Data Flow Analysis

## Issue Report
**Problem:** Customer `billing_phone` shows "Indonesia" instead of phone number  
**Source:** Customer created via Order module  
**Impact:** Incorrect customer data stored in database

## Data Flow Investigation

### A. Customer as Guest (Not Site Member)

#### 1. Order Creation Flow
**File:** `OrdersController.php` → `create_order()` method

**Steps:**
1. Order form submits billing data including `phone`
2. Data flows through `$billing['phone']` parameter
3. Order billing is set via `$order->set_billing_phone($billing['phone'])`
4. **No WC_Customer object created** - guest orders only store data in order meta

**Code Location:** Lines 780-1120

```php
// Guest customer - data only in order
$order->set_billing_first_name($billing['first_name'] ?? '');
$order->set_billing_last_name($billing['last_name'] ?? '');
$order->set_billing_email($billing['email'] ?? '');
$order->set_billing_phone($billing['phone'] ?? '');  // ← Data here
// ... more fields
```

**Issue:** Guest customers don't have WC_Customer records, so viewing them in Customer module will fail or show incorrect data.

---

### B. Customer as Site Member

#### 1. Existing Member - Order Creation
**File:** `OrdersController.php` → Lines 1020-1064

**Flow:**
1. User exists, found by email
2. **Upgrade subscriber to customer role** (if needed)
3. Create `WC_Customer` object
4. **Update customer data** from order billing/shipping
5. Save customer
6. Link order to customer

**Code:**
```php
if ($user) {
  // Upgrade role if needed
  if (in_array('subscriber', (array) $user->roles, true)) {
    $user->set_role('customer');
  }
  
  // Update customer billing & shipping data
  $customer = new \WC_Customer($user->ID);
  
  // Update billing address
  if (! empty($billing['first_name'])) $customer->set_billing_first_name($billing['first_name']);
  if (! empty($billing['last_name']))  $customer->set_billing_last_name($billing['last_name']);
  if (! empty($billing['email']))      $customer->set_billing_email($billing['email']);
  if (! empty($billing['phone']))      $customer->set_billing_phone($billing['phone']);  // ← HERE
  // ... more fields
  
  $customer->save();
}
```

**Validation:** Uses `! empty()` check  
**Problem:** If `$billing['phone']` contains "Indonesia" (non-empty string), it will be saved!

---

#### 2. New Member - Auto-Registration
**File:** `OrdersController.php` → Lines 1065-1118

**Flow:**
1. User doesn't exist
2. Auto-register setting is ON
3. Create WordPress user
4. Create `WC_Customer` object
5. Set billing/shipping from order data
6. Save customer
7. Send welcome email

**Code:**
```php
elseif ($register_member) {
  // Create user
  $user_id = wp_insert_user($userdata);
  
  if (!is_wp_error($user_id)) {
    $customer = new \WC_Customer($user_id);
    
    // Billing address
    if (! empty($billing['first_name'])) $customer->set_billing_first_name($billing['first_name']);
    // ...
    if (! empty($billing['phone'])) $customer->set_billing_phone($billing['phone']);  // ← HERE
    // ...
    
    $customer->save();
  }
}
```

**Same Issue:** `! empty()` check allows "Indonesia" to be saved.

---

### C. Customer Module Direct Edit

**File:** `CustomersController.php` → `update_customer()` method (Lines 232-310)

**Flow:**
1. Receive customer data via PUT request
2. Update WordPress user meta
3. Update `WC_Customer` billing/shipping
4. Save customer

**Code:**
```php
$customer = new WC_Customer($id);

// Billing address
if (!empty($data['billing'])) {
  $billing = $data['billing'];
  if (isset($billing['first_name'])) $customer->set_billing_first_name(...);
  // ...
  if (isset($billing['phone'])) $customer->set_billing_phone(sanitize_text_field($billing['phone']));
  // ...
}

$customer->save();
```

**Validation:** Uses `isset()` check (better than `! empty()`)  
**Sanitization:** Uses `sanitize_text_field()` ✅

---

## Root Cause Analysis

### Possible Sources of "Indonesia" Value

1. **Frontend Default Value**
   - Check `OrderForm.tsx` for default country/phone values
   - Check if "Indonesia" is being set as placeholder or default

2. **Backend Fallback**
   - Check if WooCommerce has default country settings
   - Check if there's a fallback to country name instead of phone

3. **Data Validation Issue**
   - `! empty()` check allows ANY non-empty string
   - No validation that phone is actually a phone number
   - No sanitization before saving

4. **Virtual Products Case**
   - When cart has only virtual products, address fields are hidden
   - Phone field might still be submitted with wrong value

---

## Issues Found

### 1. ❌ Weak Validation in OrdersController

**Problem:**
```php
if (! empty($billing['phone'])) $customer->set_billing_phone($billing['phone']);
```

- `! empty()` allows "Indonesia", "test", "abc", etc.
- No phone number format validation
- No sanitization

**Should Be:**
```php
if (isset($billing['phone']) && $billing['phone'] !== '') {
  $customer->set_billing_phone(sanitize_text_field($billing['phone']));
}
```

---

### 2. ❌ No Data Sanitization in Order Creation

**Problem:**
- Direct assignment without sanitization
- Allows any string value
- No format validation

**Should Add:**
- `sanitize_text_field()` for all text fields
- Phone number format validation
- Empty string handling

---

### 3. ❌ Inconsistent Validation Between Controllers

**OrdersController:**
- Uses `! empty()` check
- No sanitization

**CustomersController:**
- Uses `isset()` check ✅
- Has `sanitize_text_field()` ✅

**Should:** Use same validation pattern everywhere

---

### 4. ❌ Virtual Products Address Handling

**Current Behavior:**
- Frontend hides address fields for virtual products
- But phone field is ALWAYS shown
- Backend might receive wrong data

**Check:**
- OrderForm.tsx line 1023: `setBPhone(data.billing.phone || '');`
- Does this fallback to something else?

---

## Action Items

### 1. Fix OrdersController Validation

**File:** `OrdersController.php`  
**Lines:** 1039-1047, 1088-1096

**Change:**
```php
// OLD (Lines 1042)
if (! empty($billing['phone'])) $customer->set_billing_phone($billing['phone']);

// NEW
if (isset($billing['phone']) && trim($billing['phone']) !== '') {
  $customer->set_billing_phone(sanitize_text_field($billing['phone']));
}
```

Apply to:
- Existing member update (lines 1039-1047)
- New member creation (lines 1088-1096)

---

### 2. Add Phone Number Validation

**Create Helper Function:**
```php
private static function sanitize_phone($phone) {
  if (empty($phone)) {
    return '';
  }
  
  // Remove non-numeric characters except + and spaces
  $phone = preg_replace('/[^0-9+\s-]/', '', $phone);
  
  // Trim whitespace
  $phone = trim($phone);
  
  // If result is empty or just symbols, return empty
  if (empty($phone) || preg_match('/^[+\s-]+$/', $phone)) {
    return '';
  }
  
  return $phone;
}
```

---

### 3. Check Frontend Data Source

**File:** `OrderForm.tsx`  
**Line:** ~1023

**Check:**
- Where does `data.billing.phone` come from?
- Is there a default value being set?
- Is "Indonesia" coming from country field?

---

### 4. Test Cases

**A. Guest Customer:**
1. Create order with phone = "08123456789"
2. Check order billing_phone
3. Verify no WC_Customer created

**B. Existing Member:**
1. Create order with existing customer
2. Phone = "08123456789"
3. Check WC_Customer billing_phone updated
4. Create another order with same customer
5. Phone = "08198765432"
6. Verify WC_Customer phone updated to new value

**C. New Member (Auto-register):**
1. Create order with new email
2. Auto-register ON
3. Phone = "08123456789"
4. Verify WC_Customer created with correct phone

**D. Virtual Products:**
1. Create order with only virtual products
2. Verify phone field behavior
3. Check what value is submitted

---

## Expected Behavior

### Order Creation with Existing Member
1. Order billing data should update WC_Customer data
2. Phone should be validated and sanitized
3. Empty phone should clear WC_Customer phone (not set to country name)

### Order Creation with New Member
1. WC_Customer should be created with correct data
2. Phone should be validated and sanitized
3. No fallback to country name

### Virtual Products
1. Phone field should still work correctly
2. No address fields needed
3. Phone should not default to country name

---

## Next Steps

1. ✅ Update PROJECT_SOP.md with mobile UX patterns
2. 🔄 Find source of "Indonesia" value
3. ⏳ Fix validation in OrdersController
4. ⏳ Add phone sanitization helper
5. ⏳ Test all scenarios
6. ⏳ Document fix in commit message
