114 lines
4.4 KiB
Go
114 lines
4.4 KiB
Go
package mysql
|
||
|
||
import (
|
||
"context"
|
||
"database/sql"
|
||
"errors"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"hyapp/pkg/appcode"
|
||
"hyapp/pkg/xerr"
|
||
"hyapp/services/wallet-service/internal/domain/ledger"
|
||
)
|
||
|
||
const (
|
||
// charge_amount 是 ca15f098 上线时的兼容口径:Agency 比例直接作用于礼物实扣金额,
|
||
// 因而主播比例与 Agency 比例必须共同受 100% 资金池约束。
|
||
agencyPointShareBaseChargeAmount = "charge_amount"
|
||
// host_income 表示平台在主播本次实际 POINT 收益之外追加 Agency 奖励。
|
||
// 该口径先完成礼物类型和主播政策换算,再对最终主播收益取比例,允许出现 100%+20%。
|
||
agencyPointShareBaseHostIncome = "host_income"
|
||
)
|
||
|
||
type walletPolicyInstance struct {
|
||
InstanceCode string
|
||
TemplateCode string
|
||
TemplateVersion string
|
||
RegionID int64
|
||
HostPointAsset string
|
||
HostPointRatioPPM int64
|
||
HostGiftTypeRatioEnabled bool
|
||
AgencyPointRatioPPM int64
|
||
AgencyPointShareBase string
|
||
PointsPerUSD int64
|
||
WithdrawFeeBPS int64
|
||
}
|
||
|
||
func (r *Repository) resolveActiveWalletPolicy(ctx context.Context, tx *sql.Tx, appCode string, regionID int64, nowMS int64) (walletPolicyInstance, bool, error) {
|
||
appCode = appcode.Normalize(appCode)
|
||
if regionID < 0 {
|
||
return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "region_id is invalid")
|
||
}
|
||
row := tx.QueryRowContext(ctx, `
|
||
SELECT instance_code, template_code, template_version, region_id, host_point_asset_type,
|
||
host_point_ratio_ppm,
|
||
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(rule_json, '$.host.use_gift_type_ratio')), 'false'),
|
||
agency_point_ratio_ppm,
|
||
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(rule_json, '$.agency.share_base')), 'charge_amount'),
|
||
points_per_usd, withdraw_fee_bps
|
||
FROM wallet_policy_instances
|
||
WHERE app_code = ?
|
||
AND region_id IN (?, 0)
|
||
AND status = 'active'
|
||
AND effective_from_ms <= ?
|
||
AND (effective_to_ms = 0 OR effective_to_ms > ?)
|
||
ORDER BY CASE WHEN region_id = ? THEN 0 ELSE 1 END, published_at_ms DESC, instance_code DESC
|
||
LIMIT 1`,
|
||
appCode, regionID, nowMS, nowMS, regionID,
|
||
)
|
||
var item walletPolicyInstance
|
||
var hostGiftTypeRatioRaw string
|
||
if err := row.Scan(
|
||
&item.InstanceCode,
|
||
&item.TemplateCode,
|
||
&item.TemplateVersion,
|
||
&item.RegionID,
|
||
&item.HostPointAsset,
|
||
&item.HostPointRatioPPM,
|
||
&hostGiftTypeRatioRaw,
|
||
&item.AgencyPointRatioPPM,
|
||
&item.AgencyPointShareBase,
|
||
&item.PointsPerUSD,
|
||
&item.WithdrawFeeBPS,
|
||
); err != nil {
|
||
if errors.Is(err, sql.ErrNoRows) {
|
||
return walletPolicyInstance{}, false, nil
|
||
}
|
||
return walletPolicyInstance{}, false, err
|
||
}
|
||
item.HostPointAsset = strings.ToUpper(strings.TrimSpace(item.HostPointAsset))
|
||
if item.HostPointAsset == "" {
|
||
item.HostPointAsset = ledger.AssetPoint
|
||
}
|
||
parsedGiftTypeRatio, err := strconv.ParseBool(strings.ToLower(strings.TrimSpace(hostGiftTypeRatioRaw)))
|
||
if err != nil {
|
||
return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy host gift type ratio flag is invalid")
|
||
}
|
||
item.HostGiftTypeRatioEnabled = parsedGiftTypeRatio
|
||
item.AgencyPointShareBase = strings.ToLower(strings.TrimSpace(item.AgencyPointShareBase))
|
||
if item.AgencyPointShareBase == "" {
|
||
item.AgencyPointShareBase = agencyPointShareBaseChargeAmount
|
||
}
|
||
if item.HostPointAsset != ledger.AssetPoint ||
|
||
item.HostPointRatioPPM <= 0 || item.HostPointRatioPPM > 1_000_000 ||
|
||
item.AgencyPointRatioPPM < 0 || item.AgencyPointRatioPPM > 1_000_000 ||
|
||
item.PointsPerUSD <= 0 || item.WithdrawFeeBPS < 0 || item.WithdrawFeeBPS > 10_000 {
|
||
return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy instance is invalid")
|
||
}
|
||
switch item.AgencyPointShareBase {
|
||
case agencyPointShareBaseChargeAmount:
|
||
// 旧实例没有 share_base,必须继续执行原先的总资金池守恒约束;否则一次重新发布就会
|
||
// 把历史 70%+20% 配置悄然解释成可超发政策。
|
||
if item.HostPointRatioPPM+item.AgencyPointRatioPPM > 1_000_000 {
|
||
return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy instance is invalid")
|
||
}
|
||
case agencyPointShareBaseHostIncome:
|
||
// host_income 是额外平台奖励,Agency 百分比相对于主播实际到账值独立校验,不能与
|
||
// host_point_ratio_ppm 相加后套用旧的 100% 上限。
|
||
default:
|
||
return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy agency share base is invalid")
|
||
}
|
||
return item, true, nil
|
||
}
|