币商扣减
This commit is contained in:
parent
7515233227
commit
0d4ce59c10
@ -108,8 +108,7 @@ func (s *AslanMongoDashboardSource) coinSellerRechargeBillUnionSQL(query CoinSel
|
||||
goldArgs := []any{s.sysOrigin}
|
||||
freightWhere := []string{
|
||||
"fbrw.sys_origin = ?",
|
||||
"fbrw.origin = 'PURCHASE'",
|
||||
"fbrw.type = 0",
|
||||
"((fbrw.origin = 'PURCHASE' AND fbrw.type = 0) OR (fbrw.origin = 'DEDUCTION' AND fbrw.type = 1))",
|
||||
"(COALESCE(fbrw.amount, 0) <> 0 OR COALESCE(fbrw.usd_quantity, 0) <> 0)",
|
||||
"ubi.country_code IS NOT NULL",
|
||||
"ubi.country_code != ''",
|
||||
@ -132,7 +131,7 @@ func (s *AslanMongoDashboardSource) coinSellerRechargeBillUnionSQL(query CoinSel
|
||||
if keyword := strings.TrimSpace(query.Keyword); keyword != "" {
|
||||
goldWhere = append(goldWhere, "(CAST(ugcr.id AS CHAR) = ? OR CONCAT('aslan-gold-coin-', ugcr.id) = ? OR CAST(ugcr.user_id AS CHAR) = ?)")
|
||||
goldArgs = append(goldArgs, keyword, keyword, keyword)
|
||||
freightWhere = append(freightWhere, "(CAST(fbrw.id AS CHAR) = ? OR CONCAT('aslan-freight-purchase-', fbrw.id) = ? OR CAST(fbrw.user_id AS CHAR) = ?)")
|
||||
freightWhere = append(freightWhere, "(CAST(fbrw.id AS CHAR) = ? OR CONCAT('aslan-freight-', LOWER(fbrw.origin), '-', fbrw.id) = ? OR CAST(fbrw.user_id AS CHAR) = ?)")
|
||||
freightArgs = append(freightArgs, keyword, keyword, keyword)
|
||||
}
|
||||
if countryFilter.Applied {
|
||||
@ -170,11 +169,18 @@ FROM user_gold_coin_recharge ugcr
|
||||
INNER JOIN user_base_info ubi ON ubi.id = ugcr.user_id
|
||||
WHERE ` + strings.Join(goldWhere, " AND ") + `
|
||||
UNION ALL
|
||||
SELECT CONCAT('aslan-freight-purchase-', fbrw.id) AS transaction_id,
|
||||
'freight_purchase' AS source,
|
||||
SELECT CONCAT('aslan-freight-', LOWER(fbrw.origin), '-', fbrw.id) AS transaction_id,
|
||||
CONCAT('freight_', LOWER(fbrw.origin)) AS source,
|
||||
fbrw.user_id,
|
||||
UPPER(ubi.country_code) AS country_code,
|
||||
CAST(CASE WHEN fbrw.amount IS NOT NULL AND fbrw.amount <> 0 THEN fbrw.amount ELSE COALESCE(fbrw.usd_quantity, 0) END AS CHAR) AS amount,
|
||||
CAST(CASE
|
||||
WHEN fbrw.origin = 'DEDUCTION' OR fbrw.type = 1 THEN -ABS(CASE
|
||||
WHEN fbrw.amount IS NOT NULL AND fbrw.amount <> 0 THEN fbrw.amount
|
||||
ELSE COALESCE(fbrw.usd_quantity, 0)
|
||||
END)
|
||||
WHEN fbrw.amount IS NOT NULL AND fbrw.amount <> 0 THEN fbrw.amount
|
||||
ELSE COALESCE(fbrw.usd_quantity, 0)
|
||||
END AS CHAR) AS amount,
|
||||
fbrw.create_time AS created_at
|
||||
FROM ` + quoteMySQLIdentifier(walletDatabase) + `.user_freight_balance_running_water fbrw
|
||||
INNER JOIN user_base_info ubi ON ubi.id = fbrw.user_id
|
||||
|
||||
@ -836,7 +836,7 @@ func (s *AslanMongoDashboardSource) loadLegacyCoinSellerRechargeStats(ctx contex
|
||||
if err := s.loadLegacyGoldCoinRechargeStats(ctx, startDate, endDate, countryFilter, grid, distinctUsers, perUser); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.loadLegacyFreightPurchaseRechargeStats(ctx, startDate, endDate, countryFilter, grid, distinctUsers, perUser); err != nil {
|
||||
if err := s.loadLegacyFreightStockRechargeStats(ctx, startDate, endDate, countryFilter, grid, distinctUsers, perUser); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -912,17 +912,17 @@ GROUP BY DATE_FORMAT(ugcr.create_time, '%Y-%m-%d'), UPPER(ubi.country_code), ugc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *AslanMongoDashboardSource) loadLegacyFreightPurchaseRechargeStats(ctx context.Context, startDate time.Time, endDate time.Time, countryFilter externalDashboardCountryFilter, grid *legacyMongoGrid, distinctUsers map[aslanMongoDayCountryUsers]map[string]struct{}, perUser map[string]map[int64]int64) error {
|
||||
func (s *AslanMongoDashboardSource) loadLegacyFreightStockRechargeStats(ctx context.Context, startDate time.Time, endDate time.Time, countryFilter externalDashboardCountryFilter, grid *legacyMongoGrid, distinctUsers map[aslanMongoDayCountryUsers]map[string]struct{}, perUser map[string]map[int64]int64) error {
|
||||
walletDatabase := strings.TrimSpace(s.legacyWalletDatabase)
|
||||
if walletDatabase == "" {
|
||||
return nil
|
||||
}
|
||||
// 后台“金币代理 > 发货”实际是给代理进货:origin=PURCHASE/type=0,表单金额落 amount;
|
||||
// “扣减”是库存/USDT 冲减:origin=DEDUCTION/type=1,amount 在源系统仍是正数,统计时必须转成负数。
|
||||
// App/经销商路径可能只落 usd_quantity,因此金额优先取 amount,空值再回退 usd_quantity。
|
||||
where := []string{
|
||||
"fbrw.sys_origin = ?",
|
||||
"fbrw.origin = 'PURCHASE'",
|
||||
"fbrw.type = 0",
|
||||
"((fbrw.origin = 'PURCHASE' AND fbrw.type = 0) OR (fbrw.origin = 'DEDUCTION' AND fbrw.type = 1))",
|
||||
"fbrw.create_time >= ?",
|
||||
"fbrw.create_time < ?",
|
||||
"(COALESCE(fbrw.amount, 0) <> 0 OR COALESCE(fbrw.usd_quantity, 0) <> 0)",
|
||||
@ -956,6 +956,10 @@ SELECT DATE_FORMAT(fbrw.create_time, '%Y-%m-%d') AS stat_day,
|
||||
UPPER(ubi.country_code) AS country_code,
|
||||
fbrw.user_id,
|
||||
CAST(COALESCE(SUM(CASE
|
||||
WHEN fbrw.origin = 'DEDUCTION' OR fbrw.type = 1 THEN -ABS(CASE
|
||||
WHEN fbrw.amount IS NOT NULL AND fbrw.amount <> 0 THEN fbrw.amount
|
||||
ELSE COALESCE(fbrw.usd_quantity, 0)
|
||||
END)
|
||||
WHEN fbrw.amount IS NOT NULL AND fbrw.amount <> 0 THEN fbrw.amount
|
||||
ELSE COALESCE(fbrw.usd_quantity, 0)
|
||||
END), 0) AS CHAR) AS amount
|
||||
@ -964,7 +968,7 @@ FROM `+quoteMySQLIdentifier(walletDatabase)+`.user_freight_balance_running_water
|
||||
WHERE `+strings.Join(where, " AND ")+`
|
||||
GROUP BY DATE_FORMAT(fbrw.create_time, '%Y-%m-%d'), UPPER(ubi.country_code), fbrw.user_id`, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("query legacy freight purchase recharge: %w", err)
|
||||
return fmt.Errorf("query legacy freight stock recharge: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
@ -974,7 +978,7 @@ GROUP BY DATE_FORMAT(fbrw.create_time, '%Y-%m-%d'), UPPER(ubi.country_code), fbr
|
||||
var userID int64
|
||||
var amountText string
|
||||
if err := rows.Scan(&day, &countryCode, &userID, &amountText); err != nil {
|
||||
return fmt.Errorf("scan legacy freight purchase recharge: %w", err)
|
||||
return fmt.Errorf("scan legacy freight stock recharge: %w", err)
|
||||
}
|
||||
day = strings.TrimSpace(day)
|
||||
countryCode = aslanMongoCountryCode(countryCode)
|
||||
@ -983,24 +987,27 @@ GROUP BY DATE_FORMAT(fbrw.create_time, '%Y-%m-%d'), UPPER(ubi.country_code), fbr
|
||||
}
|
||||
amount, err := decimalTextToMinor(amountText)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parse legacy freight purchase recharge amount for %s/%s/%d: %w", day, countryCode, userID, err)
|
||||
return fmt.Errorf("parse legacy freight stock recharge amount for %s/%s/%d: %w", day, countryCode, userID, err)
|
||||
}
|
||||
addLegacyCoinSellerRecharge(grid, distinctUsers, perUser, day, countryCode, userID, amount)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return fmt.Errorf("iterate legacy freight purchase recharge: %w", err)
|
||||
return fmt.Errorf("iterate legacy freight stock recharge: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addLegacyCoinSellerRecharge(grid *legacyMongoGrid, distinctUsers map[aslanMongoDayCountryUsers]map[string]struct{}, perUser map[string]map[int64]int64, day string, countryCode string, userID int64, amount int64) {
|
||||
if amount <= 0 {
|
||||
if amount == 0 {
|
||||
return
|
||||
}
|
||||
metric := grid.at(day, countryCode)
|
||||
metric.RechargeUSDMinor += amount
|
||||
metric.CoinSellerRechargeUSDMinor += amount
|
||||
addLegacyRechargeUser(distinctUsers, perUser, day, countryCode, userID, amount)
|
||||
// 扣减流水按负数冲减金额,但不是一次新的付费行为,不能增加付费用户或新用户充值。
|
||||
if amount > 0 {
|
||||
addLegacyRechargeUser(distinctUsers, perUser, day, countryCode, userID, amount)
|
||||
}
|
||||
}
|
||||
|
||||
func addLegacyStandardRecharge(grid *legacyMongoGrid, distinctUsers map[aslanMongoDayCountryUsers]map[string]struct{}, perUser map[string]map[int64]int64, day string, countryCode string, userID int64, amount int64) {
|
||||
@ -1748,7 +1755,7 @@ func aslanMongoDashboardMetricSources(goldWater bool, legacyRecharge bool) []map
|
||||
}
|
||||
}
|
||||
legacySources := []map[string]any{
|
||||
{"field": "coin_seller_recharge_usd_minor", "available": true, "source": "likei legacy MySQL user_gold_coin_recharge gold_coin_source=2 recharge_amount + user_freight_balance_running_water PURCHASE amount/usd_quantity"},
|
||||
{"field": "coin_seller_recharge_usd_minor", "available": true, "source": "likei legacy MySQL user_gold_coin_recharge gold_coin_source=2 recharge_amount + user_freight_balance_running_water PURCHASE amount/usd_quantity - DEDUCTION amount/usd_quantity"},
|
||||
}
|
||||
rechargeUsersSource := "likei Mongo in_app_purchase_details SUCCESS distinct acceptUserId(排除 FREIGHT_GOLD)"
|
||||
rechargeAmountSource := "likei Mongo in_app_purchase_details amountUsd(排除 FREIGHT_GOLD)"
|
||||
@ -1760,7 +1767,7 @@ func aslanMongoDashboardMetricSources(goldWater bool, legacyRecharge bool) []map
|
||||
}
|
||||
} else {
|
||||
rechargeUsersSource += " + legacy MySQL order_other_recharge/user_gold_coin_recharge/user_freight_balance_running_water distinct user_id"
|
||||
rechargeAmountSource += " + legacy MySQL order_other_recharge amount + user_gold_coin_recharge recharge_amount + user_freight_balance_running_water PURCHASE amount/usd_quantity"
|
||||
rechargeAmountSource += " + legacy MySQL order_other_recharge amount + user_gold_coin_recharge recharge_amount + user_freight_balance_running_water PURCHASE amount/usd_quantity - DEDUCTION amount/usd_quantity"
|
||||
mifaPaySource += " + legacy MySQL order_other_recharge amount"
|
||||
newUserRechargeSource += "/legacy 其他充值/legacy 币商充值"
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ func TestAslanMongoLegacyOtherRechargeFeedsThirdPartyChannel(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAslanMongoLegacyFreightPurchaseRechargeFeedsCoinSellerChannel(t *testing.T) {
|
||||
func TestAslanMongoLegacyFreightStockAdjustmentsFeedCoinSellerChannel(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("sqlmock: %v", err)
|
||||
@ -196,11 +196,12 @@ func TestAslanMongoLegacyFreightPurchaseRechargeFeedsCoinSellerChannel(t *testin
|
||||
mock.ExpectQuery("FROM user_gold_coin_recharge[\\s\\S]*ugcr\\.gold_coin_source = 2").
|
||||
WithArgs("ATYOU", start, end).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"stat_day", "country_code", "user_id", "amount"}))
|
||||
mock.ExpectQuery("FROM `atyou_wallet`\\.user_freight_balance_running_water fbrw[\\s\\S]*fbrw\\.origin = 'PURCHASE'[\\s\\S]*fbrw\\.type = 0").
|
||||
mock.ExpectQuery("FROM `atyou_wallet`\\.user_freight_balance_running_water fbrw[\\s\\S]*fbrw\\.origin = 'PURCHASE'[\\s\\S]*fbrw\\.origin = 'DEDUCTION'").
|
||||
WithArgs("ATYOU", start, end).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"stat_day", "country_code", "user_id", "amount"}).
|
||||
AddRow("2026-07-05", "PH", int64(2069828597070528514), "2000.00").
|
||||
AddRow("2026-07-05", "PK", int64(2071589123112779777), "25.47"))
|
||||
AddRow("2026-07-05", "PK", int64(2071589123112779777), "25.47").
|
||||
AddRow("2026-07-05", "SA", int64(2071589123112779778), "-1000.00"))
|
||||
|
||||
if err := source.loadLegacyCoinSellerRechargeStats(context.Background(), start, end, externalDashboardCountryFilter{}, grid, distinctUsers, perUser); err != nil {
|
||||
t.Fatalf("loadLegacyCoinSellerRechargeStats: %v", err)
|
||||
@ -218,6 +219,12 @@ func TestAslanMongoLegacyFreightPurchaseRechargeFeedsCoinSellerChannel(t *testin
|
||||
assertInt64(t, pkRow["coin_seller_recharge_usd_minor"], 2547)
|
||||
assertInt64(t, pkRow["recharge_usd_minor"], 2547)
|
||||
|
||||
saRow := grid.metrics["2026-07-05"]["SA"].toExternal(nil).toMap()
|
||||
assertInt64(t, saRow["coin_seller_recharge_usd_minor"], -100000)
|
||||
assertInt64(t, saRow["recharge_usd_minor"], -100000)
|
||||
assertInt64(t, saRow["user_recharge_usd_minor"], 0)
|
||||
assertInt64(t, saRow["paid_users"], 0)
|
||||
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("sql expectations: %v", err)
|
||||
}
|
||||
@ -244,10 +251,11 @@ func TestAslanMongoListCoinSellerRechargeBills(t *testing.T) {
|
||||
queryPattern := "FROM user_gold_coin_recharge ugcr[\\s\\S]*UNION ALL[\\s\\S]*FROM `atyou_wallet`\\.user_freight_balance_running_water fbrw"
|
||||
mock.ExpectQuery("SELECT COUNT\\(\\*\\) FROM \\([\\s\\S]*"+queryPattern).
|
||||
WithArgs("ATYOU", startArg, endArg, "ATYOU", startArg, endArg).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(int64(2)))
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(int64(3)))
|
||||
mock.ExpectQuery("SELECT transaction_id, source, user_id, country_code, amount, created_at[\\s\\S]*"+queryPattern).
|
||||
WithArgs("ATYOU", startArg, endArg, "ATYOU", startArg, endArg, 10, 0).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"transaction_id", "source", "user_id", "country_code", "amount", "created_at"}).
|
||||
AddRow("aslan-freight-deduction-100", "freight_deduction", int64(2069828597070528516), "ae", "-1000.00", createdAt.Add(time.Minute)).
|
||||
AddRow("aslan-freight-purchase-99", "freight_purchase", int64(2069828597070528514), "ph", "1327.90", createdAt).
|
||||
AddRow("aslan-gold-coin-7", "gold_coin_recharge", int64(2069828597070528515), "SA", "42.00", createdAt.Add(-time.Hour)))
|
||||
|
||||
@ -260,18 +268,21 @@ func TestAslanMongoListCoinSellerRechargeBills(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("ListCoinSellerRechargeBills: %v", err)
|
||||
}
|
||||
if total != 2 || len(items) != 2 {
|
||||
if total != 3 || len(items) != 3 {
|
||||
t.Fatalf("unexpected result total=%d items=%+v", total, items)
|
||||
}
|
||||
if items[0].TransactionID != "aslan-freight-purchase-99" || items[0].Source != "freight_purchase" || items[0].CountryCode != "PH" {
|
||||
if items[0].TransactionID != "aslan-freight-deduction-100" || items[0].Source != "freight_deduction" || items[0].CountryCode != "AE" {
|
||||
t.Fatalf("unexpected first item identity: %+v", items[0])
|
||||
}
|
||||
if items[0].USDMinorAmount != 132790 || items[0].CreatedAtMS != createdAt.UnixMilli() {
|
||||
if items[0].USDMinorAmount != -100000 || items[0].CreatedAtMS != createdAt.Add(time.Minute).UnixMilli() {
|
||||
t.Fatalf("unexpected first item amount/time: %+v", items[0])
|
||||
}
|
||||
if items[1].TransactionID != "aslan-gold-coin-7" || items[1].USDMinorAmount != 4200 {
|
||||
if items[1].TransactionID != "aslan-freight-purchase-99" || items[1].USDMinorAmount != 132790 {
|
||||
t.Fatalf("unexpected second item: %+v", items[1])
|
||||
}
|
||||
if items[2].TransactionID != "aslan-gold-coin-7" || items[2].USDMinorAmount != 4200 {
|
||||
t.Fatalf("unexpected third item: %+v", items[2])
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("sql expectations: %v", err)
|
||||
}
|
||||
@ -300,24 +311,31 @@ func TestAslanMongoRechargeMatchExcludesFreightGold(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAslanMongoLegacyRechargeSkipsNonPositiveAmount(t *testing.T) {
|
||||
func TestAslanMongoLegacyRechargeHandlesZeroAndDeductionAmount(t *testing.T) {
|
||||
start := time.Date(2026, 7, 5, 0, 0, 0, 0, time.UTC)
|
||||
grid := newLegacyMongoGrid(start, start.AddDate(0, 0, 1))
|
||||
distinctUsers := map[aslanMongoDayCountryUsers]map[string]struct{}{}
|
||||
perUser := map[string]map[int64]int64{}
|
||||
|
||||
addLegacyStandardRecharge(grid, distinctUsers, perUser, "2026-07-05", "SA", 101, 0)
|
||||
addLegacyCoinSellerRecharge(grid, distinctUsers, perUser, "2026-07-05", "SA", 102, -100)
|
||||
addLegacyCoinSellerRecharge(grid, distinctUsers, perUser, "2026-07-05", "SA", 102, 0)
|
||||
if row := grid.metrics["2026-07-05"]["SA"]; row != nil {
|
||||
t.Fatalf("zero legacy recharge should not create metric row: %#v", row)
|
||||
}
|
||||
|
||||
addLegacyCoinSellerRecharge(grid, distinctUsers, perUser, "2026-07-05", "SA", 102, -100)
|
||||
row := grid.metrics["2026-07-05"]["SA"]
|
||||
if row != nil {
|
||||
t.Fatalf("non-positive legacy recharge should not create metric row: %#v", row)
|
||||
if row == nil {
|
||||
t.Fatalf("negative coin seller deduction should create metric row")
|
||||
}
|
||||
if row.RechargeUSDMinor != -100 || row.CoinSellerRechargeUSDMinor != -100 {
|
||||
t.Fatalf("deduction should reduce recharge metrics: %#v", row)
|
||||
}
|
||||
if len(distinctUsers) != 0 {
|
||||
t.Fatalf("non-positive legacy recharge should not create paid users: %#v", distinctUsers)
|
||||
t.Fatalf("deduction should not create paid users: %#v", distinctUsers)
|
||||
}
|
||||
if len(perUser) != 0 {
|
||||
t.Fatalf("non-positive legacy recharge should not create per-user recharge: %#v", perUser)
|
||||
t.Fatalf("deduction should not create per-user recharge: %#v", perUser)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -296,7 +296,7 @@ func (s *MongoRechargeBillSource) listCoinSellerRechargeBills(ctx context.Contex
|
||||
item := rechargeBillDTO{
|
||||
AppCode: s.config.AppCode,
|
||||
TransactionID: row.TransactionID,
|
||||
RechargeType: "coin_seller_stock_purchase",
|
||||
RechargeType: legacyCoinSellerBillRechargeType(row.Source),
|
||||
Status: "succeeded",
|
||||
ExternalRef: row.Source,
|
||||
SellerUserID: row.UserID,
|
||||
@ -318,6 +318,15 @@ func (s *MongoRechargeBillSource) listCoinSellerRechargeBills(ctx context.Contex
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
func legacyCoinSellerBillRechargeType(source string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(source)) {
|
||||
case "freight_deduction", "coin_seller_stock_deduction":
|
||||
return "coin_seller_stock_deduction"
|
||||
default:
|
||||
return "coin_seller_stock_purchase"
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MongoRechargeBillSource) listBillsByFilter(ctx context.Context, filter bson.M, page int, pageSize int) ([]rechargeBillDTO, int64, error) {
|
||||
total, err := s.collection.CountDocuments(ctx, filter)
|
||||
if err != nil {
|
||||
|
||||
@ -237,15 +237,25 @@ func (s *fakeDashboardRechargeSource) ListCoinSellerRechargeBills(_ context.Cont
|
||||
func TestLegacyCoinSellerListUsesDashboardBillSource(t *testing.T) {
|
||||
dashboardSource := &fakeDashboardRechargeSource{
|
||||
appCode: "aslan",
|
||||
billTotal: 1,
|
||||
bills: []dashboard.CoinSellerRechargeBill{{
|
||||
TransactionID: "aslan-freight-purchase-99",
|
||||
Source: "freight_purchase",
|
||||
UserID: 2069828597070528514,
|
||||
CountryCode: "PH",
|
||||
USDMinorAmount: 132790,
|
||||
CreatedAtMS: 1_783_530_000_000,
|
||||
}},
|
||||
billTotal: 2,
|
||||
bills: []dashboard.CoinSellerRechargeBill{
|
||||
{
|
||||
TransactionID: "aslan-freight-purchase-99",
|
||||
Source: "freight_purchase",
|
||||
UserID: 2069828597070528514,
|
||||
CountryCode: "PH",
|
||||
USDMinorAmount: 132790,
|
||||
CreatedAtMS: 1_783_530_000_000,
|
||||
},
|
||||
{
|
||||
TransactionID: "aslan-freight-deduction-100",
|
||||
Source: "freight_deduction",
|
||||
UserID: 2069828597070528515,
|
||||
CountryCode: "AE",
|
||||
USDMinorAmount: -100000,
|
||||
CreatedAtMS: 1_783_530_060_000,
|
||||
},
|
||||
},
|
||||
}
|
||||
source := &MongoRechargeBillSource{
|
||||
config: aslanBillSourceConfig(),
|
||||
@ -254,6 +264,11 @@ func TestLegacyCoinSellerListUsesDashboardBillSource(t *testing.T) {
|
||||
RegionID: 301,
|
||||
Name: "Philippines",
|
||||
Countries: []string{"PH"},
|
||||
}, {
|
||||
AppCode: "aslan",
|
||||
RegionID: 302,
|
||||
Name: "United Arab Emirates",
|
||||
Countries: []string{"AE"},
|
||||
}}}},
|
||||
}
|
||||
source.SetDashboardCoinSellerSource(dashboardSource)
|
||||
@ -268,7 +283,7 @@ func TestLegacyCoinSellerListUsesDashboardBillSource(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("ListRechargeBills: %v", err)
|
||||
}
|
||||
if total != 1 || len(items) != 1 {
|
||||
if total != 2 || len(items) != 2 {
|
||||
t.Fatalf("unexpected result total=%d items=%+v", total, items)
|
||||
}
|
||||
item := items[0]
|
||||
@ -284,6 +299,19 @@ func TestLegacyCoinSellerListUsesDashboardBillSource(t *testing.T) {
|
||||
if item.UserPaidCurrencyCode != "USD" || item.UserPaidAmountMicro != 1_327_900_000 {
|
||||
t.Fatalf("paid facts mismatch: %+v", item)
|
||||
}
|
||||
deduction := items[1]
|
||||
if deduction.RechargeType != "coin_seller_stock_deduction" || deduction.ProviderCode != "coin_seller" {
|
||||
t.Fatalf("unexpected deduction mapping: %+v", deduction)
|
||||
}
|
||||
if deduction.TransactionID != "aslan-freight-deduction-100" || deduction.SellerUserID != 2069828597070528515 || deduction.USDMinorAmount != -100000 {
|
||||
t.Fatalf("unexpected deduction fields: %+v", deduction)
|
||||
}
|
||||
if deduction.SellerRegionID != 302 || deduction.TargetRegionID != 302 {
|
||||
t.Fatalf("deduction region mapping failed: %+v", deduction)
|
||||
}
|
||||
if deduction.UserPaidCurrencyCode != "USD" || deduction.UserPaidAmountMicro != -1_000_000_000 {
|
||||
t.Fatalf("deduction paid facts mismatch: %+v", deduction)
|
||||
}
|
||||
if dashboardSource.billCalls != 1 || dashboardSource.billQuery.PageSize != 20 || dashboardSource.billQuery.StatTZ != "Asia/Shanghai" {
|
||||
t.Fatalf("dashboard bill source not called as expected: calls=%d query=%+v", dashboardSource.billCalls, dashboardSource.billQuery)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user