本提交完成了多个核心模块的功能完善与业务对齐: 1. 工位终端:固定工位配置、移除自选工位逻辑、适配配置化工位号 2. MES核心:重构工位组合逻辑、新增工单/流程状态管理、补全报工/追溯逻辑 3. WMS客户端:新增修改密码功能、优化帮助弹窗逻辑 4. 文档与权限:补充完整操作手册、统一菜单名称与权限描述 5. 修复多业务校验:排产数量校验、工单状态校验、工位绑定规则
103 lines
3.3 KiB
Go
103 lines
3.3 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"bj_power_mes/ent"
|
|
"bj_power_mes/ent/dailyplan"
|
|
"bj_power_mes/ent/workorder"
|
|
)
|
|
|
|
// parseDate 解析 yyyy-MM-dd 或标准时间
|
|
func parseDate(v string) (time.Time, error) {
|
|
if t, err := time.ParseInLocation("2006-01-02", v, time.Local); err == nil {
|
|
return t, nil
|
|
}
|
|
return time.ParseInLocation(time.RFC3339, v, time.Local)
|
|
}
|
|
|
|
type DailyPlanReq struct {
|
|
Id int `json:"id"`
|
|
OrderNo string `json:"orderNo"`
|
|
PlanDate string `json:"planDate"`
|
|
PlanQty int `json:"planQty"`
|
|
CompletedQty int `json:"completedQty"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
// SaveDailyPlan 创建/更新日排产(同一 工单+日期 唯一)
|
|
func (s *Service) SaveDailyPlan(ctx context.Context, req DailyPlanReq, operator string) error {
|
|
if req.OrderNo == "" || req.PlanDate == "" {
|
|
return errors.New("工单号和排产日期必填")
|
|
}
|
|
// 校验:该工单所有日排产计划数量累计不得超过工单总数量(保存时合计,改小可、改大不超总量)
|
|
wo, err := s.ctx.EntClient.WorkOrder.Query().Where(workorder.WorkOrderNo(req.OrderNo)).First(ctx)
|
|
if err != nil {
|
|
return errors.New("工单不存在")
|
|
}
|
|
if wo.Status == "DONE" || wo.Status == "CLOSED" {
|
|
return errors.New("该工单已完成/关闭,不能排产")
|
|
}
|
|
cur, err := s.ctx.EntClient.DailyPlan.Query().
|
|
Where(dailyplan.OrderNo(req.OrderNo)).All(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// 计算合计:同「工单+日期」的记录无论原状态如何,都以本次新值替换(只算一次),避免旧值+新值重复累计
|
|
total := 0
|
|
for _, p := range cur {
|
|
if p.PlanDate == req.PlanDate {
|
|
if p.CompletedQty > 0 {
|
|
return errors.New("该排产日已有完工数量,不能修改计划数量")
|
|
}
|
|
total += req.PlanQty
|
|
continue
|
|
}
|
|
total += p.PlanQty
|
|
}
|
|
if total > wo.Quantity {
|
|
return errors.New("排产合计数量超过工单总数量,无法保存")
|
|
}
|
|
exist, err := s.ctx.EntClient.DailyPlan.Query().
|
|
Where(dailyplan.OrderNo(req.OrderNo), dailyplan.PlanDate(req.PlanDate)).First(ctx)
|
|
status := req.Status
|
|
if status == "" {
|
|
status = "PENDING"
|
|
}
|
|
if err == nil && exist != nil {
|
|
_, err = s.ctx.EntClient.DailyPlan.UpdateOneID(exist.ID).
|
|
SetOrderNo(req.OrderNo).SetPlanDate(req.PlanDate).SetPlanQty(req.PlanQty).SetStatus(status).Save(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
_, err = s.ctx.EntClient.DailyPlan.Create().
|
|
SetOrderNo(req.OrderNo).SetPlanDate(req.PlanDate).SetPlanQty(req.PlanQty).
|
|
SetStatus(status).SetOperator(operator).Save(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
s.ctx.EventLog.Write(ctx, "daily.plan.save", req.OrderNo, operator, "daily_plan", req.OrderNo, "保存日排产", map[string]any{"planDate": req.PlanDate, "planQty": req.PlanQty})
|
|
return nil
|
|
}
|
|
|
|
// ListDailyPlans 按工单/日期查询日排产
|
|
func (s *Service) ListDailyPlans(ctx context.Context, orderNo, planDate string) ([]*ent.DailyPlan, error) {
|
|
q := s.ctx.EntClient.DailyPlan.Query()
|
|
if orderNo != "" {
|
|
q = q.Where(dailyplan.OrderNo(orderNo))
|
|
}
|
|
if planDate != "" {
|
|
q = q.Where(dailyplan.PlanDate(planDate))
|
|
}
|
|
return q.Order(ent.Desc(dailyplan.FieldPlanDate)).All(ctx)
|
|
}
|
|
|
|
// DeleteDailyPlan 删除一条日排产记录
|
|
func (s *Service) DeleteDailyPlan(ctx context.Context, id int) error {
|
|
return s.ctx.EntClient.DailyPlan.DeleteOneID(id).Exec(ctx)
|
|
}
|