material_manage_system/internal/repository/outbound_organization_test.go
2026-10-09 12:21:53 +08:00

120 lines
3.7 KiB
Go

package repository
import (
"database/sql"
"testing"
"time"
"github.com/wmms/wmms/internal/model"
)
func TestOutboundRepoOrganizationIsolationReads(t *testing.T) {
db := isolationDB(t, false)
seedOrderIsolation(t, db)
repo := NewOutboundRepo()
ownOrder, err := repo.GetByID(102, 102)
if err != nil || ownOrder.ID != 102 || ownOrder.OrganizationID != 102 {
t.Fatalf("B 读自己的单据失败: %+v err=%v", ownOrder, err)
}
if _, err := repo.GetByID(102, 101); err != sql.ErrNoRows {
t.Fatalf("B 读 A 的单据必须 ErrNoRows, got %v", err)
}
ordersA, totalA, err := repo.List(101, "", 20, 0)
if err != nil {
t.Fatal(err)
}
if totalA != 1 || len(ordersA) != 1 || ordersA[0].ID != 101 {
t.Fatalf("A 列表=%+v total=%d", ordersA, totalA)
}
ordersB, totalB, err := repo.List(102, "", 20, 0)
if err != nil {
t.Fatal(err)
}
if totalB != 1 || len(ordersB) != 1 || ordersB[0].ID != 102 {
t.Fatalf("B 列表=%+v total=%d", ordersB, totalB)
}
recordsB, err := repo.GetByMaterialID(102, 102)
if err != nil || len(recordsB) != 1 {
t.Fatalf("B 物料历史=%+v err=%v", recordsB, err)
}
recordsCross, err := repo.GetByMaterialID(102, 101)
if err != nil || len(recordsCross) != 0 {
t.Fatalf("B 读 A 物料历史必须为空, got %+v err=%v", recordsCross, err)
}
}
func TestOutboundRepoCreatePersistsDimensionsAndRestrictsItems(t *testing.T) {
db := isolationDB(t, false)
seedOrderIsolation(t, db)
repo := NewOutboundRepo()
order := &model.OutboundOrder{
OrganizationID: 102,
WarehouseID: 102,
LocationID: 102,
OutboundDate: time.Now(),
Operator: "op",
Handler: "h",
Receiver: "r",
Items: []model.OutboundItem{{MaterialID: 102, Quantity: 2}},
}
if err := repo.Create(order); err != nil {
t.Fatal(err)
}
var org, warehouse, location int64
if err := db.QueryRow(`SELECT organization_id, warehouse_id, location_id FROM outbound_orders WHERE id = ?`, order.ID).Scan(&org, &warehouse, &location); err != nil {
t.Fatal(err)
}
if org != 102 || warehouse != 102 || location != 102 {
t.Fatalf("头表维度=%d/%d/%d, want 102/102/102", org, warehouse, location)
}
// 塞一条 A 的物料明细:物料外键合法,但读取时的同组织关联会把它挡掉。
mustSQL(t, db, `INSERT INTO outbound_items(outbound_order_id, material_id, quantity) VALUES (?, ?, ?)`, order.ID, 101, 9)
loaded, err := repo.GetByID(102, order.ID)
if err != nil {
t.Fatal(err)
}
if len(loaded.Items) != 1 || loaded.Items[0].MaterialID != 102 {
t.Fatalf("跨公司物料明细必须被关联条件挡掉, got %+v", loaded.Items)
}
}
func TestOutboundRepoUpdateAndDeleteScopeToOrganization(t *testing.T) {
db := isolationDB(t, false)
seedOrderIsolation(t, db)
repo := NewOutboundRepo()
if err := repo.Update(102, 101, &model.UpdateOutboundRequest{Handler: "hacked", Receiver: "hacked"}); err != sql.ErrNoRows {
t.Fatalf("B 改 A 的单据必须 ErrNoRows, got %v", err)
}
var handler, receiver string
if err := db.QueryRow(`SELECT handler, receiver FROM outbound_orders WHERE id = 101`).Scan(&handler, &receiver); err != nil {
t.Fatal(err)
}
if handler != "A-out" || receiver != "recA" {
t.Fatalf("A 的单据头被改动: %s/%s", handler, receiver)
}
var itemCount int
if err := db.QueryRow(`SELECT COUNT(*) FROM outbound_items WHERE outbound_order_id = 101`).Scan(&itemCount); err != nil {
t.Fatal(err)
}
if itemCount != 1 {
t.Fatalf("A 的明细被改动: %d 行", itemCount)
}
if err := repo.Delete(102, 101); err != nil {
t.Fatal(err)
}
var orderCount int
if err := db.QueryRow(`SELECT COUNT(*) FROM outbound_orders WHERE id = 101`).Scan(&orderCount); err != nil {
t.Fatal(err)
}
if orderCount != 1 {
t.Fatal("B 删掉了 A 的单据")
}
}