/*
 * @description: 审批流程数据库操作相关
 * @Author: LanJianRong
 * @Date: 2021-01-06
 * @FilePath: \construction_management\dao\approver_dao.go
 */

package dao

import (
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/go-xorm/xorm"
	"go.mod/comm"
	"go.mod/conf"
	"go.mod/models"
	"go.mod/web/viewmodels"
)

// 数据库操作引擎
type ApproverDao struct {
	engine *xorm.Engine
}

// 获得一个DAO对象
func NewApproverDao(engine *xorm.Engine) *ApproverDao {
	return &ApproverDao{
		engine: engine,
	}
}

// 批量插入数据
func (d *ApproverDao) InsertData(cur_uid int, bid int, pid int, dataType int, dataId int, auditors []int, reAuditors []int) error {
	data := make([]models.CmApprover, 0)
	msg := make([]models.CmProjectMessage, 0)
	var content string
	var title string
	if dataType == 1 {
		safe := &models.CmSafe{Id: dataId}
		_, err := d.engine.Get(safe)
		if err != nil {
			return err
		}
		account := &models.CmProjectAccount{Id: safe.Uid}
		_, err = d.engine.Get(account)
		title = fmt.Sprintf("%s - %s", account.Name, account.Position)
		content = fmt.Sprintf("%s|%s|已上报，审批中", safe.Code, safe.InspectionDetail)
	} else {
		quality := &models.CmQuality{Id: dataId}
		_, err := d.engine.Get(quality)
		if err != nil {
			return err
		}
		account := &models.CmProjectAccount{Id: quality.Uid}
		_, err = d.engine.Get(account)
		if err != nil {
			return err
		}
		title = fmt.Sprintf("%s - %s", account.Name, account.Position)
		content = fmt.Sprintf("%s|%s|已上报，审批中", quality.Code, quality.InspectionDetail)
	}
	_, err := d.engine.Exec("delete from project_message where data_type = ? and data_id = ?", dataType, dataId)
	for i, item := range auditors {
		approverVM := models.CmApprover{}
		approverVM.AuditId = item
		approverVM.AuditOrder = i + 1
		approverVM.Progress = 0
		approverVM.BidsectionId = bid
		approverVM.ProjectId = pid
		approverVM.DataType = dataType
		approverVM.DataId = dataId
		approverVM.CreateTime = time.Now()
		approverVM.Status = 0
		if i == 0 {
			approverVM.Status = 1
		}
		data = append(data, approverVM)

		// 消息推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = item
		msgVM.BidsectionId = bid
		msgVM.ProjectId = pid
		msgVM.DataId = dataId
		msgVM.DataType = 1
		msgVM.Content = content
		msgVM.Title = title
		msgVM.CreateTime = time.Now()
		msg = append(msg, msgVM)
	}
	checkVM := models.CmApprover{}
	checkVM.AuditOrder = len(auditors) + 1
	checkVM.Progress = 1
	checkVM.BidsectionId = bid
	checkVM.ProjectId = pid
	checkVM.DataType = dataType
	checkVM.DataId = dataId
	data = append(data, checkVM)
	for i, item := range reAuditors {
		approverVM := models.CmApprover{}
		approverVM.AuditId = item
		approverVM.AuditOrder = i + 2 + len(auditors)
		approverVM.Progress = 2
		approverVM.BidsectionId = bid
		approverVM.ProjectId = pid
		approverVM.DataType = dataType
		approverVM.DataId = dataId
		approverVM.CreateTime = time.Now()
		data = append(data, approverVM)

		// 消息推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = item
		msgVM.BidsectionId = bid
		msgVM.ProjectId = pid
		msgVM.DataId = dataId
		msgVM.DataType = 1
		msgVM.Content = content
		msgVM.Title = title
		msgVM.CreateTime = time.Now()
		msg = append(msg, msgVM)
	}
	// 再推送自己
	msgVM := models.CmProjectMessage{}
	msgVM.AccountId = cur_uid
	msgVM.BidsectionId = bid
	msgVM.ProjectId = pid
	msgVM.DataId = dataId
	msgVM.DataType = 1
	msgVM.Content = content
	msgVM.Title = title
	msgVM.CreateTime = time.Now()
	msg = append(msg, msgVM)
	_, err = d.engine.Insert(data)
	_, err = d.engine.Insert(msg)

	return err
}

