700 lines
17 KiB
Go
700 lines
17 KiB
Go
package resource
|
||
|
||
import (
|
||
"strings"
|
||
"unicode/utf8"
|
||
|
||
"hyapp/services/wallet-service/internal/domain/ledger"
|
||
)
|
||
|
||
const (
|
||
TypeAvatarFrame = "avatar_frame"
|
||
TypeProfileCard = "profile_card"
|
||
TypeCoin = "coin"
|
||
TypeVehicle = "vehicle"
|
||
TypeChatBubble = "chat_bubble"
|
||
TypeBadge = "badge"
|
||
TypeFloatingScreen = "floating_screen"
|
||
TypeGift = "gift"
|
||
TypeMicSeatIcon = "mic_seat_icon"
|
||
TypeMicSeatAnimation = "mic_seat_animation"
|
||
TypeEmojiPack = "emoji_pack"
|
||
|
||
StatusActive = "active"
|
||
StatusDisabled = "disabled"
|
||
|
||
GrantStrategyWalletCredit = "wallet_credit"
|
||
GrantStrategyNewEntitlement = "new_entitlement"
|
||
GrantStrategyExtendExpiry = "extend_expiry"
|
||
GrantStrategyIncreaseQuantity = "increase_quantity"
|
||
GrantStrategySetActiveFlag = "set_active_flag"
|
||
|
||
GrantSubjectResource = "resource"
|
||
GrantSubjectGroup = "resource_group"
|
||
|
||
GrantSourceAdmin = "admin"
|
||
GrantSourceManagerCenter = "manager_center"
|
||
GrantSourceGrowthLevel = "growth_level"
|
||
GrantSourceAchievement = "achievement"
|
||
GrantSourceResourceShop = "resource_shop"
|
||
GrantStatusDone = "succeeded"
|
||
ResultWalletCredit = "wallet_credit"
|
||
ResultEntitlement = "entitlement"
|
||
|
||
GroupItemTypeResource = "resource"
|
||
GroupItemTypeWalletAsset = "wallet_asset"
|
||
|
||
GiftTypeNormal = "normal"
|
||
GiftTypeCP = "cp"
|
||
GiftTypeLucky = "lucky"
|
||
GiftTypeSuperLucky = "super_lucky"
|
||
GiftTypeExclusive = "exclusive"
|
||
GiftTypeNoble = "noble"
|
||
GiftTypeFlag = "flag"
|
||
GiftTypeActivity = "activity"
|
||
GiftTypeMagic = "magic"
|
||
GiftTypeCustom = "custom"
|
||
|
||
GiftTypeTabKeyNormal = "Gift"
|
||
GiftTypeTabKeyCP = "CP"
|
||
GiftTypeTabKeyLucky = "Lucky"
|
||
GiftTypeTabKeySuperLucky = "Super Lucky"
|
||
GiftTypeTabKeyExclusive = "Exclusive"
|
||
GiftTypeTabKeyNoble = "Noble"
|
||
GiftTypeTabKeyFlag = "Flag"
|
||
GiftTypeTabKeyActivity = "Activity"
|
||
GiftTypeTabKeyMagic = "Magic"
|
||
GiftTypeTabKeyCustom = "Custom"
|
||
|
||
GiftEffectAnimation = "animation"
|
||
GiftEffectMusic = "music"
|
||
GiftEffectGlobalBroadcast = "global_broadcast"
|
||
|
||
PriceTypeCoin = "coin"
|
||
PriceTypeFree = "free"
|
||
|
||
ShopDurationOneDay int32 = 1
|
||
ShopDurationThreeDays int32 = 3
|
||
ShopDurationSevenDays int32 = 7
|
||
)
|
||
|
||
type Resource struct {
|
||
AppCode string
|
||
ResourceID int64
|
||
ResourceCode string
|
||
ResourceType string
|
||
Name string
|
||
Status string
|
||
Grantable bool
|
||
GrantStrategy string
|
||
WalletAssetType string
|
||
WalletAssetAmount int64
|
||
PriceType string
|
||
CoinPrice int64
|
||
// GiftPointAmount 是历史字段;GIFT_POINT 已下线,新资源和礼物配置只保留真实 COIN 价格。
|
||
GiftPointAmount int64
|
||
UsageScopes []string
|
||
AssetURL string
|
||
PreviewURL string
|
||
AnimationURL string
|
||
MetadataJSON string
|
||
SortOrder int32
|
||
CreatedByUserID int64
|
||
UpdatedByUserID int64
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
ManagerGrantEnabled bool
|
||
}
|
||
|
||
type ResourceGroupItem struct {
|
||
GroupItemID int64
|
||
GroupID int64
|
||
ItemType string
|
||
ResourceID int64
|
||
Resource Resource
|
||
WalletAssetType string
|
||
WalletAssetAmount int64
|
||
Quantity int64
|
||
DurationMS int64
|
||
SortOrder int32
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
}
|
||
|
||
type ResourceGroup struct {
|
||
AppCode string
|
||
GroupID int64
|
||
GroupCode string
|
||
Name string
|
||
Status string
|
||
Description string
|
||
SortOrder int32
|
||
Items []ResourceGroupItem
|
||
CreatedByUserID int64
|
||
UpdatedByUserID int64
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
}
|
||
|
||
type GiftConfig struct {
|
||
AppCode string
|
||
GiftID string
|
||
ResourceID int64
|
||
Resource Resource
|
||
Status string
|
||
Name string
|
||
SortOrder int32
|
||
PresentationJSON string
|
||
PriceVersion string
|
||
CoinPrice int64
|
||
// GiftPointAmount 是历史字段;送礼结算不再读取,新配置固定为 0。
|
||
GiftPointAmount int64
|
||
HeatValue int64
|
||
GiftTypeCode string
|
||
// CPRelationType 只在 gift_type_code=cp 的礼物上使用,值为 cp、brother 或 sister。
|
||
CPRelationType string
|
||
ChargeAssetType string
|
||
EffectiveFromMS int64
|
||
EffectiveToMS int64
|
||
EffectTypes []string
|
||
CreatedByUserID int64
|
||
UpdatedByUserID int64
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
RegionIDs []int64
|
||
}
|
||
|
||
type GiftTypeConfig struct {
|
||
AppCode string
|
||
TypeCode string
|
||
Name string
|
||
TabKey string
|
||
Status string
|
||
SortOrder int32
|
||
CreatedByUserID int64
|
||
UpdatedByUserID int64
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
}
|
||
|
||
type ResourceShopItem struct {
|
||
AppCode string
|
||
ShopItemID int64
|
||
ResourceID int64
|
||
Resource Resource
|
||
Status string
|
||
DurationDays int32
|
||
PriceType string
|
||
CoinPrice int64
|
||
EffectiveFromMS int64
|
||
EffectiveToMS int64
|
||
SortOrder int32
|
||
CreatedByUserID int64
|
||
UpdatedByUserID int64
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
}
|
||
|
||
type UserResourceEntitlement struct {
|
||
AppCode string
|
||
EntitlementID string
|
||
UserID int64
|
||
ResourceID int64
|
||
Resource Resource
|
||
Status string
|
||
Quantity int64
|
||
RemainingQuantity int64
|
||
EffectiveAtMS int64
|
||
ExpiresAtMS int64
|
||
SourceGrantID string
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
Equipped bool
|
||
}
|
||
|
||
type ResourceGrantItem struct {
|
||
GrantItemID int64
|
||
GrantID string
|
||
ResourceID int64
|
||
ResourceSnapshotJSON string
|
||
Quantity int64
|
||
DurationMS int64
|
||
ResultType string
|
||
WalletTransactionID string
|
||
EntitlementID string
|
||
CreatedAtMS int64
|
||
}
|
||
|
||
type ResourceGrant struct {
|
||
AppCode string
|
||
GrantID string
|
||
CommandID string
|
||
TargetUserID int64
|
||
GrantSource string
|
||
GrantSubjectType string
|
||
GrantSubjectID string
|
||
Status string
|
||
Reason string
|
||
OperatorUserID int64
|
||
Items []ResourceGrantItem
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
}
|
||
|
||
type ListResourcesQuery struct {
|
||
AppCode string
|
||
ResourceType string
|
||
Status string
|
||
Keyword string
|
||
Page int32
|
||
PageSize int32
|
||
ActiveOnly bool
|
||
ManagerGrantOnly bool
|
||
}
|
||
|
||
type ResourceCommand struct {
|
||
AppCode string
|
||
ResourceID int64
|
||
ResourceCode string
|
||
ResourceType string
|
||
Name string
|
||
Status string
|
||
Grantable bool
|
||
GrantStrategy string
|
||
WalletAssetType string
|
||
WalletAssetAmount int64
|
||
PriceType string
|
||
CoinPrice int64
|
||
// GiftPointAmount 是历史字段;保存资源时固定为 0,保留字段只兼容旧表结构。
|
||
GiftPointAmount int64
|
||
UsageScopes []string
|
||
AssetURL string
|
||
PreviewURL string
|
||
AnimationURL string
|
||
MetadataJSON string
|
||
SortOrder int32
|
||
OperatorUserID int64
|
||
ManagerGrantEnabled bool
|
||
}
|
||
|
||
type StatusCommand struct {
|
||
AppCode string
|
||
ID int64
|
||
StringID string
|
||
Status string
|
||
OperatorUserID int64
|
||
}
|
||
|
||
type ResourceGroupItemInput struct {
|
||
ItemType string
|
||
ResourceID int64
|
||
WalletAssetType string
|
||
WalletAssetAmount int64
|
||
Quantity int64
|
||
DurationMS int64
|
||
SortOrder int32
|
||
}
|
||
|
||
type ListResourceGroupsQuery struct {
|
||
AppCode string
|
||
Status string
|
||
Keyword string
|
||
Page int32
|
||
PageSize int32
|
||
ActiveOnly bool
|
||
}
|
||
|
||
type ResourceGroupCommand struct {
|
||
AppCode string
|
||
GroupID int64
|
||
GroupCode string
|
||
Name string
|
||
Status string
|
||
Description string
|
||
SortOrder int32
|
||
Items []ResourceGroupItemInput
|
||
OperatorUserID int64
|
||
}
|
||
|
||
type ListGiftConfigsQuery struct {
|
||
AppCode string
|
||
Status string
|
||
Keyword string
|
||
GiftTypeCode string
|
||
Page int32
|
||
PageSize int32
|
||
ActiveOnly bool
|
||
RegionID int64
|
||
FilterRegion bool
|
||
}
|
||
|
||
type ListGiftTypeConfigsQuery struct {
|
||
AppCode string
|
||
Status string
|
||
ActiveOnly bool
|
||
}
|
||
|
||
type GiftConfigCommand struct {
|
||
AppCode string
|
||
GiftID string
|
||
ResourceID int64
|
||
Status string
|
||
Name string
|
||
SortOrder int32
|
||
PresentationJSON string
|
||
PriceVersion string
|
||
CoinPrice int64
|
||
// GiftPointAmount 是历史字段;保存礼物价格时固定为 0,业务计算只读 CoinPrice。
|
||
GiftPointAmount int64
|
||
HeatValue int64
|
||
EffectiveAtMS int64
|
||
GiftTypeCode string
|
||
// CPRelationType 会写入 presentation_json,避免新增 gift_configs 表字段。
|
||
CPRelationType string
|
||
ChargeAssetType string
|
||
EffectiveFromMS int64
|
||
EffectiveToMS int64
|
||
EffectTypes []string
|
||
OperatorUserID int64
|
||
RegionIDs []int64
|
||
}
|
||
|
||
type GiftTypeConfigCommand struct {
|
||
AppCode string
|
||
TypeCode string
|
||
Name string
|
||
TabKey string
|
||
Status string
|
||
SortOrder int32
|
||
OperatorUserID int64
|
||
}
|
||
|
||
type GrantResourceCommand struct {
|
||
AppCode string
|
||
CommandID string
|
||
TargetUserID int64
|
||
ResourceID int64
|
||
Quantity int64
|
||
DurationMS int64
|
||
Reason string
|
||
OperatorUserID int64
|
||
GrantSource string
|
||
}
|
||
|
||
type GrantResourceGroupCommand struct {
|
||
AppCode string
|
||
CommandID string
|
||
TargetUserID int64
|
||
GroupID int64
|
||
Reason string
|
||
OperatorUserID int64
|
||
GrantSource string
|
||
}
|
||
|
||
type ListUserResourcesQuery struct {
|
||
AppCode string
|
||
UserID int64
|
||
ResourceType string
|
||
ActiveOnly bool
|
||
}
|
||
|
||
type EquipUserResourceCommand struct {
|
||
AppCode string
|
||
UserID int64
|
||
ResourceID int64
|
||
EntitlementID string
|
||
}
|
||
|
||
type UnequipUserResourceCommand struct {
|
||
AppCode string
|
||
UserID int64
|
||
ResourceType string
|
||
}
|
||
|
||
type UnequipUserResourceResult struct {
|
||
ResourceType string
|
||
Unequipped bool
|
||
UpdatedAtMS int64
|
||
}
|
||
|
||
type BatchGetUserEquippedResourcesQuery struct {
|
||
AppCode string
|
||
UserIDs []int64
|
||
ResourceTypes []string
|
||
}
|
||
|
||
type UserEquippedResources struct {
|
||
UserID int64
|
||
Resources []UserResourceEntitlement
|
||
}
|
||
|
||
type ListResourceGrantsQuery struct {
|
||
AppCode string
|
||
TargetUserID int64
|
||
Status string
|
||
Page int32
|
||
PageSize int32
|
||
}
|
||
|
||
type ResourceShopItemInput struct {
|
||
ShopItemID int64
|
||
ResourceID int64
|
||
Status string
|
||
DurationDays int32
|
||
EffectiveFromMS int64
|
||
EffectiveToMS int64
|
||
SortOrder int32
|
||
}
|
||
|
||
type ListResourceShopItemsQuery struct {
|
||
AppCode string
|
||
ResourceType string
|
||
Status string
|
||
Keyword string
|
||
Page int32
|
||
PageSize int32
|
||
ActiveOnly bool
|
||
}
|
||
|
||
type ResourceShopItemsCommand struct {
|
||
AppCode string
|
||
Items []ResourceShopItemInput
|
||
OperatorUserID int64
|
||
}
|
||
|
||
type ResourceShopItemStatusCommand struct {
|
||
AppCode string
|
||
ShopItemID int64
|
||
Status string
|
||
OperatorUserID int64
|
||
}
|
||
|
||
type ResourceShopPurchaseCommand struct {
|
||
AppCode string
|
||
CommandID string
|
||
UserID int64
|
||
ShopItemID int64
|
||
}
|
||
|
||
type ResourceShopPurchaseReceipt struct {
|
||
OrderID string
|
||
TransactionID string
|
||
ShopItem ResourceShopItem
|
||
Resource UserResourceEntitlement
|
||
Balance ledger.AssetBalance
|
||
CoinSpent int64
|
||
GrantID string
|
||
}
|
||
|
||
// BadgeGrantOutbox is a wallet resource grant event relayed to activity-service badge display projection.
|
||
type BadgeGrantOutbox struct {
|
||
AppCode string
|
||
EventID string
|
||
EventType string
|
||
CommandID string
|
||
UserID int64
|
||
GrantID string
|
||
GrantSource string
|
||
PayloadJSON string
|
||
Status string
|
||
AttemptCount int32
|
||
FailureReason string
|
||
CreatedAtMS int64
|
||
UpdatedAtMS int64
|
||
Items []BadgeGrantItem
|
||
}
|
||
|
||
// BadgeGrantItem is the badge subset of a resource grant item.
|
||
type BadgeGrantItem struct {
|
||
ResourceID int64 `json:"resource_id"`
|
||
ResourceCode string `json:"resource_code"`
|
||
ResourceType string `json:"resource_type"`
|
||
Name string `json:"name"`
|
||
EntitlementID string `json:"entitlement_id"`
|
||
ResourceSnapshotJSON string `json:"resource_snapshot_json"`
|
||
MetadataJSON string `json:"metadata_json"`
|
||
}
|
||
|
||
func NormalizeStatus(value string) string {
|
||
value = strings.ToLower(strings.TrimSpace(value))
|
||
if value == "" {
|
||
return StatusActive
|
||
}
|
||
return value
|
||
}
|
||
|
||
func NormalizeGrantSource(value string) string {
|
||
value = strings.ToLower(strings.TrimSpace(value))
|
||
if value == "" {
|
||
return GrantSourceAdmin
|
||
}
|
||
return value
|
||
}
|
||
|
||
func ValidResourceType(value string) bool {
|
||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||
case TypeAvatarFrame, TypeProfileCard, TypeCoin, TypeVehicle, TypeChatBubble, TypeBadge, TypeFloatingScreen, TypeGift, TypeMicSeatIcon, TypeMicSeatAnimation, TypeEmojiPack:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func ResourceTypeSellableInShop(value string) bool {
|
||
switch NormalizeResourceType(value) {
|
||
case TypeAvatarFrame, TypeProfileCard, TypeVehicle, TypeChatBubble, TypeBadge, TypeMicSeatIcon, TypeMicSeatAnimation:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func ValidShopDurationDays(value int32) bool {
|
||
switch value {
|
||
case ShopDurationOneDay, ShopDurationThreeDays, ShopDurationSevenDays:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func ValidStatus(value string) bool {
|
||
switch NormalizeStatus(value) {
|
||
case StatusActive, StatusDisabled:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func ValidGrantStrategy(value string) bool {
|
||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||
case GrantStrategyWalletCredit, GrantStrategyNewEntitlement, GrantStrategyExtendExpiry, GrantStrategyIncreaseQuantity, GrantStrategySetActiveFlag:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func NormalizeGroupItemType(value string) string {
|
||
value = strings.ToLower(strings.TrimSpace(value))
|
||
if value == "" {
|
||
return GroupItemTypeResource
|
||
}
|
||
return value
|
||
}
|
||
|
||
func ValidGroupItemType(value string) bool {
|
||
switch NormalizeGroupItemType(value) {
|
||
case GroupItemTypeResource, GroupItemTypeWalletAsset:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func NormalizeResourceType(value string) string {
|
||
return strings.ToLower(strings.TrimSpace(value))
|
||
}
|
||
|
||
func NormalizeGrantStrategy(value string) string {
|
||
return strings.ToLower(strings.TrimSpace(value))
|
||
}
|
||
|
||
func NormalizeWalletAssetType(value string) string {
|
||
return strings.ToUpper(strings.TrimSpace(value))
|
||
}
|
||
|
||
func NormalizePriceType(value string) string {
|
||
return strings.ToLower(strings.TrimSpace(value))
|
||
}
|
||
|
||
func ValidPriceType(value string) bool {
|
||
switch NormalizePriceType(value) {
|
||
case PriceTypeCoin, PriceTypeFree:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func NormalizeGiftTypeCode(value string) string {
|
||
value = strings.ToLower(strings.TrimSpace(value))
|
||
value = strings.ReplaceAll(value, "-", "_")
|
||
if value == "" {
|
||
return GiftTypeNormal
|
||
}
|
||
return value
|
||
}
|
||
|
||
func ValidGiftTypeCode(value string) bool {
|
||
value = NormalizeGiftTypeCode(value)
|
||
if value == "" || len(value) > 32 {
|
||
return false
|
||
}
|
||
for index, char := range value {
|
||
if index == 0 && (char < 'a' || char > 'z') {
|
||
return false
|
||
}
|
||
if (char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char == '_' {
|
||
continue
|
||
}
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
func NormalizeGiftTypeTabKey(value string) string {
|
||
return strings.TrimSpace(value)
|
||
}
|
||
|
||
func ValidGiftTypeTabKey(value string) bool {
|
||
value = NormalizeGiftTypeTabKey(value)
|
||
return value != "" && utf8.RuneCountInString(value) <= 32
|
||
}
|
||
|
||
func DefaultGiftTypeConfigs(appCode string) []GiftTypeConfig {
|
||
appCode = strings.TrimSpace(appCode)
|
||
defaults := []GiftTypeConfig{
|
||
{TypeCode: GiftTypeNormal, Name: "普通礼物", TabKey: GiftTypeTabKeyNormal, Status: StatusActive, SortOrder: 10},
|
||
{TypeCode: GiftTypeCP, Name: "CP礼物", TabKey: GiftTypeTabKeyCP, Status: StatusActive, SortOrder: 20},
|
||
{TypeCode: GiftTypeLucky, Name: "幸运礼物", TabKey: GiftTypeTabKeyLucky, Status: StatusActive, SortOrder: 30},
|
||
{TypeCode: GiftTypeSuperLucky, Name: "超级幸运礼物", TabKey: GiftTypeTabKeySuperLucky, Status: StatusActive, SortOrder: 40},
|
||
{TypeCode: GiftTypeExclusive, Name: "专属礼物", TabKey: GiftTypeTabKeyExclusive, Status: StatusActive, SortOrder: 50},
|
||
{TypeCode: GiftTypeNoble, Name: "贵族礼物", TabKey: GiftTypeTabKeyNoble, Status: StatusActive, SortOrder: 60},
|
||
{TypeCode: GiftTypeFlag, Name: "国旗礼物", TabKey: GiftTypeTabKeyFlag, Status: StatusActive, SortOrder: 70},
|
||
{TypeCode: GiftTypeActivity, Name: "活动礼物", TabKey: GiftTypeTabKeyActivity, Status: StatusActive, SortOrder: 80},
|
||
{TypeCode: GiftTypeMagic, Name: "魔法礼物", TabKey: GiftTypeTabKeyMagic, Status: StatusActive, SortOrder: 90},
|
||
{TypeCode: GiftTypeCustom, Name: "定制礼物", TabKey: GiftTypeTabKeyCustom, Status: StatusActive, SortOrder: 100},
|
||
}
|
||
for index := range defaults {
|
||
defaults[index].AppCode = appCode
|
||
}
|
||
return defaults
|
||
}
|
||
|
||
func NormalizeGiftEffectType(value string) string {
|
||
return strings.ToLower(strings.TrimSpace(value))
|
||
}
|
||
|
||
func ValidGiftEffectType(value string) bool {
|
||
switch NormalizeGiftEffectType(value) {
|
||
case GiftEffectAnimation, GiftEffectMusic, GiftEffectGlobalBroadcast:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func IsWalletCredit(resource Resource) bool {
|
||
return NormalizeGrantStrategy(resource.GrantStrategy) == GrantStrategyWalletCredit
|
||
}
|
||
|
||
func IsCoinResource(resource Resource) bool {
|
||
return NormalizeResourceType(resource.ResourceType) == TypeCoin
|
||
}
|
||
|
||
func WalletAssetForCoin() string {
|
||
return ledger.AssetCoin
|
||
}
|