Files
Asai Neko fb087986f0
All checks were successful
Server Prod Build (NixCN CMS) TeamCity build finished
Server Check Build (NixCN CMS) TeamCity build finished
Fix event join service attendanceSearch check GetAttendance func order
Signed-off-by: Asai Neko <sugar@sne.moe>
2026-05-04 01:45:18 +08:00

305 lines
7.0 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"
"gorm.io/gorm"
)
type EventJoinData struct {
EventId string `json:"event_id" validate:"required"`
KycId string `json:"kyc_id"`
UserId string `json:"user_id" swaggerignore:"true"`
Role string `json:"role" swaggerignore:"true"`
State string `json:"state" swaggerignore:"true"`
}
type EventJoinPayload struct {
Context context.Context
Data *EventJoinData
}
type EventJoinResponse struct {
AttendanceId string `json:"attendance_id" validate:"required"`
}
type EventJoinResult struct {
Common shared.CommonResult
Data *EventJoinResponse
}
func (self *EventServiceImpl) Join(payload *EventJoinPayload) (result *EventJoinResult) {
ctx, span := tracer.StartSpan(
payload.Context,
"service_event",
"join",
)
defer span.End()
ctx = exception.ContextWithService(ctx, exception.ServiceEventJoin)
var err error
eventId, err := uuid.Parse(payload.Data.EventId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(err),
).Throw(ctx)
result = &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 400,
Exception: exc,
},
Data: nil,
}
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 = &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 500,
Exception: exc,
},
Data: nil,
}
return
}
if eventData.EnableKYC == true && payload.Data.KycId == "" {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(errors.New("KYC is required for this event")),
).Throw(ctx)
result = &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 400,
Exception: exc,
},
Data: nil,
}
return
}
userId, err := uuid.Parse(payload.Data.UserId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(err),
).Throw(ctx)
result = &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 400,
Exception: exc,
},
Data: nil,
}
return
}
userData, err := new(data.User).GetByUserId(ctx, &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 = &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 500,
Exception: exc,
},
Data: nil,
}
return
}
if userData.Nickname == "" {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorInvalidInput),
exception.WithError(errors.New("user nickname is empty")),
).Throw(ctx)
result = &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 500,
Exception: exc,
},
Data: nil,
}
return
}
attendenceSearch, err := new(data.Attendance).GetAttendance(ctx, userId, eventId)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
return &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 500,
Exception: exc,
},
Data: nil,
}
}
if err == nil && attendenceSearch != nil && attendenceSearch.AttendanceId != uuid.Nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeSpecific),
exception.WithOriginal(exception.EventJoinEventInvalid),
exception.WithError(errors.New("user already joined this event")),
).Throw(ctx)
return &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 403,
Exception: exc,
},
Data: nil,
}
}
attendenceCount, err := new(data.Attendance).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)
return &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 500,
Exception: exc,
},
Data: nil,
}
}
attendanceOpts := []data.AttendanceOption{
data.WithUserId(userId),
data.WithEventId(eventId),
data.WithRole("normal"),
}
if attendenceCount >= eventData.Quota {
if attendenceCount >= eventData.Limit {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeSpecific),
exception.WithOriginal(exception.EventJoinLimitExceeded),
exception.WithError(errors.New("event limit exceeded")),
).Throw(ctx)
return &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 403,
Exception: exc,
},
Data: nil,
}
}
attendanceOpts = append(attendanceOpts, data.WithState("out_of_limit"))
} else {
attendanceOpts = append(attendanceOpts, data.WithState("success"))
}
if payload.Data.KycId != "" {
kycUUID, err := uuid.Parse(payload.Data.KycId)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusUser),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorUuidParseFailed),
exception.WithError(err),
).Throw(ctx)
return &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 400,
Exception: exc,
},
}
}
attendanceOpts = append(attendanceOpts, data.WithKycId(kycUUID))
}
attendanceId, err := data.NewAttendance(attendanceOpts...).Create(ctx)
if err != nil {
exc := exception.New(
exception.WithStatus(exception.StatusServer),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonErrorDatabase),
exception.WithError(err),
).Throw(ctx)
return &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 500,
Exception: exc,
},
Data: nil,
}
}
exc := exception.New(
exception.WithStatus(exception.StatusSuccess),
exception.WithType(exception.TypeCommon),
exception.WithOriginal(exception.CommonSuccess),
).Throw(ctx)
result = &EventJoinResult{
Common: shared.CommonResult{
HttpCode: 200,
Exception: exc,
},
Data: &EventJoinResponse{
AttendanceId: attendanceId.String(),
},
}
return
}