Files
bj_power/bj_power_mes/internal/wmsstock/client.go
T

145 lines
4.3 KiB
Go
Raw Normal View History

2026-08-27 19:50:57 +08:00
package wmsstock
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
// Client WMS 内部 API 客户端(X-API-TOKEN 写死 token 保护)
type Client struct {
BaseURL string
Token string
HTTP *http.Client
}
func New(baseURL, token string) *Client {
return &Client{
BaseURL: baseURL,
Token: token,
HTTP: &http.Client{Timeout: 15 * time.Second},
}
}
// wmsResp WMS 统一响应 {code,message,data}
type wmsResp struct {
Code int `json:"code"`
Message string `json:"message"`
Data json.RawMessage `json:"data"`
}
func (c *Client) call(method, path string, body any) (json.RawMessage, error) {
var rd io.Reader
if body != nil {
b, err := json.Marshal(body)
if err != nil {
return nil, err
}
rd = bytes.NewReader(b)
}
req, err := http.NewRequest(method, c.BaseURL+path, rd)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-TOKEN", c.Token)
resp, err := c.HTTP.Do(req)
if err != nil {
return nil, fmt.Errorf("WMS 不可达(%s): %w", path, err)
}
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
var wr wmsResp
if err := json.Unmarshal(raw, &wr); err != nil {
return nil, fmt.Errorf("WMS 响应解析失败(%s): %s", path, truncate(string(raw), 200))
}
if wr.Code != 0 {
return nil, fmt.Errorf("WMS 返回错误(%s): %s", path, wr.Message)
}
return wr.Data, nil
}
func truncate(s string, n int) string {
if len(s) > n {
return s[:n]
}
return s
}
// ============ 数据结构(与 C 的内部接口契约对齐)============
type CheckItem struct {
MaterialCode string `json:"materialCode"`
Qty int `json:"qty"`
}
type LockItem struct {
MaterialCode string `json:"materialCode"`
BatchNo string `json:"batchNo,omitempty"`
Sn string `json:"sn,omitempty"`
Qty int `json:"qty"`
}
type LedgerItem struct {
MaterialCode string `json:"materialCode"`
MaterialName string `json:"materialName"`
TotalQty int `json:"totalQty"`
}
// ============ 业务方法 ============
// CheckStock 批量校验库存是否充足
func (c *Client) CheckStock(items []CheckItem) (json.RawMessage, error) {
return c.call(http.MethodPost, "/api/internal/stock/check", map[string]any{"items": items})
}
// LockStock 锁定库存(结构件锁批次量 / 精密件逐 SN)
func (c *Client) LockStock(orderNo string, items []LockItem) (json.RawMessage, error) {
return c.call(http.MethodPost, "/api/internal/stock/lock", map[string]any{"orderNo": orderNo, "items": items})
}
// UnlockStock 解锁库存
func (c *Client) UnlockStock(orderNo string, lockIds []int) (json.RawMessage, error) {
return c.call(http.MethodPost, "/api/internal/stock/unlock", map[string]any{"orderNo": orderNo, "lockIds": lockIds})
}
// Deduct 出库扣减(领料出库,累计≤台账需求)
func (c *Client) Deduct(req map[string]any) (json.RawMessage, error) {
return c.call(http.MethodPost, "/api/internal/stock/deduct", req)
}
// QueryStock 库存查询(FIFO 分配用)
func (c *Client) QueryStock(materialCode, zoneCode string) (json.RawMessage, error) {
return c.call(http.MethodGet, "/api/internal/stock/query?materialCode="+materialCode+"&zoneCode="+zoneCode+"&pageSize=500", nil)
}
// LedgerSync 同步工单 BOM 台账到 WMS
func (c *Client) LedgerSync(orderNo, productCode string, items []LedgerItem) (json.RawMessage, error) {
return c.call(http.MethodPost, "/api/internal/ledger/sync", map[string]any{
"orderNo": orderNo, "productCode": productCode, "items": items,
})
}
// SemiInbound 半成品入库暂存
func (c *Client) SemiInbound(sn, materialCode, completedProcess, zoneCode, orderNo, operator string) (json.RawMessage, error) {
return c.call(http.MethodPost, "/api/internal/semi/inbound", map[string]any{
"sn": sn, "materialCode": materialCode, "completedProcess": completedProcess,
"zoneCode": zoneCode, "orderNo": orderNo, "operator": operator,
})
}
// SemiOutbound 半成品出库重上线
func (c *Client) SemiOutbound(sn, zoneCode, operator string) (json.RawMessage, error) {
return c.call(http.MethodPost, "/api/internal/semi/outbound", map[string]any{
"sn": sn, "zoneCode": zoneCode, "operator": operator,
})
}
// DisplayOverview 库存总览(大屏用)
func (c *Client) DisplayOverview() (json.RawMessage, error) {
return c.call(http.MethodGet, "/api/internal/display/overview", nil)
}