fix: 档口入库码按货运单号直查顺运宝 (#245)
This commit is contained in:
@@ -2,9 +2,12 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"cmautobuy/admin/model"
|
||||
"cmautobuy/admin/repository"
|
||||
"cmautobuy/admin/syb"
|
||||
)
|
||||
|
||||
@@ -41,17 +44,123 @@ func TestReadInnerCodeDetails_总量不限且每批最多100(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestInnerCodeStockIDFromJSON(t *testing.T) {
|
||||
for _, raw := range []string{
|
||||
`{"stock":{"id":75104587},"detail":{"id":1}}`,
|
||||
`{"stock":{"id":"75104587"},"detail":{"id":1}}`,
|
||||
} {
|
||||
if got, ok := innerCodeStockIDFromJSON(raw); !ok || got != 75104587 {
|
||||
t.Fatalf("解析 stock id 失败 got=%d ok=%v", got, ok)
|
||||
type orderQueryInnerCodeReader struct {
|
||||
rowsByOrder map[string][]syb.StockRow
|
||||
detailsByID map[int64]syb.StockDetail
|
||||
queries []string
|
||||
detailCalls [][]int64
|
||||
err error
|
||||
}
|
||||
|
||||
func (r *orderQueryInnerCodeReader) ListByOrderNumber(_ context.Context, order string) ([]syb.StockRow, error) {
|
||||
r.queries = append(r.queries, order)
|
||||
if r.err != nil {
|
||||
return nil, r.err
|
||||
}
|
||||
return r.rowsByOrder[order], nil
|
||||
}
|
||||
|
||||
func (r *orderQueryInnerCodeReader) DetailListByStock(_ context.Context, ids []int64) ([]syb.StockDetail, error) {
|
||||
r.detailCalls = append(r.detailCalls, append([]int64(nil), ids...))
|
||||
result := make([]syb.StockDetail, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
if detail, exists := r.detailsByID[id]; exists {
|
||||
result = append(result, detail)
|
||||
}
|
||||
}
|
||||
if _, ok := innerCodeStockIDFromJSON(`{"stock":{}}`); ok {
|
||||
t.Fatal("缺少 stock.id 时不应成功")
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func TestReadInnerCodeStockIDs_按去重订单直查远端并保留零和多命中(t *testing.T) {
|
||||
reader := &orderQueryInnerCodeReader{rowsByOrder: map[string][]syb.StockRow{
|
||||
"ORDER-1": {{ID: 20, Code: "ORDER-1"}, {ID: 10, Code: "ORDER-1"}},
|
||||
"ORDER-2": {},
|
||||
}}
|
||||
got, err := readInnerCodeStockIDs(context.Background(), reader, []string{"ORDER-1", "ORDER-2"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(reader.queries, []string{"ORDER-1", "ORDER-2"}) ||
|
||||
!reflect.DeepEqual(got["ORDER-1"], []int64{10, 20}) || len(got["ORDER-2"]) != 0 {
|
||||
t.Fatalf("远端货运单定位结果不正确 queries=%v got=%v", reader.queries, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadInnerCodeStockIDs_协议或网络错误中止整批(t *testing.T) {
|
||||
reader := &orderQueryInnerCodeReader{err: errors.New("network down")}
|
||||
if _, err := readInnerCodeStockIDs(context.Background(), reader, []string{"ORDER"}); err == nil {
|
||||
t.Fatal("远端查询失败时必须中止整批")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUniqueInnerCodeOrders_同一货运单只查询一次(t *testing.T) {
|
||||
orders := uniqueInnerCodeOrders([]model.InnerCodeRecord{
|
||||
{OrderNumber: "ORDER-1"}, {OrderNumber: "ORDER-1"}, {OrderNumber: "ORDER-2"},
|
||||
})
|
||||
if !reflect.DeepEqual(orders, []string{"ORDER-1", "ORDER-2"}) {
|
||||
t.Fatalf("订单号去重结果不正确: %v", orders)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanInnerCodeRecords_本地没有SybOrder仍可直查远端生成计划(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
now := model.NowISO()
|
||||
user := model.User{
|
||||
UserID: "INNER-CODE-REMOTE-USER", Username: "inner-code-remote-user", PasswordHash: "test",
|
||||
Role: model.RoleAdmin, Status: model.UserActive, PasswordChangedAt: now, CreatedAt: now, UpdatedAt: now,
|
||||
}
|
||||
if err := repository.CreateUser(db, user); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = repository.UpsertInnerCodeImportRow(tx, model.InnerCodeImportRow{
|
||||
BusinessDate: "2026-08-15", SourceRow: 4, OrderNumber: "REMOTE-ORDER",
|
||||
Stall: "", SpecRaw: "黑色,M", SpecKey: NormalizeInnerCodeSpecKey("黑色,M"),
|
||||
InnerCode: "DK260815TEST01", SourceDuplicateCount: 1, CreatedByUserID: user.UserID,
|
||||
}, now)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var recordID int64
|
||||
if err := db.QueryRow(`SELECT id FROM syb_inner_code_records WHERE order_number='REMOTE-ORDER'`).Scan(&recordID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var localSybCount int
|
||||
if err := db.QueryRow(`SELECT COUNT(*) FROM syb_orders WHERE order_no='REMOTE-ORDER'`).Scan(&localSybCount); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if localSybCount != 0 {
|
||||
t.Fatal("测试前提失败:本地不应存在该货运单")
|
||||
}
|
||||
|
||||
item := innerCodeTestItem(9002, "黑色,M", nil)
|
||||
reader := &orderQueryInnerCodeReader{
|
||||
rowsByOrder: map[string][]syb.StockRow{"REMOTE-ORDER": {{ID: 9001, Code: "REMOTE-ORDER"}}},
|
||||
detailsByID: map[int64]syb.StockDetail{9001: {ID: 9001, Code: "REMOTE-ORDER", Details: []syb.DetailItem{item}}},
|
||||
}
|
||||
result, err := PlanInnerCodeRecords(context.Background(), db, reader, "2026-08-15", []int64{recordID})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.Ready != 1 || !reflect.DeepEqual(reader.queries, []string{"REMOTE-ORDER"}) ||
|
||||
!reflect.DeepEqual(reader.detailCalls, [][]int64{{9001}}) {
|
||||
t.Fatalf("远端规划编排不正确 result=%+v queries=%v detailCalls=%v", result, reader.queries, reader.detailCalls)
|
||||
}
|
||||
var status model.InnerCodeStatus
|
||||
var stockID, detailID int64
|
||||
if err := db.QueryRow(`SELECT status,stock_id,detail_id FROM syb_inner_code_records WHERE id=?`, recordID).
|
||||
Scan(&status, &stockID, &detailID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if status != model.InnerCodeReady || stockID != 9001 || detailID != 9002 {
|
||||
t.Fatalf("保存计划不正确 status=%s stock=%d detail=%d", status, stockID, detailID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +201,9 @@ func TestPlanInnerCodeRows_聚合码放行且其他异常继续阻断(t *testing
|
||||
t.Errorf("第 %d 条 status=%s message=%s,期望 %s", index, plans[index].Status, plans[index].ResultMessage, want)
|
||||
}
|
||||
}
|
||||
if plans[4].ResultMessage != "顺运宝未找到货运单" {
|
||||
t.Fatalf("零命中提示不正确: %q", plans[4].ResultMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanInnerCodeRows_同一远端明细不会占用两次(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user