2026-06-25 21:30:26 +08:00

443 lines
17 KiB
Go

package mysql
import (
"context"
"database/sql"
"encoding/json"
"strings"
"hyapp/pkg/appcode"
"hyapp/services/wallet-service/internal/domain/ledger"
resourcedomain "hyapp/services/wallet-service/internal/domain/resource"
)
func (r *Repository) receiptForGiftTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.Receipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.Receipt{}, err
}
var metadata giftMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.Receipt{}, err
}
return receiptFromGiftMetadata(transactionID, metadata), nil
}
func receiptFromGiftMetadata(transactionID string, metadata giftMetadata) ledger.Receipt {
chargeAssetType := ledger.NormalizeGiftChargeAssetType(metadata.ChargeAssetType)
if metadata.RobotGift {
chargeAssetType = ledger.AssetRobotCoin
}
chargeAmount := metadata.ChargeAmount
if chargeAmount == 0 {
chargeAmount = metadata.CoinSpent
}
return ledger.Receipt{
BillingReceiptID: metadata.BillingReceipt,
TransactionID: transactionID,
CoinSpent: metadata.CoinSpent,
ChargeAssetType: chargeAssetType,
ChargeAmount: chargeAmount,
GiftPointAdded: 0,
HeatValue: metadata.HeatValue,
GiftTypeCode: metadata.GiftTypeCode,
CPRelationType: metadata.CPRelationType,
GiftName: metadata.GiftName,
GiftIconURL: metadata.GiftIconURL,
GiftAnimationURL: metadata.GiftAnimationURL,
GiftEffectTypes: normalizeGiftEffectTypes(metadata.GiftEffectTypes),
PriceVersion: metadata.PriceVersion,
BalanceAfter: metadata.BalanceAfter,
HostPeriodDiamondAdded: metadata.HostPeriodDiamondAdded,
HostPeriodCycleKey: metadata.HostPeriodCycleKey,
EntitlementID: strings.TrimSpace(metadata.EntitlementID),
ChargeSource: normalizeGiftChargeSource(metadata.ChargeSource, metadata.EntitlementID),
GiftIncomeCoinAmount: metadata.GiftIncomeCoinAmount,
GiftIncomeBalanceAfter: metadata.GiftIncomeBalanceAfter,
}
}
func giftDisplayIconURL(resource resourcedomain.Resource) string {
if value := strings.TrimSpace(resource.PreviewURL); value != "" {
return value
}
return strings.TrimSpace(resource.AssetURL)
}
func (r *Repository) receiptForTaskRewardTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.TaskRewardReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.TaskRewardReceipt{}, err
}
var metadata taskRewardMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.TaskRewardReceipt{}, err
}
return receiptFromTaskRewardMetadata(transactionID, metadata), nil
}
func receiptFromTaskRewardMetadata(transactionID string, metadata taskRewardMetadata) ledger.TaskRewardReceipt {
return ledger.TaskRewardReceipt{
TransactionID: transactionID,
Balance: ledger.AssetBalance{
AppCode: metadata.AppCode,
UserID: metadata.TargetUserID,
AssetType: metadata.AssetType,
AvailableAmount: metadata.BalanceAfter,
},
Amount: metadata.Amount,
GrantedAtMS: metadata.GrantedAtMS,
}
}
func (r *Repository) receiptForLuckyGiftRewardTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.LuckyGiftRewardReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.LuckyGiftRewardReceipt{}, err
}
var metadata luckyGiftRewardMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.LuckyGiftRewardReceipt{}, err
}
return receiptFromLuckyGiftRewardMetadata(transactionID, metadata), nil
}
func receiptFromLuckyGiftRewardMetadata(transactionID string, metadata luckyGiftRewardMetadata) ledger.LuckyGiftRewardReceipt {
return ledger.LuckyGiftRewardReceipt{
TransactionID: transactionID,
Balance: ledger.AssetBalance{
AppCode: metadata.AppCode,
UserID: metadata.TargetUserID,
AssetType: metadata.AssetType,
AvailableAmount: metadata.BalanceAfter,
},
Amount: metadata.Amount,
GrantedAtMS: metadata.GrantedAtMS,
}
}
func (r *Repository) receiptForWheelRewardTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.WheelRewardReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.WheelRewardReceipt{}, err
}
var metadata wheelRewardMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.WheelRewardReceipt{}, err
}
return receiptFromWheelRewardMetadata(transactionID, metadata), nil
}
func receiptFromWheelRewardMetadata(transactionID string, metadata wheelRewardMetadata) ledger.WheelRewardReceipt {
return ledger.WheelRewardReceipt{
TransactionID: transactionID,
Balance: ledger.AssetBalance{
AppCode: metadata.AppCode,
UserID: metadata.TargetUserID,
AssetType: metadata.AssetType,
AvailableAmount: metadata.BalanceAfter,
},
Amount: metadata.Amount,
GrantedAtMS: metadata.GrantedAtMS,
}
}
func (r *Repository) receiptForRoomTurnoverRewardTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.RoomTurnoverRewardReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.RoomTurnoverRewardReceipt{}, err
}
var metadata roomTurnoverRewardMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.RoomTurnoverRewardReceipt{}, err
}
return receiptFromRoomTurnoverRewardMetadata(transactionID, metadata), nil
}
func receiptFromRoomTurnoverRewardMetadata(transactionID string, metadata roomTurnoverRewardMetadata) ledger.RoomTurnoverRewardReceipt {
return ledger.RoomTurnoverRewardReceipt{
TransactionID: transactionID,
Balance: ledger.AssetBalance{
AppCode: metadata.AppCode,
UserID: metadata.TargetUserID,
AssetType: metadata.AssetType,
AvailableAmount: metadata.BalanceAfter,
},
Amount: metadata.Amount,
GrantedAtMS: metadata.GrantedAtMS,
}
}
func (r *Repository) receiptForInviteActivityRewardTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.InviteActivityRewardReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.InviteActivityRewardReceipt{}, err
}
var metadata inviteActivityRewardMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.InviteActivityRewardReceipt{}, err
}
return receiptFromInviteActivityRewardMetadata(transactionID, metadata), nil
}
func receiptFromInviteActivityRewardMetadata(transactionID string, metadata inviteActivityRewardMetadata) ledger.InviteActivityRewardReceipt {
return ledger.InviteActivityRewardReceipt{
TransactionID: transactionID,
Balance: ledger.AssetBalance{
AppCode: metadata.AppCode,
UserID: metadata.TargetUserID,
AssetType: metadata.AssetType,
AvailableAmount: metadata.BalanceAfter,
},
Amount: metadata.Amount,
GrantedAtMS: metadata.GrantedAtMS,
}
}
func (r *Repository) receiptForAgencyOpeningRewardTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.AgencyOpeningRewardReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.AgencyOpeningRewardReceipt{}, err
}
var metadata agencyOpeningRewardMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.AgencyOpeningRewardReceipt{}, err
}
return receiptFromAgencyOpeningRewardMetadata(transactionID, metadata), nil
}
func receiptFromAgencyOpeningRewardMetadata(transactionID string, metadata agencyOpeningRewardMetadata) ledger.AgencyOpeningRewardReceipt {
return ledger.AgencyOpeningRewardReceipt{
TransactionID: transactionID,
Balance: ledger.AssetBalance{
AppCode: metadata.AppCode,
UserID: metadata.TargetUserID,
AssetType: metadata.AssetType,
AvailableAmount: metadata.BalanceAfter,
},
Amount: metadata.Amount,
GrantedAtMS: metadata.GrantedAtMS,
}
}
func (r *Repository) receiptForGameTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.GameCoinChangeReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.GameCoinChangeReceipt{}, err
}
var metadata gameCoinMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.GameCoinChangeReceipt{}, err
}
return receiptFromGameMetadata(transactionID, metadata, false), nil
}
func receiptFromGameMetadata(transactionID string, metadata gameCoinMetadata, idempotentReplay bool) ledger.GameCoinChangeReceipt {
return ledger.GameCoinChangeReceipt{
TransactionID: transactionID,
BalanceAfter: metadata.BalanceAfter,
IdempotentReplay: idempotentReplay,
}
}
func (r *Repository) receiptForCoinSellerStockTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.CoinSellerStockCreditReceipt, error) {
row := tx.QueryRowContext(ctx,
`SELECT seller_user_id, stock_type, coin_amount, paid_currency_code, paid_amount_micro,
counts_as_seller_recharge, balance_after, metadata_json, created_at_ms
FROM coin_seller_stock_records
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
)
var receipt ledger.CoinSellerStockCreditReceipt
var metadataJSON string
if err := row.Scan(
&receipt.SellerUserID,
&receipt.StockType,
&receipt.CoinAmount,
&receipt.PaidCurrencyCode,
&receipt.PaidAmountMicro,
&receipt.CountsAsSellerRecharge,
&receipt.BalanceAfter,
&metadataJSON,
&receipt.CreatedAtMS,
); err != nil {
return ledger.CoinSellerStockCreditReceipt{}, err
}
if metadataJSON != "" {
var metadata coinSellerStockMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err == nil {
receipt.SellerCountryID = metadata.SellerCountryID
receipt.SellerRegionID = metadata.SellerRegionID
}
}
receipt.TransactionID = transactionID
return receipt, nil
}
func receiptFromCoinSellerStockMetadata(transactionID string, metadata coinSellerStockMetadata) ledger.CoinSellerStockCreditReceipt {
return ledger.CoinSellerStockCreditReceipt{
TransactionID: transactionID,
SellerUserID: metadata.SellerUserID,
SellerCountryID: metadata.SellerCountryID,
SellerRegionID: metadata.SellerRegionID,
StockType: metadata.StockType,
CoinAmount: metadata.CoinAmount,
PaidCurrencyCode: metadata.PaidCurrencyCode,
PaidAmountMicro: metadata.PaidAmountMicro,
CountsAsSellerRecharge: metadata.CountsAsSellerRecharge,
BalanceAfter: metadata.BalanceAfter,
CreatedAtMS: metadata.CreatedAtMS,
}
}
func (r *Repository) receiptForCoinSellerTransferTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.CoinSellerTransferReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.CoinSellerTransferReceipt{}, err
}
var metadata coinSellerTransferMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.CoinSellerTransferReceipt{}, err
}
return receiptFromCoinSellerTransferMetadata(transactionID, metadata), nil
}
func receiptFromCoinSellerTransferMetadata(transactionID string, metadata coinSellerTransferMetadata) ledger.CoinSellerTransferReceipt {
return ledger.CoinSellerTransferReceipt{
TransactionID: transactionID,
SellerBalanceAfter: metadata.SellerBalanceAfter,
TargetBalanceAfter: metadata.TargetBalanceAfter,
Amount: metadata.Amount,
RechargeSequence: metadata.RechargeSequence,
RechargeUSDMinor: metadata.RechargeUSDMinor,
RechargeCurrencyCode: metadata.RechargeCurrencyCode,
RechargePolicyID: metadata.RechargePolicyID,
RechargePolicyVersion: metadata.RechargePolicyVersion,
RechargePolicyCoinAmount: metadata.RechargePolicyCoinAmount,
RechargePolicyUSDMinorUnit: metadata.RechargePolicyUSDMinorAmount,
}
}
func (r *Repository) receiptForSalaryExchangeTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.SalaryExchangeReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.SalaryExchangeReceipt{}, err
}
var metadata salaryExchangeMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.SalaryExchangeReceipt{}, err
}
return receiptFromSalaryExchangeMetadata(transactionID, metadata), nil
}
func receiptFromSalaryExchangeMetadata(transactionID string, metadata salaryExchangeMetadata) ledger.SalaryExchangeReceipt {
return ledger.SalaryExchangeReceipt{
TransactionID: transactionID,
UserID: metadata.UserID,
SalaryAssetType: metadata.SalaryAssetType,
SalaryBalanceAfter: metadata.SalaryBalanceAfter,
CoinBalanceAfter: metadata.CoinBalanceAfter,
SalaryUSDMinor: metadata.SalaryUSDMinor,
CoinAmount: metadata.CoinAmount,
CoinPerUSD: metadata.CoinPerUSD,
CreatedAtMS: metadata.CreatedAtMS,
}
}
func (r *Repository) receiptForSalaryTransferToCoinSellerTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.SalaryTransferToCoinSellerReceipt, error) {
var metadataJSON string
if err := tx.QueryRowContext(ctx,
`SELECT COALESCE(CAST(metadata_json AS CHAR), '{}')
FROM wallet_transactions
WHERE app_code = ? AND transaction_id = ?`,
appcode.FromContext(ctx),
transactionID,
).Scan(&metadataJSON); err != nil {
return ledger.SalaryTransferToCoinSellerReceipt{}, err
}
var metadata salaryTransferToCoinSellerMetadata
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
return ledger.SalaryTransferToCoinSellerReceipt{}, err
}
return receiptFromSalaryTransferToCoinSellerMetadata(transactionID, metadata), nil
}
func receiptFromSalaryTransferToCoinSellerMetadata(transactionID string, metadata salaryTransferToCoinSellerMetadata) ledger.SalaryTransferToCoinSellerReceipt {
return ledger.SalaryTransferToCoinSellerReceipt{
TransactionID: transactionID,
SourceUserID: metadata.SourceUserID,
SellerUserID: metadata.SellerUserID,
SalaryAssetType: metadata.SalaryAssetType,
SourceSalaryBalanceAfter: metadata.SourceSalaryBalanceAfter,
SellerBalanceAfter: metadata.SellerBalanceAfter,
SalaryUSDMinor: metadata.SalaryUSDMinor,
CoinAmount: metadata.CoinAmount,
CoinPerUSD: metadata.CoinPerUSD,
RateMinUSDMinor: metadata.RateMinUSDMinor,
RateMaxUSDMinor: metadata.RateMaxUSDMinor,
CreatedAtMS: metadata.CreatedAtMS,
}
}