feat(backend): 入库/出库列表 keyword 支持酒名模糊反查

- keyword 在单号/往来单位基础上,新增按酒名反查含该酒明细的单据
- 酒名匹配复用拼音基建:name(优先 product 回退快照) + name_pinyin + name_initials
- 子查询带 shop_id,多租户隔离不破
- 补 stock_in/stock_out List 按酒名+拼音命中的测试用例

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-23 23:57:28 +08:00
parent 08b41a8f63
commit e8f416ddea
4 changed files with 92 additions and 4 deletions
@@ -212,6 +212,42 @@ func TestStockOutHandler_List_FilterByKeyword(t *testing.T) {
assert.Equal(t, float64(2), parseResponse(w)["total"].(float64))
}
func TestStockOutHandler_List_FilterByProductName(t *testing.T) {
db := testutil.SetupTestDB()
shop := testutil.CreateTestShop(db, "SO012")
user := testutil.CreateTestUser(db, shop.ID, "admin", "pass", "admin")
warehouse := testutil.CreateTestWarehouse(db, shop.ID, "Warehouse")
maotai := testutil.CreateTestProduct(db, shop.ID, "飞天茅台")
lafei := testutil.CreateTestProduct(db, shop.ID, "拉菲红酒")
token := getAuthToken(user.ID, shop.ID, "admin")
r := setupProtectedRouter(db)
w := makeRequest(r, "POST", "/api/v1/stock-out/orders", token, map[string]interface{}{
"warehouse_id": warehouse.ID,
"order_date": time.Now().Format(time.RFC3339),
"items": []map[string]interface{}{{"product_id": maotai.ID, "quantity": 1.0}},
})
require.Equal(t, http.StatusCreated, w.Code)
w = makeRequest(r, "POST", "/api/v1/stock-out/orders", token, map[string]interface{}{
"warehouse_id": warehouse.ID,
"order_date": time.Now().Format(time.RFC3339),
"items": []map[string]interface{}{{"product_id": lafei.ID, "quantity": 1.0}},
})
require.Equal(t, http.StatusCreated, w.Code)
// 按酒名模糊反查 → 各命中 1 单
w = makeRequest(r, "GET", "/api/v1/stock-out/orders?keyword=茅台", token, nil)
assert.Equal(t, float64(1), parseResponse(w)["total"].(float64))
w = makeRequest(r, "GET", "/api/v1/stock-out/orders?keyword=红酒", token, nil)
assert.Equal(t, float64(1), parseResponse(w)["total"].(float64))
// 无关键词 → 两单都在
w = makeRequest(r, "GET", "/api/v1/stock-out/orders", token, nil)
assert.Equal(t, float64(2), parseResponse(w)["total"].(float64))
}
func TestStockOutHandler_Reject(t *testing.T) {
db := testutil.SetupTestDB()
shop := testutil.CreateTestShop(db, "SO004")