package grpc import ( "context" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" "hyapp/pkg/xerr" resourcedomain "hyapp/services/wallet-service/internal/domain/resource" ) func (s *Server) ListResources(ctx context.Context, req *walletv1.ListResourcesRequest) (*walletv1.ListResourcesResponse, error) { items, total, err := s.svc.ListResources(ctx, resourcedomain.ListResourcesQuery{ AppCode: req.GetAppCode(), ResourceType: req.GetResourceType(), Status: req.GetStatus(), Keyword: req.GetKeyword(), Page: req.GetPage(), PageSize: req.GetPageSize(), ActiveOnly: req.GetActiveOnly(), ManagerGrantOnly: req.GetManagerGrantOnly(), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListResourcesResponse{Resources: make([]*walletv1.Resource, 0, len(items)), Total: total} for _, item := range items { resp.Resources = append(resp.Resources, resourceToProto(item)) } return resp, nil } func (s *Server) GetResource(ctx context.Context, req *walletv1.GetResourceRequest) (*walletv1.GetResourceResponse, error) { resource, err := s.svc.GetResource(ctx, req.GetAppCode(), req.GetResourceId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GetResourceResponse{Resource: resourceToProto(resource)}, nil } func (s *Server) CreateResource(ctx context.Context, req *walletv1.CreateResourceRequest) (*walletv1.ResourceResponse, error) { resource, err := s.svc.CreateResource(ctx, resourceCommandFromCreate(req)) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceResponse{Resource: resourceToProto(resource)}, nil } func (s *Server) UpdateResource(ctx context.Context, req *walletv1.UpdateResourceRequest) (*walletv1.ResourceResponse, error) { resource, err := s.svc.UpdateResource(ctx, resourceCommandFromUpdate(req)) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceResponse{Resource: resourceToProto(resource)}, nil } func (s *Server) SetResourceStatus(ctx context.Context, req *walletv1.SetResourceStatusRequest) (*walletv1.ResourceResponse, error) { resource, err := s.svc.SetResourceStatus(ctx, resourcedomain.StatusCommand{ AppCode: req.GetAppCode(), ID: req.GetResourceId(), Status: req.GetStatus(), OperatorUserID: req.GetOperatorUserId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceResponse{Resource: resourceToProto(resource)}, nil } func (s *Server) ListResourceGroups(ctx context.Context, req *walletv1.ListResourceGroupsRequest) (*walletv1.ListResourceGroupsResponse, error) { items, total, err := s.svc.ListResourceGroups(ctx, resourcedomain.ListResourceGroupsQuery{ AppCode: req.GetAppCode(), Status: req.GetStatus(), Keyword: req.GetKeyword(), Page: req.GetPage(), PageSize: req.GetPageSize(), ActiveOnly: req.GetActiveOnly(), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListResourceGroupsResponse{Groups: make([]*walletv1.ResourceGroup, 0, len(items)), Total: total} for _, item := range items { resp.Groups = append(resp.Groups, resourceGroupToProto(item)) } return resp, nil } func (s *Server) GetResourceGroup(ctx context.Context, req *walletv1.GetResourceGroupRequest) (*walletv1.GetResourceGroupResponse, error) { group, err := s.svc.GetResourceGroup(ctx, req.GetAppCode(), req.GetGroupId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GetResourceGroupResponse{Group: resourceGroupToProto(group)}, nil } func (s *Server) CreateResourceGroup(ctx context.Context, req *walletv1.CreateResourceGroupRequest) (*walletv1.ResourceGroupResponse, error) { group, err := s.svc.CreateResourceGroup(ctx, resourceGroupCommandFromCreate(req)) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceGroupResponse{Group: resourceGroupToProto(group)}, nil } func (s *Server) UpdateResourceGroup(ctx context.Context, req *walletv1.UpdateResourceGroupRequest) (*walletv1.ResourceGroupResponse, error) { group, err := s.svc.UpdateResourceGroup(ctx, resourceGroupCommandFromUpdate(req)) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceGroupResponse{Group: resourceGroupToProto(group)}, nil } func (s *Server) SetResourceGroupStatus(ctx context.Context, req *walletv1.SetResourceGroupStatusRequest) (*walletv1.ResourceGroupResponse, error) { group, err := s.svc.SetResourceGroupStatus(ctx, resourcedomain.StatusCommand{ AppCode: req.GetAppCode(), ID: req.GetGroupId(), Status: req.GetStatus(), OperatorUserID: req.GetOperatorUserId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceGroupResponse{Group: resourceGroupToProto(group)}, nil } func (s *Server) ListGiftConfigs(ctx context.Context, req *walletv1.ListGiftConfigsRequest) (*walletv1.ListGiftConfigsResponse, error) { items, total, err := s.svc.ListGiftConfigs(ctx, resourcedomain.ListGiftConfigsQuery{ AppCode: req.GetAppCode(), Status: req.GetStatus(), Keyword: req.GetKeyword(), Page: req.GetPage(), PageSize: req.GetPageSize(), ActiveOnly: req.GetActiveOnly(), RegionID: req.GetRegionId(), FilterRegion: req.GetFilterRegion(), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListGiftConfigsResponse{Gifts: make([]*walletv1.GiftConfig, 0, len(items)), Total: total} for _, item := range items { resp.Gifts = append(resp.Gifts, giftConfigToProto(item)) } return resp, nil } func (s *Server) CreateGiftConfig(ctx context.Context, req *walletv1.CreateGiftConfigRequest) (*walletv1.GiftConfigResponse, error) { gift, err := s.svc.CreateGiftConfig(ctx, giftConfigCommandFromCreate(req)) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GiftConfigResponse{Gift: giftConfigToProto(gift)}, nil } func (s *Server) UpdateGiftConfig(ctx context.Context, req *walletv1.UpdateGiftConfigRequest) (*walletv1.GiftConfigResponse, error) { gift, err := s.svc.UpdateGiftConfig(ctx, giftConfigCommandFromUpdate(req)) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GiftConfigResponse{Gift: giftConfigToProto(gift)}, nil } func (s *Server) SetGiftConfigStatus(ctx context.Context, req *walletv1.SetGiftConfigStatusRequest) (*walletv1.GiftConfigResponse, error) { gift, err := s.svc.SetGiftConfigStatus(ctx, resourcedomain.StatusCommand{ AppCode: req.GetAppCode(), StringID: req.GetGiftId(), Status: req.GetStatus(), OperatorUserID: req.GetOperatorUserId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GiftConfigResponse{Gift: giftConfigToProto(gift)}, nil } func (s *Server) GrantResource(ctx context.Context, req *walletv1.GrantResourceRequest) (*walletv1.ResourceGrantResponse, error) { grant, err := s.svc.GrantResource(ctx, resourcedomain.GrantResourceCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), TargetUserID: req.GetTargetUserId(), ResourceID: req.GetResourceId(), Quantity: req.GetQuantity(), DurationMS: req.GetDurationMs(), Reason: req.GetReason(), OperatorUserID: req.GetOperatorUserId(), GrantSource: req.GetGrantSource(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceGrantResponse{Grant: resourceGrantToProto(grant)}, nil } func (s *Server) GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) { grant, err := s.svc.GrantResourceGroup(ctx, resourcedomain.GrantResourceGroupCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), TargetUserID: req.GetTargetUserId(), GroupID: req.GetGroupId(), Reason: req.GetReason(), OperatorUserID: req.GetOperatorUserId(), GrantSource: req.GetGrantSource(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ResourceGrantResponse{Grant: resourceGrantToProto(grant)}, nil } func (s *Server) ListUserResources(ctx context.Context, req *walletv1.ListUserResourcesRequest) (*walletv1.ListUserResourcesResponse, error) { items, err := s.svc.ListUserResources(ctx, resourcedomain.ListUserResourcesQuery{ AppCode: req.GetAppCode(), UserID: req.GetUserId(), ResourceType: req.GetResourceType(), ActiveOnly: req.GetActiveOnly(), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListUserResourcesResponse{Resources: make([]*walletv1.UserResourceEntitlement, 0, len(items))} for _, item := range items { resp.Resources = append(resp.Resources, userResourceToProto(item)) } return resp, nil } func (s *Server) EquipUserResource(ctx context.Context, req *walletv1.EquipUserResourceRequest) (*walletv1.EquipUserResourceResponse, error) { item, err := s.svc.EquipUserResource(ctx, resourcedomain.EquipUserResourceCommand{ AppCode: req.GetAppCode(), UserID: req.GetUserId(), ResourceID: req.GetResourceId(), EntitlementID: req.GetEntitlementId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.EquipUserResourceResponse{Resource: userResourceToProto(item)}, nil } func (s *Server) ListResourceGrants(ctx context.Context, req *walletv1.ListResourceGrantsRequest) (*walletv1.ListResourceGrantsResponse, error) { items, total, err := s.svc.ListResourceGrants(ctx, resourcedomain.ListResourceGrantsQuery{ AppCode: req.GetAppCode(), TargetUserID: req.GetTargetUserId(), Status: req.GetStatus(), Page: req.GetPage(), PageSize: req.GetPageSize(), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListResourceGrantsResponse{Grants: make([]*walletv1.ResourceGrant, 0, len(items)), Total: total} for _, item := range items { resp.Grants = append(resp.Grants, resourceGrantToProto(item)) } return resp, nil } func resourceCommandFromCreate(req *walletv1.CreateResourceRequest) resourcedomain.ResourceCommand { return resourcedomain.ResourceCommand{ AppCode: req.GetAppCode(), ResourceCode: req.GetResourceCode(), ResourceType: req.GetResourceType(), Name: req.GetName(), Status: req.GetStatus(), Grantable: req.GetGrantable(), GrantStrategy: req.GetGrantStrategy(), WalletAssetType: req.GetWalletAssetType(), WalletAssetAmount: req.GetWalletAssetAmount(), UsageScopes: req.GetUsageScopes(), AssetURL: req.GetAssetUrl(), PreviewURL: req.GetPreviewUrl(), AnimationURL: req.GetAnimationUrl(), MetadataJSON: req.GetMetadataJson(), SortOrder: req.GetSortOrder(), OperatorUserID: req.GetOperatorUserId(), ManagerGrantEnabled: managerGrantEnabledOrDefault(req.ManagerGrantEnabled), } } func resourceCommandFromUpdate(req *walletv1.UpdateResourceRequest) resourcedomain.ResourceCommand { command := resourceCommandFromCreate(&walletv1.CreateResourceRequest{ AppCode: req.GetAppCode(), ResourceCode: req.GetResourceCode(), ResourceType: req.GetResourceType(), Name: req.GetName(), Status: req.GetStatus(), Grantable: req.GetGrantable(), GrantStrategy: req.GetGrantStrategy(), WalletAssetType: req.GetWalletAssetType(), WalletAssetAmount: req.GetWalletAssetAmount(), UsageScopes: req.GetUsageScopes(), AssetUrl: req.GetAssetUrl(), PreviewUrl: req.GetPreviewUrl(), AnimationUrl: req.GetAnimationUrl(), MetadataJson: req.GetMetadataJson(), SortOrder: req.GetSortOrder(), OperatorUserId: req.GetOperatorUserId(), ManagerGrantEnabled: managerGrantEnabledOrDefault(req.ManagerGrantEnabled), }) command.ResourceID = req.GetResourceId() return command } func resourceGroupCommandFromCreate(req *walletv1.CreateResourceGroupRequest) resourcedomain.ResourceGroupCommand { return resourcedomain.ResourceGroupCommand{ AppCode: req.GetAppCode(), GroupCode: req.GetGroupCode(), Name: req.GetName(), Status: req.GetStatus(), Description: req.GetDescription(), SortOrder: req.GetSortOrder(), Items: groupItemInputs(req.GetItems()), OperatorUserID: req.GetOperatorUserId(), } } func resourceGroupCommandFromUpdate(req *walletv1.UpdateResourceGroupRequest) resourcedomain.ResourceGroupCommand { return resourcedomain.ResourceGroupCommand{ AppCode: req.GetAppCode(), GroupID: req.GetGroupId(), GroupCode: req.GetGroupCode(), Name: req.GetName(), Status: req.GetStatus(), Description: req.GetDescription(), SortOrder: req.GetSortOrder(), Items: groupItemInputs(req.GetItems()), OperatorUserID: req.GetOperatorUserId(), } } func giftConfigCommandFromCreate(req *walletv1.CreateGiftConfigRequest) resourcedomain.GiftConfigCommand { return resourcedomain.GiftConfigCommand{ AppCode: req.GetAppCode(), GiftID: req.GetGiftId(), ResourceID: req.GetResourceId(), Status: req.GetStatus(), Name: req.GetName(), SortOrder: req.GetSortOrder(), PresentationJSON: req.GetPresentationJson(), PriceVersion: req.GetPriceVersion(), CoinPrice: req.GetCoinPrice(), GiftPointAmount: req.GetGiftPointAmount(), HeatValue: req.GetHeatValue(), EffectiveAtMS: req.GetEffectiveAtMs(), GiftTypeCode: req.GetGiftTypeCode(), ChargeAssetType: req.GetChargeAssetType(), EffectiveFromMS: req.GetEffectiveFromMs(), EffectiveToMS: req.GetEffectiveToMs(), EffectTypes: req.GetEffectTypes(), OperatorUserID: req.GetOperatorUserId(), RegionIDs: req.GetRegionIds(), } } func giftConfigCommandFromUpdate(req *walletv1.UpdateGiftConfigRequest) resourcedomain.GiftConfigCommand { return resourcedomain.GiftConfigCommand{ AppCode: req.GetAppCode(), GiftID: req.GetGiftId(), ResourceID: req.GetResourceId(), Status: req.GetStatus(), Name: req.GetName(), SortOrder: req.GetSortOrder(), PresentationJSON: req.GetPresentationJson(), PriceVersion: req.GetPriceVersion(), CoinPrice: req.GetCoinPrice(), GiftPointAmount: req.GetGiftPointAmount(), HeatValue: req.GetHeatValue(), EffectiveAtMS: req.GetEffectiveAtMs(), GiftTypeCode: req.GetGiftTypeCode(), ChargeAssetType: req.GetChargeAssetType(), EffectiveFromMS: req.GetEffectiveFromMs(), EffectiveToMS: req.GetEffectiveToMs(), EffectTypes: req.GetEffectTypes(), OperatorUserID: req.GetOperatorUserId(), RegionIDs: req.GetRegionIds(), } } func groupItemInputs(items []*walletv1.ResourceGroupItemInput) []resourcedomain.ResourceGroupItemInput { out := make([]resourcedomain.ResourceGroupItemInput, 0, len(items)) for _, item := range items { if item == nil { continue } out = append(out, resourcedomain.ResourceGroupItemInput{ ItemType: item.GetItemType(), ResourceID: item.GetResourceId(), WalletAssetType: item.GetWalletAssetType(), WalletAssetAmount: item.GetWalletAssetAmount(), Quantity: item.GetQuantity(), DurationMS: item.GetDurationMs(), SortOrder: item.GetSortOrder(), }) } return out } func resourceToProto(resource resourcedomain.Resource) *walletv1.Resource { return &walletv1.Resource{ AppCode: appcode.Normalize(resource.AppCode), ResourceId: resource.ResourceID, ResourceCode: resource.ResourceCode, ResourceType: resource.ResourceType, Name: resource.Name, Status: resource.Status, Grantable: resource.Grantable, GrantStrategy: resource.GrantStrategy, WalletAssetType: resource.WalletAssetType, WalletAssetAmount: resource.WalletAssetAmount, UsageScopes: resource.UsageScopes, AssetUrl: resource.AssetURL, PreviewUrl: resource.PreviewURL, AnimationUrl: resource.AnimationURL, MetadataJson: resource.MetadataJSON, SortOrder: resource.SortOrder, CreatedByUserId: resource.CreatedByUserID, UpdatedByUserId: resource.UpdatedByUserID, CreatedAtMs: resource.CreatedAtMS, UpdatedAtMs: resource.UpdatedAtMS, ManagerGrantEnabled: resource.ManagerGrantEnabled, } } func managerGrantEnabledOrDefault(value *bool) bool { if value == nil { // 新建/编辑入口如果没显式携带开关,仍按产品规则默认允许经理中心赠送。 return true } return *value } func resourceGroupToProto(group resourcedomain.ResourceGroup) *walletv1.ResourceGroup { items := make([]*walletv1.ResourceGroupItem, 0, len(group.Items)) for _, item := range group.Items { items = append(items, &walletv1.ResourceGroupItem{ GroupItemId: item.GroupItemID, GroupId: item.GroupID, ResourceId: item.ResourceID, Resource: resourceToProto(item.Resource), Quantity: item.Quantity, DurationMs: item.DurationMS, SortOrder: item.SortOrder, CreatedAtMs: item.CreatedAtMS, UpdatedAtMs: item.UpdatedAtMS, ItemType: item.ItemType, WalletAssetType: item.WalletAssetType, WalletAssetAmount: item.WalletAssetAmount, }) } return &walletv1.ResourceGroup{ AppCode: appcode.Normalize(group.AppCode), GroupId: group.GroupID, GroupCode: group.GroupCode, Name: group.Name, Status: group.Status, Description: group.Description, SortOrder: group.SortOrder, Items: items, CreatedByUserId: group.CreatedByUserID, UpdatedByUserId: group.UpdatedByUserID, CreatedAtMs: group.CreatedAtMS, UpdatedAtMs: group.UpdatedAtMS, } } func giftConfigToProto(gift resourcedomain.GiftConfig) *walletv1.GiftConfig { return &walletv1.GiftConfig{ AppCode: appcode.Normalize(gift.AppCode), GiftId: gift.GiftID, ResourceId: gift.ResourceID, Resource: resourceToProto(gift.Resource), Status: gift.Status, Name: gift.Name, SortOrder: gift.SortOrder, PresentationJson: gift.PresentationJSON, PriceVersion: gift.PriceVersion, ChargeAssetType: gift.ChargeAssetType, CoinPrice: gift.CoinPrice, GiftPointAmount: gift.GiftPointAmount, HeatValue: gift.HeatValue, GiftTypeCode: gift.GiftTypeCode, EffectiveFromMs: gift.EffectiveFromMS, EffectiveToMs: gift.EffectiveToMS, EffectTypes: gift.EffectTypes, CreatedByUserId: gift.CreatedByUserID, UpdatedByUserId: gift.UpdatedByUserID, CreatedAtMs: gift.CreatedAtMS, UpdatedAtMs: gift.UpdatedAtMS, RegionIds: gift.RegionIDs, } } func userResourceToProto(item resourcedomain.UserResourceEntitlement) *walletv1.UserResourceEntitlement { return &walletv1.UserResourceEntitlement{ AppCode: appcode.Normalize(item.AppCode), EntitlementId: item.EntitlementID, UserId: item.UserID, ResourceId: item.ResourceID, Resource: resourceToProto(item.Resource), Status: item.Status, Quantity: item.Quantity, RemainingQuantity: item.RemainingQuantity, EffectiveAtMs: item.EffectiveAtMS, ExpiresAtMs: item.ExpiresAtMS, SourceGrantId: item.SourceGrantID, CreatedAtMs: item.CreatedAtMS, UpdatedAtMs: item.UpdatedAtMS, } } func resourceGrantToProto(grant resourcedomain.ResourceGrant) *walletv1.ResourceGrant { items := make([]*walletv1.ResourceGrantItem, 0, len(grant.Items)) for _, item := range grant.Items { items = append(items, &walletv1.ResourceGrantItem{ GrantItemId: item.GrantItemID, GrantId: item.GrantID, ResourceId: item.ResourceID, ResourceSnapshotJson: item.ResourceSnapshotJSON, Quantity: item.Quantity, DurationMs: item.DurationMS, ResultType: item.ResultType, WalletTransactionId: item.WalletTransactionID, EntitlementId: item.EntitlementID, CreatedAtMs: item.CreatedAtMS, }) } return &walletv1.ResourceGrant{ AppCode: appcode.Normalize(grant.AppCode), GrantId: grant.GrantID, CommandId: grant.CommandID, TargetUserId: grant.TargetUserID, GrantSource: grant.GrantSource, GrantSubjectType: grant.GrantSubjectType, GrantSubjectId: grant.GrantSubjectID, Status: grant.Status, Reason: grant.Reason, OperatorUserId: grant.OperatorUserID, Items: items, CreatedAtMs: grant.CreatedAtMS, UpdatedAtMs: grant.UpdatedAtMS, } }