fix: rebuild MES as compilable go-zero+ent backend (renamed bj_power_mes), restore 3 workstation projects from pristine original, align naming; all Go projects go build clean
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
package measurement
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/workorder"
|
||||
"bj_power_mes/internal/svc"
|
||||
)
|
||||
|
||||
// categoryByWorkOrder 批量查询 workOrderId -> product_type.category 映射。
|
||||
// measurement 表无 product_type 关联,需经 work_order.productTypeId 间接获取。
|
||||
func categoryByWorkOrder(ctx context.Context, svcCtx *svc.ServiceContext, workOrderIDs []int) (map[int]string, error) {
|
||||
res := make(map[int]string, len(workOrderIDs))
|
||||
if len(workOrderIDs) == 0 {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
wos, err := svcCtx.EntClient.WorkOrder.Query().
|
||||
Where(workorder.IDIn(workOrderIDs...)).
|
||||
WithProductType().
|
||||
All(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, wo := range wos {
|
||||
if wo.Edges.ProductType != nil {
|
||||
res[wo.ID] = string(wo.Edges.ProductType.Category)
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// collectWorkOrderIDs 从 measurement 列表中去重收集 workOrderId。
|
||||
func collectWorkOrderIDs(list []*ent.Measurement) []int {
|
||||
seen := make(map[int]struct{}, len(list))
|
||||
ids := make([]int, 0, len(list))
|
||||
for _, m := range list {
|
||||
if _, ok := seen[m.WorkOrderId]; ok {
|
||||
continue
|
||||
}
|
||||
seen[m.WorkOrderId] = struct{}{}
|
||||
ids = append(ids, m.WorkOrderId)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package measurement
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/measurement"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetMeasurementLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 查询工件测量数据
|
||||
func NewGetMeasurementLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMeasurementLogic {
|
||||
return &GetMeasurementLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetMeasurementLogic) GetMeasurement(req *types.JobIdPath) (resp *types.MeasurementReply, err error) {
|
||||
m, err := l.svcCtx.EntClient.Measurement.Query().
|
||||
Where(measurement.JobIdEQ(req.JobId)).
|
||||
Only(l.ctx)
|
||||
if err != nil {
|
||||
if ent.IsNotFound(err) {
|
||||
// 无测量数据返回空(200),前端按 null 处理
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := toReply(m)
|
||||
catMap, err := categoryByWorkOrder(l.ctx, l.svcCtx, []int{m.WorkOrderId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.Category = catMap[m.WorkOrderId]
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func toReply(m *ent.Measurement) *types.MeasurementReply {
|
||||
const layout = "2006-01-02 15:04:05"
|
||||
resp := &types.MeasurementReply{
|
||||
Id: m.ID,
|
||||
JobId: m.JobId,
|
||||
WorkpieceNo: m.WorkpieceNo,
|
||||
WorkOrderNo: m.WorkOrderNo,
|
||||
PalletCode: m.PalletCode,
|
||||
BottomHoleLeft: m.BottomHoleLeft,
|
||||
PistonHoleLarge: m.PistonHoleLarge,
|
||||
PistonHoleSmall: m.PistonHoleSmall,
|
||||
PistonHoleRight: m.PistonHoleRight,
|
||||
CreatedAt: m.CreatedAt.Format(layout),
|
||||
UpdatedAt: m.UpdatedAt.Format(layout),
|
||||
}
|
||||
if m.CapturedAt != nil {
|
||||
resp.Timestamp = m.CapturedAt.Format(layout)
|
||||
}
|
||||
return resp
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package measurement
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/measurement"
|
||||
"bj_power_mes/ent/producttype"
|
||||
"bj_power_mes/ent/workorder"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type QueryMeasurementsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 查询抽检测量数据列表(报表用,跨工单)
|
||||
func NewQueryMeasurementsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryMeasurementsLogic {
|
||||
return &QueryMeasurementsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryMeasurementsLogic) QueryMeasurements(req *types.QueryMeasurementsReq) (resp *types.QueryMeasurementsReply, err error) {
|
||||
query := l.svcCtx.EntClient.Measurement.Query()
|
||||
|
||||
if req.StartDate != "" {
|
||||
if t, err := time.ParseInLocation("2006-01-02", req.StartDate, time.Local); err == nil {
|
||||
query = query.Where(measurement.CapturedAtGTE(t))
|
||||
}
|
||||
}
|
||||
if req.EndDate != "" {
|
||||
if t, err := time.ParseInLocation("2006-01-02", req.EndDate, time.Local); err == nil {
|
||||
// 小于结束日期+1天,覆盖结束日全天(00:00:00 ~ 23:59:59)
|
||||
query = query.Where(measurement.CapturedAtLT(t.Add(24 * time.Hour)))
|
||||
}
|
||||
}
|
||||
if req.WorkOrderNo != "" {
|
||||
query = query.Where(measurement.WorkOrderNoContains(req.WorkOrderNo))
|
||||
}
|
||||
if req.PalletCode != "" {
|
||||
query = query.Where(measurement.PalletCodeContains(req.PalletCode))
|
||||
}
|
||||
if req.WorkpieceNo != "" {
|
||||
query = query.Where(measurement.WorkpieceNoContains(req.WorkpieceNo))
|
||||
}
|
||||
|
||||
// category 筛选:category → product_type ids → work_order ids → measurement.workOrderIdIn
|
||||
if req.Category != "" {
|
||||
ptIDs, err := l.svcCtx.EntClient.ProductType.Query().
|
||||
Where(producttype.CategoryEQ(producttype.Category(req.Category))).
|
||||
IDs(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ptIDs) == 0 {
|
||||
return &types.QueryMeasurementsReply{Data: []types.MeasurementReply{}, Total: 0}, nil
|
||||
}
|
||||
woIDs, err := l.svcCtx.EntClient.WorkOrder.Query().
|
||||
Where(workorder.ProductTypeIdIn(ptIDs...)).
|
||||
IDs(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(woIDs) == 0 {
|
||||
return &types.QueryMeasurementsReply{Data: []types.MeasurementReply{}, Total: 0}, nil
|
||||
}
|
||||
query = query.Where(measurement.WorkOrderIdIn(woIDs...))
|
||||
}
|
||||
|
||||
total, err := query.Count(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limit := req.Limit
|
||||
if limit <= 0 || limit > 200 {
|
||||
limit = 20
|
||||
}
|
||||
offset := (req.Page - 1) * limit
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
|
||||
list, err := query.
|
||||
Order(ent.Desc(measurement.FieldCapturedAt)).
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
All(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make([]types.MeasurementReply, 0, len(list))
|
||||
catMap, err := categoryByWorkOrder(l.ctx, l.svcCtx, collectWorkOrderIDs(list))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, m := range list {
|
||||
r := toReply(m)
|
||||
r.Category = catMap[m.WorkOrderId]
|
||||
data = append(data, *r)
|
||||
}
|
||||
|
||||
return &types.QueryMeasurementsReply{
|
||||
Data: data,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package measurement
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/measurement"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type QueryMeasurementsOfWorkOrderLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 查询工单测量数据列表
|
||||
func NewQueryMeasurementsOfWorkOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryMeasurementsOfWorkOrderLogic {
|
||||
return &QueryMeasurementsOfWorkOrderLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryMeasurementsOfWorkOrderLogic) QueryMeasurementsOfWorkOrder(req *types.QueryMeasurementsOfWorkOrderReq) (resp *types.QueryMeasurementsOfWorkOrderReply, err error) {
|
||||
query := l.svcCtx.EntClient.Measurement.Query().
|
||||
Where(measurement.WorkOrderIdEQ(req.Id))
|
||||
|
||||
total, err := query.Count(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limit := req.Limit
|
||||
if limit <= 0 || limit > 200 {
|
||||
limit = 20
|
||||
}
|
||||
offset := (req.Page - 1) * limit
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
|
||||
list, err := query.
|
||||
Order(ent.Desc(measurement.FieldCapturedAt)).
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
All(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make([]types.MeasurementReply, 0, len(list))
|
||||
catMap, err := categoryByWorkOrder(l.ctx, l.svcCtx, []int{req.Id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, m := range list {
|
||||
r := toReply(m)
|
||||
r.Category = catMap[req.Id]
|
||||
data = append(data, *r)
|
||||
}
|
||||
|
||||
return &types.QueryMeasurementsOfWorkOrderReply{
|
||||
Data: data,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package measurement
|
||||
|
||||
import (
|
||||
"context"
|
||||
"bj_power_mes/common/errorx"
|
||||
"time"
|
||||
|
||||
"bj_power_mes/constants"
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/equipment"
|
||||
"bj_power_mes/ent/equipmentslot"
|
||||
"bj_power_mes/ent/equipmenttype"
|
||||
"bj_power_mes/ent/job"
|
||||
"bj_power_mes/ent/measurement"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type UploadMeasurementLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 上传抽检测量数据(外部测量软件调用,自动匹配抽检台当前工件)
|
||||
func NewUploadMeasurementLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadMeasurementLogic {
|
||||
return &UploadMeasurementLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UploadMeasurementLogic) UploadMeasurement(req *types.UploadMeasurementReq) (resp *types.UploadMeasurementReply, err error) {
|
||||
// 1. 查抽检台(SAMPLING 类型)当前占用槽位的工件
|
||||
slot, err := l.svcCtx.EntClient.EquipmentSlot.Query().
|
||||
Where(
|
||||
equipmentslot.StatusEQ(constants.SlotStatus_Occupied),
|
||||
equipmentslot.HasEquipmentWith(
|
||||
equipment.HasEquipmentTypeWith(
|
||||
equipmenttype.CodeEQ(constants.EquipmentTypeCode_Sampling),
|
||||
),
|
||||
),
|
||||
).
|
||||
Only(l.ctx)
|
||||
if err != nil {
|
||||
if ent.IsNotFound(err) {
|
||||
return nil, errorx.NewDirectError("当前抽检台无工件,无法上传测量数据")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if slot.CurrentJobId == nil || *slot.CurrentJobId <= 0 {
|
||||
return nil, errorx.NewDirectError("当前抽检台槽位未绑定工件")
|
||||
}
|
||||
jobId := *slot.CurrentJobId
|
||||
|
||||
// 2. 查工件关联的工单/托盘信息
|
||||
j, err := l.svcCtx.EntClient.Job.Query().
|
||||
Where(job.IDEQ(jobId)).
|
||||
WithWorkOrder().
|
||||
WithPallet().
|
||||
Only(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var workOrderId int
|
||||
var workOrderNo, palletCode string
|
||||
if j.Edges.WorkOrder != nil {
|
||||
workOrderId = j.Edges.WorkOrder.ID
|
||||
workOrderNo = j.Edges.WorkOrder.WorkOrderNo
|
||||
}
|
||||
if j.Edges.Pallet != nil {
|
||||
palletCode = j.Edges.Pallet.PalletCode
|
||||
}
|
||||
|
||||
// 3. 解析测量时间(支持 RFC3339 或 yyyy-MM-dd HH:mm:ss)
|
||||
var capturedAt *time.Time
|
||||
if req.Timestamp != "" {
|
||||
if t, parseErr := time.Parse(time.RFC3339, req.Timestamp); parseErr == nil {
|
||||
capturedAt = &t
|
||||
} else if t, parseErr := time.ParseInLocation("2006-01-02 15:04:05", req.Timestamp, time.Local); parseErr == nil {
|
||||
capturedAt = &t
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 覆盖写入:按 jobId 唯一约束,已存在则更新
|
||||
existing, err := l.svcCtx.EntClient.Measurement.Query().
|
||||
Where(measurement.JobIdEQ(jobId)).
|
||||
Only(l.ctx)
|
||||
if err != nil && !ent.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ent.IsNotFound(err) {
|
||||
// 新建
|
||||
m, err := l.svcCtx.EntClient.Measurement.Create().
|
||||
SetJobId(jobId).
|
||||
SetWorkOrderId(workOrderId).
|
||||
SetWorkpieceNo(j.WorkpieceNo).
|
||||
SetWorkOrderNo(workOrderNo).
|
||||
SetPalletCode(palletCode).
|
||||
SetNillableBottomHoleLeft(req.BottomHoleLeft).
|
||||
SetNillablePistonHoleLarge(req.PistonHoleLarge).
|
||||
SetNillablePistonHoleSmall(req.PistonHoleSmall).
|
||||
SetNillablePistonHoleRight(req.PistonHoleRight).
|
||||
SetNillableCapturedAt(capturedAt).
|
||||
Save(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.UploadMeasurementReply{Id: m.ID, JobId: jobId, WorkpieceNo: j.WorkpieceNo}, nil
|
||||
}
|
||||
|
||||
// 覆盖更新:未传的测量值清空,保证"覆盖只留最新"语义
|
||||
upd := l.svcCtx.EntClient.Measurement.UpdateOneID(existing.ID).
|
||||
SetWorkOrderId(workOrderId).
|
||||
SetWorkpieceNo(j.WorkpieceNo).
|
||||
SetWorkOrderNo(workOrderNo).
|
||||
SetPalletCode(palletCode).
|
||||
SetNillableBottomHoleLeft(req.BottomHoleLeft).
|
||||
SetNillablePistonHoleLarge(req.PistonHoleLarge).
|
||||
SetNillablePistonHoleSmall(req.PistonHoleSmall).
|
||||
SetNillablePistonHoleRight(req.PistonHoleRight)
|
||||
if req.BottomHoleLeft == nil {
|
||||
upd.ClearBottomHoleLeft()
|
||||
}
|
||||
if req.PistonHoleLarge == nil {
|
||||
upd.ClearPistonHoleLarge()
|
||||
}
|
||||
if req.PistonHoleSmall == nil {
|
||||
upd.ClearPistonHoleSmall()
|
||||
}
|
||||
if req.PistonHoleRight == nil {
|
||||
upd.ClearPistonHoleRight()
|
||||
}
|
||||
if capturedAt == nil {
|
||||
upd.ClearCapturedAt()
|
||||
} else {
|
||||
upd.SetNillableCapturedAt(capturedAt)
|
||||
}
|
||||
m, err := upd.Save(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.UploadMeasurementReply{Id: m.ID, JobId: jobId, WorkpieceNo: j.WorkpieceNo}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user