// 更改状态
func (d *ApproverDao) ChangeStatus(id int, status int) error {
	data := &models.CmApprover{Status: status}
	_, err := d.engine.Where("id = ?", id).Cols("status").Update(data)
	return err
}

// 更改审批人
func (d *ApproverDao) ChangeAuditId(bid int, dataType int, dataId int, auditOrder int, uid int) error {
	data := &models.CmApprover{AuditId: uid}
	_, err := d.engine.Where("bidsection_id = ? and data_type = ? and data_id = ? and audit_order = ?", bid, dataType, dataId, auditOrder).Cols("audit_id").Update(data)
	return err
}

// 更改下一个审批人的状态
func (d *ApproverDao) ChangeNextStatus(id int, status int) error {
	data := &models.CmApprover{Id: id}
	_, err := d.engine.Get(data)
	newData := &models.CmApprover{Status: status}
	_, err = d.engine.Where("bidsection_id = ? and data_type = ? and data_id = ? and audit_order = ?", data.BidsectionId, data.DataType, data.DataId, data.AuditOrder+1).Cols("status").Update(newData)
	return err
}

// 根据当前times，获取审批流程(包括原报)
func (d *ApproverDao) GetAuditorsWithOwner(bid int, dataType int, dataId int, cur_uid int) []viewmodels.Auditors {
	auditors := make([]viewmodels.Auditors, 0)
	auditor := viewmodels.Auditors{Progress: "", Id: "0", Status: 2}

	_, err := d.engine.Sql("select name, company, position, mobile, id as `audit_id` from `cm_project_account` where id = ?", cur_uid).Get(&auditor)

	if err != nil {
		fmt.Println(err)
	}
	auditors = append(auditors, auditor)

	d.engine.Sql("select pa.`company`, pa.`name`, pa.`account_group`,pa.`mobile`, pa.`position`,ca.`audit_id` as `audit_id`, ca.`id`, ca.`status`, ca.`audit_order`, ca.`progress` from `cm_project_account` as pa, `cm_approver` as ca where ca.`bidsection_id` = ? and ca.`data_type` = ? and ca.`data_id` = ? and ca.audit_id = pa.id order by `audit_order`", bid, dataType, dataId).Find(&auditors)
	// 原报
	return auditors
}

func (d *ApproverDao) FindApproverById(id int) (*models.CmApprover, error) {
	data := &models.CmApprover{}
	_, err := d.engine.ID(id).Get(data)
	return data, err
}

// 获取最新的审核人
func (d *ApproverDao) GetLastedAuditor(bid int, dataType int, dataId int) *viewmodels.Approver {
	data := &models.CmApprover{BidsectionId: bid, DataType: dataType, DataId: dataId, Status: 1}
	has, _ := d.engine.Get(data)
	approverVM := &viewmodels.Approver{}
	if has == true {
		id, _ := comm.AesEncrypt(strconv.Itoa(data.Id), conf.SignSecret)
		approverVM.Id = id
		pid, _ := comm.AesEncrypt(strconv.Itoa(data.ProjectId), conf.SignSecret)
		approverVM.ProjectId = pid
		bid, _ := comm.AesEncrypt(strconv.Itoa(data.BidsectionId), conf.SignSecret)
		approverVM.BidsectionId = bid
		dataId, _ := comm.AesEncrypt(strconv.Itoa(data.DataId), conf.SignSecret)
		approverVM.DataId = dataId
		auditId, _ := comm.AesEncrypt(strconv.Itoa(data.AuditId), conf.SignSecret)
		approverVM.AuditId = auditId
		approverVM.AuditOrder = data.AuditOrder
		approverVM.DataType = data.DataType
		approverVM.Progress = strconv.Itoa(data.Progress)
		approverVM.Status = data.Status
	}
	return approverVM
}

// 获取最后一个审批人
func (d *ApproverDao) GetLastAuditor(bid int, dataType int, dataId int) (*models.CmApprover, error) {
	data := &models.CmApprover{BidsectionId: bid, DataType: dataType, DataId: dataId}
	_, err := d.engine.Desc("audit_order").Limit(1).Get(data)
	return data, err
}

