Add backend foundation and config-driven workbench
This commit is contained in:
164
backend/internal/service/entry_home_service.go
Normal file
164
backend/internal/service/entry_home_service.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"cmr-backend/internal/apperr"
|
||||
"cmr-backend/internal/store/postgres"
|
||||
)
|
||||
|
||||
type EntryHomeService struct {
|
||||
store *postgres.Store
|
||||
}
|
||||
|
||||
type EntryHomeInput struct {
|
||||
UserID string
|
||||
ChannelCode string
|
||||
ChannelType string
|
||||
PlatformAppID string
|
||||
TenantCode string
|
||||
}
|
||||
|
||||
type EntryHomeResult struct {
|
||||
User struct {
|
||||
ID string `json:"id"`
|
||||
PublicID string `json:"publicId"`
|
||||
Status string `json:"status"`
|
||||
Nickname *string `json:"nickname,omitempty"`
|
||||
AvatarURL *string `json:"avatarUrl,omitempty"`
|
||||
} `json:"user"`
|
||||
Tenant struct {
|
||||
ID string `json:"id"`
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
} `json:"tenant"`
|
||||
Channel struct {
|
||||
ID string `json:"id"`
|
||||
Code string `json:"code"`
|
||||
Type string `json:"type"`
|
||||
PlatformAppID *string `json:"platformAppId,omitempty"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Status string `json:"status"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
} `json:"channel"`
|
||||
Cards []CardResult `json:"cards"`
|
||||
OngoingSession *EntrySessionSummary `json:"ongoingSession,omitempty"`
|
||||
RecentSession *EntrySessionSummary `json:"recentSession,omitempty"`
|
||||
}
|
||||
|
||||
type EntrySessionSummary struct {
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
EventID string `json:"eventId"`
|
||||
EventName string `json:"eventName"`
|
||||
ReleaseID *string `json:"releaseId,omitempty"`
|
||||
ConfigLabel *string `json:"configLabel,omitempty"`
|
||||
RouteCode *string `json:"routeCode,omitempty"`
|
||||
LaunchedAt string `json:"launchedAt"`
|
||||
StartedAt *string `json:"startedAt,omitempty"`
|
||||
EndedAt *string `json:"endedAt,omitempty"`
|
||||
}
|
||||
|
||||
func NewEntryHomeService(store *postgres.Store) *EntryHomeService {
|
||||
return &EntryHomeService{store: store}
|
||||
}
|
||||
|
||||
func (s *EntryHomeService) GetEntryHome(ctx context.Context, input EntryHomeInput) (*EntryHomeResult, error) {
|
||||
input.UserID = strings.TrimSpace(input.UserID)
|
||||
if input.UserID == "" {
|
||||
return nil, apperr.New(http.StatusUnauthorized, "unauthorized", "user is required")
|
||||
}
|
||||
|
||||
user, err := s.store.GetUserByID(ctx, s.store.Pool(), input.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, apperr.New(http.StatusNotFound, "user_not_found", "user not found")
|
||||
}
|
||||
|
||||
entry, err := s.store.FindEntryChannel(ctx, postgres.FindEntryChannelParams{
|
||||
ChannelCode: strings.TrimSpace(input.ChannelCode),
|
||||
ChannelType: strings.TrimSpace(input.ChannelType),
|
||||
PlatformAppID: strings.TrimSpace(input.PlatformAppID),
|
||||
TenantCode: strings.TrimSpace(input.TenantCode),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry == nil {
|
||||
return nil, apperr.New(http.StatusNotFound, "entry_channel_not_found", "entry channel not found")
|
||||
}
|
||||
|
||||
cards, err := s.store.ListCardsForEntry(ctx, entry.TenantID, &entry.ID, "home_primary", nowUTC(), 20)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sessions, err := s.store.ListSessionsByUserID(ctx, user.ID, 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &EntryHomeResult{
|
||||
Cards: mapCards(cards),
|
||||
}
|
||||
result.User.ID = user.ID
|
||||
result.User.PublicID = user.PublicID
|
||||
result.User.Status = user.Status
|
||||
result.User.Nickname = user.Nickname
|
||||
result.User.AvatarURL = user.AvatarURL
|
||||
result.Tenant.ID = entry.TenantID
|
||||
result.Tenant.Code = entry.TenantCode
|
||||
result.Tenant.Name = entry.TenantName
|
||||
result.Channel.ID = entry.ID
|
||||
result.Channel.Code = entry.ChannelCode
|
||||
result.Channel.Type = entry.ChannelType
|
||||
result.Channel.PlatformAppID = entry.PlatformAppID
|
||||
result.Channel.DisplayName = entry.DisplayName
|
||||
result.Channel.Status = entry.Status
|
||||
result.Channel.IsDefault = entry.IsDefault
|
||||
|
||||
if len(sessions) > 0 {
|
||||
recent := buildEntrySessionSummary(&sessions[0])
|
||||
result.RecentSession = &recent
|
||||
}
|
||||
|
||||
for i := range sessions {
|
||||
if sessions[i].Status == "launched" || sessions[i].Status == "running" {
|
||||
ongoing := buildEntrySessionSummary(&sessions[i])
|
||||
result.OngoingSession = &ongoing
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func buildEntrySessionSummary(session *postgres.Session) EntrySessionSummary {
|
||||
summary := EntrySessionSummary{
|
||||
ID: session.SessionPublicID,
|
||||
Status: session.Status,
|
||||
RouteCode: session.RouteCode,
|
||||
LaunchedAt: session.LaunchedAt.Format(timeRFC3339),
|
||||
}
|
||||
if session.EventPublicID != nil {
|
||||
summary.EventID = *session.EventPublicID
|
||||
}
|
||||
if session.EventDisplayName != nil {
|
||||
summary.EventName = *session.EventDisplayName
|
||||
}
|
||||
summary.ReleaseID = session.ReleasePublicID
|
||||
summary.ConfigLabel = session.ConfigLabel
|
||||
if session.StartedAt != nil {
|
||||
value := session.StartedAt.Format(timeRFC3339)
|
||||
summary.StartedAt = &value
|
||||
}
|
||||
if session.EndedAt != nil {
|
||||
value := session.EndedAt.Format(timeRFC3339)
|
||||
summary.EndedAt = &value
|
||||
}
|
||||
return summary
|
||||
}
|
||||
Reference in New Issue
Block a user