151 lines
5.1 KiB
Go
151 lines
5.1 KiB
Go
package service
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/xuri/excelize/v2"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestNormalizeInnerCodeSpecKey(t *testing.T) {
|
||
|
|
tests := map[string]string{
|
||
|
|
"A-027 黑色,M碼 建議45-55公斤": "黑色,M",
|
||
|
|
"杏色(预售), 2xl【备注】": "杏色,2XL",
|
||
|
|
"白 色,均码": "白色,均码",
|
||
|
|
"无逗号 规格": "无逗号规格",
|
||
|
|
"": "",
|
||
|
|
}
|
||
|
|
for input, want := range tests {
|
||
|
|
if got := NormalizeInnerCodeSpecKey(input); got != want {
|
||
|
|
t.Errorf("NormalizeInnerCodeSpecKey(%q)=%q,期望 %q", input, got, want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestParseInnerCodeWorkbook_表头前置行与重复业务组(t *testing.T) {
|
||
|
|
book := excelize.NewFile()
|
||
|
|
defaultSheet := book.GetSheetList()[0]
|
||
|
|
if err := book.SetSheetName(defaultSheet, innerCodeSheetName); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
rows := [][]string{
|
||
|
|
{"线下档口标签"},
|
||
|
|
{"标签打印序号", "内部档口入库码", "Shopee订单编号", "清洗后规格", "档口名称", "档口货号", "店铺名称"},
|
||
|
|
{"1", "DK001", "ORDER-1", "A-027 黑色,M碼 建議45-55公斤", "A档", "027", "shop-a"},
|
||
|
|
{"2", "DK001", "ORDER-1", "A-027 黑色,M碼 建議45-55公斤", "A档", "027", "shop-a"},
|
||
|
|
{"3", "DK002", "ORDER-2", "杏色,XL", "B档", "102", "shop-b"},
|
||
|
|
}
|
||
|
|
setInnerCodeWorkbookRows(t, book, rows)
|
||
|
|
|
||
|
|
result, imported, err := parseInnerCodeWorkbook(book, "2026-08-15", "user-1")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if result.TotalRows != 3 || result.DuplicateRows != 1 || len(imported) != 2 {
|
||
|
|
t.Fatalf("统计不正确: result=%+v rows=%d", result, len(imported))
|
||
|
|
}
|
||
|
|
first := imported[0]
|
||
|
|
if first.SpecKey != "黑色,M" || first.Stall != "A档#027" || first.SourceDuplicateCount != 2 {
|
||
|
|
t.Fatalf("首行业务字段不正确: %+v", first)
|
||
|
|
}
|
||
|
|
if first.SourceRow != 3 || first.PrintSequence != 1 || first.ShopName != "shop-a" {
|
||
|
|
t.Fatalf("首行来源字段不正确: %+v", first)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestParseInnerCodeWorkbook_同日入库码指向不同业务键时报错(t *testing.T) {
|
||
|
|
book := excelize.NewFile()
|
||
|
|
defaultSheet := book.GetSheetList()[0]
|
||
|
|
if err := book.SetSheetName(defaultSheet, innerCodeSheetName); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
setInnerCodeWorkbookRows(t, book, [][]string{
|
||
|
|
{"内部档口入库码", "Shopee订单编号", "清洗后规格", "档口及货号"},
|
||
|
|
{"DK001", "ORDER-1", "黑色,M", "A#1"},
|
||
|
|
{"DK001", "ORDER-2", "白色,L", "B#2"},
|
||
|
|
})
|
||
|
|
_, _, err := parseInnerCodeWorkbook(book, "2026-08-15", "user-1")
|
||
|
|
if err == nil || !strings.Contains(err.Error(), "对应多组") {
|
||
|
|
t.Fatalf("期望同日入库码冲突错误,实际 %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestParseInnerCodeWorkbook_业务键相同但入库码不同时报错(t *testing.T) {
|
||
|
|
book := excelize.NewFile()
|
||
|
|
defaultSheet := book.GetSheetList()[0]
|
||
|
|
if err := book.SetSheetName(defaultSheet, innerCodeSheetName); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
setInnerCodeWorkbookRows(t, book, [][]string{
|
||
|
|
{"内部档口入库码", "Shopee订单编号", "清洗后规格", "档口及货号"},
|
||
|
|
{"DK001", "ORDER-1", "黑色,M", "A#1"},
|
||
|
|
{"DK002", "ORDER-1", "黑色,M", "A#1"},
|
||
|
|
})
|
||
|
|
_, _, err := parseInnerCodeWorkbook(book, "2026-08-15", "user-1")
|
||
|
|
if err == nil || !strings.Contains(err.Error(), "业务键相同") {
|
||
|
|
t.Fatalf("期望业务键冲突错误,实际 %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateInnerCodeUpload(t *testing.T) {
|
||
|
|
if err := ValidateInnerCodeUpload("labels.xlsx", 100, []byte{'P', 'K', 3, 4}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
for _, tc := range []struct {
|
||
|
|
name string
|
||
|
|
size int64
|
||
|
|
head []byte
|
||
|
|
}{
|
||
|
|
{"labels.xls", 100, []byte{'P', 'K', 3, 4}},
|
||
|
|
{"labels.xlsx", 0, []byte{'P', 'K', 3, 4}},
|
||
|
|
{"labels.xlsx", MaxInnerCodeUploadBytes + 1, []byte{'P', 'K', 3, 4}},
|
||
|
|
{"labels.xlsx", 100, []byte("text")},
|
||
|
|
} {
|
||
|
|
if err := ValidateInnerCodeUpload(tc.name, tc.size, tc.head); err == nil {
|
||
|
|
t.Errorf("%+v 应被拒绝", tc)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestParseInnerCodeWorkbook_脱敏文件可重开(t *testing.T) {
|
||
|
|
path := filepath.Join(t.TempDir(), "inner-code.xlsx")
|
||
|
|
book := excelize.NewFile()
|
||
|
|
defaultSheet := book.GetSheetList()[0]
|
||
|
|
if err := book.SetSheetName(defaultSheet, innerCodeSheetName); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
setInnerCodeWorkbookRows(t, book, [][]string{
|
||
|
|
{"内部档口入库码", "Shopee订单编号", "原始产品规格(源Excel D列,原样直拷)", "档口及货号"},
|
||
|
|
{"DK-TEST-1", "ORDER-TEST-1", "蓝色,L", "T#001"},
|
||
|
|
})
|
||
|
|
if err := book.SaveAs(path); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
book.Close()
|
||
|
|
reopened, err := excelize.OpenFile(path)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
defer reopened.Close()
|
||
|
|
_, imported, err := parseInnerCodeWorkbook(reopened, "2026-08-15", "user-1")
|
||
|
|
if err != nil || len(imported) != 1 || imported[0].SpecKey != "蓝色,L" {
|
||
|
|
t.Fatalf("重开解析失败 rows=%+v err=%v", imported, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func setInnerCodeWorkbookRows(t *testing.T, book *excelize.File, rows [][]string) {
|
||
|
|
t.Helper()
|
||
|
|
for rowIndex, row := range rows {
|
||
|
|
for columnIndex, value := range row {
|
||
|
|
cell, err := excelize.CoordinatesToCellName(columnIndex+1, rowIndex+1)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if err := book.SetCellValue(innerCodeSheetName, cell, value); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|