From 85b58968d10bf80648f064d018ba97d8a2a5faf9 Mon Sep 17 00:00:00 2001 From: henry Date: Fri, 5 Nov 2021 18:07:32 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=AE=8C=E5=96=84=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/config.go | 17 +++- app/api/work.go | 17 +++- app/common/model/work_instance.go | 2 +- app/common/model/work_progress.go | 18 ++++- app/common/model/work_schedule.go | 12 ++- app/controller/config/breakdown.go | 20 ++++- app/controller/work/person.go | 103 +++++++++++++++++++++++++ app/model/manage_material.go | 4 +- app/model/manage_materiral_purchase.go | 4 +- app/model/sys_user.go | 4 +- app/model/work_instance.go | 4 +- app/model/work_progress.go | 11 +++ app/model/work_schedule.go | 55 +++++++++++++ 13 files changed, 254 insertions(+), 17 deletions(-) create mode 100644 app/controller/work/person.go create mode 100644 app/model/work_progress.go create mode 100644 app/model/work_schedule.go diff --git a/app/api/config.go b/app/api/config.go index 3393740..b7628fd 100644 --- a/app/api/config.go +++ b/app/api/config.go @@ -100,6 +100,21 @@ func (*Config) Breakdown(c *gin.Context) { APIResponse(err, data)(c) } -func (*Config) BreakdownAdd() { +func (*Config) BreakdownAdd(c *gin.Context) { } + +func (*Config) BreakdownEdit(c *gin.Context) { + +} + +func (*Config) BreakdownDelete(c *gin.Context) { + form := new(IDStringForm) + + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := config.NewBreakdown()(getSession()(c).(*service.Session)).Delete(form.Convert()) + APIResponse(err)(c) +} diff --git a/app/api/work.go b/app/api/work.go index 97b27ff..3de9ee9 100644 --- a/app/api/work.go +++ b/app/api/work.go @@ -71,10 +71,25 @@ func (*Work) Instance(c *gin.Context) { APIResponse(err, data)(c) } +func (*Work) ToDo(c *gin.Context) { + +} + func (*Work) Launch(c *gin.Context) { } func (*Work) Examine(c *gin.Context) { - + form := &struct { + IDStringForm + Status int `json:"status" form:"status" binding:"required"` + Remark string `json:"remark" form:"remark"` + IsAssist int `json:"is_assist" form:"is_assist"` + }{} + if err := bind(form)(c); err != nil { + APIFailure(err.(error))(c) + return + } + err := work.NewPerson()(getSession()(c).(*service.Session)).Examine(form.Convert(), form.Status, form.Remark, form.IsAssist) + APIResponse(err) } diff --git a/app/common/model/work_instance.go b/app/common/model/work_instance.go index 8f3866b..d0bc1ea 100644 --- a/app/common/model/work_instance.go +++ b/app/common/model/work_instance.go @@ -11,7 +11,7 @@ type WorkInstance struct { PlateNumber string `gorm:"column:plate_number;type:varchar(10);default:null;comment:车牌号" json:"plate_number"` Breakdown string `gorm:"column:breakdown;type:varchar(150);default:null;comment:故障" json:"breakdown"` Priority WorkInstancePriority `gorm:"column:priority;type:tinyint(1);default:1;comment:工单优先级" json:"priority"` - Progress int `gorm:"column:progress;type:tinyint(1);default:1;comment:工单进度" json:"progress"` + Schedule uint64 `gorm:"column:schedule;type:int(11);default:1;comment:工单进度" json:"schedule"` Status WorkInstanceStatus `gorm:"column:status;type:tinyint(1);default:0;comment:工单状态" json:"status"` Remark string `gorm:"column:remark;type:varchar(255);default:null;comment:备注信息" json:"remark"` ModelDeleted diff --git a/app/common/model/work_progress.go b/app/common/model/work_progress.go index 6a587fe..008910e 100644 --- a/app/common/model/work_progress.go +++ b/app/common/model/work_progress.go @@ -3,13 +3,25 @@ package model // WorkProgress 工单进度数据模型 type WorkProgress struct { Model - UID uint64 `gorm:"column:uid;type:int;default:0;comment:用户uuid" json:"-"` - WorkID uint64 `gorm:"column:work_id;type:int(11);default:0;comment:工单ID" json:"-"` - Remark string `gorm:"column:remark;type:varchar(255);default:null;comment:备注信息" json:"remark"` + UID uint64 `gorm:"column:uid;type:int;default:0;comment:用户uuid" json:"-"` + WorkID uint64 `gorm:"column:work_id;type:int(11);default:0;comment:工单ID" json:"-"` + ScheduleID uint64 `gorm:"column:schedule_id;type:int(11);default:0;comment:工单流程ID" json:"-"` + Status WorkProgressStatus `gorm:"column:status;type:tinyint(1);default:1;comment:状态" json:"-"` + Remark string `gorm:"column:remark;type:varchar(255);default:null;comment:备注信息" json:"remark"` ModelDeleted ModelAt } +// WorkProgressStatus 工单进度状态 +type WorkProgressStatus int + +const ( + // WorkProgressStatusForRefuse 拒绝 + WorkProgressStatusForRefuse WorkProgressStatus = iota - 1 + // WorkProgressStatusForAgree 同意 + WorkProgressStatusForAgree +) + func (m *WorkProgress) TableName() string { return "work_progress" } diff --git a/app/common/model/work_schedule.go b/app/common/model/work_schedule.go index b6b866b..f843411 100644 --- a/app/common/model/work_schedule.go +++ b/app/common/model/work_schedule.go @@ -1,5 +1,7 @@ package model +import "strings" + // WorkSchedule 工单流程数据模型 type WorkSchedule struct { Model @@ -17,7 +19,7 @@ type WorkScheduleTarget int const ( // WorkScheduleTargetForPerson 个人 - WorkScheduleTargetForPerson int = iota + 1 + WorkScheduleTargetForPerson WorkScheduleTarget = iota + 1 // WorkScheduleTargetForRole 角色 WorkScheduleTargetForRole ) @@ -26,6 +28,14 @@ func (m *WorkSchedule) TableName() string { return "work_schedule" } +func (m *WorkSchedule) GetTargetValueAttribute() []string { + return strings.Split(m.TargetValue, ",") +} + +func (m *WorkSchedule) SetTargetValueAttribute(value []string) { + m.TargetValue = strings.Join(value, ",") +} + func NewWorkSchedule() *WorkSchedule { return &WorkSchedule{} } diff --git a/app/controller/config/breakdown.go b/app/controller/config/breakdown.go index 829d171..8558eaa 100644 --- a/app/controller/config/breakdown.go +++ b/app/controller/config/breakdown.go @@ -16,6 +16,7 @@ type BreakdownInfo struct { *model2.SysBreakdown } +// List 列表信息 func (c *Breakdown) List(title string, page, pageSize int) (*basic.PageDataResponse, error) { mSysBreakdown := model.NewSysBreakdown() @@ -43,12 +44,27 @@ func (c *Breakdown) List(title string, page, pageSize int) (*basic.PageDataRespo return &basic.PageDataResponse{Data: list, Count: count}, nil } +// Form 数据处理 func (c *Breakdown) Form(id uint64, title, remark string) error { - return nil + mSysBreakdown := model.NewSysBreakdown() + + if id > 0 { + mSysBreakdown.ID = mSysBreakdown.ID + + return model2.Updates(mSysBreakdown.SysBreakdown, map[string]interface{}{ + "title": title, "remark": remark, + }) + } + mSysBreakdown.Title = title + mSysBreakdown.Remark = remark + return model2.Create(mSysBreakdown.SysBreakdown) } +// Delete 删除操作 func (c *Breakdown) Delete(id uint64) error { - return nil + mSysBreakdown := model.NewSysBreakdown() + mSysBreakdown.ID = id + return model2.Delete(mSysBreakdown.SysBreakdown) } func NewBreakdown() BreakdownHandle { diff --git a/app/controller/work/person.go b/app/controller/work/person.go new file mode 100644 index 0000000..b25e4d1 --- /dev/null +++ b/app/controller/work/person.go @@ -0,0 +1,103 @@ +package work + +import ( + model2 "ArmedPolice/app/common/model" + "ArmedPolice/app/controller/basic" + "ArmedPolice/app/model" + "ArmedPolice/app/service" + "ArmedPolice/serve/orm" + "errors" + "gorm.io/gorm" + "time" +) + +type Person struct{ *service.Session } + +type PersonHandle func(session *service.Session) *Person + +func (c *Person) List() (*basic.PageDataResponse, error) { + return &basic.PageDataResponse{Data: nil, Count: 0}, nil +} + +// Examine 审核操作 +func (c *Person) Examine(id uint64, status int, remark string, isAssist int) error { + _status := model2.WorkProgressStatus(status) + + if _status != model2.WorkProgressStatusForAgree && _status != model2.WorkProgressStatusForRefuse { + return errors.New("操作错误,审核状态异常") + } + mWorkInstance := model.NewWorkInstance() + mWorkInstance.ID = id + + isExist, err := model2.FirstField(mWorkInstance.WorkInstance, []string{"id", "schedule", "status"}) + + if err != nil { + return err + } else if !isExist { + return errors.New("操作错误,工单信息不存在") + } else if mWorkInstance.Status == model2.WorkInstanceStatusForComplete { + return errors.New("操作错误,当前工单信息已结束") + } + // 查询当前工单所在流程的信息 + mWorkSchedule := model.NewWorkSchedule() + mWorkSchedule.ID = mWorkInstance.Schedule + + if isExist, err = model2.First(mWorkSchedule); err != nil { + return err + } else if !isExist { + return errors.New("操作错误,未知的工单流程") + } + // 验证审核权限 + isAuth := false + + if isAuth, err = mWorkSchedule.ValidateAuth(c.UID); err != nil { + return err + } else if !isAuth { + return errors.New("操作错误,无权限审批") + } + if err = orm.GetDB().Transaction(func(tx *gorm.DB) error { + // 工单流程记录 + mWorkProgress := model.NewWorkProgress() + mWorkProgress.UID = c.UID + mWorkProgress.WorkID = id + mWorkProgress.ScheduleID = mWorkSchedule.ID + mWorkProgress.Status = _status + mWorkProgress.Remark = remark + + if err = model2.Create(mWorkProgress.WorkProgress, tx); err != nil { + return err + } + workUpdates := map[string]interface{}{ + "status": model2.WorkInstanceStatusForComplete, "updated_at": time.Now(), + } + // 下一流程 + newNextScheduleInfo := new(model.WorkScheduleInfo) + + // 拒绝审批,工单直接结束 + if _status == model2.WorkProgressStatusForRefuse { + goto FINISH + } + if newNextScheduleInfo, err = mWorkSchedule.NextSchedule(); err != nil { + return err + } + // 无下一流程,工单直接完成 + if newNextScheduleInfo == nil { + goto FINISH + } + workUpdates["status"] = model2.WorkInstanceStatusForOngoing + FINISH: + if err = model2.Updates(mWorkInstance.WorkInstance, workUpdates, tx); err != nil { + return err + } + return nil + }); err != nil { + return err + } + return nil +} + +func NewPerson() PersonHandle { + return func(session *service.Session) *Person { + return &Person{session} + } +} diff --git a/app/model/manage_material.go b/app/model/manage_material.go index 91ccd5a..97e3555 100644 --- a/app/model/manage_material.go +++ b/app/model/manage_material.go @@ -43,10 +43,10 @@ func (m *ManageMaterial) Materials(page, pageSize int, count *int64, where ...*m } out := make([]*ManageMaterialInfo, 0) - if err := db.Order("p.id " + model.OrderModeToDesc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { + if err := db.Count(count).Error; err != nil { return nil, err } - if err := db.Count(count).Error; err != nil { + if err := db.Order("p.id " + model.OrderModeToDesc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { return nil, err } return out, nil diff --git a/app/model/manage_materiral_purchase.go b/app/model/manage_materiral_purchase.go index fe4b1ee..4408404 100644 --- a/app/model/manage_materiral_purchase.go +++ b/app/model/manage_materiral_purchase.go @@ -33,10 +33,10 @@ func (m *ManageMaterialPurchase) Purchases(page, pageSize int, count *int64, whe } out := make([]*ManageMaterialPurchaseInfo, 0) - if err := db.Order("p.id " + model.OrderModeToDesc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { + if err := db.Count(count).Error; err != nil { return nil, err } - if err := db.Count(count).Error; err != nil { + if err := db.Order("p.id " + model.OrderModeToDesc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { return nil, err } return out, nil diff --git a/app/model/sys_user.go b/app/model/sys_user.go index cb3f31f..57a5752 100644 --- a/app/model/sys_user.go +++ b/app/model/sys_user.go @@ -58,10 +58,10 @@ func (m *SysUser) Users(page, pageSize int, count *int64, where ...*model.ModelW db = db.Where(wo.Condition, wo.Value) } } - if err := db.Order("u.id " + model.OrderModeToAsc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { + if err := db.Count(count).Error; err != nil { return nil, err } - if err := db.Count(count).Error; err != nil { + if err := db.Order("u.id " + model.OrderModeToAsc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { return nil, err } return out, nil diff --git a/app/model/work_instance.go b/app/model/work_instance.go index c91b21c..7bb1b45 100644 --- a/app/model/work_instance.go +++ b/app/model/work_instance.go @@ -40,10 +40,10 @@ func (m *WorkInstance) Instances(page, pageSize int, count *int64, where ...*mod } out := make([]*WorkInstanceInfo, 0) - if err := db.Order("w.id " + model.OrderModeToDesc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { + if err := orm.GetDB().Table(m.TableName()).Where("is_deleted = ?", model.DeleteStatusForNot).Count(count).Error; err != nil { return nil, err } - if err := db.Count(count).Error; err != nil { + if err := db.Order("w.id " + model.OrderModeToDesc).Offset((page - 1) * pageSize).Limit(pageSize).Scan(&out).Error; err != nil { return nil, err } return out, nil diff --git a/app/model/work_progress.go b/app/model/work_progress.go new file mode 100644 index 0000000..97ff53e --- /dev/null +++ b/app/model/work_progress.go @@ -0,0 +1,11 @@ +package model + +import "ArmedPolice/app/common/model" + +type WorkProgress struct { + *model.WorkProgress +} + +func NewWorkProgress() *WorkProgress { + return &WorkProgress{model.NewWorkProgress()} +} diff --git a/app/model/work_schedule.go b/app/model/work_schedule.go new file mode 100644 index 0000000..c5604dd --- /dev/null +++ b/app/model/work_schedule.go @@ -0,0 +1,55 @@ +package model + +import ( + "ArmedPolice/app/common/model" + "fmt" +) + +type WorkSchedule struct { + *model.WorkSchedule +} + +// WorkScheduleInfo 工单流程信息 +type WorkScheduleInfo struct { + ID uint64 `json:"id"` + Reviewer []uint64 `json:"reviewer"` +} + +// ValidateAuth 验证权限 +func (m *WorkSchedule) ValidateAuth(uid uint64) (bool, error) { + // 流程权限信息 + auths := make(map[string]bool, 0) + + for _, v := range m.GetTargetValueAttribute() { + auths[v] = true + } + // 触发审核对象 + switch m.Target { + case model.WorkScheduleTargetForPerson: // 个人 + _, has := auths[fmt.Sprintf("%d", uid)] + return has, nil + case model.WorkScheduleTargetForRole: // 角色 + // 查询角色信息 + roleIDs := make([]uint64, 0) + mSysUserRole := model.NewSysUserRole() + + if err := model.Pluck(mSysUserRole, "role_id", &roleIDs, model.NewWhere("uid", uid)); err != nil { + return false, err + } + for _, v := range roleIDs { + if _, has := auths[fmt.Sprintf("%d", v)]; has { + return has, nil + } + } + break + } + return false, nil +} + +func (m *WorkSchedule) NextSchedule() (*WorkScheduleInfo, error) { + return nil, nil +} + +func NewWorkSchedule() *WorkSchedule { + return &WorkSchedule{model.NewWorkSchedule()} +}