material_manage_system/internal/service/stock_test.go
2026-09-20 14:29:41 +08:00

71 lines
2.6 KiB
Go

package service
import (
"testing"
"github.com/shopspring/decimal"
"github.com/wmms/wmms/internal/model"
)
// ClassifyStock 是库存状态的唯一判定入口,这张表同时钉住"新增物料不误报"和
// "真的低于阈值要报警"两侧的边界。它必须与 repository.stockWarningHavingSQL 一致。
func TestClassifyStockBoundaries(t *testing.T) {
cases := []struct {
name string
totalOnHand string
warningStock string
warningEnabled bool
want string
}{
// 阈值为 0 是合法配置,含义是"库存降到 0 时预警",不再被排除在预警之外。
{"阈值0启用且库存归零", "0", "0", true, model.StockStatusLow},
{"阈值0启用但还剩一点", "0.000001", "0", true, model.StockStatusNormal},
{"有货且阈值为0", "5", "0", true, model.StockStatusNormal},
// 没配过规则和手动关闭预警由同一个 warningEnabled=false 表达,一律不报警。
{"没配过预警规则", "0", "0", false, model.StockStatusNormal},
{"设了阈值但库存归零", "0", "10", true, model.StockStatusLow},
{"低于阈值", "5", "10", true, model.StockStatusLow},
{"恰好触达阈值即预警", "10", "10", true, model.StockStatusLow},
{"略高于阈值", "10.000001", "10", true, model.StockStatusNormal},
{"高于阈值", "15", "10", true, model.StockStatusNormal},
{"用完但手动关闭预警", "0", "10", false, model.StockStatusNormal},
{"低于阈值但手动关闭预警", "5", "10", false, model.StockStatusNormal},
{"有货且手动关闭预警", "15", "10", false, model.StockStatusNormal},
// 数量是 decimal 字符串,按字典序比较会把 "370" 判成小于 "50"。
{"大数按数值而非字典序比较", "370.000000", "50.000000", true, model.StockStatusNormal},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := ClassifyStock(
decimal.RequireFromString(tc.totalOnHand),
decimal.RequireFromString(tc.warningStock),
tc.warningEnabled,
)
if got != tc.want {
t.Fatalf("ClassifyStock(%s, %s, %v) = %s, want %s",
tc.totalOnHand, tc.warningStock, tc.warningEnabled, got, tc.want)
}
})
}
}
func TestSignedChangeQuantityUsesTheSameConventionForInboundAndOutbound(t *testing.T) {
quantity := decimal.NewFromInt(100)
cases := []struct {
logType string
want string
}{
{logType: "in", want: "100"},
{logType: "out", want: "-100"},
}
for _, tc := range cases {
t.Run(tc.logType, func(t *testing.T) {
if got := signedChangeQuantity(tc.logType, quantity); !got.Equal(decimal.RequireFromString(tc.want)) {
t.Fatalf("signedChangeQuantity(%q, 100) = %s, want %s", tc.logType, got, tc.want)
}
})
}
}