package grpc import ( "context" "time" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" "hyapp/pkg/xerr" "hyapp/services/wallet-service/internal/domain/ledger" ) func (s *Server) GetRedPacketConfig(ctx context.Context, req *walletv1.GetRedPacketConfigRequest) (*walletv1.GetRedPacketConfigResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) config, err := s.svc.GetRedPacketConfig(ctx, req.GetAppCode()) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GetRedPacketConfigResponse{ Config: redPacketConfigToProto(config), ServerTimeMs: time.Now().UTC().UnixMilli(), }, nil } func (s *Server) UpdateRedPacketConfig(ctx context.Context, req *walletv1.UpdateRedPacketConfigRequest) (*walletv1.UpdateRedPacketConfigResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) config, err := s.svc.UpdateRedPacketConfig(ctx, ledger.RedPacketConfig{ AppCode: req.GetAppCode(), Enabled: req.GetEnabled(), CountTiers: req.GetCountTiers(), AmountTiers: req.GetAmountTiers(), DelayedOpenSeconds: req.GetDelayedOpenSeconds(), ExpireSeconds: req.GetExpireSeconds(), DailySendLimit: req.GetDailySendLimit(), UpdatedByAdminID: req.GetOperatorUserId(), RuleURL: req.GetRuleUrl(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.UpdateRedPacketConfigResponse{ Config: redPacketConfigToProto(config), ServerTimeMs: time.Now().UTC().UnixMilli(), }, nil } func (s *Server) CreateRedPacket(ctx context.Context, req *walletv1.CreateRedPacketRequest) (*walletv1.CreateRedPacketResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.CreateRedPacket(ctx, ledger.RedPacketCreateCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), SenderUserID: req.GetSenderUserId(), RoomID: req.GetRoomId(), RegionID: req.GetRegionId(), PacketType: req.GetPacketType(), TotalAmount: req.GetTotalAmount(), PacketCount: req.GetPacketCount(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.CreateRedPacketResponse{ Packet: redPacketToProto(receipt.Packet), BalanceAfter: receipt.BalanceAfter, ServerTimeMs: time.Now().UTC().UnixMilli(), }, nil } func (s *Server) ClaimRedPacket(ctx context.Context, req *walletv1.ClaimRedPacketRequest) (*walletv1.ClaimRedPacketResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.ClaimRedPacket(ctx, ledger.RedPacketClaimCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), PacketID: req.GetPacketId(), UserID: req.GetUserId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ClaimRedPacketResponse{ Claim: redPacketClaimToProto(receipt.Claim), BalanceAfter: receipt.BalanceAfter, ServerTimeMs: time.Now().UTC().UnixMilli(), Packet: redPacketToProto(receipt.Packet), }, nil } func (s *Server) ListRedPackets(ctx context.Context, req *walletv1.ListRedPacketsRequest) (*walletv1.ListRedPacketsResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) packets, total, err := s.svc.ListRedPackets(ctx, ledger.RedPacketQuery{ AppCode: req.GetAppCode(), RoomID: req.GetRoomId(), SenderUserID: req.GetSenderUserId(), RegionID: req.GetRegionId(), PacketType: req.GetPacketType(), Status: req.GetStatus(), ViewerUserID: req.GetViewerUserId(), StartAtMS: req.GetStartAtMs(), EndAtMS: req.GetEndAtMs(), Page: req.GetPage(), PageSize: req.GetPageSize(), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListRedPacketsResponse{Packets: make([]*walletv1.RedPacket, 0, len(packets)), Total: total, ServerTimeMs: time.Now().UTC().UnixMilli()} for _, packet := range packets { resp.Packets = append(resp.Packets, redPacketToProto(packet)) } return resp, nil } func (s *Server) GetRedPacket(ctx context.Context, req *walletv1.GetRedPacketRequest) (*walletv1.GetRedPacketResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) packet, err := s.svc.GetRedPacket(ctx, req.GetAppCode(), req.GetPacketId(), req.GetViewerUserId(), req.GetIncludeClaims()) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GetRedPacketResponse{Packet: redPacketToProto(packet), ServerTimeMs: time.Now().UTC().UnixMilli()}, nil } func (s *Server) ExpireRedPackets(ctx context.Context, req *walletv1.ExpireRedPacketsRequest) (*walletv1.ExpireRedPacketsResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) result, err := s.svc.ExpireRedPackets(ctx, req.GetAppCode(), req.GetBatchSize()) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.ExpireRedPacketsResponse{ ExpiredCount: result.ExpiredCount, RefundedAmount: result.RefundedAmount, ServerTimeMs: time.Now().UTC().UnixMilli(), }, nil } func (s *Server) RetryRedPacketRefund(ctx context.Context, req *walletv1.RetryRedPacketRefundRequest) (*walletv1.RetryRedPacketRefundResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.RetryRedPacketRefund(ctx, req.GetAppCode(), req.GetPacketId(), req.GetOperatorUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.RetryRedPacketRefundResponse{ Packet: redPacketToProto(receipt.Packet), RefundedAmount: receipt.RefundedAmount, ServerTimeMs: time.Now().UTC().UnixMilli(), }, nil } func redPacketConfigToProto(config ledger.RedPacketConfig) *walletv1.RedPacketConfig { return &walletv1.RedPacketConfig{ AppCode: config.AppCode, Enabled: config.Enabled, CountTiers: config.CountTiers, AmountTiers: config.AmountTiers, DelayedOpenSeconds: config.DelayedOpenSeconds, ExpireSeconds: config.ExpireSeconds, DailySendLimit: config.DailySendLimit, UpdatedByAdminId: config.UpdatedByAdminID, CreatedAtMs: config.CreatedAtMS, UpdatedAtMs: config.UpdatedAtMS, RuleUrl: config.RuleURL, } } func redPacketToProto(packet ledger.RedPacket) *walletv1.RedPacket { claims := make([]*walletv1.RedPacketClaim, 0, len(packet.Claims)) for _, claim := range packet.Claims { claims = append(claims, redPacketClaimToProto(claim)) } return &walletv1.RedPacket{ AppCode: packet.AppCode, PacketId: packet.PacketID, CommandId: packet.CommandID, SenderUserId: packet.SenderUserID, RoomId: packet.RoomID, RegionId: packet.RegionID, PacketType: packet.PacketType, TotalAmount: packet.TotalAmount, PacketCount: packet.PacketCount, RemainingAmount: packet.RemainingAmount, RemainingCount: packet.RemainingCount, Status: packet.Status, OpenAtMs: packet.OpenAtMS, ExpiresAtMs: packet.ExpiresAtMS, CreatedAtMs: packet.CreatedAtMS, UpdatedAtMs: packet.UpdatedAtMS, ClaimedByViewer: packet.ClaimedByViewer, ViewerClaimAmount: packet.ViewerClaimAmount, Claims: claims, RefundAmount: packet.RefundAmount, RefundStatus: packet.RefundStatus, RefundedAtMs: packet.RefundedAtMS, } } func redPacketClaimToProto(claim ledger.RedPacketClaim) *walletv1.RedPacketClaim { return &walletv1.RedPacketClaim{ AppCode: claim.AppCode, ClaimId: claim.ClaimID, CommandId: claim.CommandID, PacketId: claim.PacketID, UserId: claim.UserID, Amount: claim.Amount, WalletTransactionId: claim.WalletTransactionID, Status: claim.Status, FailureReason: claim.FailureReason, CreatedAtMs: claim.CreatedAtMS, UpdatedAtMs: claim.UpdatedAtMS, } }