Files
Asai Neko 714b98cb1a
Some checks failed
Server Check Build (NixCN CMS) TeamCity build failed
Fix attendance_list and stats allow lv40+ view info
Signed-off-by: Asai Neko <sugar@sne.moe>
2026-03-28 13:11:38 +08:00

205 lines
5.3 KiB
Go

package service_event
import (
"context"
"errors"
"nixcn-cms/data"
"nixcn-cms/internal/exception"
"nixcn-cms/service/shared"
"nixcn-cms/tracer"
"github.com/google/uuid"
)
type EventStatsData struct {
EventId string `json:"event_id" validate:"required"`
}
type EventStatsPayload struct {
Context context.Context
UserId uuid.UUID
Data *EventStatsData
}
type EventStatsResponse struct {
JoinCount int64 `json:"join_count"`
CheckinCount int64 `json:"checkin_count"`
KycPassRate float64 `json:"kyc_pass_rate"`
AgendaSubmissionCount int64 `json:"agenda_submission_count"`
}
type EventStatsResult struct {
Common shared.CommonResult
Data *EventStatsResponse
}
func (self *EventServiceImpl) Stats(payload *EventStatsPayload) (result *EventStatsResult) {
ctx, span := tracer.StartSpan(
payload.Context,
"service_event",
"stats",
)
defer span.End()
ctx = exception.ContextWithService(ctx, exception.ServiceEventStats)
eventId, err := uuid.Parse(payload.Data.EventId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorUuidParseFailed),
exception.WithError(err),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 400, Exception: exc},
}
return
}
eventData, err := new(data.Event).GetEventById(ctx, eventId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
if eventData == nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(errors.New("event not found")),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 404, Exception: exc},
}
return
}
if eventData.Owner != payload.UserId {
callerData, err := new(data.User).GetByUserId(ctx, &payload.UserId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
if callerData == nil || callerData.PermissionLevel < 40 {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeSpecific),
exception.WithOriginal(exception.EventStatsNotOwner),
exception.WithError(errors.New("only the event owner may view event stats")),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 403, Exception: exc},
}
return
}
}
attRepo := new(data.Attendance)
joinCount, err := attRepo.CountUsersByEventID(ctx, eventId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
checkinCount, err := attRepo.CountCheckedInUsersByEventID(ctx, eventId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
withKycCount, err := attRepo.CountWithKycByEventID(ctx, eventId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
agendaCount, err := new(data.Agenda).CountByEventId(ctx, eventId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 500, Exception: exc},
}
return
}
var kycPassRate float64
if joinCount > 0 {
kycPassRate = float64(withKycCount) / float64(joinCount) * 100
}
exc := exception.New(
exception.WithStatus(exception.StatusSuccess),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonSuccess),
).Throw(ctx)
result = &EventStatsResult{
Common: shared.CommonResult{HttpCode: 200, Exception: exc},
Data: &EventStatsResponse{
JoinCount: joinCount,
CheckinCount: checkinCount,
KycPassRate: kycPassRate,
AgendaSubmissionCount: agendaCount,
},
}
return
}