docs: Critical audit and strategy documents
## Point 1: Addon Bridge Pattern ✅ Created ADDON_BRIDGE_PATTERN.md documenting: - WooNooW Core = Zero addon dependencies - Bridge snippet pattern for Rajaongkir compatibility - Proper addon development approach - Hook system usage **Key Decision:** - ❌ No Rajaongkir integration in core - ✅ Provide bridge snippets for compatibility - ✅ Encourage proper WooNooW addons - ✅ Keep core clean and maintainable --- ## Point 2: Calculation Efficiency Audit 🚨 CRITICAL Created CALCULATION_EFFICIENCY_AUDIT.md revealing: **BLOATED Implementation Found:** - 2 separate API calls (/shipping/calculate + /orders/preview) - Cart initialized TWICE - Shipping calculated TWICE - Taxes calculated TWICE - ~1000ms total time **Recommended Solution:** - Single /orders/calculate endpoint - ONE cart initialization - ONE calculation - ~300ms total time (70% faster!) - 50% fewer requests - 50% less server load **This is exactly what we discussed at the beginning:** > "WooCommerce is bloated because of separate requests. We need efficient flow that handles everything at once." **Current implementation repeats WooCommerce's mistake!** **Status:** ❌ NOT IMPLEMENTED YET **Priority:** 🚨 CRITICAL **Impact:** 🔥 HIGH - Performance bottleneck --- ## Point 3: Settings Placement Strategy ✅ Created SETTINGS_PLACEMENT_STRATEGY.md proposing: **No separate "WooNooW Settings" page.** Instead: - Store Logo → WooCommerce > Settings > General - Order Format → WooCommerce > Settings > Orders - Product Settings → WooCommerce > Settings > Products - UI Settings → WooCommerce > Settings > Admin UI (new tab) **Benefits:** - Contextual placement - Familiar to users - No clutter - Seamless integration - Feels native to WooCommerce **Philosophy:** WooNooW should feel like a native part of WooCommerce, not a separate plugin. --- ## Summary **Point 1:** ✅ Documented addon bridge pattern **Point 2:** 🚨 CRITICAL - Current calculation is bloated, needs refactoring **Point 3:** ✅ Settings placement strategy documented **Next Action Required:** Implement unified /orders/calculate endpoint to fix performance bottleneck.
This commit is contained in:
325
ADDON_BRIDGE_PATTERN.md
Normal file
325
ADDON_BRIDGE_PATTERN.md
Normal file
@@ -0,0 +1,325 @@
|
||||
# Addon Bridge Pattern - Rajaongkir Example
|
||||
|
||||
## Philosophy
|
||||
|
||||
**WooNooW Core = Zero Addon Dependencies**
|
||||
|
||||
We don't integrate specific addons into WooNooW core. Instead, we provide:
|
||||
1. **Hook system** for addons to extend functionality
|
||||
2. **Bridge snippets** for compatibility with existing plugins
|
||||
3. **Addon development guide** for building proper WooNooW addons
|
||||
|
||||
---
|
||||
|
||||
## Problem: Rajaongkir Plugin
|
||||
|
||||
Rajaongkir is a WooCommerce plugin that:
|
||||
- Removes standard address fields (city, state)
|
||||
- Adds custom destination dropdown
|
||||
- Stores data in WooCommerce session
|
||||
- Works on WooCommerce checkout page
|
||||
|
||||
**It doesn't work with WooNooW OrderForm because:**
|
||||
- OrderForm uses standard WooCommerce fields
|
||||
- Rajaongkir expects session-based destination
|
||||
- No destination = No shipping calculation
|
||||
|
||||
---
|
||||
|
||||
## Solution: Bridge Snippet (Not Core Integration!)
|
||||
|
||||
### Option A: Standalone Bridge Plugin
|
||||
|
||||
Create a tiny bridge plugin that makes Rajaongkir work with WooNooW:
|
||||
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: WooNooW Rajaongkir Bridge
|
||||
* Description: Makes Rajaongkir plugin work with WooNooW OrderForm
|
||||
* Version: 1.0.0
|
||||
* Requires: WooNooW, Rajaongkir Official
|
||||
*/
|
||||
|
||||
// Hook into WooNooW's shipping calculation
|
||||
add_filter('woonoow_before_shipping_calculate', function($shipping_data) {
|
||||
// If Indonesia and has city, convert to Rajaongkir destination
|
||||
if ($shipping_data['country'] === 'ID' && !empty($shipping_data['city'])) {
|
||||
// Search Rajaongkir API for destination
|
||||
$api = Cekongkir_API::get_instance();
|
||||
$results = $api->search_destination_api($shipping_data['city']);
|
||||
|
||||
if (!empty($results[0])) {
|
||||
// Set Rajaongkir session data
|
||||
WC()->session->set('selected_destination_id', $results[0]['id']);
|
||||
WC()->session->set('selected_destination_label', $results[0]['text']);
|
||||
}
|
||||
}
|
||||
|
||||
return $shipping_data;
|
||||
});
|
||||
|
||||
// Add Rajaongkir destination field to OrderForm via hook system
|
||||
add_action('wp_enqueue_scripts', function() {
|
||||
if (!is_admin()) return;
|
||||
|
||||
wp_enqueue_script(
|
||||
'woonoow-rajaongkir-bridge',
|
||||
plugin_dir_url(__FILE__) . 'dist/bridge.js',
|
||||
['woonoow-admin'],
|
||||
'1.0.0',
|
||||
true
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
**Frontend (bridge.js):**
|
||||
|
||||
```typescript
|
||||
import { addonLoader, addFilter } from '@woonoow/hooks';
|
||||
|
||||
addonLoader.register({
|
||||
id: 'rajaongkir-bridge',
|
||||
name: 'Rajaongkir Bridge',
|
||||
version: '1.0.0',
|
||||
init: () => {
|
||||
// Add destination search field after shipping address
|
||||
addFilter('woonoow_order_form_after_shipping', (content, formData, setFormData) => {
|
||||
// Only for Indonesia
|
||||
if (formData.shipping?.country !== 'ID') return content;
|
||||
|
||||
return (
|
||||
<>
|
||||
{content}
|
||||
<div className="border rounded-lg p-4 mt-4">
|
||||
<h3 className="font-medium mb-3">📍 Shipping Destination</h3>
|
||||
<RajaongkirDestinationSearch
|
||||
value={formData.shipping?.destination_id}
|
||||
onChange={(id, label) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
shipping: {
|
||||
...formData.shipping,
|
||||
destination_id: id,
|
||||
destination_label: label,
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Option B: Code Snippet (No Plugin)
|
||||
|
||||
For users who don't want a separate plugin, provide a code snippet:
|
||||
|
||||
```php
|
||||
// Add to theme's functions.php or custom plugin
|
||||
|
||||
// Bridge Rajaongkir with WooNooW
|
||||
add_filter('woonoow_shipping_data', function($data) {
|
||||
if ($data['country'] === 'ID' && !empty($data['city'])) {
|
||||
// Auto-search and set destination
|
||||
$api = Cekongkir_API::get_instance();
|
||||
$results = $api->search_destination_api($data['city']);
|
||||
if (!empty($results[0])) {
|
||||
WC()->session->set('selected_destination_id', $results[0]['id']);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Proper Solution: Build WooNooW Addon
|
||||
|
||||
Instead of bridging Rajaongkir, build a proper WooNooW addon:
|
||||
|
||||
**WooNooW Indonesia Shipping Addon**
|
||||
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: WooNooW Indonesia Shipping
|
||||
* Description: Indonesia shipping with Rajaongkir API
|
||||
* Version: 1.0.0
|
||||
* Requires: WooNooW 1.0.0+
|
||||
*/
|
||||
|
||||
// Register addon
|
||||
add_filter('woonoow/addon_registry', function($addons) {
|
||||
$addons['indonesia-shipping'] = [
|
||||
'id' => 'indonesia-shipping',
|
||||
'name' => 'Indonesia Shipping',
|
||||
'version' => '1.0.0',
|
||||
'spa_bundle' => plugin_dir_url(__FILE__) . 'dist/addon.js',
|
||||
'dependencies' => ['woocommerce' => '8.0'],
|
||||
];
|
||||
return $addons;
|
||||
});
|
||||
|
||||
// Add API endpoints
|
||||
add_action('rest_api_init', function() {
|
||||
register_rest_route('woonoow/v1', '/indonesia/search-destination', [
|
||||
'methods' => 'GET',
|
||||
'callback' => function($req) {
|
||||
$query = $req->get_param('query');
|
||||
$api = new RajaongkirAPI(get_option('rajaongkir_api_key'));
|
||||
return $api->searchDestination($query);
|
||||
},
|
||||
]);
|
||||
|
||||
register_rest_route('woonoow/v1', '/indonesia/calculate-shipping', [
|
||||
'methods' => 'POST',
|
||||
'callback' => function($req) {
|
||||
$origin = $req->get_param('origin');
|
||||
$destination = $req->get_param('destination');
|
||||
$weight = $req->get_param('weight');
|
||||
|
||||
$api = new RajaongkirAPI(get_option('rajaongkir_api_key'));
|
||||
return $api->calculateShipping($origin, $destination, $weight);
|
||||
},
|
||||
]);
|
||||
});
|
||||
```
|
||||
|
||||
**Frontend:**
|
||||
|
||||
```typescript
|
||||
// dist/addon.ts
|
||||
|
||||
import { addonLoader, addFilter } from '@woonoow/hooks';
|
||||
import { DestinationSearch } from './components/DestinationSearch';
|
||||
|
||||
addonLoader.register({
|
||||
id: 'indonesia-shipping',
|
||||
name: 'Indonesia Shipping',
|
||||
version: '1.0.0',
|
||||
init: () => {
|
||||
// Add destination field
|
||||
addFilter('woonoow_order_form_after_shipping', (content, formData, setFormData) => {
|
||||
if (formData.shipping?.country !== 'ID') return content;
|
||||
|
||||
return (
|
||||
<>
|
||||
{content}
|
||||
<DestinationSearch
|
||||
value={formData.shipping?.destination_id}
|
||||
onChange={(id, label) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
shipping: { ...formData.shipping, destination_id: id, destination_label: label }
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
// Add validation
|
||||
addFilter('woonoow_order_form_validation', (errors, formData) => {
|
||||
if (formData.shipping?.country === 'ID' && !formData.shipping?.destination_id) {
|
||||
errors.destination = 'Please select shipping destination';
|
||||
}
|
||||
return errors;
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Comparison
|
||||
|
||||
### Bridge Snippet (Quick Fix)
|
||||
✅ Works immediately
|
||||
✅ No new plugin needed
|
||||
✅ Minimal code
|
||||
❌ Depends on Rajaongkir plugin
|
||||
❌ Limited features
|
||||
❌ Not ideal UX
|
||||
|
||||
### Proper WooNooW Addon (Best Practice)
|
||||
✅ Native WooNooW integration
|
||||
✅ Better UX
|
||||
✅ More features
|
||||
✅ Independent of Rajaongkir plugin
|
||||
✅ Can use any shipping API
|
||||
❌ More development effort
|
||||
❌ Separate plugin to maintain
|
||||
|
||||
---
|
||||
|
||||
## Recommendation
|
||||
|
||||
**For WooNooW Core:**
|
||||
- ❌ Don't integrate Rajaongkir
|
||||
- ✅ Provide hook system
|
||||
- ✅ Document bridge pattern
|
||||
- ✅ Provide code snippets
|
||||
|
||||
**For Users:**
|
||||
- **Quick fix:** Use bridge snippet
|
||||
- **Best practice:** Build proper addon or use community addon
|
||||
|
||||
**For Community:**
|
||||
- Build "WooNooW Indonesia Shipping" addon
|
||||
- Publish on WordPress.org
|
||||
- Support Rajaongkir, Biteship, and other Indonesian shipping APIs
|
||||
|
||||
---
|
||||
|
||||
## Hook Points Needed in WooNooW Core
|
||||
|
||||
To support addons like this, WooNooW core should provide:
|
||||
|
||||
```php
|
||||
// Before shipping calculation
|
||||
apply_filters('woonoow_before_shipping_calculate', $shipping_data);
|
||||
|
||||
// After shipping calculation
|
||||
apply_filters('woonoow_after_shipping_calculate', $rates, $shipping_data);
|
||||
|
||||
// Modify shipping data
|
||||
apply_filters('woonoow_shipping_data', $data);
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Frontend hooks
|
||||
'woonoow_order_form_after_shipping'
|
||||
'woonoow_order_form_shipping_fields'
|
||||
'woonoow_order_form_validation'
|
||||
'woonoow_order_form_submit'
|
||||
```
|
||||
|
||||
**These hooks already exist in our addon system!**
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
**WooNooW Core = Zero addon dependencies**
|
||||
|
||||
Instead of integrating Rajaongkir into core:
|
||||
1. Provide hook system ✅ (Already done)
|
||||
2. Document bridge pattern ✅ (This document)
|
||||
3. Encourage community addons ✅
|
||||
|
||||
This keeps WooNooW core:
|
||||
- Clean
|
||||
- Maintainable
|
||||
- Flexible
|
||||
- Extensible
|
||||
|
||||
Users can choose:
|
||||
- Bridge snippet (quick fix)
|
||||
- Proper addon (best practice)
|
||||
- Build their own
|
||||
|
||||
**No bloat in core!**
|
||||
Reference in New Issue
Block a user