// 初始化审批流程状态
func (d *ApproverDao) InitStatus(auditType string, bid int, dataType int, dataId int, auditId int, times int, progress int, opinion string) error {
	session := d.engine.NewSession()
	defer session.Close()
	err := session.Begin()
	if err != nil {
		return errors.New("操作失败-db")
	}

	// 消息推送，先删除旧的推送
	_, err = session.Exec("delete from cm_project_message where data_type = ? and data_id = ?", auditType, dataId)
	if err != nil {
		session.Rollback()
		return err
	}
	approvers := make([]models.CmApprover, 0)
	err = session.Where("data_type = ? and data_id = ? and audit_id != 0", dataType, dataId).Find(&approvers)
	if err != nil {
		session.Rollback()
		return err
	}

	data := &models.CmApprover{Status: 0}
	_, err = session.Where("bidsection_id = ? and data_type = ? and data_id = ?", bid, dataType, dataId).Cols("status").Update(data)
	if err != nil {
		session.Rollback()
		return err
	}
	if auditType == "safe" {
		safe := &models.CmSafe{}
		_, err = session.ID(dataId).Get(safe)
		if err != nil {
			session.Rollback()
			return err
		}

		account := &models.CmProjectAccount{Id: safe.Uid}
		_, err = d.engine.Get(account)
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)
		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|审批退回到上报人", safe.Code, safe.InspectionDetail)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = safe.Uid
		msgVM.BidsectionId = safe.BidsectionId
		msgVM.ProjectId = safe.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = safe.Id
		msgVM.DataType = 1
		msgVM.Content = fmt.Sprintf("%s|%s|审批退回到上报人", safe.Code, safe.InspectionDetail)
		msgVM.Title = title
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}
		_, err = session.Exec("update cm_safe set status = ?, times = ? where id = ?", 0, times+1, dataId)
		if err != nil {
			session.Rollback()
			return err
		}
		// 增加审批日志
		safeAudit := &models.CmSafeAudit{BidsectionId: bid, SafeId: dataId, Times: times, AuditId: auditId, Status: 1, Progress: progress, CreateTime: time.Now(), Opinion: opinion}
		_, err = session.Insert(safeAudit)
		if err != nil {
			session.Rollback()
			return err
		}
		// 说明本身除于整改人流程，退回原报，要将整改总数-1，未整改总数+1
		if progress-1 != 0 {
			_, err = session.Exec("update cm_tree set safe_rectification = safe_rectification + 1, safe_rectification_in = if(safe_rectification_in >= 1, safe_rectification_in - 1, 0) where bidsection_id = ?", bid)
		}
	} else {
		quality := &models.CmQuality{}
		_, err = session.ID(dataId).Get(quality)
		if err != nil {
			session.Rollback()
			return err
		}

		account := &models.CmProjectAccount{Id: quality.Uid}
		_, err = d.engine.Get(account)
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)
		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|审批退回到上报人", quality.Code, quality.InspectionDetail)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = quality.Uid
		msgVM.BidsectionId = quality.BidsectionId
		msgVM.ProjectId = quality.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = quality.Id
		msgVM.DataType = 1
		msgVM.Content = fmt.Sprintf("%s|%s|审批退回到上报人", quality.Code, quality.InspectionDetail)
		msgVM.Title = title
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}
		_, err = session.Exec("update cm_quality set status = ?, times = ? where id = ?", 0, times+1, dataId)
		if err != nil {
			session.Rollback()
			return err
		}
		// 增加审批日志
		qualityAudit := &models.CmQualityAudit{BidsectionId: bid, QualityId: dataId, Times: times, AuditId: auditId, Status: 1, Progress: progress, CreateTime: time.Now(), Opinion: opinion}
		_, err = session.Insert(qualityAudit)
		if err != nil {
			session.Rollback()
			return err
		}
		if progress-1 != 0 {
			_, err = session.Exec("update cm_tree set quality_rectification = quality_rectification + 1, quality_rectification_in = if(quality_rectification_in >= 1, quality_rectification_in - 1, 0) where bidsection_id = ?", bid)
		}
	}

	err = session.Commit()
	return err
}

