docs: add multicurrency implementation audit
- Comprehensive trace of multicurrency functionality - Identified gaps: frontend currency selector, ExchangeRateAPI implementation, conversion logic - Documented defects: hardcoded IDR, empty API class, missing Bank Transfer currency column - Provided implementation order and testing checklist
This commit is contained in:
343
MULTICURRENCY_AUDIT.md
Normal file
343
MULTICURRENCY_AUDIT.md
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
# Formipay — Multicurrency Implementation Audit
|
||||||
|
|
||||||
|
**Date:** April 18, 2026
|
||||||
|
**Scope:** Complete trace of multicurrency functionality
|
||||||
|
**Purpose:** Identify gaps, defects, and opportunities before Phase 4 implementation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
The multicurrency system has a **solid foundation** in the admin (settings UI, data structures, per-currency pricing) but is **incomplete for end-users**. The framework exists but critical pieces are missing: frontend currency selection, exchange rate API integration, and actual conversion logic.
|
||||||
|
|
||||||
|
**Status:** 🟡 Partial — Works in admin, broken on frontend
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. What Works ✅
|
||||||
|
|
||||||
|
### 1.1 Admin Settings & Configuration
|
||||||
|
**Location:** `includes/Settings.php` lines 56-133
|
||||||
|
|
||||||
|
| Feature | Status | Details |
|
||||||
|
|---------|--------|---------|
|
||||||
|
| Enable/disable toggle | ✅ | `enable_multicurrency` checkbox |
|
||||||
|
| Currency management | ✅ | `multicurrencies` repeater with full config |
|
||||||
|
| Default currency | ✅ | `default_currency` setting |
|
||||||
|
| Per-currency decimals | ✅ | Custom decimal_digits, decimal_symbol, thousand_separator |
|
||||||
|
| Exchange rate fields | ✅ | Manual rate input (API integration non-functional) |
|
||||||
|
| Gateway association | ✅ | Link currencies to payment gateways |
|
||||||
|
|
||||||
|
**Data Structure:** Currencies stored as `code:::name:::symbol` (e.g., `USD:::United States Dollar:::$`)
|
||||||
|
|
||||||
|
### 1.2 Currency Data Source
|
||||||
|
**Location:** `admin/assets/json/currencies.json`
|
||||||
|
|
||||||
|
- **196 currencies** available
|
||||||
|
- Loaded via `formipay_currency_array()`
|
||||||
|
- Cached via static variable (F1.13 optimization)
|
||||||
|
- Includes code, name, symbol, flag
|
||||||
|
|
||||||
|
### 1.3 Product Pricing Per Currency
|
||||||
|
**Location:** `includes/Product.php` lines 386-432
|
||||||
|
|
||||||
|
Products can have different prices for each currency:
|
||||||
|
- Static items: `amount_{currency_code}` field
|
||||||
|
- Default currency price: `setting_product_price_regular_{code}`
|
||||||
|
- Sale price: `setting_product_price_sale_{code}`
|
||||||
|
|
||||||
|
### 1.4 Price Formatting
|
||||||
|
**Location:** `admin/functions.php` lines 179-200
|
||||||
|
|
||||||
|
`formipay_price_format()` properly handles:
|
||||||
|
- Product-specific currency metadata
|
||||||
|
- Custom decimal digits, symbols, separators
|
||||||
|
- Format: `{symbol} {formatted_number}`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. What's Broken/Incomplete ❌
|
||||||
|
|
||||||
|
### 2.1 Frontend Currency Selection — **MISSING**
|
||||||
|
|
||||||
|
**Problem:** Users have NO way to select currency on forms.
|
||||||
|
|
||||||
|
**What exists:**
|
||||||
|
- `formipay.currency_code` hardcoded to `'IDR'` in `form-action.js:224`
|
||||||
|
- Currency data passed to admin via `wp_localize_script()` (Form.php:1289-1292)
|
||||||
|
- No UI element rendered on frontend forms
|
||||||
|
|
||||||
|
**Impact:** Multicurrency is admin-only; frontend users always see default currency prices.
|
||||||
|
|
||||||
|
### 2.2 Exchange Rate API — **EMPTY CLASS**
|
||||||
|
|
||||||
|
**Location:** `includes/Integration/ExchangeRateAPI.php`
|
||||||
|
|
||||||
|
**Status:** Completely empty class (8 lines total):
|
||||||
|
```php
|
||||||
|
class ExchangeRateAPI extends Payment {
|
||||||
|
use SingletonTrait;
|
||||||
|
protected function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
// Empty - no implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**What's missing:**
|
||||||
|
- No API integration (ExchangeRate-API.io, Fixer.io, etc.)
|
||||||
|
- No rate fetching logic
|
||||||
|
- No caching mechanism
|
||||||
|
- No error handling
|
||||||
|
- Settings UI exists but non-functional
|
||||||
|
|
||||||
|
### 2.3 Currency Conversion Logic — **NOT IMPLEMENTED**
|
||||||
|
|
||||||
|
**Problem:** No actual conversion calculations anywhere.
|
||||||
|
|
||||||
|
**What exists:**
|
||||||
|
- Framework for per-currency prices in products
|
||||||
|
- Manual exchange rate fields in settings (unused)
|
||||||
|
- `formipay_price_format()` displays but doesn't convert
|
||||||
|
|
||||||
|
**Missing:**
|
||||||
|
- Conversion calculation functions
|
||||||
|
- Dynamic price switching based on user selection
|
||||||
|
- Conversion indicators on frontend
|
||||||
|
|
||||||
|
### 2.4 Bank Transfer — Missing Currency Tracking
|
||||||
|
|
||||||
|
**Location:** `includes/Payment/BankTransfer.php` create_db()
|
||||||
|
|
||||||
|
**Problem:** Bank transfer transaction table has NO currency column:
|
||||||
|
```php
|
||||||
|
CREATE TABLE `formipay_bank_transfer_trx` (
|
||||||
|
...
|
||||||
|
`total` float(10, 2) DEFAULT 0,
|
||||||
|
-- Missing: `currency_code` text
|
||||||
|
...
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact:** Can't determine which currency was used for bank transfer payments.
|
||||||
|
|
||||||
|
### 2.5 Order Storage — Inconsistent
|
||||||
|
|
||||||
|
| Gateway | Currency Stored | Location |
|
||||||
|
|---------|-----------------|----------|
|
||||||
|
| PayPal | ✅ `currency_code` | `Paypal.php:84` |
|
||||||
|
| Bank Transfer | ❌ Missing | — |
|
||||||
|
| General | ⚠️ `$this->currency` | `Order.php:95` (not in DB schema) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Gaps & Missing Features
|
||||||
|
|
||||||
|
### 3.1 Critical Gaps
|
||||||
|
|
||||||
|
| # | Gap | Impact | Priority |
|
||||||
|
|---|------|-------|----------|
|
||||||
|
| 1 | Frontend currency selector | Users can't choose currency | 🔴 High |
|
||||||
|
| 2 | ExchangeRateAPI implementation | No live rates | 🔴 High |
|
||||||
|
| 3 | Conversion calculation logic | Prices don't convert | 🔴 High |
|
||||||
|
| 4 | Bank Transfer currency tracking | Data loss | 🟡 Medium |
|
||||||
|
| 5 | Dynamic price display on frontend | Always shows default currency | 🔴 High |
|
||||||
|
|
||||||
|
### 3.2 Data Flow Gaps
|
||||||
|
|
||||||
|
```
|
||||||
|
Expected Flow:
|
||||||
|
User selects currency → Fetch exchange rate → Convert prices → Display converted prices
|
||||||
|
|
||||||
|
Actual Flow:
|
||||||
|
User selects currency → [NOT IMPLEMENTED] → [NOT IMPLEMENTED] → Shows default currency only
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Missing Validation
|
||||||
|
|
||||||
|
- No currency validation on form submission
|
||||||
|
- No check if selected currency is in allowed currencies
|
||||||
|
- No validation that required currencies have prices set
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Defects & Bugs
|
||||||
|
|
||||||
|
### 4.1 Critical Bugs
|
||||||
|
|
||||||
|
| # | Bug | Location | Impact |
|
||||||
|
|---|-----|----------|--------|
|
||||||
|
| 1 | `formipay.currency_code` hardcoded to 'IDR' | `public/assets/js/form-action.js:224` | Frontend always uses IDR |
|
||||||
|
| 2 | ExchangeRateAPI class is empty | `includes/Integration/ExchangeRateAPI.php` | Settings UI does nothing |
|
||||||
|
| 3 | Bank transfer has no currency column | `includes/Payment/BankTransfer.php:40-50` | Lost currency data |
|
||||||
|
|
||||||
|
### 4.2 Minor Issues
|
||||||
|
|
||||||
|
| # | Issue | Location |
|
||||||
|
|---|-------|----------|
|
||||||
|
| 1 | Fallback pattern conflicts | Multiple files |
|
||||||
|
| 2 | No currency flag in frontend | Render.php |
|
||||||
|
| 3 | Mixed code/symbol usage | Inconsistent display |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Architecture & Data Flow
|
||||||
|
|
||||||
|
### 5.1 Current Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ Admin Settings (WPCFTO) │
|
||||||
|
│ - enable_multicurrency toggle │
|
||||||
|
│ - multicurrencies[] repeater (currencies + rates) │
|
||||||
|
│ - default_currency │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ Product Editor (Vue) │
|
||||||
|
│ - Per-currency pricing fields │
|
||||||
|
│ - Variation pricing per currency │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌<EFBFBD>─────────────────────────────────────────────────────┐
|
||||||
|
│ Form Rendering (PHP SSR) │
|
||||||
|
│ - formipay.currency_code = 'IDR' (HARDCODED ❌) │
|
||||||
|
│ - formipay_price_format($amount, $post_id) │
|
||||||
|
│ - Shows: {symbol} {formatted_amount} │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ Order Storage │
|
||||||
|
│ - PayPal: has currency_code ✅ │
|
||||||
|
│ - Bank Transfer: no currency ❌ │
|
||||||
|
│ - General: $this->currency (not in DB) ⚠️ │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Data Structures
|
||||||
|
|
||||||
|
**Currency Format:** `code:::name:::symbol`
|
||||||
|
- Example: `USD:::United States Dollar:::$`
|
||||||
|
- Example with symbol: `IDR:::Indonesian Rupiah:::Rp`
|
||||||
|
|
||||||
|
**Product Price Storage:**
|
||||||
|
```php
|
||||||
|
// Per currency (static items)
|
||||||
|
$static_item['amount_USD'] = '29.99';
|
||||||
|
$static_item['amount_IDR'] = '450000';
|
||||||
|
|
||||||
|
// Default currency
|
||||||
|
get_post_meta($post_id, 'product_currency'); // "USD:::..."
|
||||||
|
get_post_meta($post_id, 'product_currency_decimal_digits'); // 2
|
||||||
|
```
|
||||||
|
|
||||||
|
**Order Currency Storage:**
|
||||||
|
```php
|
||||||
|
// PayPal (correct)
|
||||||
|
$currency_code = $currency_parts[0]; // 'USD'
|
||||||
|
|
||||||
|
// Bank Transfer (missing)
|
||||||
|
// No currency stored ❌
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Opportunities for Improvement
|
||||||
|
|
||||||
|
### 6.1 High Priority (Phase 4)
|
||||||
|
|
||||||
|
| # | Opportunity | Benefit | Effort |
|
||||||
|
|---|------------|---------|--------|
|
||||||
|
| 1 | Frontend currency dropdown selector | Users can finally use multicurrency | Medium |
|
||||||
|
| 2 | Complete ExchangeRateAPI with live rates | Accurate pricing, manual entry backup | Medium |
|
||||||
|
| 3 | Currency conversion calculation layer | Dynamic pricing, better UX | Medium |
|
||||||
|
| 4 | Add currency column to Bank Transfer table | Data completeness | Low |
|
||||||
|
| 5 | Real-time price updates on currency change | Better UX, clearer pricing | Medium |
|
||||||
|
|
||||||
|
### 6.2 Medium Priority
|
||||||
|
|
||||||
|
| # | Opportunity | Benefit | Effort |
|
||||||
|
|---|------------|---------|--------|
|
||||||
|
| 1 | Currency flag icons in frontend | Visual clarity, UX improvement | Low |
|
||||||
|
| 2 | Currency validation on form submit | Data integrity | Low |
|
||||||
|
| 3 | Conversion rate history/audit trail | Accounting, debugging | Medium |
|
||||||
|
| 4 | Multi-currency reports in dashboard | Business insights | Medium |
|
||||||
|
| 5 | Auto-fetch rates on schedule | Always-current rates without manual entry | Low |
|
||||||
|
|
||||||
|
### 6.3 Nice-to-Have
|
||||||
|
|
||||||
|
| # | Opportunity | Benefit |
|
||||||
|
|---|------------|---------|
|
||||||
|
| 1 | Display original + converted prices (e.g., "$29.99 (~Rp 450.000)") | Transparency |
|
||||||
|
| 2 | Currency switcher widget (cookies remember preference) | UX convenience |
|
||||||
|
| 3 | GEO IP detection to auto-select currency | Personalization |
|
||||||
|
| 4 | Admin-side currency conversion calculator | Admin convenience |
|
||||||
|
| 5 | Support for 3+ decimal currencies (e.g., cryptocurrencies) | Future-proofing |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Recommended Implementation Order
|
||||||
|
|
||||||
|
### Phase 4A — Core Multicurrency (Weeks 11-12)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Frontend currency selector dropdown
|
||||||
|
2. ExchangeRateAPI implementation (one API provider)
|
||||||
|
3. Conversion calculation functions
|
||||||
|
4. Fix Bank Transfer currency column
|
||||||
|
5. Dynamic price display on forms
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 4B — Enhanced Features (Weeks 15-16)
|
||||||
|
|
||||||
|
```
|
||||||
|
6. Currency validation
|
||||||
|
7. Conversion rate history
|
||||||
|
8. Multi-currency dashboard reports
|
||||||
|
9. GEO IP auto-detection
|
||||||
|
10. Admin conversion calculator
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Code Locations Reference
|
||||||
|
|
||||||
|
| File | Lines | Purpose |
|
||||||
|
|------|-------|---------|
|
||||||
|
| `includes/Settings.php` | 56-133 | Multicurrency settings UI |
|
||||||
|
| `admin/functions.php` | 28-36, 47-81, 179-200, 202-218 | Currency utility functions |
|
||||||
|
| `admin/assets/json/currencies.json` | — | Currency data source (196 currencies) |
|
||||||
|
| `public/assets/js/form-action.js` | 224 | Currency code (hardcoded bug) |
|
||||||
|
| `includes/Product.php` | 386-432 | Product pricing per currency |
|
||||||
|
| `includes/Order.php` | 95 | Order currency property |
|
||||||
|
| `includes/Integration/Paypal.php` | 75, 84 | PayPal currency handling |
|
||||||
|
| `includes/Payment/BankTransfer.php` | 40-50 | Bank transfer schema (missing currency) |
|
||||||
|
| `includes/Integration/ExchangeRateAPI.php` | all | Empty class (needs implementation) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Testing Checklist
|
||||||
|
|
||||||
|
When implementing multicurrency features:
|
||||||
|
|
||||||
|
- [ ] Enable multicurrency in settings
|
||||||
|
- [ ] Add 3+ currencies
|
||||||
|
- [ ] Set prices for default currency
|
||||||
|
- [ ] Set prices for additional currencies
|
||||||
|
- [ ] Submit form with each currency selected
|
||||||
|
- [ ] Verify order currency stored correctly
|
||||||
|
- [ ] Verify payment gateway receives correct currency
|
||||||
|
- [ ] Test ExchangeRateAPI rate fetching
|
||||||
|
- [ ] Test manual exchange rate override
|
||||||
|
- [ ] Test price conversion calculations
|
||||||
|
- [ ] Test currency formatting display
|
||||||
|
- [ ] Test Bank Transfer with currency column
|
||||||
|
- [ ] Test frontend currency dropdown
|
||||||
|
- [ ] Test GEO IP auto-detection (if implemented)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*End of Multicurrency Audit.*
|
||||||
Reference in New Issue
Block a user