Files
2026-03-27 20:16:04 +08:00

244 lines
6.2 KiB
Go

package service_event
import (
"context"
"errors"
"nixcn-cms/data"
"nixcn-cms/internal/exception"
"nixcn-cms/service/shared"
"nixcn-cms/tracer"
"strconv"
"github.com/google/uuid"
)
type EventListData struct {
Limit *string `json:"limit"`
Offset *string `json:"offset" validate:"required"`
Type *string `json:"type"`
SortBy *string `json:"sort_by"`
SortOrder *string `json:"sort_order"`
PermissionLevel uint `json:"permission_level" swaggerignore:"true"`
}
type EventListPayload struct {
Context context.Context
UserId uuid.UUID
Data *EventListData
}
type EventListItems struct {
data.EventIndexDoc
IsJoined bool `json:"is_joined"`
IsCheckedIn bool `json:"is_checked_in"`
JoinCount int64 `json:"join_count"`
CheckinCount int64 `json:"checkin_count"`
}
type EventListResponse struct {
Items *[]EventListItems `json:"items"`
Total int64 `json:"total"`
}
type EventListResult struct {
Common shared.CommonResult
Data *EventListResponse `json:"event_list"`
}
func (self *EventServiceImpl) List(payload *EventListPayload) (result *EventListResult) {
ctx, span := tracer.StartSpan(
payload.Context,
"service_event",
"list",
)
defer span.End()
ctx = exception.ContextWithService(ctx, exception.ServiceEventList)
var limit string
if payload.Data.Limit == nil || *payload.Data.Limit == "" {
limit = "20"
} else {
limit = *payload.Data.Limit
}
var offset string
if payload.Data.Offset == nil || *payload.Data.Offset == "" {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(errors.New("offset is required")),
).Throw(ctx)
return &EventListResult{
Common: shared.CommonResult{HttpCode: 400, Exception: exc},
}
} else {
offset = *payload.Data.Offset
}
limitNum, err := strconv.Atoi(limit)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(err),
).Throw(ctx)
result = &EventListResult{
Common: shared.CommonResult{HttpCode: 400, Exception: exc},
}
return
}
offsetNum, err := strconv.Atoi(offset)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(err),
).Throw(ctx)
result = &EventListResult{
Common: shared.CommonResult{HttpCode: 400, Exception: exc},
}
return
}
opts := data.EventListOptions{
Limit: int64(limitNum),
Offset: int64(offsetNum),
}
if payload.Data.Type != nil && *payload.Data.Type != "" {
opts.TypeFilter = *payload.Data.Type
}
if payload.Data.SortBy != nil {
opts.SortBy = *payload.Data.SortBy
}
if payload.Data.SortOrder != nil {
opts.SortOrder = *payload.Data.SortOrder
}
// Lv30 users only see their own events
if payload.Data.PermissionLevel == 30 {
opts.OwnerId = &payload.UserId
}
eventList, total, err := new(data.Event).ListEventsWithOptions(ctx, opts)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
return &EventListResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
}
items := make([]EventListItems, 0)
if eventList != nil && len(*eventList) > 0 {
var eventIds []uuid.UUID
for _, e := range *eventList {
if parsedId, parseErr := uuid.Parse(e.EventId); parseErr == nil {
eventIds = append(eventIds, parsedId)
}
}
joinedMap, err := new(data.Attendance).GetJoinedEventIDs(ctx, payload.UserId, eventIds)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventListResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
checkedInMap, err := new(data.Attendance).GetCheckedInEventIDs(ctx, payload.UserId, eventIds)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventListResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
joinCountMap, err := new(data.Attendance).CountUsersByEventIDs(ctx, eventIds)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventListResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
checkinCountMap, err := new(data.Attendance).CountCheckedInUsersByEventIDs(ctx, eventIds)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventListResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
for _, i := range *eventList {
currentIdUuid, _ := uuid.Parse(i.EventId)
items = append(items, EventListItems{
EventIndexDoc: i,
IsJoined: joinedMap[currentIdUuid],
IsCheckedIn: checkedInMap[currentIdUuid],
JoinCount: joinCountMap[currentIdUuid],
CheckinCount: checkinCountMap[currentIdUuid],
})
}
}
exc := exception.New(
exception.WithStatus(exception.StatusSuccess),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonSuccess),
).Throw(ctx)
result = &EventListResult{
Common: shared.CommonResult{HttpCode: 200, Exception: exc},
Data: &EventListResponse{
Items: &items,
Total: total,
},
}
return
}