// 审批通过
func (d *ApproverDao) PassHandler(auditType string, id int, uid int, auditId int, opinion string, content string, rectifiedTime string) error {
	session := d.engine.NewSession()
	defer session.Close()
	// add Begin() before any action
	err := session.Begin()
	auditor, err := d.FindApproverById(id)
	if err != nil {
		return err
	}
	if auditor.AuditId != uid {
		return errors.New("该用户没有审批权限")
	}

	var msgContent string
	switch auditor.Progress {
	case 0:
		msgContent = "审批完成，待整改"
	case 1:
		msgContent = "整改完成，待复查"
	case 2:
		msgContent = "复查完成"
	}
	// 消息推送，先删除旧的推送
	_, err = session.Exec("delete from cm_project_message where data_type = ? and data_id = ?", auditor.DataType, auditor.DataId)
	if err != nil {
		session.Rollback()
		return err
	}
	approvers := make([]models.CmApprover, 0)
	err = session.Where("data_type = ? and data_id = ? and audit_id != 0", auditor.DataType, auditor.DataId).Find(&approvers)
	if err != nil {
		session.Rollback()
		return err
	}

	// 安全巡检
	if auditType == "safe" {
		safe := &models.CmSafe{}
		_, err = session.ID(auditor.DataId).Get(safe)
		if err != nil {
			session.Rollback()
			return err
		}

		account := &models.CmProjectAccount{Id: safe.Uid}
		_, err = d.engine.Get(account)
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)
		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|%s", msgContent, safe.Code, safe.InspectionDetail)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = safe.Uid
		msgVM.BidsectionId = safe.BidsectionId
		msgVM.ProjectId = safe.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = safe.Id
		msgVM.DataType = 1
		msgVM.Content = fmt.Sprintf("%s|%s|%s", msgContent, safe.Code, safe.InspectionDetail)
		msgVM.Title = title
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}
		// 增加审批日志
		auditReacord := &models.CmSafeAudit{BidsectionId: auditor.BidsectionId, SafeId: auditor.DataId, AuditId: auditor.AuditId, Times: safe.Times, CreateTime: time.Now(), Status: 0, Progress: auditor.Progress + 1, Opinion: opinion}
		_, err = session.Insert(auditReacord)
		if err != nil {
			session.Rollback()
			return err
		}
		// 改变审批流程中当前审批人以及下一个审批人的审批流程状态
		curData := &models.CmApprover{Status: 2}
		_, err = session.ID(id).Cols("status").Update(curData)
		if err != nil {
			session.Rollback()
			return err
		}
		nextData := &models.CmApprover{Status: 1}
		_, err = session.Where("bidsection_id = ? and data_type = ? and data_id = ? and audit_order = ?", auditor.BidsectionId, auditor.DataType, auditor.DataId, auditor.AuditOrder+1).Cols("status").Update(nextData)
		if err != nil {
			session.Rollback()
			return err
		}
		if auditId != 0 {
			// 审批人选择了整改人
			// 修改cm_safe表的status状态为待整改
			_, err = session.Exec("update `cm_safe` set status = ? where id = ?", 2, auditor.DataId)
			if err != nil {
				session.Rollback()
				return err
			}

			// 将cm_tree的safe_rectification待整改+1
			_, err = session.Exec("update cm_tree set safe_rectification_in = safe_rectification_in + 1, safe_rectification = if(safe_rectification >= 1, safe_rectification - 1, 0) where bidsection_id = ?", auditor.BidsectionId)
			if err != nil {
				session.Rollback()
				return err
			}
			// 改变审批流程中的整改人id, 以及创建时间
			create_time := time.Now().Format(conf.SysTimeform)
			_, err = session.Exec("update `cm_approver` set `audit_id` = ? , `create_time` = ? where `bidsection_id` = ? and `project_id` = ? and `data_type` = ? and `data_id` = ? and `audit_order` = ? limit 1",
				auditId, create_time, auditor.BidsectionId, auditor.ProjectId, auditor.DataType, auditor.DataId, auditor.AuditOrder+1)
			if err != nil {
				session.Rollback()
				return err
			}
		} else {
			if auditor.Progress == 1 {
				// 整改人审批流程
				// 修改cm_safe表的status状态为待复查
				_, err = session.Exec("update `cm_safe` set status = ? where id = ?", 3, auditor.DataId)
				if err != nil {
					session.Rollback()
					return err
				}

				newRectifiedTime, _ := time.Parse(conf.SysTimeform, rectifiedTime)
				// 将整改单的状态->完成，并且填入整改日期
				rectification := &models.CmRectification{
					BidsectionId:  safe.BidsectionId,
					ProjectId:     safe.ProjectId,
					DataId:        safe.Id,
					DataType:      1,
					AccountId:     auditor.AuditId,
					RectifiedTime: newRectifiedTime,
					CreateTime:    time.Now(),
					Content:       content,
					Status:        1,
					UpdateTime:    time.Now(),
				}
				_, err = session.Insert(rectification)
				if err != nil {
					session.Rollback()
					return err
				}
			} else {
				// 复查流程
				// 查找最后一个审批人
				lastAuditor := &models.CmApprover{BidsectionId: auditor.BidsectionId, DataType: auditor.DataType, DataId: auditor.DataId}
				_, err = session.Desc("audit_order").Limit(1).Get(lastAuditor)
				if err != nil {
					session.Rollback()
					return err
				}
				if lastAuditor.Id == auditor.Id {
					// 说明审批流程已经走完
					_, err = session.Exec("update `cm_safe` set status = ? where id = ?", 4, auditor.DataId)
					if err != nil {
						session.Rollback()
						return err
					}
					// 将cm_tree的safe_rectification_finish待整改+1
					_, err := session.Exec("update cm_tree set safe_rectification_finish = safe_rectification_finish + 1,  safe_rectification_in = if(safe_rectification_in >= 1, safe_rectification_in - 1, 0)where bidsection_id = ?", auditor.BidsectionId)
					if err != nil {
						session.Rollback()
						return err
					}
				}
			}
		}
	} else {
		// 质量巡检
		quality := &models.CmQuality{}
		_, err = session.ID(auditor.DataId).Get(quality)
		if err != nil {
			session.Rollback()
			return err
		}

		account := &models.CmProjectAccount{Id: quality.Uid}
		_, err = d.engine.Get(account)
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)
		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|%s", msgContent, quality.Code, quality.InspectionDetail)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = quality.Uid
		msgVM.BidsectionId = quality.BidsectionId
		msgVM.ProjectId = quality.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = quality.Id
		msgVM.DataType = 1
		msgVM.Content = fmt.Sprintf("%s|%s|%s", msgContent, quality.Code, quality.InspectionDetail)
		msgVM.Title = title
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}

		// 增加审批日志
		auditReacord := &models.CmQualityAudit{BidsectionId: auditor.BidsectionId, QualityId: auditor.DataId, AuditId: auditor.AuditId, Times: quality.Times, CreateTime: time.Now(), Status: 0, Progress: auditor.Progress + 1, Opinion: opinion}
		_, err = session.Insert(auditReacord)
		if err != nil {
			session.Rollback()
			return err
		}
		// 改变审批流程中当前审批人以及下一个审批人的审批流程状态
		curData := &models.CmApprover{Status: 2}
		_, err = session.ID(id).Cols("status").Update(curData)
		if err != nil {
			session.Rollback()
			return err
		}
		nextData := &models.CmApprover{Status: 1}
		_, err = session.Where("bidsection_id = ? and data_type = ? and data_id = ? and audit_order = ?", auditor.BidsectionId, auditor.DataType, auditor.DataId, auditor.AuditOrder+1).Cols("status").Update(nextData)
		if err != nil {
			session.Rollback()
			return err
		}
		if auditId != 0 {
			// 审批人选择了整改人
			// 修改cm_quality表的status状态为待整改
			_, err = session.Exec("update `cm_quality` set status = ? where id = ?", 2, auditor.DataId)
			if err != nil {
				session.Rollback()
				return err
			}

			// 将cm_tree的quality_rectification待整改+1
			_, err = session.Exec("update cm_tree set quality_rectification_in = quality_rectification_in + 1, quality_rectification = if(quality_rectification >= 1, quality_rectification - 1, 0) where bidsection_id = ?", auditor.BidsectionId)
			if err != nil {
				session.Rollback()
				return err
			}
			// 改变审批流程中的整改人id
			create_time := time.Now().Format(conf.SysTimeform)
			_, err = session.Exec("update `cm_approver` set `audit_id` = ?, `create_time` = ? where `bidsection_id` = ? and `project_id` = ? and `data_type` = ? and `data_id` = ? and `audit_order` = ? limit 1", auditId, create_time, auditor.BidsectionId, auditor.ProjectId, auditor.DataType, auditor.DataId, auditor.AuditOrder+1)
			if err != nil {
				session.Rollback()
				return err
			}
		} else {
			if auditor.Progress == 1 {
				// 整改人审批流程
				// 修改cm_quality表的status状态为待复查
				_, err = session.Exec("update `cm_quality` set status = ? where id = ?", 3, auditor.DataId)
				if err != nil {
					session.Rollback()
					return err
				}

				// 将整改单的状态->完成，并且填入整改日期

				newRectifiedTime, err := time.Parse(conf.SysTimeform, rectifiedTime)
				if err != nil {
					session.Rollback()
					return err
				}

				rectification := &models.CmRectification{
					BidsectionId:  quality.BidsectionId,
					ProjectId:     quality.ProjectId,
					DataId:        quality.Id,
					DataType:      2,
					AccountId:     auditor.AuditId,
					CreateTime:    time.Now(),
					RectifiedTime: newRectifiedTime,
					Content:       content,
					Status:        1,
					UpdateTime:    time.Now(),
				}
				_, err = session.Insert(rectification)
				if err != nil {
					session.Rollback()
					return err
				}

			} else {
				// 复查流程
				// 查找最后一个审批人
				lastAuditor := &models.CmApprover{BidsectionId: auditor.BidsectionId, DataType: auditor.DataType, DataId: auditor.DataId}
				_, err = session.Desc("audit_order").Limit(1).Get(lastAuditor)
				if err != nil {
					session.Rollback()
					return err
				}
				if lastAuditor.Id == auditor.Id {
					// 说明审批流程已经走完
					_, err = session.Exec("update `cm_quality` set status = ? where id = ?", 4, auditor.DataId)
					if err != nil {
						session.Rollback()
						return err
					}
					// 将cm_tree的quality_rectification_finish待整改+1
					_, err := session.Exec("update cm_tree set quality_rectification_finish = quality_rectification_finish + 1, quality_rectification_in = if(quality_rectification_in >= 1, quality_rectification_in - 1, 0) where bidsection_id = ?", auditor.BidsectionId)
					if err != nil {
						session.Rollback()
						return err
					}
				}
			}
		}
	}

	err = session.Commit()
	return err
}

