import { expect, test } from "vitest"; import { buildApplicationPayload, buildCoinSellerRechargeReceiptPayload, buildCoinSellerRechargeExchangeRatePayload, buildCoinSellerRechargeOrderPayload, buildCoinSellerRechargeQuotePayload, coinSellerRechargeProviderLabel, normalizeApplicationPage, normalizeCoinSellerRechargeOrderPage, normalizeRechargeBillPage, normalizeWithdrawalApplicationPage, operationLabel, rechargeTypeLabel, statusLabel, validateApplicationPayload, validateCoinSellerRechargeOrderPayload, validateCoinSellerRechargeExchangeRatePayload, walletIdentityLabel, } from "./format.js"; test("builds and validates finance application payload", () => { const payload = buildApplicationPayload({ appCode: " lalu ", coinAmount: "3000", credentialImageUrl: "", credentialText: "bank receipt", operation: "user_wallet_credit", rechargeAmount: "15.5", targetUserId: " 10001 ", walletIdentity: "agency", }); expect(payload).toEqual({ appCode: "lalu", coinAmount: 3000, credentialImageUrl: "", credentialText: "bank receipt", operation: "user_wallet_credit", rechargeAmount: 15.5, targetUserId: "10001", walletIdentity: "agency", }); expect(validateApplicationPayload(payload)).toBe(""); }); test("requires wallet identity and credential for wallet operations", () => { const payload = buildApplicationPayload({ appCode: "lalu", coinAmount: "100", operation: "user_wallet_debit", rechargeAmount: "1", targetUserId: "10001", }); expect(validateApplicationPayload(payload)).toBe("请选择钱包身份"); expect(validateApplicationPayload({ ...payload, walletIdentity: "host" })).toBe("请上传凭证图片或填写凭证文字"); }); test("allows zero recharge amount only for user coin operations", () => { const payload = buildApplicationPayload({ appCode: "lalu", coinAmount: "1111", credentialText: "测试", operation: "user_coin_credit", rechargeAmount: "0", targetUserId: "163185", }); expect(validateApplicationPayload(payload)).toBe(""); expect(validateApplicationPayload({ ...payload, operation: "user_wallet_credit", walletIdentity: "agency" })).toBe( "请填写大于 0 的充值金额", ); expect(validateApplicationPayload({ ...payload, operation: "coin_seller_coin_credit" })).toBe( "请填写大于 0 的充值金额", ); }); test("normalizes finance application list rows", () => { const page = normalizeApplicationPage({ items: [ { app_code: "lalu", applicant_name: "张三", audited_at_ms: 1760003600000, auditor_name: "李四", auditor_user_id: 99, coin_amount: 200, created_at_ms: 1760000000000, id: 9, operation: "coin_seller_coin_credit", recharge_amount: 20, status: "pending", target_user_id: 88, }, ], page: 1, page_size: 50, total: 1, }); expect(page.items[0]).toMatchObject({ appCode: "lalu", applicantName: "张三", auditedAtMs: 1760003600000, auditorName: "李四", auditorUserId: 99, coinAmount: 200, operation: "coin_seller_coin_credit", targetUserId: "88", }); expect(page.pageSize).toBe(50); expect(operationLabel("coin_seller_coin_credit")).toBe("增加币商金币"); expect(statusLabel("pending")).toBe("待审核"); expect(walletIdentityLabel("bd")).toBe("BD 钱包"); }); test("normalizes finance withdrawal application list rows", () => { const page = normalizeWithdrawalApplicationPage({ items: [ { app_code: "lalu", approved_at_ms: 1760007200000, approver_name: "财务一", approver_user_id: 21, audit_image_url: "https://cdn.example.com/pay.png", audit_remark: "已打款", audit_transaction_id: "tx-audit", created_at_ms: 1760000000000, freeze_transaction_id: "tx-freeze", id: 7, salary_asset_type: "HOST_SALARY_USD", status: "approved", user_id: 10001, withdraw_address: "TRX-address", withdraw_amount: "12.5", withdraw_amount_minor: 1250, withdraw_method: "USDT-TRC20", }, ], page: 2, page_size: 50, total: 51, }); expect(page).toMatchObject({ page: 2, pageSize: 50, total: 51, }); expect(page.items[0]).toMatchObject({ appCode: "lalu", approvedAtMs: 1760007200000, approverName: "财务一", approverUserId: 21, auditImageUrl: "https://cdn.example.com/pay.png", auditRemark: "已打款", auditTransactionId: "tx-audit", createdAtMs: 1760000000000, freezeTransactionId: "tx-freeze", id: 7, salaryAssetType: "HOST_SALARY_USD", userId: "10001", withdrawAddress: "TRX-address", withdrawAmount: 12.5, withdrawAmountMinor: 1250, withdrawMethod: "USDT-TRC20", }); }); test("builds validates and normalizes coin seller recharge orders", () => { const payload = buildCoinSellerRechargeOrderPayload({ appCode: " lalu ", coinAmount: "100000", externalOrderNo: " MIFA-001 ", orderDateMs: 1760000000000, providerAmount: "1250.5", providerCode: "mifapay", providerCurrencyCode: " php ", remark: " 人工补单 ", targetUserId: " 10001 ", usdAmount: "10.5", }); expect(payload).toEqual({ appCode: "lalu", externalOrderNo: "MIFA-001", isMakeup: false, orderDateMs: 1760000000000, providerAmountMinor: 125050, providerCode: "mifapay", providerCurrencyCode: "PHP", remark: "人工补单", targetUserId: "10001", usdAmount: 10.5, }); expect( buildCoinSellerRechargeReceiptPayload({ ...payload, coinAmount: "", targetUserId: "", }), ).toEqual({ appCode: "lalu", externalOrderNo: "MIFA-001", orderDateMs: 1760000000000, providerAmountMinor: 125050, providerCode: "mifapay", providerCurrencyCode: "PHP", usdAmount: 10.5, }); expect(validateCoinSellerRechargeOrderPayload(payload)).toBe(""); expect(validateCoinSellerRechargeOrderPayload({ ...payload, providerCurrencyCode: "" })).toBe("请填写币种"); expect(validateCoinSellerRechargeOrderPayload({ ...payload, providerAmountMinor: 0 })).toBe( "请填写大于 0 的币种金额", ); expect(validateCoinSellerRechargeOrderPayload({ ...payload, remark: "x".repeat(513) })).toBe("备注不能超过 512 字"); expect(validateCoinSellerRechargeOrderPayload({ ...payload, providerCode: "usdt", chain: "" })).toBe( "请选择 USDT 链", ); const boundaryPayload = buildCoinSellerRechargeOrderPayload({ ...payload, externalOrderNo: "V5-001", providerAmount: "0.01", providerCode: "v5pay", providerCurrencyCode: "try", }); expect(boundaryPayload).toMatchObject({ externalOrderNo: "V5-001", providerAmountMinor: 1, providerCode: "v5pay", providerCurrencyCode: "TRY", }); expect(validateCoinSellerRechargeOrderPayload(boundaryPayload)).toBe(""); expect( validateCoinSellerRechargeOrderPayload( buildCoinSellerRechargeOrderPayload({ ...payload, providerAmount: "abc", providerCode: "v5pay", providerCurrencyCode: "TRY", }), ), ).toBe("请填写大于 0 的币种金额"); expect( validateCoinSellerRechargeOrderPayload( buildCoinSellerRechargeOrderPayload({ ...payload, providerAmount: "", providerAmountMinor: undefined, providerCode: "v5pay", providerCurrencyCode: "TRY", }), ), ).toBe("请填写大于 0 的币种金额"); expect( buildCoinSellerRechargeOrderPayload({ ...payload, chain: "tron", providerAmount: "48", providerCode: "usdt", providerCurrencyCode: "PHP", }), ).toEqual({ appCode: "lalu", chain: "TRON", externalOrderNo: "MIFA-001", isMakeup: false, orderDateMs: 1760000000000, providerCode: "usdt", remark: "人工补单", targetUserId: "10001", usdAmount: 10.5, }); expect( buildCoinSellerRechargeReceiptPayload({ ...payload, chain: "bsc", providerAmount: "48", providerCode: "usdt", providerCurrencyCode: "PHP", }), ).toEqual({ appCode: "lalu", chain: "BSC", externalOrderNo: "MIFA-001", orderDateMs: 1760000000000, providerCode: "usdt", usdAmount: 10.5, }); const page = normalizeCoinSellerRechargeOrderPage({ items: [ { app_code: "lalu", coin_amount: 100000, created_at_ms: 1760000000000, external_order_no: "MIFA-001", grant_status: "pending", id: "order-1", provider_code: "mifapay", order_date_ms: 1759900000000, remark: "人工补单", target_display_user_id: "165075", target_user_id: "10001", usd_amount: "10.50", verify_status: "verified", wallet_transaction_id: "wallet-tx", }, ], page: 1, page_size: 50, total: 1, }); expect(page.items[0]).toMatchObject({ appCode: "lalu", coinAmount: 100000, externalOrderNo: "MIFA-001", id: "order-1", orderDateMs: 1759900000000, providerCode: "mifapay", remark: "人工补单", targetDisplayUserId: "165075", targetUserId: "10001", verifyStatus: "verified", walletTransactionId: "wallet-tx", }); expect(coinSellerRechargeProviderLabel("mifapay")).toBe("MiFaPay"); }); test("builds coin seller recharge quotes and validates exchange rate config", () => { expect(buildCoinSellerRechargeQuotePayload({ appCode: " lalu ", targetUserId: " 123456 ", usdAmount: "150" })).toEqual({ appCode: "lalu", targetUserId: "123456", usdAmount: 150, }); const payload = buildCoinSellerRechargeExchangeRatePayload({ tiers: [ { minUsdAmount: "100", maxUsdAmount: "200", coinsPerUsd: "80000" }, { minUsdAmount: "201", maxUsdAmount: "300", coinsPerUsd: "90000" }, ], whitelist: [{ userId: " 123456 ", coinsPerUsd: "100000" }], }); expect(validateCoinSellerRechargeExchangeRatePayload(payload)).toBe(""); expect(payload).toEqual({ tiers: [ { minUsdAmount: 100, maxUsdAmount: 200, coinsPerUsd: 80000 }, { minUsdAmount: 201, maxUsdAmount: 300, coinsPerUsd: 90000 }, ], whitelist: [{ userId: "123456", coinsPerUsd: 100000 }], }); expect( validateCoinSellerRechargeExchangeRatePayload({ ...payload, tiers: [ payload.tiers[0], { minUsdAmount: 200, maxUsdAmount: 300, coinsPerUsd: 90000 }, ], }), ).toBe("USD 金额区间不能重叠"); }); test("normalizes app recharge detail list rows with optional payment fields", () => { const page = normalizeRechargeBillPage({ items: [ { app_code: "lalu", bill_amount_minor: 1299, coin_amount: 90000, command_id: "cmd-1", created_at_ms: 1760000000000, currency_code: "USD", exchange_coin_amount: 90000, exchange_usd_minor_amount: 999, external_ref: "GPA.1", paid_amount_micro: 12990000, provider_amount_minor: 1299, recharge_type: "google_play_recharge", status: "succeeded", tax_rate: "0.15", third_party_tax_deduction_minor: 195, transaction_id: "tx-google", usd_minor_amount: 999, }, ], page: 1, page_size: 50, total: 1, }); expect(page.items[0]).toMatchObject({ appCode: "lalu", billAmountMinor: 1299, coinAmount: 90000, commandId: "cmd-1", exchangeCoinAmount: 90000, exchangeUsdMinorAmount: 999, externalRef: "GPA.1", providerAmountMinor: 1299, rechargeType: "google_play_recharge", taxDeductionMinor: 195, taxRate: 0.15, transactionId: "tx-google", userPaidAmountMicro: 12990000, usdMinorAmount: 999, }); expect(rechargeTypeLabel("google_play_recharge")).toBe("谷歌充值"); });