作者 yangfu

机会提交审核

... ... @@ -4,6 +4,7 @@ import (
"encoding/json"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"opp/protocol"
"opp/services/chance"
"opp/services/message"
)
... ... @@ -52,3 +53,24 @@ func (this *H5Controller) AnnouncementSubmit() {
header := GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(message.H5AnnouncementSubmit(header, request))
}
//ChanceExample 示例
//@router /chanceExample [post]
func (this *H5Controller) ChanceExample() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *protocol.ChanceExampleRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(chance.ChanceExample(header, request))
}
... ...
... ... @@ -180,6 +180,6 @@ func ExecuteSQLWithOrmer(o orm.Ormer, sqlstr string, param ...interface{}) error
return err
}
num, _ := r.RowsAffected()
log.Debug("RowsAffected:%d", num)
log.Debug(fmt.Sprintf("RowsAffected:%d", num))
return nil
}
... ...
... ... @@ -58,3 +58,10 @@ func JoinInt8s(ids []int8, spilt string) string {
}
return strings.Join(idStrings, spilt)
}
func JoinInt64s(ids []int64, spilt string) string {
var idStrings []string = make([]string, len(ids))
for i := 0; i < len(ids); i++ {
idStrings[i] = fmt.Sprintf("%v", ids[i])
}
return strings.Join(idStrings, spilt)
}
... ...
... ... @@ -35,7 +35,7 @@ func init() {
log.Fatal("connect to redis error address:", beego.AppConfig.String("redis_add_port"), beego.AppConfig.String("redis_auth"), err)
//panic(err)
}
dataSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?loc=Asia%%2FShanghai",
dataSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?loc=Asia%%2FShanghai&charset=utf8mb4",
beego.AppConfig.String("mysql_user"),
beego.AppConfig.String("mysql_password"),
beego.AppConfig.String("mysql_host"),
... ...
... ... @@ -2,6 +2,7 @@ package models
import (
"fmt"
"opp/internal/utils"
"time"
"github.com/astaxie/beego/orm"
... ... @@ -93,3 +94,23 @@ func GetAuditFlowProcessBy(processId, uid int64) (v *AuditFlowProcess, err error
}
return nil, err
}
//当前审批批次已经结束 唤醒下一批次审批人
func UpdatetAuditFlowProcessToNext(chanceId int64, level int, uids []int64) (err error) {
o := orm.NewOrm()
sql := "update audit_flow_process set enable_status =1,is_active=1,update_at=now() where chance_id=? and level=? and uid in (?)"
if err = utils.ExecuteSQLWithOrmer(o, sql, chanceId, level, utils.JoinInt64s(uids, ",")); err != nil {
return
}
return
}
//或签 有一人已经通过 同批次在审核状态置为无效
func UpdatetAuditFlowProcessNoApprove(chanceId int64, level int, reviewStatus int) (err error) {
o := orm.NewOrm()
sql := "update audit_flow_process set enable_status =0,is_active=0,update_at=now() where chance_id=? and level=? and review_status=?"
if err = utils.ExecuteSQLWithOrmer(o, sql, chanceId, level, reviewStatus); err != nil {
return
}
return
}
... ...
... ... @@ -90,3 +90,13 @@ func GetAuditTemplates(companyId int64, chanceTypeId int) (v []*AuditTemplate, e
}
return
}
//获取模板示例
func GetAuditTemplateExample(id int64) (v string, err error) {
o := orm.NewOrm()
sql := "select example from audit_template where id=?"
if err = o.Raw(sql, id).QueryRow(&v); err == nil {
return
}
return
}
... ...
... ... @@ -92,14 +92,14 @@ type SympathyActionRequest struct {
type SympathyActionResponse struct {
}
/*ChanceType */
/*ChanceType 机会一级分类请求*/
type ChanceTypeRequest struct {
}
type ChanceTypeResponse struct {
List []*models.ChanceType `json:"list"`
}
/*Templates */
/*Templates 模板列表请求*/
type TemplatesRequest struct {
ChanceTypeId int `json:"chanceTypeId" valid:"Required"`
}
... ... @@ -107,14 +107,17 @@ type TemplatesResponse struct {
Templates []*Template `json:"list"`
}
//模板
type Template struct {
Id int64 `json:"id"`
Name string `json:"name"`
Doc string `json:"doc"`
Icon string `json:"icon"`
FormList []*Form `json:"formList"`
Link string `json:"link"` //示例
}
//表单
type Form struct {
Id int `json:"id"`
Label string `json:"label"`
... ... @@ -124,6 +127,14 @@ type Form struct {
Required int8 `json:"required"`
}
/*ChanceExample*/
type ChanceExampleRequest struct {
TemplateId int `json:"templateId" valid:"Required"`
}
type ChanceExampleResponse struct {
Content string `json:"content"`
}
type ChanceSubmitRequest struct {
Id int64 `json:"id"` // = 0添加 >0 编辑
AuditTemplateId int64 `json:"auditTemplateId" valid:"Required"`
... ...
... ... @@ -39,6 +39,9 @@ var errmessge ErrorMap = map[int]string{
5201: "该机会模板未配置审批人,请选择其他模板",
5202: "该机会已被其他人审批",
5203: "审批服务器操作失败",
//模板相关
5301: "机会模板不存在",
}
const (
... ...
... ... @@ -23,4 +23,12 @@ func init() {
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["opp/controllers:H5Controller"] = append(beego.GlobalControllerRouter["opp/controllers:H5Controller"],
beego.ControllerComments{
Method: "ChanceExample",
Router: `/chanceExample`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
}
... ...
... ... @@ -10,11 +10,55 @@ import (
)
var (
MessageApprove = "提交了一条%v机会消息,需要您审核"
MessageApproving = "提交了一条%v机会消息,需要您审核"
MessageApproveSuccess = "审核通过你提交的%v机会"
MessageApproveReject = "退回您了提交的%v机会"
)
//发送审批消息
func SendApproveMsg(receiverId int64, name string, companyId int64, chanceId int64, chanceTypeId int) (err error) {
func SendApproveMsg(receiverId int64, name string, companyId int64, chanceId int64, chanceTypeId int, reviewStatus int) (err error) {
var (
userMsg *models.UserMsg
chanceType *models.ChanceType
format string
)
switch reviewStatus {
case protocol.ReviewStatusAuditging:
format = MessageApproving
break
case protocol.ReviewStatusReturn:
format = MessageApproveReject
break
case protocol.ReviewStatusPass:
format = MessageApproveSuccess
break
default:
format = MessageApproving
break
}
if chanceType, err = models.GetChanceTypeById(chanceTypeId); err != nil {
return
}
userMsg = &models.UserMsg{
Id: idgen.Next(),
CompanyId: companyId,
ReceiveUserId: receiverId,
MsgType: protocol.MsgTypeAudit,
Message: fmt.Sprintf(format, chanceType.Name),
SourceId: chanceId,
SourceType: protocol.SourceTypeChance,
IsPublic: 0,
CreateAt: time.Now(),
}
if _, err = models.AddUserMsg(userMsg); err != nil {
return
}
logMsg(userMsg, name)
return
}
//发送审批消息
func SendApproveMsgByFormat(receiverId int64, name string, companyId int64, chanceId int64, chanceTypeId int, format string) (err error) {
var (
userMsg *models.UserMsg
chanceType *models.ChanceType
... ... @@ -27,7 +71,7 @@ func SendApproveMsg(receiverId int64, name string, companyId int64, chanceId int
CompanyId: companyId,
ReceiveUserId: receiverId,
MsgType: protocol.MsgTypeAudit,
Message: fmt.Sprintf(MessageApprove, chanceType.Name),
Message: fmt.Sprintf(format, chanceType.Name),
SourceId: chanceId,
SourceType: protocol.SourceTypeChance,
IsPublic: 0,
... ...
... ... @@ -8,8 +8,11 @@ import (
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"io/ioutil"
"net/http"
"opp/internal/utils"
"opp/models"
"opp/protocol"
"opp/services/agg"
"time"
"encoding/json"
)
... ... @@ -60,8 +63,8 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces
if relativeId == 0 {
relativeId = item.ChanceId
}
if _, ok := mapApproves[i]; ok {
approve = mapApproves[i]
if _, ok := mapApproves[item.Level]; ok {
approve = mapApproves[item.Level]
} else {
approveType = item.AuditFlowType
if approveType == protocol.AuditBySpecailUser {
... ... @@ -76,7 +79,7 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces
ApproveType: item.AuditFlowType,
ApproveWay: approveWay,
}
mapApproves[i] = approve
mapApproves[item.Level] = approve
}
if approver, err = models.GetUserByUcid(item.Uid); err != nil {
log.Error(err)
... ... @@ -88,7 +91,7 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces
})
}
request.RelativeId = relativeId
for i := 0; i < len(mapApproves); i++ {
for i := 1; i <= len(mapApproves); i++ {
if v, ok := mapApproves[i]; ok {
request.Approves = append(request.Approves, v)
}
... ... @@ -177,7 +180,7 @@ func (s SuplusApprove) DoRequest(method string, methodType string, request inter
log.Error(e)
return
}
log.Debug(fmt.Sprintf("request-%v request:%v rsp:%v", url, common.AssertJson(request), common.AssertJson(response)))
log.Debug(fmt.Sprintf("request-%v request:%v rsp:%v", url, common.AssertJson(request), string(responseData)))
return
}
... ... @@ -222,6 +225,7 @@ type contentItem struct {
ApproveInstanceId int `json:"approveInstanceId"` //审批实例-id
ApproveProcessId int `json:"approveProcessId"` //审批进程节点-id
RelativeId int `json:"relativeId"` //机会编号
MsgApproveStatus int `json:"msgApproveStatus"` //审核状态
}
type receiverInfo struct {
ReceiverUid int64 `json:"receiverUid"` //用户id
... ... @@ -239,9 +243,12 @@ type ApproveItemRequest struct {
ExtendRelativeId int64 `json:"extendRelativeId"` //业务管理id
}
type ApproveItemResponse struct {
Status int `json:"status"` //状态1-待确认2-已确认3-已驳回4-已撤回
ApproveStatus int `json:"approveStatus"` //审批状态0 待审批 1 审批中 2 同意 3 驳回 4 提交订单 5 已被其他人处理 (0这个状态不存在审批后)
IsApprove int `json:"isApprove"` //是否需要审批 1是 0 否
MessageData ApproveMessageItem `json:"messageData"`
IsOver int `json:"isOver"` //是否结束1
}
type ApproveMessageItem struct {
ApproveMessage []MessageDataItem `json:"approveMessage"`
ApplyUserMessage []MessageDataItem `json:"applyUserMessage"`
}
/*ApproveIntegrate 审核列表*/
... ... @@ -284,8 +291,8 @@ func ChanceApprove(header *protocol.RequestHeader, request *protocol.ChanceAppro
err = protocol.NewErrWithMessage(5202)
return
}
if process.ReviewStatus != protocol.ReviewStatusAuditging {
log.Error(fmt.Sprintf("已被审核 %v", process.Id))
if chance.ReviewStatus != protocol.ReviewStatusAuditging {
log.Error(fmt.Sprintf("机会已经被审核 chance_id:%v review_status:%v", chance.Id, chance.ReviewStatus))
err = protocol.NewErrWithMessage(5202)
return
}
... ... @@ -295,18 +302,74 @@ func ChanceApprove(header *protocol.RequestHeader, request *protocol.ChanceAppro
err = protocol.NewErrWithMessage(5203)
return
}
if err = utils.UpdateTableByMap(process, map[string]interface{}{
"ReviewStatus": int8(request.ReviewStatus), "ApproveTime": time.Now()}); err != nil {
log.Error("更新机会审核状态失败 process_id:", process.Id, err)
return
}
log.Info(fmt.Sprintf("用户%v 更新机会审核状态 process_id:%v 状态:%v", header.UserId, process.Id, request.ReviewStatus))
{
if approveItemResponse.IsApprove == 0 {
//更新下一批次的审核人
var nextApprovers []int64
if approveItemResponse.IsOver == 1 {
//结束审批
if err = utils.UpdateTableByMap(chance, map[string]interface{}{
"ReviewStatus": int8(request.ReviewStatus), "AuditLevel": chance.AuditLevel + 1}); err != nil {
log.Error("更新机会审核状态失败 chance_id:", chance.Id, err)
return
}
//发送审核结果消息给提交人
for i := range approveItemResponse.MessageData.ApplyUserMessage {
message := approveItemResponse.MessageData.ApplyUserMessage[i]
nextApprovers = append(nextApprovers, message.ReceiverInfo.ReceiverUid)
if err = agg.SendApproveMsg(message.ReceiverInfo.ReceiverUid, message.ReceiverInfo.ReceiverName,
header.CompanyId, chance.Id, chance.ChanceTypeId, request.ReviewStatus); err != nil {
log.Error(err)
return
}
}
} else {
//发送下一个消息给下一流程的审核人
for i := range approveItemResponse.MessageData.ApproveMessage {
message := approveItemResponse.MessageData.ApproveMessage[i]
nextApprovers = append(nextApprovers, message.ReceiverInfo.ReceiverUid)
if err = agg.SendApproveMsg(message.ReceiverInfo.ReceiverUid, message.ReceiverInfo.ReceiverName,
header.CompanyId, chance.Id, chance.ChanceTypeId, protocol.ReviewStatusAuditging); err != nil {
log.Error(err)
return
}
}
//更新下一批次的审核人 同批次的为审核的状态置为无效
if len(nextApprovers) != 0 {
if err = models.UpdatetAuditFlowProcessToNext(chance.Id, chance.AuditLevel+1, nextApprovers); err != nil {
log.Error(err)
log.Info(fmt.Sprintf("更新机会失败 chance_id:%v 下一批次审批人员:%v", chance.Id, nextApprovers))
return
}
log.Info(fmt.Sprintf("更新机会 chance_id:%v 下一批次审批人员:%v", chance.Id, nextApprovers))
if err = models.UpdatetAuditFlowProcessNoApprove(chance.Id, chance.AuditLevel, protocol.ReviewStatusAuditging); err != nil {
log.Error(err)
return
}
}
}
//更新审批节点审核信息
//更新机会
//发送下一个消息给下一流程的审核人
}
rsp = &protocol.ChanceApproveResponse{}
return
}
/*ProcessIntegrate */
type ProcessIntegrateRequest struct {
}
type ProcessIntegrateResponse struct {
}
func ProcessIntegrate(header *protocol.RequestHeader, request *ProcessIntegrateRequest) (rsp *ProcessIntegrateResponse, err error) {
var ()
rsp = &ProcessIntegrateResponse{}
return
}
//系统审核状态转为审核类型 reviewStatus - > approveType
func ConverReviewStatus(reviewStatus int) (approveType int) {
if reviewStatus == protocol.ReviewStatusPass {
... ...
... ... @@ -190,6 +190,7 @@ func Templates(header *protocol.RequestHeader, request *protocol.TemplatesReques
Icon: item.Icon,
Doc: item.Doc,
FormList: make([]*protocol.Form, len(forms)),
Link: fmt.Sprintf("%v?templateId=%v", item.Id),
}
for j := range forms {
form := forms[j]
... ... @@ -212,6 +213,20 @@ func checkTemplateIsVisible(header *protocol.RequestHeader, template *models.Aud
return
}
//模板示例
func ChanceExample(header *protocol.RequestHeader, request *protocol.ChanceExampleRequest) (rsp *protocol.ChanceExampleResponse, err error) {
var (
example string
)
if example, err = models.GetAuditTemplateExample(int64(request.TemplateId)); err != nil {
log.Error(request.TemplateId, err)
err = protocol.NewErrWithMessage(5301) //模板不存在
return
}
rsp = &protocol.ChanceExampleResponse{example}
return
}
//提交机会
func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmitRequest) (rsp *protocol.ChanceSubmitResponse, err error) {
var (
... ... @@ -280,7 +295,7 @@ func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmit
for i := range m.MessageData {
message := m.MessageData[i]
if err = agg.SendApproveMsg(message.ReceiverInfo.ReceiverUid, message.ReceiverInfo.ReceiverName,
header.CompanyId, chance.Id, chance.ChanceTypeId); err != nil {
header.CompanyId, chance.Id, chance.ChanceTypeId, protocol.ReviewStatusAuditging); err != nil {
log.Error(err)
orm.Rollback()
return
... ... @@ -501,15 +516,12 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat
AuditFlowType: config.AuditFlowType,
FlowType: config.FlowType,
ActionType: int(config.ActionType),
EnableStatus: 1,
ReviewStatus: protocol.ReviewStatusAuditging,
ReviewStatus: protocol.ReviewStatusAuditging,
}
//if uid==0 && auditConfig.NoApprover==1{//审批人为空 自动通过
// item.
//}
if config.Level == 1 {
item.IsActive = 1
//通知 user_msg
item.EnableStatus = 1
}
log.Info(fmt.Sprintf("生成机会审批流:chance_id:%v audit_id:%v audit_level:%v audit_user:%v action_type:%v", chanceId, item.Id, config.Level, uid, resolveActionType(config.ActionType)))
v = append(v, item)
... ...