fix(currency): update fields
This commit is contained in:
@@ -22,7 +22,7 @@ const Sidebar = ({ isOpen, onToggle }) => {
|
||||
{ name: 'Currency', href: '/currency', icon: DollarSign },
|
||||
{ name: 'Location', href: '/location', icon: MapPin },
|
||||
{ name: 'Issuer', href: '/issuer', icon: Building2 },
|
||||
// { name: 'Settings', href: '/settings', icon: Settings },
|
||||
{ name: 'Settings', href: '/settings', icon: Settings },
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useMemo, useState, useCallback } from 'react';
|
||||
import DataTable from '../components/DataTable';
|
||||
import { currencyAPI } from '../services/api';
|
||||
import { Plus, Search, Power, Wrench, Settings, DollarSign, Shield } from 'lucide-react';
|
||||
import { Plus, Search, Power, Wrench, Settings, DollarSign, Shield, AlertTriangle, CheckCircle2 } from 'lucide-react';
|
||||
import { ToastContainer, toast } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import { getErrorMessage, getSuccessMessage } from '../utils/errorHandler';
|
||||
@@ -49,12 +49,10 @@ const Currency = () => {
|
||||
voucherLimits: { min: null, max: null },
|
||||
});
|
||||
const [feesForm, setFeesForm] = useState({
|
||||
depositFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
cashOutFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
transferFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
exchangeFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
generateVoucherFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
expireVoucherSystemFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
depositLimits: { min: null, max: null },
|
||||
cashOutLimits: { min: null, max: null },
|
||||
transferLimits: { min: null, max: null },
|
||||
voucherLimits: { min: null, max: null },
|
||||
});
|
||||
|
||||
// دریافت ارزها
|
||||
@@ -96,7 +94,7 @@ const Currency = () => {
|
||||
}
|
||||
|
||||
// بررسی وجود ارز در لیست (برای جلوگیری از درخواست غیرضروری)
|
||||
const exists = currencies.some(c => c.currencyCode?.code?.toUpperCase() === code);
|
||||
const exists = currencies.some(c => c.currencyCode?.toUpperCase() === code);
|
||||
if (exists) {
|
||||
toast.error(`Currency ${code} already exists`);
|
||||
return;
|
||||
@@ -127,8 +125,12 @@ const Currency = () => {
|
||||
|
||||
// --- فعال/غیرفعال کردن Maintenance ---
|
||||
const onEnableMaintenance = async (currencyCode, message = '') => {
|
||||
if (!message || message.trim() === '') {
|
||||
toast.error('Maintenance message is required');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = await currencyAPI.enableMaintenance(currencyCode, message || null);
|
||||
const result = await currencyAPI.enableMaintenance(currencyCode, message);
|
||||
await fetchCurrencies();
|
||||
setMaintenanceModal(null);
|
||||
setMaintenanceMessage('');
|
||||
@@ -177,11 +179,25 @@ const Currency = () => {
|
||||
// --- بهروزرسانی Fees ---
|
||||
const onUpdateFees = async (currencyCode, fees) => {
|
||||
try {
|
||||
const result = await currencyAPI.updateFees(currencyCode, fees);
|
||||
// API PUT expects: depositFee, cashOutFee, transferFee, exchangeFee, generateVoucherByAgentFee, generateVoucherByUserFee, expireVoucherSystemFee
|
||||
// But GET returns: depositLimits, cashOutLimits, transferLimits, voucherLimits
|
||||
// Map our structure to API expected structure
|
||||
const payload = {
|
||||
depositFee: fees.depositLimits || { min: null, max: null },
|
||||
cashOutFee: fees.cashOutLimits || { min: null, max: null },
|
||||
transferFee: fees.transferLimits || { min: null, max: null },
|
||||
exchangeFee: { min: null, max: null }, // Required by API
|
||||
generateVoucherByAgentFee: fees.voucherLimits || { min: null, max: null }, // Map voucherLimits to generateVoucherByAgentFee
|
||||
generateVoucherByUserFee: { min: null, max: null }, // Required by API
|
||||
expireVoucherSystemFee: { min: null, max: null }, // Required by API
|
||||
};
|
||||
console.log('🔵 Currency - onUpdateFees payload:', payload);
|
||||
const result = await currencyAPI.updateFees(currencyCode, payload);
|
||||
await fetchCurrencies();
|
||||
setFeesModal(null);
|
||||
toast.success(getSuccessMessage(result) || 'Fees updated successfully');
|
||||
} catch (err) {
|
||||
console.error('🔴 Currency - onUpdateFees error:', err);
|
||||
toast.error(getErrorMessage(err));
|
||||
}
|
||||
};
|
||||
@@ -190,19 +206,11 @@ const Currency = () => {
|
||||
const columns = useMemo(() => [
|
||||
{
|
||||
key: 'currencyCode',
|
||||
header: 'Currency',
|
||||
header: 'Currency Code',
|
||||
render: (val) => (
|
||||
<div>
|
||||
<div className="font-semibold">{val?.code || '—'}</div>
|
||||
<div className="text-xs text-gray-500">{val?.name || ''}</div>
|
||||
</div>
|
||||
<span className="font-semibold font-mono">{val || '—'}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'currencyCode',
|
||||
header: 'Symbol',
|
||||
render: (val) => <span className="font-mono">{val?.symbol || '—'}</span>,
|
||||
},
|
||||
{
|
||||
key: 'isActive',
|
||||
header: 'Active',
|
||||
@@ -216,8 +224,18 @@ const Currency = () => {
|
||||
key: 'isUnderMaintenance',
|
||||
header: 'Maintenance',
|
||||
render: (val, row) => (
|
||||
<span className={`px-2 py-1 rounded text-xs ${val ? 'bg-yellow-100 text-yellow-800' : 'bg-gray-100 text-gray-800'}`}>
|
||||
{val ? '⚠️ Yes' : '✓ No'}
|
||||
<span className={`inline-flex items-center gap-1 px-2 py-1 rounded text-xs ${val ? 'bg-yellow-100 text-yellow-800' : 'bg-gray-100 text-gray-800'}`}>
|
||||
{val ? (
|
||||
<>
|
||||
<AlertTriangle className="h-3 w-3" />
|
||||
<span>Yes</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CheckCircle2 className="h-3 w-3" />
|
||||
<span>No</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
@@ -234,7 +252,7 @@ const Currency = () => {
|
||||
key: 'actions',
|
||||
header: 'Actions',
|
||||
render: (_val, row) => {
|
||||
const code = row.currencyCode?.code;
|
||||
const code = row.currencyCode;
|
||||
if (!code) return '—';
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
@@ -290,16 +308,32 @@ const Currency = () => {
|
||||
<Settings className="h-3 w-3 mr-1" /> Limits
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
onClick={async () => {
|
||||
setFeesModal(row);
|
||||
setFeesForm(row.fees || {
|
||||
depositFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
cashOutFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
transferFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
exchangeFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
generateVoucherFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
expireVoucherSystemFee: { percent: 0, fixed: 0, minAmount: null, maxAmount: null },
|
||||
});
|
||||
try {
|
||||
// Fetch fees data from API
|
||||
const feesData = await currencyAPI.getFees(row.currencyCode);
|
||||
// API returns: depositLimits, cashOutLimits, transferLimits, voucherLimits
|
||||
const allowedFields = ['depositLimits', 'cashOutLimits', 'transferLimits', 'voucherLimits'];
|
||||
const filteredFees = allowedFields.reduce((acc, key) => {
|
||||
if (feesData && feesData[key]) {
|
||||
acc[key] = feesData[key];
|
||||
} else {
|
||||
acc[key] = { min: null, max: null };
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
setFeesForm(filteredFees);
|
||||
} catch (err) {
|
||||
console.error('Error fetching fees:', err);
|
||||
// Fallback to default structure
|
||||
setFeesForm({
|
||||
depositLimits: { min: null, max: null },
|
||||
cashOutLimits: { min: null, max: null },
|
||||
transferLimits: { min: null, max: null },
|
||||
voucherLimits: { min: null, max: null },
|
||||
});
|
||||
}
|
||||
}}
|
||||
className="inline-flex items-center px-2 py-1 text-xs rounded-md bg-indigo-100 text-indigo-700 hover:opacity-90"
|
||||
title="Fees"
|
||||
@@ -352,7 +386,7 @@ const Currency = () => {
|
||||
// --- مودال Maintenance ---
|
||||
const renderMaintenanceModal = () => {
|
||||
if (!maintenanceModal) return null;
|
||||
const code = maintenanceModal.currencyCode?.code;
|
||||
const code = maintenanceModal.currencyCode;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -367,19 +401,23 @@ const Currency = () => {
|
||||
</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">Maintenance Message (optional)</label>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Maintenance Message <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<textarea
|
||||
value={maintenanceMessage}
|
||||
onChange={(e) => setMaintenanceMessage(e.target.value)}
|
||||
className="w-full p-2 border rounded-lg"
|
||||
rows={3}
|
||||
placeholder="Enter maintenance message..."
|
||||
placeholder="Enter maintenance message (required)..."
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={() => onEnableMaintenance(code, maintenanceMessage)}
|
||||
className="flex-1 px-4 py-2 bg-yellow-500 text-white rounded-lg hover:opacity-90"
|
||||
disabled={!maintenanceMessage || maintenanceMessage.trim() === ''}
|
||||
className="flex-1 px-4 py-2 bg-yellow-500 text-white rounded-lg hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Enable Maintenance
|
||||
</button>
|
||||
@@ -404,7 +442,7 @@ const Currency = () => {
|
||||
// --- مودال Permissions ---
|
||||
const renderPermissionsModal = () => {
|
||||
if (!permissionsModal) return null;
|
||||
const code = permissionsModal.currencyCode?.code;
|
||||
const code = permissionsModal.currencyCode;
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
@@ -443,7 +481,7 @@ const Currency = () => {
|
||||
// --- مودال Limits ---
|
||||
const renderLimitsModal = () => {
|
||||
if (!limitsModal) return null;
|
||||
const code = limitsModal.currencyCode?.code;
|
||||
const code = limitsModal.currencyCode;
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
@@ -508,19 +546,19 @@ const Currency = () => {
|
||||
// --- مودال Fees ---
|
||||
const renderFeesModal = () => {
|
||||
if (!feesModal) return null;
|
||||
const code = feesModal.currencyCode?.code;
|
||||
const code = feesModal.currencyCode;
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
onUpdateFees(code, feesForm);
|
||||
};
|
||||
|
||||
const updateFee = (category, field, value) => {
|
||||
const updateFee = (category, type, value) => {
|
||||
setFeesForm({
|
||||
...feesForm,
|
||||
[category]: {
|
||||
...feesForm[category],
|
||||
[field]: value === '' ? null : parseFloat(value) || null,
|
||||
[type]: value === '' ? null : parseFloat(value) || null,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -529,60 +567,38 @@ const Currency = () => {
|
||||
<>
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 z-40" onClick={() => setFeesModal(null)} />
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
|
||||
<div className="w-full max-w-3xl card p-6 relative bg-white rounded-2xl shadow-lg max-h-[90vh] overflow-y-auto">
|
||||
<div className="w-full max-w-2xl card p-6 relative bg-white rounded-2xl shadow-lg max-h-[90vh] overflow-y-auto">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Fees: {code}</h3>
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{Object.keys(feesForm).map((category) => (
|
||||
{Object.keys(feesForm).map((category) => {
|
||||
return (
|
||||
<div key={category} className="border rounded-lg p-3">
|
||||
<h4 className="font-medium mb-2">{category.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())}</h4>
|
||||
<h4 className="font-medium mb-2">{category}</h4>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<label className="block text-xs text-gray-600 mb-1">Percent</label>
|
||||
<label className="block text-xs text-gray-600 mb-1">Min</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.01"
|
||||
value={feesForm[category].percent ?? ''}
|
||||
onChange={(e) => updateFee(category, 'percent', e.target.value)}
|
||||
value={feesForm[category].min ?? ''}
|
||||
onChange={(e) => updateFee(category, 'min', e.target.value)}
|
||||
className="w-full p-2 border rounded"
|
||||
placeholder="Percent"
|
||||
placeholder="Min"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs text-gray-600 mb-1">Fixed</label>
|
||||
<label className="block text-xs text-gray-600 mb-1">Max</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.01"
|
||||
value={feesForm[category].fixed ?? ''}
|
||||
onChange={(e) => updateFee(category, 'fixed', e.target.value)}
|
||||
value={feesForm[category].max ?? ''}
|
||||
onChange={(e) => updateFee(category, 'max', e.target.value)}
|
||||
className="w-full p-2 border rounded"
|
||||
placeholder="Fixed"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs text-gray-600 mb-1">Min Amount</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.01"
|
||||
value={feesForm[category].minAmount ?? ''}
|
||||
onChange={(e) => updateFee(category, 'minAmount', e.target.value)}
|
||||
className="w-full p-2 border rounded"
|
||||
placeholder="Min Amount"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs text-gray-600 mb-1">Max Amount</label>
|
||||
<input
|
||||
type="number"
|
||||
step="0.01"
|
||||
value={feesForm[category].maxAmount ?? ''}
|
||||
onChange={(e) => updateFee(category, 'maxAmount', e.target.value)}
|
||||
className="w-full p-2 border rounded"
|
||||
placeholder="Max Amount"
|
||||
placeholder="Max"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
<div className="flex justify-end gap-x-2 mt-4">
|
||||
<button type="button" onClick={() => setFeesModal(null)} className="px-4 py-2 border rounded-lg">Cancel</button>
|
||||
<button type="submit" className="btn-primary px-4 py-2 rounded-lg">Save</button>
|
||||
@@ -640,9 +656,8 @@ const Currency = () => {
|
||||
data={currencies.filter(c => {
|
||||
if (!filter) return true;
|
||||
const search = filter.toLowerCase();
|
||||
const code = c.currencyCode?.code?.toLowerCase() || '';
|
||||
const name = c.currencyCode?.name?.toLowerCase() || '';
|
||||
return code.includes(search) || name.includes(search);
|
||||
const code = c.currencyCode?.toLowerCase() || '';
|
||||
return code.includes(search);
|
||||
})}
|
||||
columns={columns}
|
||||
searchable={false}
|
||||
|
||||
@@ -6,52 +6,199 @@ import api from './apiClient';
|
||||
export const currencyAPI = {
|
||||
// GET /api/v1/Currency
|
||||
async list() {
|
||||
console.log('🔵 Currency API - list request');
|
||||
const res = await api.get('/api/v1/Currency', { skipAuthRedirect: true });
|
||||
return res?.data?.data || [];
|
||||
console.log('🟢 Currency API - list response:', res?.data);
|
||||
// Response structure: { data: [{ currencyCode, isActive, permissions, limits, fees, ... }, ...] }
|
||||
return Array.isArray(res?.data?.data) ? res.data.data : (Array.isArray(res?.data) ? res.data : []);
|
||||
},
|
||||
|
||||
// GET /api/v1/Currency/{currencyCode}
|
||||
async getByCode(currencyCode) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
const res = await api.get(`/api/v1/Currency/${encodeURIComponent(currencyCode)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
},
|
||||
|
||||
// POST /api/v1/Currency
|
||||
async create(currencyCode) {
|
||||
const payload = { currencyCode: String(currencyCode || '') };
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
const payload = { currencyCode: String(currencyCode).trim() };
|
||||
const res = await api.post('/api/v1/Currency', payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PATCH /api/v1/Currency/{currencyCode}/ToggleActivation
|
||||
async toggleActivation(currencyCode) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
const res = await api.patch(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/ToggleActivation`, null, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PATCH /api/v1/Currency/{currencyCode}/Maintenance/Enable
|
||||
async enableMaintenance(currencyCode, maintenanceMessage = null) {
|
||||
const payload = maintenanceMessage ? { maintenanceMessage } : {};
|
||||
const res = await api.patch(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Maintenance/Enable`, payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
async enableMaintenance(currencyCode, maintenanceMessage) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
if (!maintenanceMessage || String(maintenanceMessage).trim() === '') {
|
||||
throw new Error('Maintenance message is required');
|
||||
}
|
||||
// API expects "Description" field (PascalCase)
|
||||
const payload = { Description: String(maintenanceMessage).trim() };
|
||||
console.log('🔵 Currency API - enableMaintenance request:', {
|
||||
currencyCode,
|
||||
payload
|
||||
});
|
||||
try {
|
||||
const res = await api.patch(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Maintenance/Enable`, payload, { skipAuthRedirect: true });
|
||||
console.log('🟢 Currency API - enableMaintenance response:', res?.data);
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - enableMaintenance error:', {
|
||||
currencyCode,
|
||||
payload,
|
||||
status: error?.response?.status,
|
||||
data: error?.response?.data,
|
||||
error: error?.response?.data || error?.message
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PATCH /api/v1/Currency/{currencyCode}/Maintenance/Disable
|
||||
async disableMaintenance(currencyCode) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
const res = await api.patch(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Maintenance/Disable`, null, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// GET /api/v1/Currency/{currencyCode}/Permissions
|
||||
async getPermissions(currencyCode) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.get(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Permissions`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
// Response structure: { statusCode, isSuccess, code, message, errors, data: {...} }
|
||||
// Return the data field from the response
|
||||
return res?.data?.data || null;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - getPermissions error:', {
|
||||
currencyCode,
|
||||
status: error?.response?.status,
|
||||
data: error?.response?.data,
|
||||
error: error?.response?.data || error?.message
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/Currency/{currencyCode}/Permissions
|
||||
async updatePermissions(currencyCode, permissions) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Permissions`, permissions, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// GET /api/v1/Currency/{currencyCode}/Limits
|
||||
async getLimits(currencyCode) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.get(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Limits`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
// Response structure: { statusCode, isSuccess, code, message, errors, data: { depositLimits, cashOutLimits, transferLimits, voucherLimits } }
|
||||
// Return the data field from the response
|
||||
return res?.data?.data || null;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - getLimits error:', {
|
||||
currencyCode,
|
||||
status: error?.response?.status,
|
||||
data: error?.response?.data,
|
||||
error: error?.response?.data || error?.message
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/Currency/{currencyCode}/Limits
|
||||
async updateLimits(currencyCode, limits) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Limits`, limits, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// GET /api/v1/Currency/{currencyCode}/Fees
|
||||
async getFees(currencyCode) {
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
console.log('🔵 Currency API - getFees request:', { currencyCode });
|
||||
const res = await api.get(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Fees`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
console.log('🟢 Currency API - getFees response:', res?.data);
|
||||
// Response structure: { statusCode, isSuccess, code, message, errors, data: { depositLimits, cashOutLimits, transferLimits, voucherLimits } }
|
||||
// Return the data field from the response
|
||||
return res?.data?.data || null;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - getFees error:', {
|
||||
currencyCode,
|
||||
status: error?.response?.status,
|
||||
data: error?.response?.data,
|
||||
error: error?.response?.data || error?.message
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/Currency/{currencyCode}/Fees
|
||||
async updateFees(currencyCode, fees) {
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Fees`, fees, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
if (!fees) {
|
||||
throw new Error('Fees data is required');
|
||||
}
|
||||
try {
|
||||
console.log('🔵 Currency API - updateFees request:', {
|
||||
currencyCode,
|
||||
payload: fees
|
||||
});
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Fees`, fees, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
console.log('🟢 Currency API - updateFees response:', res?.data);
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - updateFees error:', {
|
||||
currencyCode,
|
||||
payload: fees,
|
||||
status: error?.response?.status,
|
||||
data: error?.response?.data,
|
||||
error: error?.response?.data || error?.message
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -376,6 +376,9 @@ export const issuerAPI = {
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement
|
||||
async getTopUpAgentManagement(issuerId) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement`, {
|
||||
skipAuthRedirect: true
|
||||
@@ -388,9 +391,15 @@ export const issuerAPI = {
|
||||
},
|
||||
|
||||
// PUT /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement
|
||||
async updateTopUpAgentManagement(issuerId, maxAgents) {
|
||||
async updateTopUpAgentManagement(issuerId, settings) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
try {
|
||||
const payload = { maxAgents: Number(maxAgents) || 0 };
|
||||
// Support both old format (just maxAgents) and new format (settings object)
|
||||
const payload = typeof settings === 'number'
|
||||
? { maxAgents: Number(settings) || 0 }
|
||||
: { maxAgents: Number(settings?.maxAgents) || 0, ...settings };
|
||||
const res = await api.put(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
@@ -403,11 +412,14 @@ export const issuerAPI = {
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency
|
||||
async getTopUpAgentManagementCurrencies(issuerId) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return Array.isArray(res?.data?.data) ? res?.data?.data : [];
|
||||
return Array.isArray(res?.data?.data) ? res?.data?.data : (Array.isArray(res?.data) ? res?.data : []);
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Currencies GET error:', error);
|
||||
throw error;
|
||||
@@ -416,11 +428,17 @@ export const issuerAPI = {
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async getTopUpAgentManagementCurrency(issuerId, currencyCode) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || null;
|
||||
return res?.data?.data || res?.data || null;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Currency GET error:', error);
|
||||
throw error;
|
||||
@@ -428,27 +446,33 @@ export const issuerAPI = {
|
||||
},
|
||||
|
||||
// POST /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async createTopUpAgentManagementCurrency(issuerId, currencyCode, currencyData) {
|
||||
async createTopUpAgentManagementCurrency(issuerId, currencyCode, currencyData = {}) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
const payload = {
|
||||
voucherGeneratingFee: {
|
||||
percent: Number(currencyData.voucherGeneratingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.voucherGeneratingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.voucherGeneratingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.voucherGeneratingFee?.maxAmount) || 0
|
||||
minAmount: currencyData.voucherGeneratingFee?.minAmount != null ? Number(currencyData.voucherGeneratingFee.minAmount) : null,
|
||||
maxAmount: currencyData.voucherGeneratingFee?.maxAmount != null ? Number(currencyData.voucherGeneratingFee.maxAmount) : null
|
||||
},
|
||||
agentMarketingFee: {
|
||||
percent: Number(currencyData.agentMarketingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.agentMarketingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.agentMarketingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.agentMarketingFee?.maxAmount) || 0
|
||||
minAmount: currencyData.agentMarketingFee?.minAmount != null ? Number(currencyData.agentMarketingFee.minAmount) : null,
|
||||
maxAmount: currencyData.agentMarketingFee?.maxAmount != null ? Number(currencyData.agentMarketingFee.maxAmount) : null
|
||||
},
|
||||
agentWalletMaxBalanceLimit: {
|
||||
min: Number(currencyData.agentWalletMaxBalanceLimit?.min) || 0,
|
||||
max: Number(currencyData.agentWalletMaxBalanceLimit?.max) || 0
|
||||
min: currencyData.agentWalletMaxBalanceLimit?.min != null ? Number(currencyData.agentWalletMaxBalanceLimit.min) : null,
|
||||
max: currencyData.agentWalletMaxBalanceLimit?.max != null ? Number(currencyData.agentWalletMaxBalanceLimit.max) : null
|
||||
},
|
||||
agentWalletDepositMonthlyLimit: {
|
||||
amount: Number(currencyData.agentWalletDepositMonthlyLimit?.amount) || 0
|
||||
amount: currencyData.agentWalletDepositMonthlyLimit?.amount != null ? Number(currencyData.agentWalletDepositMonthlyLimit.amount) : null
|
||||
}
|
||||
};
|
||||
const res = await api.post(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, payload, {
|
||||
@@ -463,26 +487,35 @@ export const issuerAPI = {
|
||||
|
||||
// PUT /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async updateTopUpAgentManagementCurrency(issuerId, currencyCode, currencyData) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
if (!currencyData) {
|
||||
throw new Error('Currency data is required');
|
||||
}
|
||||
try {
|
||||
const payload = {
|
||||
voucherGeneratingFee: {
|
||||
percent: Number(currencyData.voucherGeneratingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.voucherGeneratingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.voucherGeneratingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.voucherGeneratingFee?.maxAmount) || 0
|
||||
minAmount: currencyData.voucherGeneratingFee?.minAmount != null ? Number(currencyData.voucherGeneratingFee.minAmount) : null,
|
||||
maxAmount: currencyData.voucherGeneratingFee?.maxAmount != null ? Number(currencyData.voucherGeneratingFee.maxAmount) : null
|
||||
},
|
||||
agentMarketingFee: {
|
||||
percent: Number(currencyData.agentMarketingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.agentMarketingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.agentMarketingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.agentMarketingFee?.maxAmount) || 0
|
||||
minAmount: currencyData.agentMarketingFee?.minAmount != null ? Number(currencyData.agentMarketingFee.minAmount) : null,
|
||||
maxAmount: currencyData.agentMarketingFee?.maxAmount != null ? Number(currencyData.agentMarketingFee.maxAmount) : null
|
||||
},
|
||||
agentWalletMaxBalanceLimit: {
|
||||
min: Number(currencyData.agentWalletMaxBalanceLimit?.min) || 0,
|
||||
max: Number(currencyData.agentWalletMaxBalanceLimit?.max) || 0
|
||||
min: currencyData.agentWalletMaxBalanceLimit?.min != null ? Number(currencyData.agentWalletMaxBalanceLimit.min) : null,
|
||||
max: currencyData.agentWalletMaxBalanceLimit?.max != null ? Number(currencyData.agentWalletMaxBalanceLimit.max) : null
|
||||
},
|
||||
agentWalletDepositMonthlyLimit: {
|
||||
amount: Number(currencyData.agentWalletDepositMonthlyLimit?.amount) || 0
|
||||
amount: currencyData.agentWalletDepositMonthlyLimit?.amount != null ? Number(currencyData.agentWalletDepositMonthlyLimit.amount) : null
|
||||
}
|
||||
};
|
||||
const res = await api.put(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, payload, {
|
||||
@@ -497,6 +530,12 @@ export const issuerAPI = {
|
||||
|
||||
// DELETE /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async deleteTopUpAgentManagementCurrency(issuerId, currencyCode) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.delete(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, {
|
||||
skipAuthRedirect: true
|
||||
@@ -512,11 +551,17 @@ export const issuerAPI = {
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}/Wallet/Balance
|
||||
async getTopUpAgentManagementWalletBalance(issuerId, currencyCode) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}/Wallet/Balance`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || null;
|
||||
return res?.data?.data || res?.data || null;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Wallet Balance GET error:', error);
|
||||
throw error;
|
||||
@@ -525,12 +570,21 @@ export const issuerAPI = {
|
||||
|
||||
// POST /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}/Wallet/Deposit
|
||||
async depositTopUpAgentManagementWallet(issuerId, currencyCode, amount) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
if (amount == null || amount === '') {
|
||||
throw new Error('Amount is required');
|
||||
}
|
||||
try {
|
||||
const payload = { amount: Number(amount) || 0 };
|
||||
const res = await api.post(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}/Wallet/Deposit`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Wallet Deposit POST error:', error);
|
||||
throw error;
|
||||
@@ -539,11 +593,17 @@ export const issuerAPI = {
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}/Wallet/Transactions
|
||||
async getTopUpAgentManagementWalletTransactions(issuerId, currencyCode) {
|
||||
if (!issuerId) {
|
||||
throw new Error('Issuer ID is required');
|
||||
}
|
||||
if (!currencyCode) {
|
||||
throw new Error('Currency code is required');
|
||||
}
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}/Wallet/Transactions`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return Array.isArray(res?.data?.data) ? res?.data?.data : [];
|
||||
return Array.isArray(res?.data?.data) ? res?.data?.data : (Array.isArray(res?.data) ? res?.data : []);
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Wallet Transactions GET error:', error);
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user