2026-05-12 09:53:20 +08:00

104 lines
3.1 KiB
Go

package service
import (
"context"
"fmt"
"slices"
"hyapp/pkg/appcode"
"hyapp/pkg/xerr"
)
const defaultRoomSeatCount int32 = 15
var roomSeatCountCandidates = []int32{10, 15, 20, 25, 30}
func defaultRoomSeatConfig(appCode string) RoomSeatConfig {
allowed := append([]int32(nil), roomSeatCountCandidates...)
return RoomSeatConfig{
AppCode: appcode.Normalize(appCode),
AllowedSeatCounts: allowed,
DefaultSeatCount: defaultRoomSeatCount,
}
}
func (s *Service) resolveRoomSeatCount(ctx context.Context, requested int32) (int32, error) {
if requested < 0 {
// 负数没有业务语义,不能让它落到默认值分支掩盖客户端错误。
return 0, xerr.New(xerr.InvalidArgument, "seat_count is invalid")
}
config, err := s.currentRoomSeatConfig(ctx)
if err != nil {
return 0, err
}
if requested == 0 {
return config.DefaultSeatCount, nil
}
if !seatCountAllowed(config.AllowedSeatCounts, requested) {
return 0, xerr.New(xerr.InvalidArgument, fmt.Sprintf("seat_count must be one of %v", config.AllowedSeatCounts))
}
return requested, nil
}
func (s *Service) validateRoomSeatCount(ctx context.Context, requested int32) (int32, error) {
if requested <= 0 {
return 0, xerr.New(xerr.InvalidArgument, "seat_count is invalid")
}
config, err := s.currentRoomSeatConfig(ctx)
if err != nil {
return 0, err
}
if !seatCountAllowed(config.AllowedSeatCounts, requested) {
return 0, xerr.New(xerr.InvalidArgument, fmt.Sprintf("seat_count must be one of %v", config.AllowedSeatCounts))
}
return requested, nil
}
func (s *Service) currentRoomSeatConfig(ctx context.Context) (RoomSeatConfig, error) {
config, exists, err := s.repository.GetRoomSeatConfig(ctx)
if err != nil {
return RoomSeatConfig{}, err
}
if !exists {
// 本地新库会通过 initdb/Migrate 写默认行;该兜底保护测试或手动库缺行时仍能按产品默认创建房间。
return defaultRoomSeatConfig(appcode.FromContext(ctx)), nil
}
normalized, err := normalizeRoomSeatConfig(config)
if err != nil {
return RoomSeatConfig{}, xerr.New(xerr.Unavailable, "room seat config is invalid")
}
return normalized, nil
}
func normalizeRoomSeatConfig(config RoomSeatConfig) (RoomSeatConfig, error) {
seen := make(map[int32]bool, len(config.AllowedSeatCounts))
allowed := make([]int32, 0, len(config.AllowedSeatCounts))
for _, value := range config.AllowedSeatCounts {
if seen[value] {
continue
}
if !seatCountAllowed(roomSeatCountCandidates, value) {
return RoomSeatConfig{}, fmt.Errorf("seat count candidate is invalid: %d", value)
}
seen[value] = true
allowed = append(allowed, value)
}
slices.Sort(allowed)
if len(allowed) == 0 {
return RoomSeatConfig{}, fmt.Errorf("allowed seat counts are empty")
}
if !seatCountAllowed(allowed, config.DefaultSeatCount) {
return RoomSeatConfig{}, fmt.Errorf("default seat count is not allowed: %d", config.DefaultSeatCount)
}
config.AllowedSeatCounts = allowed
config.AppCode = appcode.Normalize(config.AppCode)
return config, nil
}
func seatCountAllowed(values []int32, target int32) bool {
return slices.Contains(values, target)
}