feat: 新增预警与附件模块,优化工位派工功能
1. 新增预警规则、预警消息、业务附件数据库表与CRUD逻辑 2. 为拧紧记录添加审核人、审核时间字段及审核留痕功能 3. 优化产线点位类型与编号描述,更新工位组合下发菜单名称为工艺路线派工 4. 新增上传文件获取原文件名与大小的工具方法 5. 在系统管理菜单新增预警中心与附件中心入口
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"bj_power_mes/common/httpx"
|
||||
"bj_power_mes/internal/logic"
|
||||
"bj_power_mes/internal/svc"
|
||||
)
|
||||
|
||||
// AttachmentUploadHandler POST /attachment/upload 上传并登记(multipart: bizType,bizId,file)
|
||||
func AttachmentUploadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseMultipartForm(32 << 20); err != nil {
|
||||
httpx.BadRequest(w, "表单解析失败")
|
||||
return
|
||||
}
|
||||
bizType := r.FormValue("bizType")
|
||||
bizId := r.FormValue("bizId")
|
||||
if bizType == "" || bizId == "" {
|
||||
httpx.BadRequest(w, "bizType 与 bizId 必填")
|
||||
return
|
||||
}
|
||||
rel, fname, size, err := saveUploadFileFull(r, "file", svcCtx.Config.Upload.Dir)
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3311, "文件保存失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
rec, err := logic.New(svcCtx).AddAttachment(r.Context(), bizType, bizId, fname, rel, int(size), operator(r, ""))
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3311, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, rec)
|
||||
}
|
||||
}
|
||||
|
||||
// AttachmentListHandler GET /attachments?bizType=&bizId= 附件列表
|
||||
func AttachmentListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
data, err := logic.New(svcCtx).ListAttachments(r.Context(), q.Get("bizType"), q.Get("bizId"))
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3312, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
// AttachmentDownloadHandler GET /attachment/download?name= 下载
|
||||
func AttachmentDownloadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
name := r.URL.Query().Get("name")
|
||||
if name == "" {
|
||||
httpx.BadRequest(w, "缺少 name")
|
||||
return
|
||||
}
|
||||
serveUploadFile(w, r, svcCtx.Config.Upload.Dir, name)
|
||||
}
|
||||
}
|
||||
|
||||
// AttachmentDeleteHandler POST /attachment/delete {id} 删除(记录+物理文件)
|
||||
func AttachmentDeleteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Id int `json:"id"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil {
|
||||
httpx.BadRequest(w, "请求体解析失败")
|
||||
return
|
||||
}
|
||||
att, err := logic.New(svcCtx).DeleteAttachment(r.Context(), req.Id)
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3313, err.Error())
|
||||
return
|
||||
}
|
||||
full := filepath.Join(svcCtx.Config.Upload.Dir, filepath.FromSlash(att.FilePath))
|
||||
_ = os.Remove(full)
|
||||
httpx.OkMessage(w, "删除成功", nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package production
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"bj_power_mes/common/httpx"
|
||||
"bj_power_mes/internal/logic"
|
||||
"bj_power_mes/internal/svc"
|
||||
)
|
||||
|
||||
// CreateAlertRuleHandler POST /alert/rule 新增预警规则
|
||||
func CreateAlertRuleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Threshold float64 `json:"threshold"`
|
||||
Receiver string `json:"receiver"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil {
|
||||
httpx.BadRequest(w, "请求体解析失败")
|
||||
return
|
||||
}
|
||||
if err := logic.New(svcCtx).CreateAlertRule(r.Context(), req.Name, req.Type, req.Threshold, req.Receiver, req.Enabled, operator(r, "")); err != nil {
|
||||
httpx.Fail(w, 3301, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.OkMessage(w, "保存成功", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateAlertRuleHandler PUT /alert/rule 修改预警规则
|
||||
func UpdateAlertRuleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Threshold float64 `json:"threshold"`
|
||||
Receiver string `json:"receiver"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil {
|
||||
httpx.BadRequest(w, "请求体解析失败")
|
||||
return
|
||||
}
|
||||
if err := logic.New(svcCtx).UpdateAlertRule(r.Context(), req.Id, req.Name, req.Type, req.Threshold, req.Receiver, req.Enabled); err != nil {
|
||||
httpx.Fail(w, 3302, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.OkMessage(w, "保存成功", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteAlertRuleHandler DELETE /alert/rule?id= 删除规则
|
||||
func DeleteAlertRuleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
id := atoiDefault(r.URL.Query().Get("id"), 0)
|
||||
if id <= 0 {
|
||||
httpx.Fail(w, 3303, "缺少 id")
|
||||
return
|
||||
}
|
||||
if err := logic.New(svcCtx).DeleteAlertRule(r.Context(), id); err != nil {
|
||||
httpx.Fail(w, 3303, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.OkMessage(w, "删除成功", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// ListAlertRulesHandler GET /alert/rules 规则列表
|
||||
func ListAlertRulesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := logic.New(svcCtx).ListAlertRules(r.Context())
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3304, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
// ListAlertsHandler GET /alerts?status= 预警消息收件箱
|
||||
func ListAlertsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
status := r.URL.Query().Get("status")
|
||||
data, err := logic.New(svcCtx).ListAlerts(r.Context(), status)
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3305, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
// MarkAlertReadHandler POST /alert/read 标记已读 {id}
|
||||
func MarkAlertReadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Id int `json:"id"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil {
|
||||
httpx.BadRequest(w, "请求体解析失败")
|
||||
return
|
||||
}
|
||||
if err := logic.New(svcCtx).MarkAlertRead(r.Context(), req.Id); err != nil {
|
||||
httpx.Fail(w, 3306, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.OkMessage(w, "已标记已读", nil)
|
||||
}
|
||||
}
|
||||
@@ -149,3 +149,45 @@ func TorqueManualAddHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
httpx.OkMessage(w, "补录成功", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// TorqueAuditHandler POST /torque/audit 拧紧记录审核签字
|
||||
func TorqueAuditHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
RecordId int `json:"recordId"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil {
|
||||
httpx.BadRequest(w, "请求体解析失败")
|
||||
return
|
||||
}
|
||||
if req.RecordId <= 0 {
|
||||
httpx.Fail(w, 3208, "缺少 recordId")
|
||||
return
|
||||
}
|
||||
if err := logic.New(svcCtx).AuditTorqueRecord(r.Context(), req.RecordId, req.Remark, operator(r, "")); err != nil {
|
||||
httpx.Fail(w, 3208, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.OkMessage(w, "审核成功", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// TorqueAuditLogHandler GET /torque/audit-log 查询拧紧记录修改留痕
|
||||
func TorqueAuditLogHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
id := atoiDefault(q.Get("recordId"), 0)
|
||||
if id <= 0 {
|
||||
httpx.Fail(w, 3209, "缺少 recordId")
|
||||
return
|
||||
}
|
||||
data, err := logic.New(svcCtx).ListTorqueAuditLog(r.Context(), id)
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3209, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,8 @@ func RegisterProductionRoutes(server *rest.Server, serverCtx *svc.ServiceContext
|
||||
|
||||
{Method: http.MethodPost, Path: "/torque/report", Handler: production.TorqueReportHandler(serverCtx)},
|
||||
{Method: http.MethodGet, Path: "/torque/records", Handler: production.TorqueRecordsHandler(serverCtx)},
|
||||
{Method: http.MethodPost, Path: "/torque/audit", Handler: production.TorqueAuditHandler(serverCtx)},
|
||||
{Method: http.MethodGet, Path: "/torque/audit-log", Handler: production.TorqueAuditLogHandler(serverCtx)},
|
||||
{Method: http.MethodPost, Path: "/torque/manual-add", Handler: production.TorqueManualAddHandler(serverCtx)},
|
||||
|
||||
{Method: http.MethodPost, Path: "/scan/report", Handler: production.ScanReportHandler(serverCtx)},
|
||||
@@ -161,6 +163,20 @@ func RegisterProductionRoutes(server *rest.Server, serverCtx *svc.ServiceContext
|
||||
|
||||
{Method: http.MethodGet, Path: "/event-logs", Handler: production.ListEventLogsHandler(serverCtx)},
|
||||
|
||||
// ---------- 预警规则 + 预警中心(M10) ----------
|
||||
{Method: http.MethodPost, Path: "/alert/rule", Handler: production.CreateAlertRuleHandler(serverCtx)},
|
||||
{Method: http.MethodPut, Path: "/alert/rule", Handler: production.UpdateAlertRuleHandler(serverCtx)},
|
||||
{Method: http.MethodDelete, Path: "/alert/rule", Handler: production.DeleteAlertRuleHandler(serverCtx)},
|
||||
{Method: http.MethodGet, Path: "/alert/rules", Handler: production.ListAlertRulesHandler(serverCtx)},
|
||||
{Method: http.MethodGet, Path: "/alerts", Handler: production.ListAlertsHandler(serverCtx)},
|
||||
{Method: http.MethodPost, Path: "/alert/read", Handler: production.MarkAlertReadHandler(serverCtx)},
|
||||
|
||||
// ---------- 附件中心(M10) ----------
|
||||
{Method: http.MethodPost, Path: "/attachment/upload", Handler: AttachmentUploadHandler(serverCtx)},
|
||||
{Method: http.MethodGet, Path: "/attachments", Handler: AttachmentListHandler(serverCtx)},
|
||||
{Method: http.MethodGet, Path: "/attachment/download", Handler: AttachmentDownloadHandler(serverCtx)},
|
||||
{Method: http.MethodPost, Path: "/attachment/delete", Handler: AttachmentDeleteHandler(serverCtx)},
|
||||
|
||||
// ---------- 工艺流程/工位(块3) ----------
|
||||
{Method: http.MethodGet, Path: "/process-flows", Handler: ListProcessFlowsHandler(serverCtx)},
|
||||
{Method: http.MethodPost, Path: "/process-flows", Handler: SaveProcessFlowHandler(serverCtx)},
|
||||
|
||||
@@ -75,3 +75,31 @@ func serveUploadFile(w http.ResponseWriter, r *http.Request, dir, name string) {
|
||||
w.Header().Set("Content-Type", ct)
|
||||
http.ServeContent(w, r, name, time.Time{}, f)
|
||||
}
|
||||
|
||||
// saveUploadFileFull 同 saveUploadFile,但额外返回原始文件名与字节大小(附件登记用)
|
||||
func saveUploadFileFull(r *http.Request, field, dir string) (string, string, int64, error) {
|
||||
sub := time.Now().Format("2006-01-02")
|
||||
full := filepath.Join(dir, sub)
|
||||
if err := os.MkdirAll(full, 0o755); err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
file, header, err := r.FormFile(field)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
defer file.Close()
|
||||
ext := strings.ToLower(filepath.Ext(header.Filename))
|
||||
if ext == "" {
|
||||
ext = ".bin"
|
||||
}
|
||||
name := time.Now().Format("20060102150405") + "_" + randHex(6) + ext
|
||||
dst, err := os.Create(filepath.Join(full, name))
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
defer dst.Close()
|
||||
if _, err := io.Copy(dst, file); err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
return filepath.ToSlash(filepath.Join(sub, name)), header.Filename, header.Size, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/alert"
|
||||
"bj_power_mes/ent/alertrule"
|
||||
)
|
||||
|
||||
// CreateAlertRule 新增预警规则
|
||||
func (s *Service) CreateAlertRule(ctx context.Context, name, typ string, threshold float64, receiver string, enabled bool, createdBy string) error {
|
||||
if name == "" || typ == "" {
|
||||
return errors.New("规则名称与类型必填")
|
||||
}
|
||||
_, err := s.ctx.EntClient.AlertRule.Create().
|
||||
SetName(name).SetType(typ).SetThreshold(threshold).
|
||||
SetReceiver(receiver).SetEnabled(enabled).SetCreatedBy(createdBy).Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateAlertRule 修改预警规则
|
||||
func (s *Service) UpdateAlertRule(ctx context.Context, id int, name, typ string, threshold float64, receiver string, enabled bool) error {
|
||||
if id <= 0 {
|
||||
return errors.New("规则ID无效")
|
||||
}
|
||||
if name == "" || typ == "" {
|
||||
return errors.New("规则名称与类型必填")
|
||||
}
|
||||
_, err := s.ctx.EntClient.AlertRule.UpdateOneID(id).
|
||||
SetName(name).SetType(typ).SetThreshold(threshold).
|
||||
SetReceiver(receiver).SetEnabled(enabled).Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteAlertRule 删除预警规则
|
||||
func (s *Service) DeleteAlertRule(ctx context.Context, id int) error {
|
||||
if id <= 0 {
|
||||
return errors.New("规则ID无效")
|
||||
}
|
||||
return s.ctx.EntClient.AlertRule.DeleteOneID(id).Exec(ctx)
|
||||
}
|
||||
|
||||
// ListAlertRules 查询全部预警规则
|
||||
func (s *Service) ListAlertRules(ctx context.Context) ([]*ent.AlertRule, error) {
|
||||
return s.ctx.EntClient.AlertRule.Query().
|
||||
Order(ent.Desc(alertrule.FieldCreatedAt), ent.Desc(alertrule.FieldID)).All(ctx)
|
||||
}
|
||||
|
||||
// ListAlerts 查询预警消息(status 空=全部)
|
||||
func (s *Service) ListAlerts(ctx context.Context, status string) ([]*ent.Alert, error) {
|
||||
q := s.ctx.EntClient.Alert.Query()
|
||||
if status != "" {
|
||||
q = q.Where(alert.Status(status))
|
||||
}
|
||||
return q.Order(ent.Desc(alert.FieldCreatedAt), ent.Desc(alert.FieldID)).All(ctx)
|
||||
}
|
||||
|
||||
// UnreadAlertCount 未读预警数
|
||||
func (s *Service) UnreadAlertCount(ctx context.Context) (int, error) {
|
||||
return s.ctx.EntClient.Alert.Query().Where(alert.Status("UNREAD")).Count(ctx)
|
||||
}
|
||||
|
||||
// MarkAlertRead 标记预警已读
|
||||
func (s *Service) MarkAlertRead(ctx context.Context, id int) error {
|
||||
if id <= 0 {
|
||||
return errors.New("预警ID无效")
|
||||
}
|
||||
_, err := s.ctx.EntClient.Alert.UpdateOneID(id).SetStatus("READ").Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// alertDirection 阈值比较方向:inventory_low 为 <=,其余为 >=
|
||||
func alertDirection(typ string) int {
|
||||
if typ == "inventory_low" {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// Evaluate 预警规则评估:遍历启用且类型匹配的规则,命中阈值则写 alert 消息。
|
||||
// 由业务事件触发(如拧紧不合格),也可手动调用。
|
||||
func (s *Service) Evaluate(ctx context.Context, typ string, value float64, title, content, refType, refId string) {
|
||||
rules, err := s.ctx.EntClient.AlertRule.Query().
|
||||
Where(alertrule.Type(typ), alertrule.Enabled(true)).All(ctx)
|
||||
if err != nil || len(rules) == 0 {
|
||||
return
|
||||
}
|
||||
dir := alertDirection(typ)
|
||||
for _, r := range rules {
|
||||
hit := (dir == 1 && value >= r.Threshold) || (dir == -1 && value <= r.Threshold)
|
||||
if !hit {
|
||||
continue
|
||||
}
|
||||
_ = s.createAlert(ctx, r.ID, typ, title, content, refType, refId, r.Receiver)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) createAlert(ctx context.Context, ruleId int, typ, title, content, refType, refId, receiver string) error {
|
||||
_, err := s.ctx.EntClient.Alert.Create().
|
||||
SetRuleId(ruleId).SetType(typ).SetTitle(title).
|
||||
SetContent(content).SetRefType(refType).SetRefId(refId).
|
||||
SetReceiver(receiver).SetStatus("UNREAD").Save(ctx)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/attachment"
|
||||
)
|
||||
|
||||
// AddAttachment 新增附件记录
|
||||
func (s *Service) AddAttachment(ctx context.Context, bizType, bizId, fileName, filePath string, fileSize int, uploader string) (*ent.Attachment, error) {
|
||||
return s.ctx.EntClient.Attachment.Create().
|
||||
SetBizType(bizType).SetBizId(bizId).SetFileName(fileName).
|
||||
SetFilePath(filePath).SetFileSize(fileSize).SetUploader(uploader).Save(ctx)
|
||||
}
|
||||
|
||||
// ListAttachments 按业务类型/ID 查询附件
|
||||
func (s *Service) ListAttachments(ctx context.Context, bizType, bizId string) ([]*ent.Attachment, error) {
|
||||
q := s.ctx.EntClient.Attachment.Query()
|
||||
if bizType != "" {
|
||||
q = q.Where(attachment.BizType(bizType))
|
||||
}
|
||||
if bizId != "" {
|
||||
q = q.Where(attachment.BizId(bizId))
|
||||
}
|
||||
return q.Order(ent.Desc(attachment.FieldCreatedAt), ent.Desc(attachment.FieldID)).All(ctx)
|
||||
}
|
||||
|
||||
// DeleteAttachment 删除附件记录并返回记录(供删除物理文件)
|
||||
func (s *Service) DeleteAttachment(ctx context.Context, id int) (*ent.Attachment, error) {
|
||||
att, err := s.ctx.EntClient.Attachment.Get(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.ctx.EntClient.Attachment.DeleteOneID(id).Exec(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return att, nil
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"bj_power_mes/ent"
|
||||
"bj_power_mes/ent/station"
|
||||
"bj_power_mes/ent/stepcriterion"
|
||||
"bj_power_mes/ent/torqueauditlog"
|
||||
"bj_power_mes/ent/torquerecord"
|
||||
"bj_power_mes/ent/workpieceprocess"
|
||||
)
|
||||
@@ -63,6 +64,7 @@ func (s *Service) ReportTorque(ctx context.Context, req TorqueReq, operator stri
|
||||
func (s *Service) evaluateTorqueCriterion(ctx context.Context, sn, stationNo string, strain, angle float64, operator string) {
|
||||
q := s.ctx.EntClient.StepCriterion.Query().Where(stepcriterion.Name("扭矩"))
|
||||
crits, _ := q.All(ctx)
|
||||
ng := false
|
||||
for _, c := range crits {
|
||||
if c.Logic != "RANGE" {
|
||||
continue
|
||||
@@ -78,6 +80,12 @@ func (s *Service) evaluateTorqueCriterion(ctx context.Context, sn, stationNo str
|
||||
SetSn(sn).SetStepId(c.StepId).SetCriterionId(c.ID).
|
||||
SetCriterionName(c.Name).SetCriterionLogic(c.Logic).
|
||||
SetValue(strain).SetIsOK(ok).SetOperator(operator).Save(ctx)
|
||||
if !ok {
|
||||
ng = true
|
||||
}
|
||||
}
|
||||
if ng {
|
||||
s.Evaluate(ctx, "torque_ng", 1, "拧紧扭矩不合格", "SN="+sn+" 工位"+stationNo, "torque_record", sn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +114,7 @@ func (s *Service) AddTorqueRecord(ctx context.Context, sn, workOrderNo, screwNo,
|
||||
result = "OK"
|
||||
}
|
||||
now := time.Now()
|
||||
_, err := s.ctx.EntClient.TorqueRecord.Create().
|
||||
rec, err := s.ctx.EntClient.TorqueRecord.Create().
|
||||
SetSn(sn).SetWorkOrderNo(workOrderNo).SetScrewNo(screwNo).SetStationNo(stationNo).
|
||||
SetStrain(strain).SetTorque(strain).SetAngle(angle).
|
||||
SetResult(result).SetOperator(operator + "(补录)").SetTime(now).
|
||||
@@ -114,11 +122,41 @@ func (s *Service) AddTorqueRecord(ctx context.Context, sn, workOrderNo, screwNo,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = s.ctx.EntClient.TorqueAuditLog.Create().
|
||||
SetTorqueRecordId(rec.ID).SetAction("补录").SetOperator(operator).
|
||||
SetRemark(reason).SetNewVal(result).Save(ctx)
|
||||
s.ctx.EventLog.Write(ctx, "torque.manual.add", workOrderNo, operator, "torque_record", sn,
|
||||
"拧紧数据补录 "+workOrderNo+" "+sn, map[string]any{"reason": reason, "result": result, "screwNo": screwNo, "stationNo": stationNo})
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuditTorqueRecord 拧紧记录审核签字:标记审核人/时间并写留痕
|
||||
func (s *Service) AuditTorqueRecord(ctx context.Context, recordId int, remark, operator string) error {
|
||||
rec, err := s.ctx.EntClient.TorqueRecord.Get(ctx, recordId)
|
||||
if err != nil {
|
||||
return errors.New("拧紧记录不存在")
|
||||
}
|
||||
if rec.AuditBy != "" {
|
||||
return errors.New("该记录已审核,不可重复审核")
|
||||
}
|
||||
_, err = rec.Update().SetAuditBy(operator).SetAuditAt(time.Now()).Save(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = s.ctx.EntClient.TorqueAuditLog.Create().
|
||||
SetTorqueRecordId(rec.ID).SetAction("审核").SetOperator(operator).
|
||||
SetRemark(remark).SetOldVal(rec.AuditBy).SetNewVal(operator).Save(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListTorqueAuditLog 查询某拧紧记录的修改留痕
|
||||
func (s *Service) ListTorqueAuditLog(ctx context.Context, recordId int) ([]*ent.TorqueAuditLog, error) {
|
||||
return s.ctx.EntClient.TorqueAuditLog.Query().
|
||||
Where(torqueauditlog.TorqueRecordId(recordId)).
|
||||
Order(ent.Desc(torqueauditlog.FieldCreatedAt)).All(ctx)
|
||||
}
|
||||
|
||||
|
||||
// 计算一块工件某工序的扭矩步骤是否已报
|
||||
func (s *Service) hasWorkpieceProcess(ctx context.Context, sn string, processCode int) bool {
|
||||
cnt, _ := s.ctx.EntClient.WorkpieceProcess.Query().
|
||||
|
||||
Reference in New Issue
Block a user