// 审批流程-退回
func (d *ApproverDao) BackHandlerWithId(auditType string, id int, uid int, times int, progress int, opinion string) error {
	session := d.engine.NewSession()
	defer session.Close()
	err := session.Begin()

	auditor := &models.CmApprover{}
	_, err = session.ID(id).Get(auditor)

	// 更改safe/quality表的记录
	data := &models.CmApprover{Status: 0}

	// 将往后的所有记录的status改为0
	_, err = session.Where("bidsection_id = ? and data_type = ? and data_id = ? and audit_order > ?", auditor.BidsectionId, auditor.DataType, auditor.DataId, auditor.AuditOrder).Cols("status").Update(data)
	if err != nil {
		session.Rollback()
		return err
	}
	// 获取改账号的信息
	account := &models.CmProjectAccount{Id: auditor.AuditId}
	_, err = session.Get(account)
	if err != nil {
		session.Rollback()
		return err
	}
	// 将当前的记录改为1-待审批
	data.Status = 1
	_, err = session.ID(id).Cols("status").Update(data)
	if err != nil {
		session.Rollback()
		return err
	}

	// 消息推送，先删除旧的推送
	_, err = session.Exec("delete from cm_project_message where data_type = ? and data_id = ?", auditor.DataType, auditor.DataId)
	if err != nil {
		session.Rollback()
		return err
	}
	approvers := make([]models.CmApprover, 0)
	err = session.Where("data_type = ? and data_id = ? and audit_id != 0", auditor.DataType, auditor.DataId).Find(&approvers)
	if err != nil {
		session.Rollback()
		return err
	}

	// 增加审批日志
	if auditType == "safe" {
		safe := &models.CmSafe{}
		_, err = session.ID(auditor.DataId).Get(safe)
		if err != nil {
			session.Rollback()
			return err
		}
		safe.Status = auditor.Progress + 1
		_, err = session.Where("id = ? and bidsection_id = ?", safe.Id, safe.BidsectionId).Limit(1).Update(safe)
		if err != nil {
			session.Rollback()
			return err
		}
		account := &models.CmProjectAccount{Id: safe.Uid}
		_, err = d.engine.Get(account)
		if err != nil {
			session.Rollback()
			return err
		}
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)

		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|审批退回，退回至%s", safe.Code, safe.InspectionDetail, account.Name)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = safe.Uid
		msgVM.BidsectionId = safe.BidsectionId
		msgVM.ProjectId = safe.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = safe.Id
		msgVM.DataType = 1
		msgVM.Content = fmt.Sprintf("%s|%s|审批退回，退回至%s", safe.Code, safe.InspectionDetail, account.Name)
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}

		safeAudit := &models.CmSafeAudit{BidsectionId: auditor.BidsectionId, SafeId: auditor.DataId, Times: times, AuditId: uid, Status: 1, Progress: progress, CreateTime: time.Now(), Opinion: opinion}
		_, err = session.Insert(safeAudit)
		if err != nil {
			session.Rollback()
			return err
		}
	} else {
		quality := &models.CmQuality{}
		_, err = session.ID(auditor.DataId).Get(quality)
		if err != nil {
			session.Rollback()
			return err
		}

		quality.Status = auditor.Progress + 1
		_, err = session.Where("id =? and bidsection_id = ?", quality.Id, quality.BidsectionId).Limit(1).Update(quality)
		if err != nil {
			session.Rollback()
			return err
		}
		account := &models.CmProjectAccount{Id: quality.Uid}
		_, err = d.engine.Get(account)
		if err != nil {
			session.Rollback()
			return err
		}
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)
		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|审批退回，退回至%s", quality.Code, quality.InspectionDetail, account.Name)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = quality.Uid
		msgVM.BidsectionId = quality.BidsectionId
		msgVM.ProjectId = quality.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = quality.Id
		msgVM.DataType = 2
		msgVM.Content = fmt.Sprintf("%s|%s|审批退回，退回至%s", quality.Code, quality.InspectionDetail, account.Name)
		msgVM.Title = title
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}
		qualityAudit := &models.CmQualityAudit{BidsectionId: auditor.BidsectionId, QualityId: auditor.DataId, Times: times, AuditId: uid, Status: 1, Progress: progress, CreateTime: time.Now(), Opinion: opinion}
		_, err = session.Insert(qualityAudit)
		if err != nil {
			session.Rollback()
			return err
		}
	}
	curAuditor := &models.CmApprover{}
	_, err = session.ID(uid).Get(curAuditor)
	if err != nil {
		session.Rollback()
		return err
	}
	// 当前审批人是整改或者复查流程的并且退回的是审批流程的
	if curAuditor.Progress >= 1 && auditor.Progress == 0 {
		var sql string
		if auditType == "safe" {
			sql = "update cm_tree set safe_rectification = safe_rectification_in + 1 and safe_rectification_in = if(safe_rectification_in >= 1, safe_rectification_in - 1, 0) where bidsection_id = ?"
		} else {
			sql = "update cm_tree set quality_rectification = quality_rectification_in + 1 and quality_rectification_in = if(quality_rectification_in >= 1, quality_rectification_in - 1, 0) where bidsection_id = ?"
		}
		_, err = session.Exec(sql, auditor.BidsectionId)
		if err != nil {
			session.Rollback()
			return err
		}
	}

	err = session.Commit()
	return err
}

