feat: 重构BOM架构,新增基础设置与虚拟工位管理功能
本次重构删除原有BOM物料清单表,改用工单工艺组合×工艺物料清单作为唯一用料来源;新增系统基础设置表支持WMS地址、日志保留天数等配置,新增虚拟工位作业管理后台接口与前端页签控制功能,同时优化工位号校验逻辑、事件日志自动清理与工单用料查询能力。
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/flowmaterial"
|
||||
"bj_power_mes/ent/workorder"
|
||||
)
|
||||
|
||||
// UsageRow 工单的单台用料行(BOM 已删除:用料唯一来源 = 工单工艺组合条目 × 工艺物料清单)。
|
||||
// 同一物料出现在组合中多个工艺时合并累加;同一成品不同工单可用不同工艺,物料跟着工单走。
|
||||
type UsageRow struct {
|
||||
MaterialCode string `json:"materialCode"`
|
||||
MaterialName string `json:"materialName"`
|
||||
Spec string `json:"spec"`
|
||||
Unit string `json:"unit"`
|
||||
ManageMode string `json:"manageMode"`
|
||||
UnitQty float64 `json:"unitQty"` // 单台净用量(跨工艺累加)
|
||||
LossRate float64 `json:"lossRate"` // 综合损耗率%(按各行损耗加权折算,仅供展示)
|
||||
EffQty float64 `json:"effQty"` // 单台含损耗用量 = Σ 行单台用量×(1+损耗率/100),参与计算
|
||||
}
|
||||
|
||||
// GetOrderUsage 按工单号查询单台用料(工位终端上线位领料确认 / 管理后台展示用)
|
||||
func (s *Service) GetOrderUsage(ctx context.Context, orderNo string) ([]UsageRow, error) {
|
||||
if orderNo == "" {
|
||||
return []UsageRow{}, nil
|
||||
}
|
||||
wo, err := s.ctx.EntClient.WorkOrder.Query().
|
||||
Where(workorder.WorkOrderNo(orderNo)).First(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.New("工单不存在: " + orderNo)
|
||||
}
|
||||
return s.WorkOrderUnitUsage(ctx, wo), nil
|
||||
}
|
||||
|
||||
// WorkOrderUnitUsage 汇总工单的单台用料:工艺组合条目×flow_material,同物料合并。
|
||||
// 组合为空或工艺均无物料时返回空切片。
|
||||
func (s *Service) WorkOrderUnitUsage(ctx context.Context, wo *ent.WorkOrder) []UsageRow {
|
||||
if wo == nil {
|
||||
return nil
|
||||
}
|
||||
items, _ := RouteStationsFromWO(ctx, s.ctx.EntClient, wo)
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
idSet := map[int]bool{}
|
||||
for _, it := range items {
|
||||
idSet[it.FlowId] = true
|
||||
}
|
||||
ids := make([]int, 0, len(idSet))
|
||||
for id := range idSet {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
fms, err := s.ctx.EntClient.FlowMaterial.Query().
|
||||
Where(flowmaterial.FlowIdIn(ids...)).All(ctx)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
byCode := map[string]*UsageRow{}
|
||||
for _, fm := range fms {
|
||||
if fm.MaterialCode == "" {
|
||||
continue
|
||||
}
|
||||
r, ok := byCode[fm.MaterialCode]
|
||||
if !ok {
|
||||
r = &UsageRow{
|
||||
MaterialCode: fm.MaterialCode, MaterialName: fm.MaterialName,
|
||||
Spec: fm.Spec, Unit: fm.Unit, ManageMode: fm.ManageMode,
|
||||
}
|
||||
byCode[fm.MaterialCode] = r
|
||||
}
|
||||
if r.MaterialName == "" {
|
||||
r.MaterialName = fm.MaterialName
|
||||
}
|
||||
if r.Unit == "" {
|
||||
r.Unit = fm.Unit
|
||||
}
|
||||
r.UnitQty += fm.UnitQty
|
||||
r.EffQty += fm.UnitQty * (1 + fm.LossRate/100)
|
||||
}
|
||||
codes := make([]string, 0, len(byCode))
|
||||
for c := range byCode {
|
||||
codes = append(codes, c)
|
||||
}
|
||||
sort.Strings(codes)
|
||||
out := make([]UsageRow, 0, len(codes))
|
||||
for _, c := range codes {
|
||||
r := byCode[c]
|
||||
if r.UnitQty > 0 {
|
||||
r.LossRate = (r.EffQty/r.UnitQty - 1) * 100
|
||||
}
|
||||
out = append(out, *r)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user