Files
cmautobuy/admin/service/inner_code_apply_test.go
T

163 lines
6.1 KiB
Go
Raw Normal View History

package service
import (
"context"
"errors"
"testing"
"cmautobuy/admin/model"
"cmautobuy/admin/syb"
)
type fakeInnerCodeWriter struct {
stock syb.StockDetail
readErr error
deleteErr error
updateErr error
readCount int
deleteCount int
updateCount int
updatedCode string
}
func TestApplyInnerCodes_远程批量上限不随页面容量放宽(t *testing.T) {
ids := make([]int64, InnerCodeApplyBatchLimit+1)
for i := range ids {
ids[i] = int64(i + 1)
}
if _, err := ApplyInnerCodes(context.Background(), nil, nil, ids, "user-1"); err == nil {
t.Fatal("超过 20 条时应该在访问数据库或顺运宝前拒绝")
}
}
func (f *fakeInnerCodeWriter) DetailListByStock(context.Context, []int64) ([]syb.StockDetail, error) {
f.readCount++
if f.readErr != nil {
return nil, f.readErr
}
return []syb.StockDetail{f.stock}, nil
}
func (f *fakeInnerCodeWriter) DeleteInnerCode(_ context.Context, detailID int64) error {
f.deleteCount++
if f.deleteErr != nil {
return f.deleteErr
}
for index := range f.stock.Details {
if f.stock.Details[index].ID == detailID {
f.stock.Details[index].Raw["innerExpCode"] = ""
}
}
return nil
}
func (f *fakeInnerCodeWriter) UpdateDetailCode(_ context.Context, _, detailID int64, code string) error {
f.updateCount++
f.updatedCode = code
if f.updateErr != nil {
return f.updateErr
}
for index := range f.stock.Details {
if f.stock.Details[index].ID == detailID {
f.stock.Details[index].Raw["innerExpCode"] = code
}
}
return nil
}
func TestApplyClaimedInnerCode_聚合码只写一次并按完整值复读(t *testing.T) {
record := innerCodeApplyTestRecord("")
record.InnerCode = "DK260815A160101,DK260815A160102"
writer := innerCodeApplyTestWriter(record, "")
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeUpdated || writer.updateCount != 1 || writer.updatedCode != record.InnerCode ||
outcome.RemoteCode != record.InnerCode || writer.readCount != 2 {
t.Fatalf("outcome=%+v update=%d code=%q read=%d", outcome, writer.updateCount, writer.updatedCode, writer.readCount)
}
}
func TestApplyClaimedInnerCode_空旧值直接写并复读确认(t *testing.T) {
record := innerCodeApplyTestRecord("")
writer := innerCodeApplyTestWriter(record, "")
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeUpdated || writer.deleteCount != 0 || writer.updateCount != 1 || writer.readCount != 2 {
t.Fatalf("outcome=%+v counts read=%d delete=%d update=%d", outcome, writer.readCount, writer.deleteCount, writer.updateCount)
}
}
func TestApplyClaimedInnerCode_有旧值先删后写(t *testing.T) {
record := innerCodeApplyTestRecord("OLD")
writer := innerCodeApplyTestWriter(record, "OLD")
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeUpdated || writer.deleteCount != 1 || writer.updateCount != 1 {
t.Fatalf("outcome=%+v delete=%d update=%d", outcome, writer.deleteCount, writer.updateCount)
}
}
func TestApplyClaimedInnerCode_规划后远端值变化不写入(t *testing.T) {
record := innerCodeApplyTestRecord("OLD")
writer := innerCodeApplyTestWriter(record, "OTHER")
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeNeedsCheck || writer.deleteCount != 0 || writer.updateCount != 0 {
t.Fatalf("outcome=%+v delete=%d update=%d", outcome, writer.deleteCount, writer.updateCount)
}
}
func TestApplyClaimedInnerCode_删除明确失败不继续写(t *testing.T) {
record := innerCodeApplyTestRecord("OLD")
writer := innerCodeApplyTestWriter(record, "OLD")
writer.deleteErr = errors.New("已打单数据不能清除")
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeFailed || writer.deleteCount != 1 || writer.updateCount != 0 {
t.Fatalf("outcome=%+v delete=%d update=%d", outcome, writer.deleteCount, writer.updateCount)
}
}
func TestApplyClaimedInnerCode_写入未知结果不复读也不重试(t *testing.T) {
record := innerCodeApplyTestRecord("")
writer := innerCodeApplyTestWriter(record, "")
writer.updateErr = fmtUnknownInnerCodeWriteError()
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeNeedsCheck || writer.updateCount != 1 || writer.readCount != 1 {
t.Fatalf("outcome=%+v update=%d read=%d", outcome, writer.updateCount, writer.readCount)
}
}
func TestApplyClaimedInnerCode_采购字段出现后停止(t *testing.T) {
record := innerCodeApplyTestRecord("")
writer := innerCodeApplyTestWriter(record, "")
writer.stock.Details[0].Raw["purchaseCode"] = "CG-1"
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeSkipped || writer.updateCount != 0 {
t.Fatalf("outcome=%+v update=%d", outcome, writer.updateCount)
}
}
func TestApplyClaimedInnerCode_档口身份变化后停止(t *testing.T) {
record := innerCodeApplyTestRecord("")
record.SybSKU = "A#1"
writer := innerCodeApplyTestWriter(record, "")
writer.stock.Details[0].Raw["sku"] = "B#2"
outcome := applyClaimedInnerCode(context.Background(), writer, record)
if outcome.Status != model.InnerCodeSkipped || writer.updateCount != 0 {
t.Fatalf("outcome=%+v update=%d", outcome, writer.updateCount)
}
}
func innerCodeApplyTestRecord(oldCode string) model.InnerCodeRecord {
return model.InnerCodeRecord{ID: 1, StockID: 10, DetailID: 20, SybSpec: "黑色,M",
InnerCode: "DK-001", RemoteInnerCode: oldCode, Status: model.InnerCodeApplying}
}
func innerCodeApplyTestWriter(record model.InnerCodeRecord, currentCode string) *fakeInnerCodeWriter {
item := syb.DetailItem{ID: record.DetailID, ProductSpec: record.SybSpec, Raw: map[string]any{
"id": record.DetailID, "productSpec": record.SybSpec, "innerExpCode": currentCode,
"purchasePlatform": "", "purchaseCode": "",
}}
return &fakeInnerCodeWriter{stock: syb.StockDetail{ID: record.StockID, Details: []syb.DetailItem{item}}}
}
func fmtUnknownInnerCodeWriteError() error {
return errors.Join(syb.ErrWriteResultUnknown, errors.New("timeout"))
}