func (d *ApproverDao) CloseHandler(auditType string, id int, opinion string, curUid int, saveId int) error {
	session := d.engine.NewSession()
	defer session.Close()
	// add Begin() before any action
	err := session.Begin()
	auditor, err := d.FindApproverById(id)
	if auditor.AuditId != curUid {
		return errors.New("该用户没有审批权限!")
	}

	// 消息推送，先删除旧的推送
	_, err = session.Exec("delete from cm_project_message where data_type = ? and data_id = ?", auditor.DataType, auditor.DataId)
	if err != nil {
		session.Rollback()
		return err
	}
	approvers := make([]models.CmApprover, 0)
	err = session.Where("data_type = ? and data_id = ? and audit_id != 0", auditor.DataType, auditor.DataId).Find(&approvers)
	if err != nil {
		session.Rollback()
		return err
	}

	if auditType == "safe" {
		safe := &models.CmSafe{}
		_, err = session.ID(saveId).Get(safe)
		if err != nil {
			session.Rollback()
			return err
		}

		account := &models.CmProjectAccount{Id: safe.Uid}
		_, err = d.engine.Get(account)
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)
		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|已关闭，停止审批流程", safe.Code, safe.InspectionDetail)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = safe.Uid
		msgVM.BidsectionId = safe.BidsectionId
		msgVM.ProjectId = safe.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = safe.Id
		msgVM.DataType = 1
		msgVM.Content = fmt.Sprintf("%s|%s|已关闭，停止审批流程", safe.Code, safe.InspectionDetail)
		msgVM.Title = title
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}

		// 增加审批日志
		safeAudit := &models.CmSafeAudit{BidsectionId: auditor.BidsectionId, SafeId: auditor.DataId, Times: safe.Times, AuditId: auditor.AuditId, Status: 2, Progress: auditor.Progress, CreateTime: time.Now(), Opinion: opinion}
		_, err = session.Insert(safeAudit)
		if err != nil {
			session.Rollback()
			return err
		}
		// 更改cm_safe的记录
		_, err = session.Exec("update `cm_safe` set status = ? where id = ? ", 5, saveId)
		if err != nil {
			session.Rollback()
			return err
		}
	} else {
		quality := &models.CmQuality{}
		_, err = session.ID(saveId).Get(quality)
		if err != nil {
			session.Rollback()
			return err
		}

		account := &models.CmProjectAccount{Id: quality.Uid}
		_, err = d.engine.Get(account)
		title := fmt.Sprintf("%s - %s", account.Name, account.Position)

		msg := make([]models.CmProjectMessage, 0)
		for _, item := range approvers {
			msgVM := models.CmProjectMessage{}
			msgVM.AccountId = item.AuditId
			msgVM.BidsectionId = item.BidsectionId
			msgVM.ProjectId = item.ProjectId
			msgVM.CreateTime = time.Now()
			msgVM.DataId = item.DataId
			msgVM.DataType = item.DataType
			msgVM.Content = fmt.Sprintf("%s|%s|已关闭，停止审批流程", quality.Code, quality.InspectionDetail)
			msgVM.Title = title
			msg = append(msg, msgVM)
		}

		// 添加巡检拥有者的推送
		msgVM := models.CmProjectMessage{}
		msgVM.AccountId = quality.Uid
		msgVM.BidsectionId = quality.BidsectionId
		msgVM.ProjectId = quality.ProjectId
		msgVM.CreateTime = time.Now()
		msgVM.DataId = quality.Id
		msgVM.DataType = 2
		msgVM.Content = fmt.Sprintf("%s|%s|已关闭，停止审批流程", quality.Code, quality.InspectionDetail)
		msgVM.Title = title
		msg = append(msg, msgVM)

		// 插入消息
		_, err = session.Insert(msg)
		if err != nil {
			session.Rollback()
			return err
		}
		// 增加审批日志
		qualityAudit := &models.CmQualityAudit{BidsectionId: auditor.BidsectionId, QualityId: auditor.DataId, Times: quality.Times, AuditId: auditor.AuditId, Status: 2, Progress: auditor.Progress, CreateTime: time.Now(), Opinion: opinion}
		_, err = session.Insert(qualityAudit)
		if err != nil {
			session.Rollback()
			return err
		}
		// 更改cm_quality的记录
		_, err = session.Exec("update `cm_quality` set status = ? where id = ? ", 5, saveId)
		if err != nil {
			session.Rollback()
			return err
		}
	}
	// 更改cm_approver的记录
	_, err = session.Exec("update `cm_approver` set status = ? where id = ? ", 3, id)
	if err != nil {
		session.Rollback()
		return err
	}

	err = session.Commit()
	return err
}

// 删除旧的审批流程
func (d *ApproverDao) DeleteOldAuditors(bid int, dataType int, dataId int) error {
	data := &models.CmApprover{BidsectionId: bid, DataType: dataType, DataId: dataId}
	_, err := d.engine.Delete(data)
	return err
}

func (d *ApproverDao) GetStatusByProjectAndAccount(projectId int, projectAccountId int, status int) []models.CmApprover {
	datalist := make([]models.CmApprover, 0)
	_ = d.engine.
		Where("project_id = ? and audit_id= ? and status=? ", projectId, projectAccountId, status).
		Desc("id").
		Find(&datalist)
	return datalist
}

func (d *ApproverDao) GetDataIdByProgress(dataId int, dataType int, progress int) *models.CmApprover {
	data := &models.CmApprover{}
	_, err := d.engine.
		Where(" data_id=? and  data_type=? and progress=? ", dataId, dataType, progress).
		Get(data)
	if err != nil {
		data.Id = 0
		return data
	}
	return data
}
