You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

569 lines
14 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package model
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"github.com/fonchain_enterprise/fonchain-approval/api/approval"
"github.com/fonchain_enterprise/fonchain-approval/pkg/common/page"
msg "github.com/fonchain_enterprise/fonchain-approval/pkg/m"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
"time"
)
type KeyInfo struct {
ApprovalKey string
ApprovalName string
ApprovalType string
ApprovalValue string
}
type KeyInfos []KeyInfo
// Approval 审批
type Approval struct {
ID uint64 `gorm:"primaryKey;column:id" json:"id"`
DeletedAt soft_delete.DeletedAt `gorm:"column:deleted_at" json:"deletedAt"`
CreatedAt time.Time `gorm:"column:created_at" json:"createdAt"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updatedAt"`
SubmitterID uint64 `gorm:"column:submitter_id" json:"submitterId"`
Status int8 `gorm:"column:status" json:"status"`
SubmitterName string `gorm:"column:submitter_name" json:"submitterName"`
CopyUsers CopyUsers `gorm:"column:copy_users" json:"copyUsers"`
ApprovalUsers ApprovalUsers `gorm:"column:approval_users" json:"approvalUsers"`
Type string `gorm:"column:type" json:"type"`
Level uint8 `gorm:"column:level" json:"level"`
NowLevel uint8 `gorm:"column:now_level" json:"nowLevel"`
NowUserId uint64 `gorm:"column:now_user_id" json:"nowUserId"`
NowUserName string `gorm:"column:now_user_name" json:"nowUserName"`
Content string `gorm:"column:content" json:"content"`
ValueJson KeyInfos `gorm:"type:json;column:value_json;default:null;comment:自定义信息" json:"valueJson"`
Reply string `gorm:"column:reply" json:"reply"`
Domain *string `gorm:"column:domain" json:"domain"`
Show *Show `gorm:"foreignKey:ApprovalID" json:"Show"`
Work *Work `gorm:"foreignKey:ApprovalID" json:"Work"`
Bundle *Bundle `gorm:"foreignKey:ApprovalID" json:"Bundle"`
Exhibition *Exhibition `gorm:"foreignKey:ApprovalID" json:"Exhibition"`
ApprovalWorkFlows []*ApprovalWorkFlow `gorm:"foreignKey:ApprovalID" json:"ApprovalWorkFlows"`
}
func (j *KeyInfos) Scan(src interface{}) error {
return json.Unmarshal(src.([]byte), j)
}
func (j KeyInfos) Value() (driver.Value, error) {
v, err := json.Marshal(j)
return string(v), err
}
const (
TypeContent = "content"
TypeWork = "work"
TypeExhibition = "exhibition"
TypeShow = "show"
TypeBundle = "bundle"
)
const (
StatusDoing = 1
StatusOk = 2
StatusFail = 3
)
const (
StatusNeedViewed = 4
StatusViewed = 5
)
type ApprovalContentInterface interface {
SaveApprovalContent(in *approval.CreateRequest, a *Approval) error
UpdateApprovalContent(in *approval.CreateRequest, a *Approval) error
BuildResContent(a *Approval, request *approval.CreateRequest)
DeleteApproval(p *Approval) error
}
// TableName get sql table name.获取数据库表名
func (m *Approval) TableName() string {
return "approval"
}
func preValidateExhibition(in *approval.CreateRequest) error {
if in.Type != TypeExhibition {
return nil
}
total := GetExhibitionNumByUser(in.Domain, in.SubmitterID)
if total <= 0 {
return errors.New("您现在可选数量为0请先申请画展包数量")
}
if len(in.Exhibition.ApprovalExhibitions) > int(total) {
errStr := fmt.Sprintf("您现在可选数量为%d申请画展包数量为 %d", len(in.Exhibition.ApprovalExhibitions), total)
return errors.New(errStr)
}
return nil
}
/*
func preValidateExhibition(in *approval.CreateRequest) error {
var entity *Bundle
if in.Type != TypeExhibition {
return nil
}
if in.Exhibition == nil || in.Exhibition.PidApprovalID == 0 {
return errors.New(msg.ErrorApprovalType)
}
if err := DB.Where(Bundle{ApprovalID: in.Exhibition.PidApprovalID}).First(&entity).Error; err != nil {
return err
}
if len(in.Exhibition.ApprovalExhibitions) != int(entity.ApplicationsNum) {
return errors.New(msg.ErrorWrongNum)
}
return nil
}
*/
// GetExhibitionNumByUser 获取用户可以使用的画展包数量
func GetExhibitionNumByUser(domain string, submitterID uint64) int64 {
var total, usedNum int64
//已经使用的
str := `SELECT SUM(exhibition.num) AS total FROM exhibition
left join approval ON approval.id = exhibition.approval_id WHERE approval.STATUS != ?
AND approval.domain = ? AND approval.submitter_id = ? AND approval.type = ? AND approval.deleted_at=0`
DB.Raw(str, StatusFail, domain, submitterID, TypeExhibition).Scan(&usedNum)
fmt.Println("已经使用", usedNum)
//所有的
str1 := `SELECT SUM(bundle.applications_num) AS total FROM bundle
left join approval ON approval.id = bundle.approval_id WHERE approval.STATUS = ?
AND approval.domain = ? AND approval.submitter_id = ? AND approval.type = ? AND approval.deleted_at=0`
DB.Raw(str1, StatusOk, domain, submitterID, TypeBundle).Scan(&total)
fmt.Println("所有申请的", total)
return total - usedNum
}
func StoreApproval(in *approval.CreateRequest) (*Approval, error) {
var entity *Approval
if err1 := preValidateExhibition(in); err1 != nil {
return entity, err1
}
err := DB.Transaction(func(tx *gorm.DB) error {
setting, terr := GetApprovalSettingFromKeyWord(in.Domain, in.Type)
fmt.Println("1-----", terr, setting)
if terr != nil || setting == nil {
return errors.New("抄送人没有配置")
}
approvalUsers := setting.GetCombineApproveUsers(FormatApproveUsers(in.ApprovalUsers))
fmt.Println("2-----", approvalUsers)
// 保存基本信息
entity = &Approval{
Domain: &in.Domain,
SubmitterID: in.SubmitterID,
SubmitterName: in.SubmitterName,
CopyUsers: setting.CopyUsers,
ApprovalUsers: approvalUsers,
Type: in.Type,
Content: in.Content,
ValueJson: ToKeyInfos(in.CustomizeInfo),
Status: StatusDoing,
Level: uint8(len(approvalUsers)),
NowLevel: 1,
NowUserId: approvalUsers[0].ID,
NowUserName: approvalUsers[0].Name,
}
fmt.Println(3)
if err := DB.Create(&entity).Error; err != nil {
return err
}
// 不同类型保存不同的结构体
fmt.Println(41, entity)
err := entity.SaveContent(in)
fmt.Println(4)
if err != nil {
return err
}
fmt.Println(5)
return BatchSave(approvalUsers, entity.ID)
})
//fmt.Println("nil", entity)
//fmt.Println("nil", entity.ID)
return entity, err
}
func Viewed(in *approval.ViewedRequest) error {
var entity *Approval
var err error
var isView = false
if err = DB.First(&entity, in.ID).Error; err != nil {
return errors.New(msg.ErrorNotFound)
}
if entity.Status != StatusOk {
return errors.New(msg.ErrorDoingNotView)
}
copyUsers := entity.CopyUsers
for i, temp := range copyUsers {
if temp.ID == in.UserID {
if temp.IsViewed == true {
return errors.New(msg.ErrorAlreadySettingView)
}
isView = true
temp.IsViewed = isView
copyUsers[i] = temp
}
}
if isView == false {
return errors.New(msg.ErrorSettingView)
}
return DB.Model(&Approval{}).Where(&Approval{ID: in.ID}).Updates(&Approval{CopyUsers: copyUsers}).Error
}
func UpdateApproval(in *approval.CreateRequest) (*Approval, error) {
var entity *Approval
if err1 := preValidateExhibition(in); err1 != nil {
return entity, err1
}
err := DB.Transaction(func(tx *gorm.DB) error {
if departErr := DB.First(&entity, in.ID).Error; departErr != nil {
return errors.New(msg.ErrorNotFound)
}
if entity.Type != in.Type {
return errors.New(msg.ErrorChangeType)
}
// 保存基本信息
upEntity := &Approval{
Content: in.Content,
}
if entity.Status == StatusFail {
upEntity.Status = StatusDoing
}
if err := DB.Where(&Approval{ID: in.ID}).Updates(&upEntity).Error; err != nil {
return err
}
// 不同类型保存不同的结构体
err := entity.UpdateContent(in)
return err
})
return entity, err
}
func approvalCalc(filter *Approval) *approval.Information {
var num int64
info := &approval.Information{
Total: 0,
DoingTotal: 0,
SuccessTotal: 0,
FailTotal: 0,
}
DB.Model(&Approval{}).Where(&filter).Count(&num)
info.Total = uint64(num)
DB.Model(&Approval{}).Where(&filter).Where(&Approval{Status: StatusDoing}).Count(&num)
info.DoingTotal = uint64(num)
DB.Model(&Approval{}).Where(&filter).Where(&Approval{Status: StatusOk}).Count(&num)
info.SuccessTotal = uint64(num)
DB.Model(&Approval{}).Where(&filter).Where(&Approval{Status: StatusFail}).Count(&num)
info.FailTotal = uint64(num)
return info
}
func approvalCalcJson(domain string, userId uint64) *approval.Information {
var num int64
var jsonStr = "JSON_CONTAINS(approval_users,JSON_OBJECT('ID', ?))"
info := &approval.Information{
Total: 0,
DoingTotal: 0,
SuccessTotal: 0,
FailTotal: 0,
}
DB.Model(&Approval{}).Where(jsonStr, userId).Count(&num)
info.Total = uint64(num)
DB.Model(&Approval{}).Where(jsonStr, userId).Where(&Approval{Status: StatusDoing, Domain: &domain}).Count(&num)
info.DoingTotal = uint64(num)
DB.Model(&Approval{}).Where(jsonStr, userId).Where(&Approval{Status: StatusOk, Domain: &domain}).Count(&num)
info.SuccessTotal = uint64(num)
DB.Model(&Approval{}).Where(jsonStr, userId).Where(&Approval{Status: StatusFail, Domain: &domain}).Count(&num)
info.FailTotal = uint64(num)
return info
}
// ApprovalInfo 统计
func ApprovalInfo(in *approval.InformationRequest) (*approval.InformationResponse, error) {
response := &approval.InformationResponse{
MySubmitInfo: approvalCalc(&Approval{Domain: &in.Domain, SubmitterID: in.UserID}),
SubmitMeInfo: approvalCalcJson(in.Domain, in.UserID),
DomainInfo: approvalCalc(&Approval{Domain: &in.Domain}),
}
return response, nil
}
func (m *Approval) SaveApprovalContent(in *approval.CreateRequest, a *Approval) error {
return nil
}
func (m *Approval) UpdateApprovalContent(in *approval.CreateRequest, a *Approval) error {
return nil
}
func (m *Approval) DeleteApproval(p *Approval) error {
return nil
}
func (m *Approval) DeleteContent() error {
factory, err := getApprovalContentFactory(m.Type)
if err != nil {
return err
}
return factory.DeleteApproval(m)
}
func (m *Approval) BuildResContent(a *Approval, request *approval.CreateRequest) {
}
func (m *Approval) SetResContent(request *approval.CreateRequest) error {
factory, err := getApprovalContentFactory(m.Type)
if err != nil {
return err
}
factory.BuildResContent(m, request)
return nil
}
func (m *Approval) SaveContent(in *approval.CreateRequest) error {
factory, err := getApprovalContentFactory(in.Type)
if err != nil {
return err
}
err = factory.SaveApprovalContent(in, m)
return err
}
func (m *Approval) UpdateContent(in *approval.CreateRequest) error {
factory, err := getApprovalContentFactory(in.Type)
if err != nil {
return err
}
err = factory.UpdateApprovalContent(in, m)
return err
}
func MyWorkApprovals(in *approval.ListRequest) ([]*Approval, int64) {
var list []*Approval
var count int64
//list
modelObj := DB.Model(&Approval{}).
Preload("Show").
Preload("Work.ApprovalWorks").
Preload("Bundle").
Preload("ApprovalWorkFlows").
Preload("Exhibition.ApprovalExhibitions")
if in.Type != "" {
modelObj = modelObj.Where(&Approval{Type: in.Type})
}
/**
* 审批展示(抄送在此不表)
/ \
进行中 通过或者拒绝
/ \
当前是我审批 我参与审批的
*/
if in.UserID != 0 {
modelObj = modelObj.Where(
DB.Where("JSON_CONTAINS(approval_users,JSON_OBJECT('ID', ?))", in.UserID).
Where("status != ?", StatusDoing). //完成,我参与审批
Or(DB.Where("now_user_id", in.UserID).Where("status = ?", StatusDoing)). //进行中,当前审批人是我,
Or(DB.Where("JSON_CONTAINS(copy_users,JSON_OBJECT('ID', ?))", in.UserID).Where("status = ?", StatusOk))) //抄送人(完成抄送)
}
if in.Status != 0 {
modelObj = modelObj.Where(&Approval{Status: int8(in.Status)})
}
modelObj.Count(&count)
modelObj.Limit(int(in.PageSize)).Offset(page.GetOffset(in.Page, in.PageSize)).Order("id desc").Find(&list)
return list, count
}
func MySubmitApprovals(in *approval.ListRequest) ([]*Approval, int64) {
var list []*Approval
var count int64
//list
modelObj := DB.Model(&Approval{}).
Preload("Show").
Preload("Work.ApprovalWorks").
Preload("Bundle").
Preload("ApprovalWorkFlows").
Preload("Exhibition.ApprovalExhibitions")
if in.Status != 0 {
modelObj = modelObj.Where(&Approval{Status: int8(in.Status)})
}
if in.Type != "" {
modelObj = modelObj.Where(&Approval{Type: in.Type})
}
modelObj = modelObj.Where(&Approval{SubmitterID: in.UserID})
modelObj.Count(&count)
modelObj.Limit(int(in.PageSize)).Offset(page.GetOffset(in.Page, in.PageSize)).Order("id desc").Find(&list)
return list, count
}
func (m *Approval) Pass(reply string, workFlowId uint64) error {
return m.operateStatus(StatusOk, reply, workFlowId)
}
func (m *Approval) Refuse(reply string, workFlowId uint64) error {
return m.operateStatus(StatusFail, reply, workFlowId)
}
func (m *Approval) operateStatus(status uint8, reply string, workFlowId uint64) error {
var workFlow ApprovalWorkFlow
m.Reply = reply
if err := DB.Model(&ApprovalWorkFlow{ApprovalID: m.ID, Status: StatusDoing}).First(&workFlow, workFlowId).Error; err != nil {
return err
}
if m.NowLevel != workFlow.Level {
return errors.New(msg.ErrorOperate)
}
// 拒绝通过
if status == StatusFail {
m.Status = StatusFail
if err := DB.Save(m).Error; err != nil {
return err
}
return workFlow.Refuse(reply)
}
/*--------层级审批通过---------*/
// 整个审批通过
if m.Level == m.NowLevel {
m.Status = StatusOk
//审批层级通过
} else {
m.NowLevel = workFlow.Level + 1
nextFlow, err := GetWorkFlowByLevel(m.ID, m.NowLevel)
if err != nil {
return err
}
m.NowUserId = nextFlow.UserId
m.NowUserName = nextFlow.Name
}
if err := DB.Save(m).Error; err != nil {
return err
}
return workFlow.Pass(reply)
}
func getApprovalContentFactory(typeFiled string) (ApprovalContentInterface, error) {
switch typeFiled {
case TypeContent:
return &Approval{}, nil
case TypeShow:
return &Show{}, nil
case TypeWork:
return &Work{}, nil
case TypeBundle:
return &Bundle{}, nil
case TypeExhibition:
return &Exhibition{}, nil
default:
return &Approval{}, nil
}
}