feat: 新增检测单关联、基础数据优化与入库单升级
1. 新增出库单检测单号字段并添加索引支持溯源 2. 优化基础数据页面物料类型展示与选择逻辑 3. 升级入库单导入功能,支持自动生成单号并返回导入结果 4. 优化接驳台查询排序方式 5. 修复字符串拼接空格问题
This commit is contained in:
@@ -14,7 +14,6 @@ import (
|
||||
"bj_power_wms/ent/material"
|
||||
"bj_power_wms/internal/svc"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
@@ -313,14 +312,14 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
continue
|
||||
}
|
||||
if snSeen[pr.sn] {
|
||||
errs = append(errs, importErr{pr.row, pr.code, "SN 在文件中重复: "+pr.sn})
|
||||
errs = append(errs, importErr{pr.row, pr.code, "SN 在文件中重复: " + pr.sn})
|
||||
continue
|
||||
}
|
||||
snSeen[pr.sn] = true
|
||||
exists, _ := ctx.EntClient.Inventory.Query().
|
||||
Where(inventory.ManageModeEQ(2), inventory.SnCodeEQ(pr.sn)).Exist(ctx0())
|
||||
if exists {
|
||||
errs = append(errs, importErr{pr.row, pr.code, "SN 已存在: "+pr.sn})
|
||||
errs = append(errs, importErr{pr.row, pr.code, "SN 已存在: " + pr.sn})
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
@@ -352,6 +351,7 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
fail(w, http.StatusInternalServerError, "开启事务失败: "+e.Error())
|
||||
return
|
||||
}
|
||||
var generatedNos []string
|
||||
committed := false
|
||||
defer func() {
|
||||
if !committed {
|
||||
@@ -360,7 +360,8 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
}()
|
||||
|
||||
for _, pr := range plans {
|
||||
inboundNo := "IB" + uuid.NewString()[:12]
|
||||
inboundNo, _ := nextDailyNo(ctx, "IB")
|
||||
generatedNos = append(generatedNos, inboundNo)
|
||||
m, _ := tx.Material.Query().Where(material.CodeEQ(pr.code)).Only(ctx0())
|
||||
if mode == "sn" {
|
||||
if _, e = tx.Inventory.Create().
|
||||
@@ -386,11 +387,11 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
batchNo := pr.batchNo
|
||||
if batchNo == "" {
|
||||
// 自动批次号(物料编码-日期-流水号);同一导入内多行空批次自动取得递增流水,天然唯一
|
||||
batchNo = genBatchNo(ctx, pr.code)
|
||||
}
|
||||
batchNo := pr.batchNo
|
||||
if batchNo == "" {
|
||||
// 自动批次号(物料编码-日期-流水号);同一导入内多行空批次自动取得递增流水,天然唯一
|
||||
batchNo = genBatchNo(ctx, pr.code)
|
||||
}
|
||||
existing, e2 := tx.Inventory.Query().
|
||||
Where(inventory.ManageModeEQ(1), inventory.BatchNoEQ(batchNo)).Only(ctx0())
|
||||
if e2 == nil {
|
||||
@@ -447,7 +448,12 @@ func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
committed = true
|
||||
ok(w, map[string]any{"success": len(plans), "failed": 0, "errors": []importErr{}})
|
||||
ok(w, map[string]any{
|
||||
"success": len(plans),
|
||||
"failed": 0,
|
||||
"errors": []importErr{},
|
||||
"inboundNos": generatedNos, // 每张入库单生成的单号(与导入行一一对应)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,102 @@ import (
|
||||
"bj_power_wms/ent/inspectionrecord"
|
||||
"bj_power_wms/ent/inventory"
|
||||
"bj_power_wms/ent/material"
|
||||
"bj_power_wms/ent/outboundorder"
|
||||
"bj_power_wms/internal/svc"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
// 物料品类:4=其他(辅料/工装/试验设备),与 schema/material.go 的 item_type 保持一致
|
||||
const invItemOther = 4
|
||||
|
||||
// nextDailyNo 生成日期+流水号,格式:IB/OB + YYYYMMDD + -NNN(如 IB20260921-001)。
|
||||
// 同一天内流水号递增,跨天重置为 001。并发冲突时自动重试最多 5 次。
|
||||
// 注意:历史旧单号(IB+UUID 片段)不受影响,仅新生成的用新格式。
|
||||
func nextDailyNo(ctx *svc.ServiceContext, prefix string) (string, error) {
|
||||
const maxRetry = 5
|
||||
var lastErr error
|
||||
for attempt := 0; attempt < maxRetry; attempt++ {
|
||||
no, err := genDailyNoOnce(ctx, prefix)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
time.Sleep(20 * time.Millisecond * time.Duration(attempt+1))
|
||||
continue
|
||||
}
|
||||
// 校验唯一性——如果刚好撞号,重试
|
||||
if prefix == "IB" {
|
||||
if _, e := ctx.EntClient.InboundOrder.Query().Where(inboundorder.InboundNoEQ(no)).Only(ctx0()); e == nil {
|
||||
lastErr = fmt.Errorf("单号 %s 已存在,重试中", no)
|
||||
time.Sleep(20 * time.Millisecond * time.Duration(attempt+1))
|
||||
continue
|
||||
}
|
||||
} else if prefix == "OB" {
|
||||
if _, e := ctx.EntClient.OutboundOrder.Query().Where(outboundorder.OutboundNoEQ(no)).Only(ctx0()); e == nil {
|
||||
lastErr = fmt.Errorf("单号 %s 已存在,重试中", no)
|
||||
time.Sleep(20 * time.Millisecond * time.Duration(attempt+1))
|
||||
continue
|
||||
}
|
||||
}
|
||||
return no, nil
|
||||
}
|
||||
if lastErr != nil {
|
||||
return "", fmt.Errorf("生成单号失败(重试 %d 次仍冲突): %w", maxRetry, lastErr)
|
||||
}
|
||||
return "", fmt.Errorf("生成单号失败(未知错误)")
|
||||
}
|
||||
|
||||
func genDailyNoOnce(ctx *svc.ServiceContext, prefix string) (string, error) {
|
||||
now := time.Now()
|
||||
datePart := now.Format("20060102")
|
||||
prefixDate := prefix + datePart + "-"
|
||||
|
||||
var maxSeq int
|
||||
var rows []string
|
||||
var err error
|
||||
if prefix == "IB" {
|
||||
rows, err = ctx.EntClient.InboundOrder.Query().
|
||||
Where(inboundorder.InboundNoHasPrefix(prefixDate)).
|
||||
Select(inboundorder.FieldInboundNo).
|
||||
Strings(ctx0())
|
||||
} else if prefix == "OB" {
|
||||
rows, err = ctx.EntClient.OutboundOrder.Query().
|
||||
Where(outboundorder.OutboundNoHasPrefix(prefixDate)).
|
||||
Select(outboundorder.FieldOutboundNo).
|
||||
Strings(ctx0())
|
||||
} else {
|
||||
return "", fmt.Errorf("未知前缀: %s", prefix)
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, n := range rows {
|
||||
suffix := strings.TrimPrefix(n, prefixDate)
|
||||
if s, e := strconv.Atoi(suffix); e == nil && s > maxSeq {
|
||||
maxSeq = s
|
||||
}
|
||||
}
|
||||
seq := maxSeq + 1
|
||||
return fmt.Sprintf("%s%03d", prefixDate, seq), nil
|
||||
}
|
||||
|
||||
// validateUniqueNo 校验单据号唯一(InboundNo 或 OutboundNo 不能重复)。
|
||||
func validateUniqueNo(ctx *svc.ServiceContext, kind, no string) error {
|
||||
if no == "" {
|
||||
return nil // 空值表示走自动生成
|
||||
}
|
||||
switch kind {
|
||||
case "IB":
|
||||
if _, e := ctx.EntClient.InboundOrder.Query().Where(inboundorder.InboundNoEQ(no)).Only(ctx0()); e == nil {
|
||||
return fmt.Errorf("入库单号 %s 已存在", no)
|
||||
}
|
||||
case "OB":
|
||||
if _, e := ctx.EntClient.OutboundOrder.Query().Where(outboundorder.OutboundNoEQ(no)).Only(ctx0()); e == nil {
|
||||
return fmt.Errorf("出库单号 %s 已存在", no)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateInboundQuality 入库质量门禁:该物料/批次/SN 若已被判定"不合格",拒绝入库。
|
||||
// 依据客户诉求《问题记录》L135:「不合格不入库、不上产线,仅合格品入库存数量」。
|
||||
func validateInboundQuality(ctx *svc.ServiceContext, materialCode, batchNo string, snList []string) error {
|
||||
@@ -58,6 +145,7 @@ func validateInboundQuality(ctx *svc.ServiceContext, materialCode, batchNo strin
|
||||
func createInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
InboundNo string `json:"inboundNo"` // 可选:留空自动生成;填了必须唯一(如 IB20260921-001)
|
||||
InboundType string `json:"inboundType"` // purchase/semi/finished/return/other
|
||||
MaterialCode string `json:"materialCode"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
@@ -117,7 +205,20 @@ func createInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
inboundNo := "IB" + uuid.NewString()[:12]
|
||||
inboundNo := strings.TrimSpace(req.InboundNo)
|
||||
if inboundNo != "" {
|
||||
if err := validateUniqueNo(ctx, "IB", inboundNo); err != nil {
|
||||
fail(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
no, err := nextDailyNo(ctx, "IB")
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, "生成入库单号失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
inboundNo = no
|
||||
}
|
||||
|
||||
// 质量状态自动带出(客户诉求 问题记录 L129:入库记录增加 合格/不合格 列)
|
||||
// 按检测单号查最近一次检验结论:合格→合格;不合格且部分入库→部分;不合格→不合格;无记录→空(未关联)
|
||||
@@ -348,6 +449,9 @@ func applyInboundFilters(q *ent.InboundOrderQuery, r *http.Request) *ent.Inbound
|
||||
// 2026-09-08 用户明确:禁止"关键字"多字段混搜,各字段独立筛选
|
||||
q = q.Where(inboundorder.MaterialNameContainsFold(v))
|
||||
}
|
||||
if v := r.URL.Query().Get("inspectionNo"); v != "" {
|
||||
q = q.Where(inboundorder.InspectionNoContainsFold(v))
|
||||
}
|
||||
// 单据状态:有效 / 已作废(作废单保留可查,但不参与库存)
|
||||
if v := r.URL.Query().Get("voided"); v == "true" {
|
||||
q = q.Where(inboundorder.VoidedEQ(true))
|
||||
|
||||
@@ -3,6 +3,7 @@ package handler
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"bj_power_wms/ent"
|
||||
@@ -680,28 +681,18 @@ func inboundNosByType(ctx *svc.ServiceContext, inboundType string) ([]string, er
|
||||
return nos, nil
|
||||
}
|
||||
|
||||
// pendingInspectionItem 待检清单展开明细行
|
||||
type pendingInspectionItem struct {
|
||||
ID int `json:"id"` // inventory.id(真实主键,禁止伪 id)
|
||||
TargetId string `json:"targetId"` // 批次号或 SN
|
||||
ManageMode int `json:"manageMode"` // 1结构件/2电气件
|
||||
ItemType int `json:"itemType"` // 品类 1原材料/2半成品/3成品/4其他(§E:带入录入页判定其他类)
|
||||
Quantity int `json:"quantity"`
|
||||
ZoneCode string `json:"zoneCode"`
|
||||
}
|
||||
|
||||
// pendingInspectionRow 待检清单主行(按 入库单 + 物料 分组,§E2)
|
||||
// 详情明细改为按需分页加载(右侧抽屉),主行只带总数不塞 details 数组,避免 3000 SN 一次进内存
|
||||
type pendingInspectionRow struct {
|
||||
InboundNo string `json:"inboundNo"`
|
||||
InboundType string `json:"inboundType"`
|
||||
OwnershipType string `json:"ownershipType"`
|
||||
OwnershipNo string `json:"ownershipNo"`
|
||||
MaterialCode string `json:"materialCode"`
|
||||
MaterialName string `json:"materialName"`
|
||||
UnInspectedQty int `json:"unInspectedQty"` // 未检数量(结构件=数量求和;电气件=SN 行数)
|
||||
BatchSnCount int `json:"batchSnCount"` // 未检批次数/SN 数
|
||||
InboundTime int64 `json:"inboundTime"`
|
||||
Details []pendingInspectionItem `json:"details"`
|
||||
InboundNo string `json:"inboundNo"`
|
||||
InboundType string `json:"inboundType"`
|
||||
OwnershipType string `json:"ownershipType"`
|
||||
OwnershipNo string `json:"ownershipNo"`
|
||||
MaterialCode string `json:"materialCode"`
|
||||
MaterialName string `json:"materialName"`
|
||||
UnInspectedQty int `json:"unInspectedQty"` // 未检数量(结构件=数量求和;电气件=SN 行数)
|
||||
DetailsTotal int `json:"detailsTotal"` // 未检批次数/SN 总数(抽屉分页拉明细)
|
||||
InboundTime int64 `json:"inboundTime"`
|
||||
}
|
||||
|
||||
// pendingInspectionHandler 待检清单(来料检验问题2):列出 quality_status=未检 的库存行,
|
||||
@@ -769,9 +760,8 @@ func pendingInspectionHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// 物料名称/品类 map
|
||||
// 物料名称 map
|
||||
matName := map[string]string{}
|
||||
matItemType := map[string]int{}
|
||||
codeSet := []string{}
|
||||
seenC := map[string]bool{}
|
||||
for _, inv := range all {
|
||||
@@ -784,7 +774,6 @@ func pendingInspectionHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
if mats, e := ctx.EntClient.Material.Query().Where(material.CodeIn(codeSet...)).All(ctx0()); e == nil {
|
||||
for _, m := range mats {
|
||||
matName[m.Code] = m.Name
|
||||
matItemType[m.Code] = m.ItemType
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -818,15 +807,7 @@ func pendingInspectionHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
qty = inv.Quantity
|
||||
}
|
||||
g.UnInspectedQty += qty
|
||||
g.BatchSnCount++
|
||||
tid := inv.BatchNo
|
||||
if inv.ManageMode == 2 {
|
||||
tid = inv.SnCode
|
||||
}
|
||||
g.Details = append(g.Details, pendingInspectionItem{
|
||||
ID: inv.ID, TargetId: tid, ManageMode: inv.ManageMode, ItemType: matItemType[inv.MaterialCode],
|
||||
Quantity: inv.Quantity, ZoneCode: inv.ZoneCode,
|
||||
})
|
||||
g.DetailsTotal++
|
||||
if o != nil && o.CreatedAt > g.InboundTime {
|
||||
g.InboundTime = o.CreatedAt
|
||||
}
|
||||
@@ -856,3 +837,69 @@ func strOrEmpty(o *ent.InboundOrder) string {
|
||||
}
|
||||
return o.InboundType
|
||||
}
|
||||
|
||||
// pendingDetailsInspectionHandler GET /api/inspection/pending/details
|
||||
// 待检清单主行抽屉里的明细分页(右侧抽屉懒加载,不再主行带 details 数组)。
|
||||
// 入参:inboundNo + materialCode + page + pageSize(默认 20)。
|
||||
func pendingDetailsInspectionHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
inboundNo := q.Get("inboundNo")
|
||||
materialCode := q.Get("materialCode")
|
||||
if inboundNo == "" || materialCode == "" {
|
||||
fail(w, http.StatusBadRequest, "inboundNo 和 materialCode 不能为空")
|
||||
return
|
||||
}
|
||||
page, _ := strconv.Atoi(q.Get("page"))
|
||||
pageSize, _ := strconv.Atoi(q.Get("pageSize"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 500 {
|
||||
pageSize = 20
|
||||
}
|
||||
|
||||
qry := svcCtx.EntClient.Inventory.Query().
|
||||
Where(
|
||||
inventory.InboundNoEQ(inboundNo),
|
||||
inventory.MaterialCodeEQ(materialCode),
|
||||
inventory.QualityStatusEQ("未检"),
|
||||
)
|
||||
total, err := qry.Count(ctx0())
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
start := (page - 1) * pageSize
|
||||
list, err := qry.
|
||||
Order(inventory.ByID()).
|
||||
Offset(start).
|
||||
Limit(pageSize).
|
||||
All(ctx0())
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
// itemType 从物料档案补查(一个 materialCode 唯一)
|
||||
itemType := 0
|
||||
if m, e := svcCtx.EntClient.Material.Query().Where(material.CodeEQ(materialCode)).Only(ctx0()); e == nil {
|
||||
itemType = m.ItemType
|
||||
}
|
||||
rows := make([]map[string]any, 0, len(list))
|
||||
for _, inv := range list {
|
||||
tid := inv.BatchNo
|
||||
if inv.ManageMode == 2 {
|
||||
tid = inv.SnCode
|
||||
}
|
||||
rows = append(rows, map[string]any{
|
||||
"targetId": tid,
|
||||
"manageMode": inv.ManageMode,
|
||||
"itemType": itemType,
|
||||
"quantity": inv.Quantity,
|
||||
"zoneCode": inv.ZoneCode,
|
||||
"id": inv.ID,
|
||||
})
|
||||
}
|
||||
ok(w, map[string]any{"list": rows, "total": total, "page": page, "pageSize": pageSize})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"bj_power_wms/ent/outboundorder"
|
||||
"bj_power_wms/internal/svc"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
@@ -37,6 +36,7 @@ type deductStockRequest struct {
|
||||
LayerNo string `json:"layerNo"`
|
||||
PositionNo string `json:"positionNo"`
|
||||
Remark string `json:"remark"`
|
||||
OutboundNo string `json:"outboundNo"` // 可选:留空自动生成;填了必须唯一(如 OB20260921-001)
|
||||
// OutboundType 出库类型:workorder(备料出库,默认) / refill(工位叫料·补料出库)
|
||||
OutboundType string `json:"outboundType"`
|
||||
// NeedAgv 是否需要 AGV 配送到接驳台(备料/补料一般为 true)
|
||||
@@ -92,7 +92,20 @@ func deductStockHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
outboundNo := "OB" + uuid.NewString()[:12]
|
||||
outboundNo := strings.TrimSpace(req.OutboundNo)
|
||||
if outboundNo != "" {
|
||||
if err := validateUniqueNo(ctx, "OB", outboundNo); err != nil {
|
||||
fail(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
no, err := nextDailyNo(ctx, "OB")
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, "生成出库单号失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
outboundNo = no
|
||||
}
|
||||
|
||||
// 开启事务:出库单 + 库存扣减 + 明细 + 台账 原子提交
|
||||
tx, err := ctx.EntClient.Tx(ctx0())
|
||||
@@ -316,6 +329,7 @@ func queryOutboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
materialName := r.URL.Query().Get("materialName")
|
||||
targetStation := r.URL.Query().Get("targetStation")
|
||||
status := r.URL.Query().Get("status")
|
||||
inspectionNo := r.URL.Query().Get("inspectionNo")
|
||||
|
||||
q := ctx.EntClient.OutboundOrder.Query()
|
||||
if status != "" {
|
||||
@@ -348,6 +362,9 @@ func queryOutboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
if targetStation != "" {
|
||||
q = q.Where(outboundorder.TargetStationEQ(targetStation))
|
||||
}
|
||||
if inspectionNo != "" {
|
||||
q = q.Where(outboundorder.InspectionNoContainsFold(inspectionNo))
|
||||
}
|
||||
if v := r.URL.Query().Get("startDate"); v != "" {
|
||||
if t, err := time.ParseInLocation("2006-01-02", v, time.Local); err == nil {
|
||||
q = q.Where(outboundorder.CreatedAtGTE(t.Unix()))
|
||||
@@ -409,7 +426,9 @@ type generalOutboundRequest struct {
|
||||
BoxNo string `json:"boxNo"`
|
||||
ContractNo string `json:"contractNo"`
|
||||
Remark string `json:"remark"`
|
||||
OutboundNo string `json:"outboundNo"` // 可选:留空自动生成;填了必须唯一(如 OB20260921-001)
|
||||
OutboundCategory string `json:"outboundCategory"` // return(退料)/supplier_return(退货退供应商)/sample(样品)/scrap(报废)/deliver(发货)/other(其他)
|
||||
InspectionNo string `json:"inspectionNo"` // 可选:检测单号,退货/报废等需溯源检验单据
|
||||
OwnershipType string `json:"ownershipType"` // workorder/project/other
|
||||
OwnershipNo string `json:"ownershipNo"`
|
||||
TargetStation string `json:"targetStation"`
|
||||
@@ -469,7 +488,20 @@ func generalOutboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
req.ZoneCode, req.ShelfNo, req.LayerNo, req.PositionNo =
|
||||
outboundLocationFallback(ctx, req.BatchNo, req.SnList, req.ZoneCode, req.ShelfNo, req.LayerNo, req.PositionNo)
|
||||
|
||||
outboundNo := "OB" + uuid.NewString()[:12]
|
||||
outboundNo := strings.TrimSpace(req.OutboundNo)
|
||||
if outboundNo != "" {
|
||||
if err := validateUniqueNo(ctx, "OB", outboundNo); err != nil {
|
||||
fail(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
no, err := nextDailyNo(ctx, "OB")
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, "生成出库单号失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
outboundNo = no
|
||||
}
|
||||
|
||||
tx, err := ctx.EntClient.Tx(ctx0())
|
||||
if err != nil {
|
||||
@@ -492,6 +524,7 @@ func generalOutboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
SetNillableOutboundCategory(strPtr(req.OutboundCategory)).
|
||||
SetNillableOwnershipType(strPtr(req.OwnershipType)).
|
||||
SetNillableOwnershipNo(strPtr(req.OwnershipNo)).
|
||||
SetNillableInspectionNo(strPtr(req.InspectionNo)).
|
||||
SetNillableTargetStation(strPtr(req.TargetStation)).
|
||||
SetMaterialCode(req.MaterialCode).
|
||||
SetManageMode(manageMode).
|
||||
|
||||
@@ -133,6 +133,7 @@ func RegisterHandlers(server *rest.Server, ctx *svc.ServiceContext) {
|
||||
{Method: http.MethodGet, Path: "/api/inspection/export", Handler: exportInspectionHandler(ctx)},
|
||||
{Method: http.MethodGet, Path: "/api/inspection/stats", Handler: statsInspectionHandler(ctx)},
|
||||
{Method: http.MethodGet, Path: "/api/inspection/pending", Handler: pendingInspectionHandler(ctx)},
|
||||
{Method: http.MethodGet, Path: "/api/inspection/pending/details", Handler: pendingDetailsInspectionHandler(ctx)},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user