2026-07-15 09:43:33 +08:00

383 lines
19 KiB
Go

package activitytemplate
import (
"hyapp-admin-server/internal/integration/userclient"
activityv1 "hyapp.local/api/proto/activity/v1"
)
type localeDTO struct {
Locale string `json:"locale"`
Title string `json:"title"`
Rules string `json:"rules"`
}
type giftDTO struct {
GiftID string `json:"gift_id"`
SortOrder int32 `json:"sort_order"`
Name string `json:"name"`
IconURL string `json:"icon_url"`
CoinPrice int64 `json:"coin_price"`
PriceVersion string `json:"price_version"`
}
// rewardItemDTO is the immutable, display-safe reward item captured at publish
// time. Admin reads this snapshot instead of joining mutable wallet catalog rows.
type rewardItemDTO struct {
ItemType string `json:"item_type"`
ResourceID int64 `json:"resource_id"`
ResourceType string `json:"resource_type"`
Name string `json:"name"`
IconURL string `json:"icon_url"`
Quantity int64 `json:"quantity"`
DurationMS int64 `json:"duration_ms"`
WalletAssetType string `json:"wallet_asset_type"`
WalletAssetAmount int64 `json:"wallet_asset_amount"`
SortOrder int32 `json:"sort_order"`
}
type taskDTO struct {
TaskKey string `json:"task_key"`
TaskType string `json:"task_type"`
TargetValue int64 `json:"target_value"`
RewardResourceGroupID int64 `json:"reward_resource_group_id"`
SortOrder int32 `json:"sort_order"`
RewardSnapshotID string `json:"reward_snapshot_id"`
RewardSnapshotHash string `json:"reward_snapshot_hash"`
RewardName string `json:"reward_name"`
RewardItems []rewardItemDTO `json:"reward_items"`
}
type rankRewardDTO struct {
BoardType string `json:"board_type"`
RankFrom int32 `json:"rank_from"`
RankTo int32 `json:"rank_to"`
ResourceGroupID int64 `json:"resource_group_id"`
SortOrder int32 `json:"sort_order"`
RewardSnapshotID string `json:"reward_snapshot_id"`
RewardSnapshotHash string `json:"reward_snapshot_hash"`
RewardName string `json:"reward_name"`
RewardItems []rewardItemDTO `json:"reward_items"`
}
type assetDTO struct {
AssetKey string `json:"asset_key"`
Locale string `json:"locale"`
URL string `json:"url"`
MediaType string `json:"media_type"`
SortOrder int32 `json:"sort_order"`
}
type templateSummaryDTO struct {
AppCode string `json:"app_code"`
TemplateID string `json:"template_id"`
TemplateCode string `json:"template_code"`
Name string `json:"name"`
ActivityType string `json:"activity_type"`
Status string `json:"status"`
LifecycleStatus string `json:"lifecycle_status"`
StartMS int64 `json:"start_ms"`
EndMS int64 `json:"end_ms"`
AllRegions bool `json:"all_regions"`
RegionIDs []int64 `json:"region_ids"`
Revision int64 `json:"revision"`
PublishedVersion int64 `json:"published_version"`
CreatedByAdminID int64 `json:"created_by_admin_id"`
UpdatedByAdminID int64 `json:"updated_by_admin_id"`
CreatedAtMS int64 `json:"created_at_ms"`
UpdatedAtMS int64 `json:"updated_at_ms"`
}
type templateDTO struct {
AppCode string `json:"app_code"`
TemplateID string `json:"template_id"`
TemplateCode string `json:"template_code"`
Name string `json:"name"`
ActivityType string `json:"activity_type"`
Status string `json:"status"`
LifecycleStatus string `json:"lifecycle_status"`
StartMS int64 `json:"start_ms"`
EndMS int64 `json:"end_ms"`
AllRegions bool `json:"all_regions"`
RegionIDs []int64 `json:"region_ids"`
Locales []localeDTO `json:"locales"`
Gifts []giftDTO `json:"gifts"`
Tasks []taskDTO `json:"tasks"`
DailyLeaderboardSize int32 `json:"daily_leaderboard_size"`
TotalLeaderboardSize int32 `json:"total_leaderboard_size"`
RankRewards []rankRewardDTO `json:"rank_rewards"`
Assets []assetDTO `json:"assets"`
DisplayConfigJSON string `json:"display_config_json"`
Revision int64 `json:"revision"`
PublishedVersion int64 `json:"published_version"`
CreatedByAdminID int64 `json:"created_by_admin_id"`
UpdatedByAdminID int64 `json:"updated_by_admin_id"`
PublishedByAdminID int64 `json:"published_by_admin_id"`
CreatedAtMS int64 `json:"created_at_ms"`
UpdatedAtMS int64 `json:"updated_at_ms"`
PublishedAtMS int64 `json:"published_at_ms"`
ArchivedAtMS int64 `json:"archived_at_ms"`
}
type versionDTO struct {
TemplateID string `json:"template_id"`
VersionNo int64 `json:"version_no"`
Snapshot templateDTO `json:"snapshot"`
PublishedByAdminID int64 `json:"published_by_admin_id"`
PublishedAtMS int64 `json:"published_at_ms"`
RuntimeFromMS int64 `json:"runtime_from_ms"`
RuntimeToMS int64 `json:"runtime_to_ms"`
}
type validationIssueDTO struct {
Field string `json:"field"`
Code string `json:"code"`
Message string `json:"message"`
}
type pageDTO struct {
Items any `json:"items"`
Page int `json:"page"`
PageSize int `json:"page_size"`
Total int64 `json:"total"`
ServerTimeMS int64 `json:"server_time_ms,omitempty"`
}
type rankPeriodDTO struct {
TemplateID string `json:"template_id"`
TemplateCode string `json:"template_code"`
VersionNo int64 `json:"version_no"`
BoardType string `json:"board_type"`
PeriodKey string `json:"period_key"`
PeriodStartMS int64 `json:"period_start_ms"`
PeriodEndMS int64 `json:"period_end_ms"`
SettleAfterMS int64 `json:"settle_after_ms"`
Status string `json:"status"`
SettledAtMS int64 `json:"settled_at_ms"`
}
type leaderboardEntryDTO struct {
RankNo int32 `json:"rank_no"`
UserID int64 `json:"user_id"`
Score int64 `json:"score"`
GiftCount int64 `json:"gift_count"`
CoinAmount int64 `json:"coin_amount"`
FirstScoredAtMS int64 `json:"first_scored_at_ms"`
Snapshot bool `json:"snapshot"`
User *activityTemplateUserDTO `json:"user,omitempty"`
}
type leaderboardPageDTO struct {
Period rankPeriodDTO `json:"period"`
Items []leaderboardEntryDTO `json:"items"`
Page int `json:"page"`
PageSize int `json:"page_size"`
Total int64 `json:"total"`
}
type rewardJobDTO struct {
RewardJobID string `json:"reward_job_id"`
TemplateID string `json:"template_id"`
TemplateCode string `json:"template_code"`
VersionNo int64 `json:"version_no"`
BoardType string `json:"board_type"`
PeriodKey string `json:"period_key"`
RankNo int32 `json:"rank_no"`
UserID int64 `json:"user_id"`
Score int64 `json:"score"`
ResourceGroupID int64 `json:"resource_group_id"`
WalletCommandID string `json:"wallet_command_id"`
WalletGrantID string `json:"wallet_grant_id"`
Status string `json:"status"`
FailureReason string `json:"failure_reason"`
AttemptCount int32 `json:"attempt_count"`
MaxAttempts int32 `json:"max_attempts"`
NextRetryAtMS int64 `json:"next_retry_at_ms"`
CreatedAtMS int64 `json:"created_at_ms"`
UpdatedAtMS int64 `json:"updated_at_ms"`
GrantedAtMS int64 `json:"granted_at_ms"`
RewardSnapshotID string `json:"reward_snapshot_id"`
RewardSnapshotHash string `json:"reward_snapshot_hash"`
RewardName string `json:"reward_name"`
RewardItems []rewardItemDTO `json:"reward_items"`
User *activityTemplateUserDTO `json:"user,omitempty"`
}
type taskClaimDTO struct {
ClaimID string `json:"claim_id"`
CommandID string `json:"command_id"`
TemplateID string `json:"template_id"`
TemplateCode string `json:"template_code"`
VersionNo int64 `json:"version_no"`
TaskDay string `json:"task_day"`
TaskKey string `json:"task_key"`
UserID int64 `json:"user_id"`
RewardResourceGroupID int64 `json:"reward_resource_group_id"`
WalletCommandID string `json:"wallet_command_id"`
WalletGrantID string `json:"wallet_grant_id"`
Status string `json:"status"`
FailureReason string `json:"failure_reason"`
AttemptCount int32 `json:"attempt_count"`
CreatedAtMS int64 `json:"created_at_ms"`
UpdatedAtMS int64 `json:"updated_at_ms"`
GrantedAtMS int64 `json:"granted_at_ms"`
RewardSnapshotID string `json:"reward_snapshot_id"`
RewardSnapshotHash string `json:"reward_snapshot_hash"`
RewardName string `json:"reward_name"`
RewardItems []rewardItemDTO `json:"reward_items"`
EarningRegionID int64 `json:"earning_region_id"`
AttributionAtMS int64 `json:"attribution_at_ms"`
User *activityTemplateUserDTO `json:"user,omitempty"`
}
type activityTemplateUserDTO struct {
DisplayUserID string `json:"display_user_id"`
Username string `json:"username"`
Avatar string `json:"avatar"`
}
func rankPeriodFromProto(item *activityv1.ActivityTemplateRankPeriod) rankPeriodDTO {
if item == nil {
return rankPeriodDTO{}
}
return rankPeriodDTO{
TemplateID: item.GetTemplateId(), TemplateCode: item.GetTemplateCode(), VersionNo: item.GetVersionNo(),
BoardType: item.GetBoardType(), PeriodKey: item.GetPeriodKey(), PeriodStartMS: item.GetPeriodStartMs(),
PeriodEndMS: item.GetPeriodEndMs(), SettleAfterMS: item.GetSettleAfterMs(),
Status: item.GetStatus(), SettledAtMS: item.GetSettledAtMs(),
}
}
func leaderboardEntryFromProto(item *activityv1.ActivityTemplateLeaderboardEntry, users map[int64]*userclient.User) leaderboardEntryDTO {
if item == nil {
return leaderboardEntryDTO{}
}
out := leaderboardEntryDTO{
RankNo: item.GetRankNo(), UserID: item.GetUserId(), Score: item.GetScore(), GiftCount: item.GetGiftCount(),
CoinAmount: item.GetCoinAmount(), FirstScoredAtMS: item.GetFirstScoredAtMs(), Snapshot: item.GetSnapshot(),
}
out.User = activityTemplateUserFromClient(users[item.GetUserId()])
return out
}
func rewardJobFromProto(item *activityv1.ActivityTemplateRewardJob, users map[int64]*userclient.User) rewardJobDTO {
if item == nil {
return rewardJobDTO{}
}
out := rewardJobDTO{
RewardJobID: item.GetRewardJobId(), TemplateID: item.GetTemplateId(), TemplateCode: item.GetTemplateCode(),
VersionNo: item.GetVersionNo(), BoardType: item.GetBoardType(), PeriodKey: item.GetPeriodKey(), RankNo: item.GetRankNo(),
UserID: item.GetUserId(), Score: item.GetScore(), ResourceGroupID: item.GetResourceGroupId(),
WalletCommandID: item.GetWalletCommandId(), WalletGrantID: item.GetWalletGrantId(), Status: item.GetStatus(),
FailureReason: item.GetFailureReason(), AttemptCount: item.GetAttemptCount(), MaxAttempts: item.GetMaxAttempts(),
NextRetryAtMS: item.GetNextRetryAtMs(), CreatedAtMS: item.GetCreatedAtMs(),
UpdatedAtMS: item.GetUpdatedAtMs(), GrantedAtMS: item.GetGrantedAtMs(),
RewardSnapshotID: item.GetRewardSnapshotId(), RewardSnapshotHash: item.GetRewardSnapshotHash(),
RewardName: item.GetRewardName(), RewardItems: rewardItemsFromProto(item.GetRewardItems()),
}
out.User = activityTemplateUserFromClient(users[item.GetUserId()])
return out
}
func taskClaimFromProto(item *activityv1.ActivityTemplateTaskClaim, users map[int64]*userclient.User) taskClaimDTO {
if item == nil {
return taskClaimDTO{RewardItems: []rewardItemDTO{}}
}
out := taskClaimDTO{
ClaimID: item.GetClaimId(), CommandID: item.GetCommandId(), TemplateID: item.GetTemplateId(), TemplateCode: item.GetTemplateCode(),
VersionNo: item.GetVersionNo(), TaskDay: item.GetTaskDay(), TaskKey: item.GetTaskKey(), UserID: item.GetUserId(),
RewardResourceGroupID: item.GetRewardResourceGroupId(), WalletCommandID: item.GetWalletCommandId(), WalletGrantID: item.GetWalletGrantId(),
Status: item.GetStatus(), FailureReason: item.GetFailureReason(), AttemptCount: item.GetAttemptCount(),
CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), GrantedAtMS: item.GetGrantedAtMs(),
RewardSnapshotID: item.GetRewardSnapshotId(), RewardSnapshotHash: item.GetRewardSnapshotHash(), RewardName: item.GetRewardName(),
RewardItems: rewardItemsFromProto(item.GetRewardItems()), EarningRegionID: item.GetEarningRegionId(), AttributionAtMS: item.GetAttributionAtMs(),
}
out.User = activityTemplateUserFromClient(users[item.GetUserId()])
return out
}
func rewardItemsFromProto(items []*activityv1.ActivityTemplateRewardItem) []rewardItemDTO {
out := make([]rewardItemDTO, 0, len(items))
for _, item := range items {
if item == nil {
continue
}
out = append(out, rewardItemDTO{
ItemType: item.GetItemType(), ResourceID: item.GetResourceId(), ResourceType: item.GetResourceType(),
Name: item.GetName(), IconURL: item.GetIconUrl(), Quantity: item.GetQuantity(), DurationMS: item.GetDurationMs(),
WalletAssetType: item.GetWalletAssetType(), WalletAssetAmount: item.GetWalletAssetAmount(), SortOrder: item.GetSortOrder(),
})
}
return out
}
func activityTemplateUserFromClient(item *userclient.User) *activityTemplateUserDTO {
if item == nil {
return nil
}
return &activityTemplateUserDTO{DisplayUserID: item.DisplayUserID, Username: item.Username, Avatar: item.Avatar}
}
func summaryFromProto(item *activityv1.ActivityTemplateSummary) templateSummaryDTO {
if item == nil {
return templateSummaryDTO{RegionIDs: []int64{}}
}
return templateSummaryDTO{
AppCode: item.GetAppCode(), TemplateID: item.GetTemplateId(), TemplateCode: item.GetTemplateCode(),
Name: item.GetName(), ActivityType: item.GetActivityType(), Status: item.GetStatus(), LifecycleStatus: item.GetLifecycleStatus(),
StartMS: item.GetStartMs(), EndMS: item.GetEndMs(), AllRegions: item.GetAllRegions(), RegionIDs: cloneInt64Slice(item.GetRegionIds()),
Revision: item.GetRevision(), PublishedVersion: item.GetPublishedVersion(),
CreatedByAdminID: item.GetCreatedByAdminId(), UpdatedByAdminID: item.GetUpdatedByAdminId(),
CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(),
}
}
func templateFromProto(item *activityv1.ActivityTemplate) templateDTO {
if item == nil {
return templateDTO{RegionIDs: []int64{}, Locales: []localeDTO{}, Gifts: []giftDTO{}, Tasks: []taskDTO{}, RankRewards: []rankRewardDTO{}, Assets: []assetDTO{}}
}
out := templateDTO{
AppCode: item.GetAppCode(), TemplateID: item.GetTemplateId(), TemplateCode: item.GetTemplateCode(), Name: item.GetName(),
ActivityType: item.GetActivityType(), Status: item.GetStatus(), LifecycleStatus: item.GetLifecycleStatus(),
StartMS: item.GetStartMs(), EndMS: item.GetEndMs(), AllRegions: item.GetAllRegions(), RegionIDs: cloneInt64Slice(item.GetRegionIds()),
Locales: make([]localeDTO, 0, len(item.GetLocales())), Gifts: make([]giftDTO, 0, len(item.GetGifts())),
Tasks: make([]taskDTO, 0, len(item.GetTasks())), RankRewards: make([]rankRewardDTO, 0, len(item.GetRankRewards())),
Assets: make([]assetDTO, 0, len(item.GetAssets())), DailyLeaderboardSize: item.GetDailyLeaderboardSize(),
TotalLeaderboardSize: item.GetTotalLeaderboardSize(), DisplayConfigJSON: item.GetDisplayConfigJson(),
Revision: item.GetRevision(), PublishedVersion: item.GetPublishedVersion(),
CreatedByAdminID: item.GetCreatedByAdminId(), UpdatedByAdminID: item.GetUpdatedByAdminId(), PublishedByAdminID: item.GetPublishedByAdminId(),
CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), PublishedAtMS: item.GetPublishedAtMs(), ArchivedAtMS: item.GetArchivedAtMs(),
}
for _, locale := range item.GetLocales() {
out.Locales = append(out.Locales, localeDTO{Locale: locale.GetLocale(), Title: locale.GetTitle(), Rules: locale.GetRules()})
}
for _, gift := range item.GetGifts() {
out.Gifts = append(out.Gifts, giftDTO{GiftID: gift.GetGiftId(), SortOrder: gift.GetSortOrder(), Name: gift.GetName(), IconURL: gift.GetIconUrl(), CoinPrice: gift.GetCoinPrice(), PriceVersion: gift.GetPriceVersion()})
}
for _, task := range item.GetTasks() {
out.Tasks = append(out.Tasks, taskDTO{
TaskKey: task.GetTaskKey(), TaskType: task.GetTaskType(), TargetValue: task.GetTargetValue(),
RewardResourceGroupID: task.GetRewardResourceGroupId(), SortOrder: task.GetSortOrder(),
RewardSnapshotID: task.GetRewardSnapshotId(), RewardSnapshotHash: task.GetRewardSnapshotHash(),
RewardName: task.GetRewardName(), RewardItems: rewardItemsFromProto(task.GetRewardItems()),
})
}
for _, reward := range item.GetRankRewards() {
out.RankRewards = append(out.RankRewards, rankRewardDTO{
BoardType: reward.GetBoardType(), RankFrom: reward.GetRankFrom(), RankTo: reward.GetRankTo(),
ResourceGroupID: reward.GetResourceGroupId(), SortOrder: reward.GetSortOrder(),
RewardSnapshotID: reward.GetRewardSnapshotId(), RewardSnapshotHash: reward.GetRewardSnapshotHash(),
RewardName: reward.GetRewardName(), RewardItems: rewardItemsFromProto(reward.GetRewardItems()),
})
}
for _, asset := range item.GetAssets() {
out.Assets = append(out.Assets, assetDTO{AssetKey: asset.GetAssetKey(), Locale: asset.GetLocale(), URL: asset.GetUrl(), MediaType: asset.GetMediaType(), SortOrder: asset.GetSortOrder()})
}
return out
}
func cloneInt64Slice(items []int64) []int64 {
out := make([]int64, len(items))
copy(out, items)
return out
}