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 } 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++ 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("") 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")) }