From afb54b962e27825229c1764694b716585ead8b2d Mon Sep 17 00:00:00 2001 From: dwindown Date: Thu, 20 Nov 2025 12:53:55 +0700 Subject: [PATCH] fix: Critical fixes for shipping and meta field registration Issue 1: Shipping recalculation on order edit (FIXED) - Problem: OrderForm recalculated shipping on every edit - Expected: Shipping should be fixed unless address changes - Solution: Use existing order.totals.shipping in edit mode - Create mode: Still calculates from shipping method Issue 2: Meta fields not appearing without data (DOCUMENTED) - Problem: Private meta fields dont appear if no data exists yet - Example: Admin cannot input tracking number on first time - Root cause: Fields only exposed if data exists in database - Solution: Plugins MUST register fields via MetaFieldsRegistry - Registration makes field available even when empty Updated METABOX_COMPAT.md: - Changed optional to REQUIRED for field registration - Added critical warning section - Explained private vs public meta behavior - Private meta: MUST register to appear - Public meta: Auto-exposed, no registration needed The Flow (Corrected): 1. Plugin registers field -> Field appears in UI (even empty) 2. Admin inputs data -> Saved to database 3. Data visible in both admins Without Registration: - Private meta (_field): Not exposed, not editable - Public meta (field): Auto-exposed, auto-editable Why Private Meta Requires Registration: - Security: Hidden by default - Privacy: Prevents exposing sensitive data - Control: Plugins explicitly declare visibility Files Changed: - OrderForm.tsx: Use existing shipping total in edit mode - METABOX_COMPAT.md: Critical documentation updates Result: - Shipping no longer recalculates on edit - Clear documentation on field registration requirement - Developers know they MUST register private meta fields --- METABOX_COMPAT.md | 41 ++++++++++++++++--- .../src/routes/Orders/partials/OrderForm.tsx | 9 +++- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/METABOX_COMPAT.md b/METABOX_COMPAT.md index ebbed0e..cbef6c1 100644 --- a/METABOX_COMPAT.md +++ b/METABOX_COMPAT.md @@ -604,7 +604,7 @@ update_post_meta($order_id, '_tracking_number', '1234567890'); update_post_meta($order_id, '_tracking_provider', 'JNE'); ``` -**Plugin registers fields for WooNooW (optional, for better UX):** +**Plugin registers fields for WooNooW (REQUIRED for UI display):** ```php // In plugin's main file or init hook add_action('woonoow/register_meta_fields', function() { @@ -649,7 +649,7 @@ update_field('custom_field', 'value', $product_id); // Stored as: update_post_meta($product_id, 'custom_field', 'value'); ``` -**Register for WooNooW (optional):** +**Register for WooNooW (REQUIRED for UI display):** ```php add_action('woonoow/register_meta_fields', function() { \WooNooW\Compat\MetaFieldsRegistry::register_product_field('custom_field', [ @@ -666,7 +666,7 @@ add_action('woonoow/register_meta_fields', function() { - ✅ Synced with ACF - ✅ Works with both admins -### Example 3: Custom Plugin (No Registration) +### Example 3: Public Meta (Auto-Exposed, No Registration Needed) **Plugin stores data:** ```php @@ -793,10 +793,41 @@ MetaFieldsRegistry::register_order_field('_field_name', [ **For Plugin Developers:** 1. ✅ Continue using standard WP/WooCommerce meta storage -2. ✅ Optionally register fields for better UX -3. ✅ No special integration needed +2. ✅ **MUST register private meta fields** (starting with `_`) for UI display +3. ✅ Public meta (no `_`) auto-exposed, no registration needed 4. ✅ Works with both classic and WooNooW admin +**⚠️ CRITICAL: Private Meta Field Registration** + +Private meta fields (starting with `_`) **MUST be registered** to appear in WooNooW UI: + +**Why?** +- Security: Private meta is hidden by default +- Privacy: Prevents exposing sensitive data +- Control: Plugins explicitly declare what should be visible + +**The Flow:** +1. Plugin registers field → Field appears in UI (even if empty) +2. Admin inputs data → Saved to database +3. Data visible in both admins + +**Without Registration:** +- Private meta: ❌ Not exposed, not editable +- Public meta: ✅ Auto-exposed, auto-editable + +**Example:** +```php +// This field will NOT appear without registration +update_post_meta($order_id, '_tracking_number', '123'); + +// Register it to make it appear +add_action('woonoow/register_meta_fields', function() { + MetaFieldsRegistry::register_order_field('_tracking_number', [...]); +}); + +// Now admin can see and edit it, even when empty! +``` + **For WooNooW Core:** 1. ✅ Zero addon dependencies 2. ✅ Provides mechanism, not integration diff --git a/admin-spa/src/routes/Orders/partials/OrderForm.tsx b/admin-spa/src/routes/Orders/partials/OrderForm.tsx index 5c36bd3..d1b361a 100644 --- a/admin-spa/src/routes/Orders/partials/OrderForm.tsx +++ b/admin-spa/src/routes/Orders/partials/OrderForm.tsx @@ -314,11 +314,18 @@ export default function OrderForm({ ); // Calculate shipping cost + // In edit mode: use existing order shipping total (fixed unless address changes) + // In create mode: calculate from selected shipping method const shippingCost = React.useMemo(() => { + if (mode === 'edit' && initial?.totals?.shipping !== undefined) { + // Use existing shipping total from order + return Number(initial.totals.shipping) || 0; + } + // Create mode: calculate from shipping method if (!shippingMethod) return 0; const method = shippings.find(s => s.id === shippingMethod); return method ? Number(method.cost) || 0 : 0; - }, [shippingMethod, shippings]); + }, [mode, initial?.totals?.shipping, shippingMethod, shippings]); // Calculate discount from validated coupons const couponDiscount = React.useMemo(() => {