Files
qitongxue-api/internal/logic/event_exclude_test.go
2026-09-29 10:57:01 +08:00

113 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package logic
import (
"strings"
"testing"
"github.com/gogf/gf/v2/errors/gerror"
"tool-api/internal/consts"
)
// ============================================================================
// T04 自动排座「排除」语义单测(纯函数,不依赖 DB)
//
// 覆盖:
// - 排除桌上的座位/人员完全不被触碰(不分配、不清手工号、不计 manual_overridden);
// - fail-closed:全部桌被排除 → 4018 且 message 列出被排除的桌;
// - 部分排除 / 无桌 → 放行。
// ============================================================================
// TestPlanAutoAssignExcludesTable 排除桌的座位不参与分配,且不计入 manual_overridden。
func TestPlanAutoAssignExcludesTable(t *testing.T) {
seats := []seatBrief{
// 1 号桌:参与
{Id: 1, TableId: 1, SeatNo: 1, EmployeeId: 0},
{Id: 2, TableId: 1, SeatNo: 2, IsManual: true, EmployeeId: 0}, // 参与桌的手工位:reorder 可用
// 2 号桌:被排除(不参与自动排序)
{Id: 3, TableId: 2, SeatNo: 1, IsManual: true, EmployeeId: 0, Excluded: true}, // 排除桌的手工空位
{Id: 4, TableId: 2, SeatNo: 2, EmployeeId: 0, Excluded: true}, // 排除桌的普通空位
}
assigns, remaining, overridden := planAutoAssign(seats, []int64{101, 102, 103}, consts.SeatModeReorder)
// 排除桌 id=3、id=4 一律不可被占用
for _, a := range assigns {
if a.SeatId == 3 || a.SeatId == 4 {
t.Fatalf("排除桌的座位不应被分配,got %v", assigns)
}
}
// 参与桌有 2 个可用位(id=1、id=2),故只分配 2 人,剩 1 人
if len(assigns) != 2 {
t.Fatalf("应分配 2 人(仅参与桌),got %d (%v)", len(assigns), assigns)
}
if len(remaining) != 1 || remaining[0] != 103 {
t.Fatalf("remaining=%v want [103]", remaining)
}
// manual_overridden 只统计**参与桌**的手工位(id=2),排除桌的手工位(id=3)不计入
if overridden != 1 {
t.Fatalf("排除桌的手工位不应计入 manual_overridden,got %d want 1", overridden)
}
}
// TestPlanAutoAssignExcludesTableFill 排除桌在 fill 模式下同样不被触碰。
func TestPlanAutoAssignExcludesTableFill(t *testing.T) {
seats := []seatBrief{
{Id: 1, TableId: 1, SeatNo: 1, EmployeeId: 0},
{Id: 2, TableId: 2, SeatNo: 1, EmployeeId: 0, Excluded: true},
}
assigns, _, _ := planAutoAssign(seats, []int64{101, 102}, consts.SeatModeFill)
if len(assigns) != 1 || assigns[0].SeatId != 1 {
t.Fatalf("fill 应只填参与桌 id=1,got %v", assigns)
}
}
// TestPlanAutoGuardsAllExcluded 全部桌被排除 → 4018,且 message 列出被排除的桌。
func TestPlanAutoGuardsAllExcluded(t *testing.T) {
tables := []tableBrief{
{Id: 1, Name: "主桌", ExcludeAuto: 1},
{Id: 2, TableNo: "2", ExcludeAuto: 1},
}
err := planAutoGuards(tables)
if err == nil {
t.Fatalf("全部桌被排除应报错(fail-closed)")
}
if code := gerror.Code(err).Code(); code != consts.CodeSeatAutoInvalid {
t.Fatalf("错误码应为 %d,got %d", consts.CodeSeatAutoInvalid, code)
}
msg := err.Error()
if !strings.Contains(msg, "主桌") || !strings.Contains(msg, "2 号桌") {
t.Fatalf("错误信息应列出被排除的桌,got: %s", msg)
}
}
// TestPlanAutoGuardsPartialExcluded 部分桌可参与 → 放行(含仅 1 张桌可参与)。
func TestPlanAutoGuardsPartialExcluded(t *testing.T) {
tables := []tableBrief{
{Id: 1, Name: "签到台", ExcludeAuto: 1},
{Id: 2, Name: "1 号桌", ExcludeAuto: 0}, // 仅此 1 张可参与 → 允许
}
if err := planAutoGuards(tables); err != nil {
t.Fatalf("有 1 张可参与桌时应放行,got %v", err)
}
}
// TestPlanAutoGuardsNoTables 无桌 → 放行(交由后续逻辑自然得到 0 结果,保持老行为)。
func TestPlanAutoGuardsNoTables(t *testing.T) {
if err := planAutoGuards(nil); err != nil {
t.Fatalf("无桌不应触发 fail-closed,got %v", err)
}
}
// TestTableDisplayName 桌名回退:Name > 桌号 > id。
func TestTableDisplayName(t *testing.T) {
if got := tableDisplayName(tableBrief{Id: 1, Name: "主桌", TableNo: "1"}); got != "主桌" {
t.Fatalf("应优先用 Name,got %q", got)
}
if got := tableDisplayName(tableBrief{Id: 2, TableNo: "3"}); got != "3 号桌" {
t.Fatalf("无 Name 时用「桌号 号桌」,got %q", got)
}
if got := tableDisplayName(tableBrief{Id: 7}); got != "桌#7" {
t.Fatalf("无桌名桌号时回退 id,got %q", got)
}
}