diff --git a/SHIPPING_ADDON_RESEARCH.md b/SHIPPING_ADDON_RESEARCH.md new file mode 100644 index 0000000..c9f6772 --- /dev/null +++ b/SHIPPING_ADDON_RESEARCH.md @@ -0,0 +1,371 @@ +# Shipping Addon Integration Research + +## Problem Statement +Indonesian shipping plugins (Biteship, Woongkir, etc.) have complex requirements: +1. **Origin address** - configured in wp-admin +2. **Subdistrict field** - custom checkout field +3. **Real-time API calls** - during cart/checkout +4. **Custom field injection** - modify checkout form + +**Question:** How can WooNooW SPA accommodate these plugins without breaking their functionality? + +--- + +## How WooCommerce Shipping Addons Work + +### Standard WooCommerce Pattern +```php +class My_Shipping_Method extends WC_Shipping_Method { + public function calculate_shipping($package = array()) { + // 1. Get settings from $this->get_option() + // 2. Calculate rates based on package + // 3. Call $this->add_rate($rate) + } +} +``` + +**Key Points:** +- ✅ Extends `WC_Shipping_Method` +- ✅ Uses WooCommerce hooks: `woocommerce_shipping_init`, `woocommerce_shipping_methods` +- ✅ Settings stored in `wp_options` table +- ✅ Rates calculated during `calculate_shipping()` + +--- + +## Indonesian Shipping Plugins (Biteship, Woongkir, etc.) + +### How They Differ from Standard Plugins + +#### 1. **Custom Checkout Fields** +```php +// They add custom fields to checkout +add_filter('woocommerce_checkout_fields', function($fields) { + $fields['billing']['billing_subdistrict'] = array( + 'type' => 'select', + 'label' => 'Subdistrict', + 'required' => true, + 'options' => get_subdistricts() // API call + ); + return $fields; +}); +``` + +#### 2. **Origin Configuration** +- Stored in plugin settings (wp-admin) +- Used for API calls to calculate distance/cost +- Not exposed in standard WooCommerce shipping settings + +#### 3. **Real-time API Calls** +```php +public function calculate_shipping($package) { + // Get origin from plugin settings + $origin = get_option('biteship_origin_subdistrict_id'); + + // Get destination from checkout field + $destination = $package['destination']['subdistrict_id']; + + // Call external API + $rates = biteship_api_get_rates($origin, $destination, $weight); + + foreach ($rates as $rate) { + $this->add_rate($rate); + } +} +``` + +#### 4. **AJAX Updates** +```javascript +// Update shipping when subdistrict changes +jQuery('#billing_subdistrict').on('change', function() { + jQuery('body').trigger('update_checkout'); +}); +``` + +--- + +## Why Indonesian Plugins Are Complex + +### 1. **Geographic Complexity** +- Indonesia has **34 provinces**, **514 cities**, **7,000+ subdistricts** +- Shipping cost varies by subdistrict (not just city) +- Standard WooCommerce only has: Country → State → City → Postcode + +### 2. **Multiple Couriers** +- Each courier has different rates per subdistrict +- Real-time API calls required (can't pre-calculate) +- Some couriers don't serve all subdistricts + +### 3. **Origin-Destination Pairing** +- Cost depends on **origin subdistrict** + **destination subdistrict** +- Origin must be configured in admin +- Destination selected at checkout + +--- + +## How WooNooW SPA Should Handle This + +### ✅ **What WooNooW SHOULD Do** + +#### 1. **Display Methods Correctly** +```typescript +// Our current approach is CORRECT +const { data: zones } = useQuery({ + queryKey: ['shipping-zones'], + queryFn: () => api.get('/settings/shipping/zones') +}); +``` +- ✅ Fetch zones from WooCommerce API +- ✅ Display all methods (including Biteship, Woongkir) +- ✅ Show enable/disable toggle +- ✅ Link to WooCommerce settings for advanced config + +#### 2. **Expose Basic Settings Only** +```typescript +// Show only common settings +- Display Name (title) +- Cost (if applicable) +- Min Amount (if applicable) +``` +- ✅ Don't try to show ALL settings +- ✅ Complex settings → "Edit in WooCommerce" button + +#### 3. **Respect Plugin Behavior** +- ✅ Don't interfere with checkout field injection +- ✅ Don't modify `calculate_shipping()` logic +- ✅ Let plugins handle their own API calls + +--- + +### ❌ **What WooNooW SHOULD NOT Do** + +#### 1. **Don't Try to Manage Custom Fields** +```typescript +// ❌ DON'T DO THIS +const subdistrictField = { + type: 'select', + options: await fetchSubdistricts() +}; +``` +- ❌ Subdistrict fields are managed by shipping plugins +- ❌ They inject fields via WooCommerce hooks +- ❌ WooNooW SPA doesn't control checkout page + +#### 2. **Don't Try to Calculate Rates** +```typescript +// ❌ DON'T DO THIS +const rate = await biteshipAPI.getRates(origin, destination); +``` +- ❌ Rate calculation is plugin-specific +- ❌ Requires API keys, origin config, etc. +- ❌ Should happen during checkout, not in admin + +#### 3. **Don't Try to Show All Settings** +```typescript +// ❌ DON'T DO THIS + + + +``` +- ❌ Too complex for simplified UI +- ❌ Each plugin has different settings +- ❌ Better to link to WooCommerce settings + +--- + +## Comparison: Global vs Indonesian Shipping + +### Global Shipping Plugins (ShipStation, EasyPost, etc.) + +**Characteristics:** +- ✅ Standard address fields (Country, State, City, Postcode) +- ✅ Pre-calculated rates or simple API calls +- ✅ No custom checkout fields needed +- ✅ Settings fit in standard WooCommerce UI + +**Example: Flat Rate** +```php +public function calculate_shipping($package) { + $rate = array( + 'label' => $this->title, + 'cost' => $this->get_option('cost') + ); + $this->add_rate($rate); +} +``` + +### Indonesian Shipping Plugins (Biteship, Woongkir, etc.) + +**Characteristics:** +- ⚠️ Custom address fields (Province, City, District, **Subdistrict**) +- ⚠️ Real-time API calls with origin-destination pairing +- ⚠️ Custom checkout field injection +- ⚠️ Complex settings (API keys, origin config, courier selection) + +**Example: Biteship** +```php +public function calculate_shipping($package) { + $origin_id = get_option('biteship_origin_subdistrict_id'); + $dest_id = $package['destination']['subdistrict_id']; + + $response = wp_remote_post('https://api.biteship.com/v1/rates', array( + 'headers' => array('Authorization' => 'Bearer ' . $api_key), + 'body' => json_encode(array( + 'origin_area_id' => $origin_id, + 'destination_area_id' => $dest_id, + 'couriers' => $this->get_option('couriers'), + 'items' => $package['contents'] + )) + )); + + $rates = json_decode($response['body'])->pricing; + foreach ($rates as $rate) { + $this->add_rate(array( + 'label' => $rate->courier_name . ' - ' . $rate->courier_service_name, + 'cost' => $rate->price + )); + } +} +``` + +--- + +## Recommendations for WooNooW SPA + +### ✅ **Current Approach is CORRECT** + +Our simplified UI is perfect for: +1. **Standard shipping methods** (Flat Rate, Free Shipping, Local Pickup) +2. **Simple third-party plugins** (basic rate calculators) +3. **Non-tech users** who just want to enable/disable methods + +### ✅ **For Complex Plugins (Biteship, Woongkir)** + +**Strategy: "View-Only + Link to WooCommerce"** + +```typescript +// In the accordion, show: + + + 🚚 Biteship - JNE REG [On] + Rp 15,000 (calculated at checkout) + + + + This is a complex shipping method with advanced settings. + + + + {/* Only show basic toggle */} + + + +``` + +### ✅ **Detection Logic** + +```typescript +// Detect if method is complex +const isComplexMethod = (method: ShippingMethod) => { + const complexPlugins = [ + 'biteship', + 'woongkir', + 'anteraja', + 'shipper', + // Add more as needed + ]; + + return complexPlugins.some(plugin => + method.id.includes(plugin) + ); +}; + +// Render accordingly +{isComplexMethod(method) ? ( + +) : ( + +)} +``` + +--- + +## Testing Strategy + +### ✅ **What to Test in WooNooW SPA** + +1. **Method Display** + - ✅ Biteship methods appear in zone list + - ✅ Enable/disable toggle works + - ✅ Method name displays correctly + +2. **Settings Link** + - ✅ "Edit in WooCommerce" button works + - ✅ Opens correct settings page + +3. **Don't Break Checkout** + - ✅ Subdistrict field still appears + - ✅ Rates calculate correctly + - ✅ AJAX updates work + +### ❌ **What NOT to Test in WooNooW SPA** + +1. ❌ Rate calculation accuracy +2. ❌ API integration +3. ❌ Subdistrict field functionality +4. ❌ Origin configuration + +**These are the shipping plugin's responsibility!** + +--- + +## Conclusion + +### **WooNooW SPA's Role:** +✅ **Simplified management** for standard shipping methods +✅ **View-only + link** for complex plugins +✅ **Don't interfere** with plugin functionality + +### **Shipping Plugin's Role:** +✅ Handle complex settings (origin, API keys, etc.) +✅ Inject custom checkout fields +✅ Calculate rates via API +✅ Manage courier selection + +### **Result:** +✅ Non-tech users can enable/disable methods easily +✅ Complex configuration stays in WooCommerce admin +✅ No functionality is lost +✅ Best of both worlds! 🎯 + +--- + +## Implementation Plan + +### Phase 1: Detection (Current) +- [x] Display all methods from WooCommerce API +- [x] Show enable/disable toggle +- [x] Show basic settings (title, cost, min_amount) + +### Phase 2: Complex Method Handling (Next) +- [ ] Detect complex shipping plugins +- [ ] Show different UI for complex methods +- [ ] Add "Configure in WooCommerce" button +- [ ] Hide settings form for complex methods + +### Phase 3: Documentation (Final) +- [ ] Add help text explaining complex methods +- [ ] Link to plugin documentation +- [ ] Add troubleshooting guide + +--- + +**Last Updated:** Nov 9, 2025 +**Status:** Research Complete ✅