import { COIN_SELLER_RECHARGE_CHAINS, COIN_SELLER_RECHARGE_GRANT_STATUS, COIN_SELLER_RECHARGE_PROVIDERS, COIN_SELLER_RECHARGE_STATUS, COIN_SELLER_RECHARGE_VERIFY_STATUS, WITHDRAWAL_STATUS, } from "./constants.js"; export function normalizeWithdrawalApplication(item = {}) { return { appCode: stringValue(item.appCode ?? item.app_code), appName: stringValue(item.appName ?? item.app_name), approvedAtMs: numberOrNull(item.approvedAtMs ?? item.approved_at_ms), approverName: stringValue( item.approverName ?? item.approver_name ?? item.approverAccount ?? item.approver_account, ), approverUserId: item.approverUserId ?? item.approver_user_id, auditImageUrl: stringValue(item.auditImageUrl ?? item.audit_image_url), auditRemark: stringValue(item.auditRemark ?? item.audit_remark), auditTransactionId: stringValue(item.auditTransactionId ?? item.audit_transaction_id), createdAtMs: numberOrNull(item.createdAtMs ?? item.created_at_ms), freezeTransactionId: stringValue(item.freezeTransactionId ?? item.freeze_transaction_id), id: item.id ?? item.withdrawalApplicationId ?? item.withdrawal_application_id, salaryAssetType: stringValue(item.salaryAssetType ?? item.salary_asset_type), status: stringValue(item.status), updatedAtMs: numberOrNull(item.updatedAtMs ?? item.updated_at_ms), userId: stringValue(item.userId ?? item.user_id), withdrawAddress: stringValue(item.withdrawAddress ?? item.withdraw_address), withdrawAmount: numberValue(item.withdrawAmount ?? item.withdraw_amount), withdrawAmountMinor: numberValue(item.withdrawAmountMinor ?? item.withdraw_amount_minor), withdrawMethod: stringValue(item.withdrawMethod ?? item.withdraw_method), }; } export function normalizeWithdrawalApplicationPage(data = {}) { const items = Array.isArray(data.items) ? data.items : []; return { items: items.map(normalizeWithdrawalApplication), page: Number(data.page || 1), pageSize: Number(data.pageSize ?? data.page_size ?? items.length), total: Number(data.total ?? items.length), }; } export function buildCoinSellerRechargeOrderPayload(form) { const providerCode = stringValue(form.providerCode); const providerCurrencyCode = stringValue(form.providerCurrencyCode).toUpperCase(); const providerAmountMinor = providerAmountMinorFromForm(form); const payload = { appCode: stringValue(form.appCode), chain: providerCode === "usdt" ? stringValue(form.chain).toUpperCase() : "", externalOrderNo: stringValue(form.externalOrderNo), isMakeup: Boolean(form.isMakeup), orderDateMs: numberValue(form.orderDateMs), providerAmountMinor: requiresThirdPartyProviderAmount(providerCode) ? providerAmountMinor : "", providerCode, providerCurrencyCode: requiresThirdPartyProviderAmount(providerCode) ? providerCurrencyCode : "", remark: stringValue(form.remark), targetUserId: stringValue(form.targetUserId), usdAmount: numberValue(form.usdAmount), }; return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== "")); } export function buildCoinSellerRechargeReceiptPayload(form) { const providerCode = stringValue(form.providerCode); const providerCurrencyCode = stringValue(form.providerCurrencyCode).toUpperCase(); const providerAmountMinor = providerAmountMinorFromForm(form); return Object.fromEntries( Object.entries({ appCode: stringValue(form.appCode), chain: providerCode === "usdt" ? stringValue(form.chain).toUpperCase() : "", externalOrderNo: stringValue(form.externalOrderNo), orderDateMs: numberValue(form.orderDateMs), providerAmountMinor: requiresThirdPartyProviderAmount(providerCode) ? providerAmountMinor : "", providerCode, providerCurrencyCode: requiresThirdPartyProviderAmount(providerCode) ? providerCurrencyCode : "", usdAmount: numberValue(form.usdAmount), }).filter(([, value]) => value !== ""), ); } export function validateCoinSellerRechargeOrderPayload(payload) { if (!payload.appCode) { return "请选择 APP"; } if (!payload.targetUserId) { return "请填写目标用户 ID"; } if (!Number.isFinite(payload.usdAmount) || payload.usdAmount <= 0) { return "请填写大于 0 的 USD 金额"; } if (!Number.isInteger(payload.orderDateMs) || payload.orderDateMs <= 0) { return "请选择订单时间"; } if (!payload.providerCode) { return "请选择支付渠道"; } if (!payload.externalOrderNo) { return "请填写三方订单号"; } if (payload.providerCode === "usdt" && !payload.chain) { return "请选择 USDT 链"; } if (requiresThirdPartyProviderAmount(payload.providerCode)) { if (!payload.providerCurrencyCode) { return "请填写币种"; } if (!Number.isInteger(payload.providerAmountMinor) || payload.providerAmountMinor <= 0) { return "请填写大于 0 的币种金额"; } } if (payload.remark && payload.remark.length > 512) { return "备注不能超过 512 字"; } return ""; } export function buildCoinSellerRechargeQuotePayload(form) { return { appCode: stringValue(form.appCode), targetUserId: stringValue(form.targetUserId), usdAmount: numberValue(form.usdAmount), }; } export function buildCoinSellerRechargeExchangeRatePayload(config) { return { tiers: (config.tiers || []).map((item) => ({ coinsPerUsd: numberValue(item.coinsPerUsd), maxUsdAmount: numberValue(item.maxUsdAmount), minUsdAmount: numberValue(item.minUsdAmount), })), whitelist: (config.whitelist || []).map((item) => ({ coinsPerUsd: numberValue(item.coinsPerUsd), userId: stringValue(item.userId), })), }; } export function validateCoinSellerRechargeExchangeRatePayload(payload) { if (!payload.tiers.length) { return "至少添加一个 USD 金额区间"; } const tiers = [...payload.tiers].sort((left, right) => left.minUsdAmount - right.minUsdAmount); for (let index = 0; index < tiers.length; index += 1) { const item = tiers[index]; if ( !Number.isFinite(item.minUsdAmount) || item.minUsdAmount <= 0 || !Number.isFinite(item.maxUsdAmount) || item.maxUsdAmount < item.minUsdAmount || !Number.isInteger(item.coinsPerUsd) || item.coinsPerUsd <= 0 ) { return "请填写正确的 USD 金额区间和金币汇率"; } if (index > 0 && item.minUsdAmount <= tiers[index - 1].maxUsdAmount) { return "USD 金额区间不能重叠"; } } const userIds = new Set(); for (const item of payload.whitelist) { if (!item.userId || !Number.isInteger(item.coinsPerUsd) || item.coinsPerUsd <= 0) { return "请填写正确的白名单用户 ID 和金币汇率"; } if (userIds.has(item.userId)) { return `白名单用户 ID 重复:${item.userId}`; } userIds.add(item.userId); } return ""; } export function normalizeCoinSellerRechargeOrder(item = {}) { return { appCode: stringValue(item.appCode ?? item.app_code), chain: stringValue(item.chain), coinAmount: numberValue(item.coinAmount ?? item.coin_amount), createdAtMs: numberOrNull(item.createdAtMs ?? item.created_at_ms), externalOrderNo: stringValue(item.externalOrderNo ?? item.external_order_no), failureReason: stringValue(item.failureReason ?? item.failure_reason), grantStatus: stringValue(item.grantStatus ?? item.grant_status) || "pending", grantedAtMs: numberOrNull(item.grantedAtMs ?? item.granted_at_ms), grantedByName: stringValue(item.grantedByName ?? item.granted_by_name), id: stringValue(item.id ?? item.orderId ?? item.order_id), operatorName: stringValue(item.operatorName ?? item.operator_name), orderDateMs: numberOrNull(item.orderDateMs ?? item.order_date_ms), providerAmountMinor: numberOrNull(item.providerAmountMinor ?? item.provider_amount_minor), providerCode: stringValue(item.providerCode ?? item.provider_code), providerCurrencyCode: stringValue(item.providerCurrencyCode ?? item.provider_currency_code), providerOrderId: stringValue(item.providerOrderId ?? item.provider_order_id), providerPayloadJson: stringValue(item.providerPayloadJson ?? item.provider_payload_json), providerStatus: stringValue(item.providerStatus ?? item.provider_status), receiveAddress: stringValue(item.receiveAddress ?? item.receive_address), remark: stringValue(item.remark), status: stringValue(item.status) || "pending", targetDisplayUserId: stringValue(item.targetDisplayUserId ?? item.target_display_user_id), targetUserId: stringValue(item.targetUserId ?? item.target_user_id), usdAmount: item.usdAmount ?? item.usd_amount ?? "", usdMinorAmount: numberOrNull(item.usdMinorAmount ?? item.usd_minor_amount), verifiedAtMs: numberOrNull(item.verifiedAtMs ?? item.verified_at_ms), verifiedByName: stringValue(item.verifiedByName ?? item.verified_by_name), verifyStatus: stringValue(item.verifyStatus ?? item.verify_status) || "pending", walletAmountDelta: numberOrNull(item.walletAmountDelta ?? item.wallet_amount_delta), walletAssetType: stringValue(item.walletAssetType ?? item.wallet_asset_type), walletBalanceAfter: numberOrNull(item.walletBalanceAfter ?? item.wallet_balance_after), walletCommandId: stringValue(item.walletCommandId ?? item.wallet_command_id), walletTransactionId: stringValue(item.walletTransactionId ?? item.wallet_transaction_id), }; } export function normalizeCoinSellerRechargeOrderPage(data = {}) { const items = Array.isArray(data.items) ? data.items : []; return { items: items.map(normalizeCoinSellerRechargeOrder), page: Number(data.page || 1), pageSize: Number(data.pageSize ?? data.page_size ?? items.length), total: Number(data.total ?? items.length), }; } export function normalizeRechargeBill(item = {}) { return { appCode: stringValue(item.appCode ?? item.app_code), appName: stringValue(item.appName ?? item.app_name), billAmountMinor: numberOrNull(item.billAmountMinor ?? item.bill_amount_minor), billAmountText: stringValue( item.billAmountText ?? item.bill_amount_text ?? item.billAmount ?? item.bill_amount, ), coinAmount: numberValue(item.coinAmount ?? item.coin_amount), commandId: stringValue(item.commandId ?? item.command_id), createdAtMs: numberOrNull(item.createdAtMs ?? item.created_at_ms), currencyCode: stringValue(item.currencyCode ?? item.currency_code) || "USD", exchangeCoinAmount: numberValue(item.exchangeCoinAmount ?? item.exchange_coin_amount), exchangeUsdMinorAmount: numberValue(item.exchangeUsdMinorAmount ?? item.exchange_usd_minor_amount), externalRef: stringValue(item.externalRef ?? item.external_ref), id: stringValue(item.id ?? item.transactionId ?? item.transaction_id), paidSyncedAtMs: numberOrNull(item.paidSyncedAtMs ?? item.paid_synced_at_ms), providerAmountMinor: numberOrNull(item.providerAmountMinor ?? item.provider_amount_minor), providerCode: stringValue(item.providerCode ?? item.provider_code), providerFeeMicro: numberOrNull(item.providerFeeMicro ?? item.provider_fee_micro), providerNetMicro: numberOrNull(item.providerNetMicro ?? item.provider_net_micro), providerTaxMicro: numberOrNull(item.providerTaxMicro ?? item.provider_tax_micro), rechargeType: stringValue(item.rechargeType ?? item.recharge_type), sellerRegionId: numberOrNull(item.sellerRegionId ?? item.seller_region_id), sellerUserId: numberOrNull(item.sellerUserId ?? item.seller_user_id), status: stringValue(item.status), targetRegionId: numberOrNull(item.targetRegionId ?? item.target_region_id), taxDeductionMinor: numberOrNull( item.taxDeductionMinor ?? item.tax_deduction_minor ?? item.thirdPartyTaxDeductionMinor ?? item.third_party_tax_deduction_minor, ), taxDeductionText: stringValue( item.taxDeductionText ?? item.tax_deduction_text ?? item.thirdPartyTaxDeduction ?? item.third_party_tax_deduction, ), taxRate: numberOrNull(item.taxRate ?? item.tax_rate ?? item.thirdPartyTaxRate ?? item.third_party_tax_rate), transactionId: stringValue(item.transactionId ?? item.transaction_id), usdMinorAmount: numberValue(item.usdMinorAmount ?? item.usd_minor_amount), user: { displayUserId: stringValue(item.user?.displayUserId ?? item.user?.display_user_id), userId: stringValue(item.user?.userId ?? item.user?.user_id) || stringValue(item.userId ?? item.user_id), username: stringValue(item.user?.username), }, userPaidAmountMicro: numberOrNull( item.userPaidAmountMicro ?? item.user_paid_amount_micro ?? item.paidAmountMicro ?? item.paid_amount_micro, ), userPaidAmountMinor: numberOrNull( item.userPaidAmountMinor ?? item.user_paid_amount_minor ?? item.paidAmountMinor ?? item.paid_amount_minor ?? item.providerAmountMinor ?? item.provider_amount_minor, ), userPaidCurrencyCode: stringValue(item.userPaidCurrencyCode ?? item.user_paid_currency_code), userPaidText: stringValue( item.userPaidText ?? item.user_paid_text ?? item.userPaidAmount ?? item.user_paid_amount ?? item.paidAmount ?? item.paid_amount, ), }; } export function normalizeRechargeBillPage(data = {}) { const rawItems = Array.isArray(data.items) ? data.items : Array.isArray(data.bills) ? data.bills : []; return { items: rawItems.map(normalizeRechargeBill), page: Number(data.page || 1), pageSize: Number(data.pageSize ?? data.page_size ?? rawItems.length), total: Number(data.total ?? rawItems.length), }; } const EMPTY_RECHARGE_SUMMARY_BUCKET = { billCount: 0, coinAmount: 0, usdMinorAmount: 0 }; export const EMPTY_RECHARGE_SUMMARY = { coinSeller: EMPTY_RECHARGE_SUMMARY_BUCKET, googlePlay: EMPTY_RECHARGE_SUMMARY_BUCKET, thirdParty: EMPTY_RECHARGE_SUMMARY_BUCKET, total: EMPTY_RECHARGE_SUMMARY_BUCKET, }; function normalizeRechargeSummaryBucket(bucket = {}) { return { billCount: numberValue(bucket.billCount ?? bucket.bill_count) || 0, coinAmount: numberValue(bucket.coinAmount ?? bucket.coin_amount) || 0, usdMinorAmount: numberValue(bucket.usdMinorAmount ?? bucket.usd_minor_amount) || 0, }; } export function normalizeRechargeSummary(data = {}) { return { coinSeller: normalizeRechargeSummaryBucket(data.coinSeller ?? data.coin_seller), googlePlay: normalizeRechargeSummaryBucket(data.googlePlay ?? data.google_play), thirdParty: normalizeRechargeSummaryBucket(data.thirdParty ?? data.third_party), total: normalizeRechargeSummaryBucket(data.total), }; } export function mergeRechargeSummaries(summaries = []) { const merged = normalizeRechargeSummary({}); for (const summary of summaries) { for (const key of ["coinSeller", "googlePlay", "thirdParty", "total"]) { merged[key] = { billCount: merged[key].billCount + summary[key].billCount, coinAmount: merged[key].coinAmount + summary[key].coinAmount, usdMinorAmount: merged[key].usdMinorAmount + summary[key].usdMinorAmount, }; } } return merged; } export const EMPTY_RECHARGE_OVERVIEW = { daily: [], googlePaid: { coveredUsdMinor: 0, estFeeUsdMinor: 0, estNetUsdMinor: 0, estTaxUsdMinor: 0, googleBillCount: 0, syncedCount: 0, unsyncedCount: 0, }, regions: [], withdrawal: { approvedCount: 0, approvedUsdMinor: 0, totalUsdMinor: 0, transferCount: 0, transferUsdMinor: 0, }, }; export function normalizeRechargeOverview(data = {}) { const daily = Array.isArray(data.daily) ? data.daily : []; const regions = Array.isArray(data.regions) ? data.regions : []; const paid = data.googlePaid ?? data.google_paid ?? {}; const withdrawal = data.withdrawal ?? {}; return { daily: daily.map((item) => ({ coinSellerCoinAmount: numberValue(item.coinSellerCoinAmount ?? item.coin_seller_coin_amount) || 0, coinSellerUsdMinor: numberValue(item.coinSellerUsdMinor ?? item.coin_seller_usd_minor) || 0, date: stringValue(item.date), googleCoinAmount: numberValue(item.googleCoinAmount ?? item.google_coin_amount) || 0, googleUsdMinor: numberValue(item.googleUsdMinor ?? item.google_usd_minor) || 0, thirdPartyCoinAmount: numberValue(item.thirdPartyCoinAmount ?? item.third_party_coin_amount) || 0, thirdPartyUsdMinor: numberValue(item.thirdPartyUsdMinor ?? item.third_party_usd_minor) || 0, })), googlePaid: { coveredUsdMinor: numberValue(paid.coveredUsdMinor ?? paid.covered_usd_minor) || 0, estFeeUsdMinor: numberValue(paid.estFeeUsdMinor ?? paid.est_fee_usd_minor) || 0, estNetUsdMinor: numberValue(paid.estNetUsdMinor ?? paid.est_net_usd_minor) || 0, estTaxUsdMinor: numberValue(paid.estTaxUsdMinor ?? paid.est_tax_usd_minor) || 0, googleBillCount: numberValue(paid.googleBillCount ?? paid.google_bill_count) || 0, syncedCount: numberValue(paid.syncedCount ?? paid.synced_count) || 0, unsyncedCount: numberValue(paid.unsyncedCount ?? paid.unsynced_count) || 0, }, regions: regions.map((item) => ({ billCount: numberValue(item.billCount ?? item.bill_count) || 0, name: stringValue(item.name), regionId: numberOrNull(item.regionId ?? item.region_id), usdMinorAmount: numberValue(item.usdMinorAmount ?? item.usd_minor_amount) || 0, })), withdrawal: { approvedCount: numberValue(withdrawal.approvedCount ?? withdrawal.approved_count) || 0, approvedUsdMinor: numberValue(withdrawal.approvedUsdMinor ?? withdrawal.approved_usd_minor) || 0, totalUsdMinor: numberValue(withdrawal.totalUsdMinor ?? withdrawal.total_usd_minor) || 0, transferCount: numberValue(withdrawal.transferCount ?? withdrawal.transfer_count) || 0, transferUsdMinor: numberValue(withdrawal.transferUsdMinor ?? withdrawal.transfer_usd_minor) || 0, }, }; } // mergeRechargeOverviews 把多 App 概览合并成全局口径:daily 按日期求和,googlePaid 求和; // 区域 ID 属于单 App 语义,跨 App 合并时丢弃区域分布。 export function mergeRechargeOverviews(overviews = []) { const dailyByDate = new Map(); const merged = normalizeRechargeOverview({}); for (const overview of overviews) { for (const bucket of overview.daily) { const existing = dailyByDate.get(bucket.date); if (!existing) { dailyByDate.set(bucket.date, { ...bucket }); continue; } for (const key of [ "coinSellerCoinAmount", "coinSellerUsdMinor", "googleCoinAmount", "googleUsdMinor", "thirdPartyCoinAmount", "thirdPartyUsdMinor", ]) { existing[key] += bucket[key]; } } for (const key of Object.keys(merged.googlePaid)) { merged.googlePaid[key] += overview.googlePaid[key]; } for (const key of Object.keys(merged.withdrawal)) { merged.withdrawal[key] += overview.withdrawal[key]; } } merged.daily = [...dailyByDate.values()].sort((left, right) => left.date.localeCompare(right.date)); return merged; } export function normalizeRechargeRegions(data = {}) { const items = Array.isArray(data.items) ? data.items : Array.isArray(data) ? data : []; return items .map((item) => { const regionId = numberOrNull(item.regionId ?? item.region_id); if (!regionId) { return null; } return { name: stringValue(item.name), regionCode: stringValue(item.regionCode ?? item.region_code), regionId, }; }) .filter(Boolean); } export function rechargeTypeLabel(value) { if (value === "coin_seller_transfer") { return "币商充值"; } if (value === "coin_seller_stock_purchase") { return "币商进货"; } if (value === "coin_seller_stock_deduction") { return "币商冲回"; } if (value === "google_play_recharge") { return "谷歌充值"; } if (value === "mifapay") { return "三方充值 · MiFaPay"; } if (value === "v5pay") { return "三方充值 · V5Pay"; } if (value === "usdt_trc20") { return "三方充值 · USDT"; } if (value === "apple_recharge") { return "苹果充值"; } if (value === "huawei_recharge") { return "华为充值"; } if (value === "telegram_recharge") { return "Telegram 充值"; } if (value === "web_recharge") { return "三方充值 · Web"; } return value || "-"; } // rechargeSourceTone 决定来源徽章与 KPI 卡片的配色分组:google/thirdparty/coinseller。 export function rechargeSourceTone(rechargeType) { if (rechargeType === "google_play_recharge") { return "google"; } if ( rechargeType === "coin_seller_stock_purchase" || rechargeType === "coin_seller_stock_deduction" || rechargeType === "coin_seller_transfer" ) { return "coinseller"; } return "thirdparty"; } export function statusLabel(value) { return WITHDRAWAL_STATUS.find(([status]) => status === value)?.[1] || value || "-"; } export function coinSellerRechargeProviderLabel(value) { return COIN_SELLER_RECHARGE_PROVIDERS.find(([code]) => code === value)?.[1] || value || "-"; } export function coinSellerRechargeChainLabel(value) { return COIN_SELLER_RECHARGE_CHAINS.find(([code]) => code === value)?.[1] || value || "-"; } export function coinSellerRechargeStatusLabel(value) { return COIN_SELLER_RECHARGE_STATUS.find(([status]) => status === value)?.[1] || value || "-"; } export function coinSellerRechargeVerifyStatusLabel(value) { return COIN_SELLER_RECHARGE_VERIFY_STATUS.find(([status]) => status === value)?.[1] || value || "-"; } export function coinSellerRechargeGrantStatusLabel(value) { return COIN_SELLER_RECHARGE_GRANT_STATUS.find(([status]) => status === value)?.[1] || value || "-"; } export function coinSellerRechargeStatusTone(value) { if (["granted", "verified", "success", "succeeded", "completed", "passed"].includes(stringValue(value))) { return "success"; } if (["failed", "rejected", "canceled", "cancelled"].includes(stringValue(value))) { return "danger"; } return "warning"; } export function isCoinSellerRechargeVerified(order) { return ( ["verified", "success", "succeeded", "completed", "passed"].includes(stringValue(order?.verifyStatus)) || stringValue(order?.status) === "verified" ); } export function isCoinSellerRechargeGranted(order) { return ( ["granted", "success", "succeeded", "completed"].includes(stringValue(order?.grantStatus)) || stringValue(order?.status) === "granted" ); } export function formatAmount(value) { const number = Number(value); if (!Number.isFinite(number)) { return "-"; } return number.toLocaleString("zh-CN", { maximumFractionDigits: 2 }); } export function formatTime(ms) { const value = Number(ms); if (!Number.isFinite(value) || value <= 0) { return "-"; } return new Intl.DateTimeFormat("zh-CN", { day: "2-digit", hour: "2-digit", hourCycle: "h23", minute: "2-digit", month: "2-digit", timeZone: "Asia/Shanghai", year: "numeric", }).format(value); } export function formatUsdMinor(value, currency = "USD") { const number = Number(value); if (!Number.isFinite(number)) { return "-"; } return `${currency || "USD"} ${(number / 100).toLocaleString("zh-CN", { maximumFractionDigits: 2, minimumFractionDigits: 2, })}`; } export function formatMicroMoney(value, currency = "USD") { const number = Number(value); if (!Number.isFinite(number)) { return "-"; } return `${currency || "USD"} ${(number / 1_000_000).toLocaleString("zh-CN", { maximumFractionDigits: 6, minimumFractionDigits: 2, })}`; } export function formatPercent(value) { const number = Number(value); if (!Number.isFinite(number)) { return ""; } const percent = number > 1 ? number : number * 100; return `${percent.toLocaleString("zh-CN", { maximumFractionDigits: 4 })}%`; } function numberValue(value) { if (value === "" || value === null || value === undefined) { return Number.NaN; } return Number(value); } function numberOrNull(value) { const nextValue = Number(value); return Number.isFinite(nextValue) ? nextValue : null; } function providerMoneyToMinor(value) { const number = numberValue(value); if (!Number.isFinite(number)) { return Number.NaN; } return Math.round(number * 100); } function providerAmountMinorFromForm(form) { // 表单输入是常规金额,已构建 payload 重用时则直接沿用 minor,避免校验请求二次放大金额。 if (stringValue(form.providerAmount) !== "") { return providerMoneyToMinor(form.providerAmount); } return numberValue(form.providerAmountMinor); } function requiresThirdPartyProviderAmount(providerCode) { return ["mifapay", "v5pay"].includes(stringValue(providerCode).toLowerCase()); } function stringValue(value) { return String(value ?? "").trim(); }