作者 yangfu

Merge remote-tracking branch 'origin/dev' into test

@@ -27,13 +27,13 @@ @@ -27,13 +27,13 @@
27 ### 阶段二接口完成进度 27 ### 阶段二接口完成进度
28 |功能|完成状态|时间|接口路径 28 |功能|完成状态|时间|接口路径
29 |---|---|----|----| 29 |---|---|----|----|
30 -|我的机会-我提交的| | | |  
31 -|机会详情| | | | 30 +|我的机会-我提交的| | |/v1/chance/mySubmitChance|
  31 +|机会详情| | |v1/chance/detail|
32 |机会更新| | | | 32 |机会更新| | | |
33 -|机会删除| | | | 33 +|机会删除| | |/v1/chance/delete|
34 |我的机会-我的审核| | | | 34 |我的机会-我的审核| | | |
35 |机会审核(评分/修改公开状态)| | | | 35 |机会审核(评分/修改公开状态)| | | |
36 -|用户评分配置| | | | 36 +|计算发现分| | | |
37 |用户机会权限| | | | 37 |用户机会权限| | | |
38 |机会池| | | | 38 |机会池| | | |
39 |消息-点赞| | |v1/message/msgInteractive| 39 |消息-点赞| | |v1/message/msgInteractive|
@@ -49,7 +49,7 @@ @@ -49,7 +49,7 @@
49 |机会审核消息| | |v1/message/msgInteractive| 49 |机会审核消息| | |v1/message/msgInteractive|
50 |我提交的机会| | | v1/chance/chances| 50 |我提交的机会| | | v1/chance/chances|
51 |我审核的机会| | | v1/chance/chances| 51 |我审核的机会| | | v1/chance/chances|
52 -|机会详情| | | v1/chance/detail| 52 +|机会详情| | | |
53 |待抓住机会列表| | |v1/chance/chances| 53 |待抓住机会列表| | |v1/chance/chances|
54 |配置-评分| | |v1/config/score| 54 |配置-评分| | |v1/config/score|
55 |机会审核| | |v1/chance/audit| 55 |机会审核| | |v1/chance/audit|
1 appname = opportunity 1 appname = opportunity
2 httpport = 8080 2 httpport = 8080
3 -runmode = "${RUN_MODE||local}" 3 +runmode = "${RUN_MODE||dev}"
4 4
5 #没设置的话 this.Ctx.Input.RequestBody 没有值 5 #没设置的话 this.Ctx.Input.RequestBody 没有值
6 copyrequestbody = true 6 copyrequestbody = true
@@ -10,7 +10,7 @@ copyrequestbody = true @@ -10,7 +10,7 @@ copyrequestbody = true
10 #开启应用内文档开关 10 #开启应用内文档开关
11 EnableDocs = true 11 EnableDocs = true
12 12
13 -include "local.conf" 13 +include "dev.conf"
14 include "dev-online.conf" 14 include "dev-online.conf"
15 include "test.conf" 15 include "test.conf"
16 include "prod.conf" 16 include "prod.conf"
@@ -23,7 +23,7 @@ yunpian_app_key ="0bf6fb10a11a68a95dee80901eb545b5" @@ -23,7 +23,7 @@ yunpian_app_key ="0bf6fb10a11a68a95dee80901eb545b5"
23 #存储 http://ability.fjmaimaimai.com:8080/ 23 #存储 http://ability.fjmaimaimai.com:8080/
24 source_host ="http://mmm-opp-dev.fjmaimaimai.com/" 24 source_host ="http://mmm-opp-dev.fjmaimaimai.com/"
25 source_virtual_path=file/opp 25 source_virtual_path=file/opp
26 -source_path ="${aliyun_file_access||/var/www/opp/file} 26 +source_path =/var/www/opp/file
27 27
28 #网易云信 IM 28 #网易云信 IM
29 net_im_base_url ="https://api.netease.im/nimserver" 29 net_im_base_url ="https://api.netease.im/nimserver"
@@ -37,7 +37,7 @@ user_center_app_key ="39aefef9e22744a3b2d2d3791824ae7b" @@ -37,7 +37,7 @@ user_center_app_key ="39aefef9e22744a3b2d2d3791824ae7b"
37 user_center_app_secret ="cykbjnfqgctn" 37 user_center_app_secret ="cykbjnfqgctn"
38 38
39 #Html5 39 #Html5
40 -h5_host = "https://web-open.fjmaimaimai.com" 40 +h5_host = "https://web-open-test.fjmaimaimai.com"
41 41
42 #审核中心 42 #审核中心
43 suplus_host ="http://suplus-approve-dev.fjmaimaimai.com" 43 suplus_host ="http://suplus-approve-dev.fjmaimaimai.com"
1 -[local] 1 +[dev]
2 #数据库相关 2 #数据库相关
3 mysql_user = "${MYSQL_USER||root}" 3 mysql_user = "${MYSQL_USER||root}"
4 mysql_password = "${MYSQL_PASSWORD||sutianxia2015}" 4 mysql_password = "${MYSQL_PASSWORD||sutianxia2015}"
@@ -38,7 +38,7 @@ user_center_app_secret ="cykbjnfqgctn" @@ -38,7 +38,7 @@ user_center_app_secret ="cykbjnfqgctn"
38 38
39 39
40 #Html5 40 #Html5
41 -h5_host = "https://web-open.fjmaimaimai.com" 41 +h5_host = "https://web-open-test.fjmaimaimai.com"
42 42
43 #审核中心 43 #审核中心
44 suplus_approve_host ="http://suplus-approve-dev.fjmaimaimai.com" 44 suplus_approve_host ="http://suplus-approve-dev.fjmaimaimai.com"
@@ -37,7 +37,7 @@ user_center_app_key ="39aefef9e22744a3b2d2d3791824ae7b" @@ -37,7 +37,7 @@ user_center_app_key ="39aefef9e22744a3b2d2d3791824ae7b"
37 user_center_app_secret ="cykbjnfqgctn" 37 user_center_app_secret ="cykbjnfqgctn"
38 38
39 #Html5 39 #Html5
40 -h5_host = "https://web-open.fjmaimaimai.com" 40 +h5_host = "https://web-open-test.fjmaimaimai.com"
41 41
42 #审核中心 42 #审核中心
43 suplus_host ="http://suplus-approve-test.fjmaimaimai.com" 43 suplus_host ="http://suplus-approve-test.fjmaimaimai.com"
@@ -74,7 +74,6 @@ func (this *BaseController) Valid(obj interface{}) (result bool, msg *protocol.R @@ -74,7 +74,6 @@ func (this *BaseController) Valid(obj interface{}) (result bool, msg *protocol.R
74 } 74 }
75 75
76 func (this *BaseController) Resp(msg *protocol.ResponseMessage) { 76 func (this *BaseController) Resp(msg *protocol.ResponseMessage) {
77 -  
78 this.Data["json"] = msg 77 this.Data["json"] = msg
79 this.ServeJSON() 78 this.ServeJSON()
80 } 79 }
@@ -4,6 +4,7 @@ import ( @@ -4,6 +4,7 @@ import (
4 "encoding/json" 4 "encoding/json"
5 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log" 5 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
6 "opp/protocol" 6 "opp/protocol"
  7 + "opp/services/chance"
7 "opp/services/message" 8 "opp/services/message"
8 ) 9 )
9 10
@@ -52,3 +53,24 @@ func (this *H5Controller) AnnouncementSubmit() { @@ -52,3 +53,24 @@ func (this *H5Controller) AnnouncementSubmit() {
52 header := GetRequestHeader(this.Ctx) 53 header := GetRequestHeader(this.Ctx)
53 msg = protocol.NewReturnResponse(message.H5AnnouncementSubmit(header, request)) 54 msg = protocol.NewReturnResponse(message.H5AnnouncementSubmit(header, request))
54 } 55 }
  56 +
  57 +//ChanceExample 示例
  58 +//@router /chanceExample [post]
  59 +func (this *H5Controller) ChanceExample() {
  60 + var msg *protocol.ResponseMessage
  61 + defer func() {
  62 + this.Resp(msg)
  63 + }()
  64 + var request *protocol.ChanceExampleRequest
  65 + if err := json.Unmarshal(this.ByteBody, &request); err != nil {
  66 + log.Error(err)
  67 + msg = protocol.BadRequestParam(1)
  68 + return
  69 + }
  70 + if b, m := this.Valid(request); !b {
  71 + msg = m
  72 + return
  73 + }
  74 + header := GetRequestHeader(this.Ctx)
  75 + msg = protocol.NewReturnResponse(chance.ChanceExample(header, request))
  76 +}
@@ -294,8 +294,28 @@ func (this *ChanceController) ChanceDetail() { @@ -294,8 +294,28 @@ func (this *ChanceController) ChanceDetail() {
294 msg = protocol.NewReturnResponse(chance.ChanceDetail(header, request)) 294 msg = protocol.NewReturnResponse(chance.ChanceDetail(header, request))
295 } 295 }
296 296
  297 +//ChanceApproveProcess 机会审核流程信息
  298 +//func(this *ChanceController)ChanceApproveProcess(){
  299 +// var msg *protocol.ResponseMessage
  300 +// defer func() {
  301 +// this.Resp(msg)
  302 +// }()
  303 +// var request *protocol.ChanceApproveProcessRequest
  304 +// if err:=json.Unmarshal(this.ByteBody,&request);err!=nil{
  305 +// log.Error(err)
  306 +// msg = protocol.BadRequestParam(1)
  307 +// return
  308 +// }
  309 +// if b,m :=this.Valid(request);!b{
  310 +// msg = m
  311 +// return
  312 +// }
  313 +// header := controllers.GetRequestHeader(this.Ctx)
  314 +// msg = protocol.NewReturnResponse(chance.ChanceApproveProcess(header,request))
  315 +//}
  316 +
297 //ChanceDelete 机会删除 317 //ChanceDelete 机会删除
298 -//@router /chanceDelete [post] 318 +//@router /delete [post]
299 func (this *ChanceController) ChanceDelete() { 319 func (this *ChanceController) ChanceDelete() {
300 var msg *protocol.ResponseMessage 320 var msg *protocol.ResponseMessage
301 defer func() { 321 defer func() {
@@ -316,36 +336,22 @@ func (this *ChanceController) ChanceDelete() { @@ -316,36 +336,22 @@ func (this *ChanceController) ChanceDelete() {
316 } 336 }
317 337
318 //ChanceApprove 机会审核 338 //ChanceApprove 机会审核
319 -//func(this *ChanceController)ChanceApprove(){  
320 -// var msg *protocol.ResponseMessage  
321 -// defer func() {  
322 -// this.Resp(msg)  
323 -// }()  
324 -// var request *protocol.ChanceApproveRequest  
325 -// if err:=json.Unmarshal(this.ByteBody,&request);err!=nil{  
326 -// log.Error(err)  
327 -// msg = protocol.BadRequestParam(1)  
328 -// return  
329 -// }  
330 -// if b,m :=this.Valid(request);!b{  
331 -// msg = m  
332 -// return  
333 -// }  
334 -// header := controllers.GetRequestHeader(this.Ctx)  
335 -// msg = protocol.NewReturnResponse(chance.ChanceApprove(header,request))  
336 -//}  
337 -//  
338 -///*ChanceApprove */  
339 -//type ChanceApproveRequest struct {  
340 -// Xxx string`json:"xxx" valid:"Required"`  
341 -//}  
342 -//type ChanceApproveResponse struct {  
343 -//}  
344 -//  
345 -//func ChanceApprove(header *protocol.RequestHeader,request *protocol.ChanceApproveRequest)(rsp *protocol.ChanceApproveResponse,err error){  
346 -// var (  
347 -//  
348 -// )  
349 -// rsp =&protocol.ChanceApproveResponse{}  
350 -// return  
351 -//} 339 +//@router /approve [post]
  340 +func (this *ChanceController) ChanceApprove() {
  341 + var msg *protocol.ResponseMessage
  342 + defer func() {
  343 + this.Resp(msg)
  344 + }()
  345 + var request *protocol.ChanceApproveRequest
  346 + if err := json.Unmarshal(this.ByteBody, &request); err != nil {
  347 + log.Error(err)
  348 + msg = protocol.BadRequestParam(1)
  349 + return
  350 + }
  351 + if b, m := this.Valid(request); !b {
  352 + msg = m
  353 + return
  354 + }
  355 + header := controllers.GetRequestHeader(this.Ctx)
  356 + msg = protocol.NewReturnResponse(chance.ChanceApprove(header, request))
  357 +}
@@ -4,6 +4,7 @@ go 1.12 @@ -4,6 +4,7 @@ go 1.12
4 4
5 require ( 5 require (
6 github.com/astaxie/beego v1.10.0 6 github.com/astaxie/beego v1.10.0
  7 + github.com/disintegration/imaging v1.6.2
7 github.com/go-sql-driver/mysql v1.4.1 8 github.com/go-sql-driver/mysql v1.4.1
8 github.com/gomodule/redigo v1.7.0 9 github.com/gomodule/redigo v1.7.0
9 github.com/gorilla/websocket v1.4.1 10 github.com/gorilla/websocket v1.4.1
@@ -13,7 +14,6 @@ require ( @@ -13,7 +14,6 @@ require (
13 github.com/satori/go.uuid v1.2.0 14 github.com/satori/go.uuid v1.2.0
14 github.com/sony/sonyflake v1.0.0 15 github.com/sony/sonyflake v1.0.0
15 gitlab.fjmaimaimai.com/mmm-go/gocomm v0.0.1 16 gitlab.fjmaimaimai.com/mmm-go/gocomm v0.0.1
16 - golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 // indirect  
17 google.golang.org/appengine v1.6.2 // indirect 17 google.golang.org/appengine v1.6.2 // indirect
18 ) 18 )
19 19
@@ -180,6 +180,6 @@ func ExecuteSQLWithOrmer(o orm.Ormer, sqlstr string, param ...interface{}) error @@ -180,6 +180,6 @@ func ExecuteSQLWithOrmer(o orm.Ormer, sqlstr string, param ...interface{}) error
180 return err 180 return err
181 } 181 }
182 num, _ := r.RowsAffected() 182 num, _ := r.RowsAffected()
183 - log.Debug("RowsAffected:%d", num) 183 + log.Debug(fmt.Sprintf("RowsAffected:%d", num))
184 return nil 184 return nil
185 } 185 }
@@ -58,3 +58,19 @@ func JoinInt8s(ids []int8, spilt string) string { @@ -58,3 +58,19 @@ func JoinInt8s(ids []int8, spilt string) string {
58 } 58 }
59 return strings.Join(idStrings, spilt) 59 return strings.Join(idStrings, spilt)
60 } 60 }
  61 +func JoinInt64s(ids []int64, spilt string) string {
  62 + var idStrings []string = make([]string, len(ids))
  63 + for i := 0; i < len(ids); i++ {
  64 + idStrings[i] = fmt.Sprintf("%v", ids[i])
  65 + }
  66 + return strings.Join(idStrings, spilt)
  67 +}
  68 +
  69 +//判断是否为空
  70 +func IsNil(i interface{}) bool {
  71 + vi := reflect.ValueOf(i)
  72 + if vi.Kind() == reflect.Ptr {
  73 + return vi.IsNil()
  74 + }
  75 + return false
  76 +}
@@ -35,7 +35,7 @@ func init() { @@ -35,7 +35,7 @@ func init() {
35 log.Fatal("connect to redis error address:", beego.AppConfig.String("redis_add_port"), beego.AppConfig.String("redis_auth"), err) 35 log.Fatal("connect to redis error address:", beego.AppConfig.String("redis_add_port"), beego.AppConfig.String("redis_auth"), err)
36 //panic(err) 36 //panic(err)
37 } 37 }
38 - dataSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?loc=Asia%%2FShanghai", 38 + dataSource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?loc=Asia%%2FShanghai&charset=utf8mb4",
39 beego.AppConfig.String("mysql_user"), 39 beego.AppConfig.String("mysql_user"),
40 beego.AppConfig.String("mysql_password"), 40 beego.AppConfig.String("mysql_password"),
41 beego.AppConfig.String("mysql_host"), 41 beego.AppConfig.String("mysql_host"),
@@ -2,6 +2,7 @@ package models @@ -2,6 +2,7 @@ package models
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
  5 + "opp/internal/utils"
5 "time" 6 "time"
6 7
7 "github.com/astaxie/beego/orm" 8 "github.com/astaxie/beego/orm"
@@ -24,6 +25,9 @@ type AuditFlowProcess struct { @@ -24,6 +25,9 @@ type AuditFlowProcess struct {
24 CreateAt time.Time `orm:"column(create_at);type(timestamp)" description:"创建时间"` 25 CreateAt time.Time `orm:"column(create_at);type(timestamp)" description:"创建时间"`
25 UpdateAt time.Time `orm:"column(update_at);type(timestamp)" description:"更新时间"` 26 UpdateAt time.Time `orm:"column(update_at);type(timestamp)" description:"更新时间"`
26 EnableStatus int8 `orm:"column(enable_status)" description:"有效状态 0:无效 1:有效 (被驳回以后,未完成的审核置为无效)"` 27 EnableStatus int8 `orm:"column(enable_status)" description:"有效状态 0:无效 1:有效 (被驳回以后,未完成的审核置为无效)"`
  28 + UserName string `orm:"column(user_name);size(50)" description:"用户名-冗余"`
  29 + RoleName string `orm:"column(role_name);size(50)" description:"角色名-冗余"`
  30 + RoleId int `orm:"column(role_id);size(50)" description:"角色id-冗余"`
27 } 31 }
28 32
29 func (t *AuditFlowProcess) TableName() string { 33 func (t *AuditFlowProcess) TableName() string {
@@ -82,3 +86,54 @@ func DeleteAuditFlowProcess(id int64) (err error) { @@ -82,3 +86,54 @@ func DeleteAuditFlowProcess(id int64) (err error) {
82 } 86 }
83 return 87 return
84 } 88 }
  89 +
  90 +//审核流程编号 按用户编号
  91 +//获取审核流节点
  92 +func GetAuditFlowProcessBy(processId, uid int64) (v *AuditFlowProcess, err error) {
  93 + o := orm.NewOrm()
  94 + sql := "select * from audit_flow_process where id=? and uid=? and enable_status=1"
  95 + if err = o.Raw(sql, processId, uid).QueryRow(&v); err == nil {
  96 + return v, nil
  97 + }
  98 + return nil, err
  99 +}
  100 +
  101 +//当前审批批次已经结束 唤醒下一批次审批人
  102 +func UpdatetAuditFlowProcessToNext(chanceId int64, level int, uids []int64) (err error) {
  103 + o := orm.NewOrm()
  104 + sql := "update audit_flow_process set enable_status =1,is_active=1,update_at=now() where chance_id=? and level=? and uid in (?)"
  105 + if err = utils.ExecuteSQLWithOrmer(o, sql, chanceId, level, utils.JoinInt64s(uids, ",")); err != nil {
  106 + return
  107 + }
  108 + return
  109 +}
  110 +
  111 +//或签 有一人已经通过 同批次在审核状态置为无效
  112 +func UpdatetAuditFlowProcessNoApprove(chanceId int64, level int, reviewStatus int) (err error) {
  113 + o := orm.NewOrm()
  114 + sql := "update audit_flow_process set enable_status =0,is_active=0,update_at=now() where chance_id=? and level=? and review_status=?"
  115 + if err = utils.ExecuteSQLWithOrmer(o, sql, chanceId, level, reviewStatus); err != nil {
  116 + return
  117 + }
  118 + return
  119 +}
  120 +
  121 +//获取机会审核流信息
  122 +func GetAuditFlowProcessList(chanceId int64) (v []*AuditFlowProcess, err error) {
  123 + o := orm.NewOrm()
  124 + sql := "select * from audit_flow_process where chance_id=? and enable_status=1 order by id,review_status"
  125 + if _, err = o.Raw(sql, chanceId).QueryRows(&v); err == nil {
  126 + return v, nil
  127 + }
  128 + return nil, err
  129 +}
  130 +
  131 +//删除机会时关闭所有审核信息
  132 +func CloseAuditFlowProcess(chanceId int64) (err error) {
  133 + o := orm.NewOrm()
  134 + sql := "update audit_flow_process set enable_status =0,is_active=0,update_at=now() where chance_id=?"
  135 + if err = utils.ExecuteSQLWithOrmer(o, sql, chanceId); err != nil {
  136 + return
  137 + }
  138 + return
  139 +}
@@ -90,3 +90,13 @@ func GetAuditTemplates(companyId int64, chanceTypeId int) (v []*AuditTemplate, e @@ -90,3 +90,13 @@ func GetAuditTemplates(companyId int64, chanceTypeId int) (v []*AuditTemplate, e
90 } 90 }
91 return 91 return
92 } 92 }
  93 +
  94 +//获取模板示例
  95 +func GetAuditTemplateExample(id int64) (v string, err error) {
  96 + o := orm.NewOrm()
  97 + sql := "select example from audit_template where id=?"
  98 + if err = o.Raw(sql, id).QueryRow(&v); err == nil {
  99 + return
  100 + }
  101 + return
  102 +}
@@ -30,6 +30,7 @@ type Chance struct { @@ -30,6 +30,7 @@ type Chance struct {
30 ValueSorce float64 `orm:"column(value_sorce);null;digits(4);decimals(1)" description:"价值评分"` 30 ValueSorce float64 `orm:"column(value_sorce);null;digits(4);decimals(1)" description:"价值评分"`
31 DiscoverySorce float64 `orm:"column(discovery_sorce);null;digits(4);decimals(1)" description:"发现得分(发现得分=基础评分*系数 + 附加评分*系数 + 价值评分*系数)"` 31 DiscoverySorce float64 `orm:"column(discovery_sorce);null;digits(4);decimals(1)" description:"发现得分(发现得分=基础评分*系数 + 附加评分*系数 + 价值评分*系数)"`
32 PublishStatus int `orm:"column(publish_status)" description:"公开状态 0未公开、1部门公开、2公司公开"` 32 PublishStatus int `orm:"column(publish_status)" description:"公开状态 0未公开、1部门公开、2公司公开"`
  33 + PublishData string `orm:"column(publish_data)" description:"公开数据 冗余"`
33 AuditLevel int `orm:"column(audit_level)" description:"当前审批步骤"` 34 AuditLevel int `orm:"column(audit_level)" description:"当前审批步骤"`
34 } 35 }
35 36
@@ -38,6 +38,7 @@ const ( @@ -38,6 +38,7 @@ const (
38 ReviewStatusAuditging = 1 //待审核 38 ReviewStatusAuditging = 1 //待审核
39 ReviewStatusReturn = 2 //退回 39 ReviewStatusReturn = 2 //退回
40 ReviewStatusPass = 3 //通过 40 ReviewStatusPass = 3 //通过
  41 + ReviewStatusSubmit = 4 //提交
41 ) 42 )
42 43
43 //公开状态 44 //公开状态
@@ -92,14 +93,14 @@ type SympathyActionRequest struct { @@ -92,14 +93,14 @@ type SympathyActionRequest struct {
92 type SympathyActionResponse struct { 93 type SympathyActionResponse struct {
93 } 94 }
94 95
95 -/*ChanceType */ 96 +/*ChanceType 机会一级分类请求*/
96 type ChanceTypeRequest struct { 97 type ChanceTypeRequest struct {
97 } 98 }
98 type ChanceTypeResponse struct { 99 type ChanceTypeResponse struct {
99 List []*models.ChanceType `json:"list"` 100 List []*models.ChanceType `json:"list"`
100 } 101 }
101 102
102 -/*Templates */ 103 +/*Templates 模板列表请求*/
103 type TemplatesRequest struct { 104 type TemplatesRequest struct {
104 ChanceTypeId int `json:"chanceTypeId" valid:"Required"` 105 ChanceTypeId int `json:"chanceTypeId" valid:"Required"`
105 } 106 }
@@ -107,14 +108,17 @@ type TemplatesResponse struct { @@ -107,14 +108,17 @@ type TemplatesResponse struct {
107 Templates []*Template `json:"list"` 108 Templates []*Template `json:"list"`
108 } 109 }
109 110
  111 +//模板
110 type Template struct { 112 type Template struct {
111 Id int64 `json:"id"` 113 Id int64 `json:"id"`
112 Name string `json:"name"` 114 Name string `json:"name"`
113 Doc string `json:"doc"` 115 Doc string `json:"doc"`
114 Icon string `json:"icon"` 116 Icon string `json:"icon"`
115 FormList []*Form `json:"formList"` 117 FormList []*Form `json:"formList"`
  118 + Link string `json:"link"` //示例
116 } 119 }
117 120
  121 +//表单
118 type Form struct { 122 type Form struct {
119 Id int `json:"id"` 123 Id int `json:"id"`
120 Label string `json:"label"` 124 Label string `json:"label"`
@@ -124,6 +128,14 @@ type Form struct { @@ -124,6 +128,14 @@ type Form struct {
124 Required int8 `json:"required"` 128 Required int8 `json:"required"`
125 } 129 }
126 130
  131 +/*ChanceExample*/
  132 +type ChanceExampleRequest struct {
  133 + TemplateId int `json:"templateId" valid:"Required"`
  134 +}
  135 +type ChanceExampleResponse struct {
  136 + Content string `json:"content"`
  137 +}
  138 +
127 type ChanceSubmitRequest struct { 139 type ChanceSubmitRequest struct {
128 Id int64 `json:"id"` // = 0添加 >0 编辑 140 Id int64 `json:"id"` // = 0添加 >0 编辑
129 AuditTemplateId int64 `json:"auditTemplateId" valid:"Required"` 141 AuditTemplateId int64 `json:"auditTemplateId" valid:"Required"`
@@ -208,7 +220,9 @@ type ChanceDetailRequest struct { @@ -208,7 +220,9 @@ type ChanceDetailRequest struct {
208 } 220 }
209 type ChanceDetailResponse struct { 221 type ChanceDetailResponse struct {
210 ChanceDetail ChanceItem `json:"chanceDetail"` 222 ChanceDetail ChanceItem `json:"chanceDetail"`
211 - ApproveProcess interface{} `json:"approveProcess"` 223 + PublicData *PublicData `json:"publicData"`
  224 + ApproveProcess []*ProcessItem `json:"approveProcess"`
  225 + ApproveAccess *ApproveAccess `json:"approveAccess"` //
212 } 226 }
213 227
214 /*ChanceDelete 机会删除*/ 228 /*ChanceDelete 机会删除*/
1 package protocol 1 package protocol
2 2
  3 +const (
  4 + ApproveTypePass = 2 //审核通过
  5 + ApproveTypeReject = 3 //审核驳回
  6 + //ApproveReturn =4 //审核撤回
  7 +)
  8 +
3 type ApproveProcess struct { 9 type ApproveProcess struct {
4 //RelativeId int64 `json:"relativeId"` 10 //RelativeId int64 `json:"relativeId"`
5 Uid int64 `json:"uid"` 11 Uid int64 `json:"uid"`
@@ -9,3 +15,86 @@ type ApproveProcess struct { @@ -9,3 +15,86 @@ type ApproveProcess struct {
9 Active int `json:"active"` 15 Active int `json:"active"`
10 ApproveTime int64 `json:"approveTime"` //审核时间 16 ApproveTime int64 `json:"approveTime"` //审核时间
11 } 17 }
  18 +
  19 +/*ChanceApprove 机会审核*/
  20 +type ChanceApproveRequest struct {
  21 + Uid int64 `json:"uid"` //TODO:测试使用 注入审核人
  22 + ChanceId int64 `json:"chanceId"` //机会编号
  23 + ProcessId int64 `json:"processId"` //审批流程编号
  24 + ReviewStatus int `json:"reviewStatus"` //protocol.ReviewStatus
  25 + //Suggestion string `json:"suggestion"` //原因/建议
  26 +}
  27 +type ChanceApproveResponse struct {
  28 +}
  29 +
  30 +/*ChanceApproveProcess 机会审核流程信息*/
  31 +type ChanceApproveProcessRequest struct {
  32 + ChanceId int64 `json:"chanceId"`
  33 +}
  34 +type ChanceApproveProcessResponse struct {
  35 + ApproveProcess []*ProcessItem `json:"approveProcess"`
  36 + ApproveAccess *ApproveAccess `json:"approveOperate"`
  37 +}
  38 +
  39 +//进程项
  40 +type ProcessItem struct {
  41 + Id int64 `json:"id"`
  42 + ReviewStatus int `json:"reviewStatus"` //当前步骤审批状态 0-待处理 1- 待审核 2- 退回 3-通过 4-提交 6-撤销
  43 + ApproveWay int `json:"approveWay"` //审批方式 1 会签 2 或签
  44 + ApproveType int `json:"approveType"` //审批类型 1 业务区域负责人 2 指定成员 3 角色
  45 + ApproveTime int64 `json:"approveTime"` //审核时间
  46 + //Role Role `json:"role"` //角色
  47 + Uid int64 `json:"uid"`
  48 + Name string `json:"name"`
  49 + RoleName string `json:"roleName"`
  50 + Role int `json:"-"`
  51 + ApproveData ApproveData `json:"ApproveData"` //审核数据
  52 + //ApproveUser UserItem `json:"approveUser"` //审核人 //状态不是审核中
  53 + ApproveUsers []UserItem `json:"approveUsers"` //审核人员 //1 会签 2 或签 //审核中 1.部门长 2.角色
  54 +}
  55 +
  56 +//用户项
  57 +type UserItem struct {
  58 + Uid int64 `json:"uid"`
  59 + Name string `json:"name"`
  60 +}
  61 +
  62 +//角色项
  63 +type Role struct {
  64 + Id int `json:"id"`
  65 + Name string `json:"name"`
  66 +}
  67 +
  68 +//审核数据 审核通过
  69 +type ApproveData struct {
  70 + PublicData *PublicData `json:"publicData"` // 公开数据
  71 + Score *Score `json:"score"`
  72 +}
  73 +
  74 +//公开数据
  75 +type PublicData struct {
  76 + PublishStatus int `json:"publishStatus"`
  77 + VisibleObjects []*VisibleObject `json:"visibleObject"`
  78 +}
  79 +
  80 +//可见对象
  81 +type VisibleObject struct {
  82 + Id string `json:"id"`
  83 + Name string `json:"name,omitempty"`
  84 + Type int `json:"type"` //1:部门 2:指定人员
  85 +}
  86 +
  87 +//评分
  88 +type Score struct {
  89 + BasicScore int `json:"basicScore"` //基础评分
  90 + ExtraScore int `json:"extraScore"` //额外分
  91 + ValueScore int `json:"valueScore"` //价值分
  92 + DiscoveryScore int `json:"-"` //发现分
  93 +}
  94 +
  95 +//审核操作权限
  96 +type ApproveAccess struct {
  97 + ProcessId int64 `json:"processId"`
  98 + AllowApprove int `json:"allowApprove"`
  99 + AllowReject int `json:"allowReject"`
  100 +}
@@ -37,8 +37,20 @@ var errmessge ErrorMap = map[int]string{ @@ -37,8 +37,20 @@ var errmessge ErrorMap = map[int]string{
37 37
38 //机会审批相关 38 //机会审批相关
39 5201: "该机会模板未配置审批人,请选择其他模板", 39 5201: "该机会模板未配置审批人,请选择其他模板",
  40 + 5202: "该机会已被审批",
  41 + 5203: "审批服务器操作失败",
  42 +
  43 + //模板相关
  44 + 5301: "机会模板不存在",
40 } 45 }
41 46
  47 +const (
  48 + MsgTypeBulletin = 1 //公告
  49 + MsgTypeCommend = 2 //表彰
  50 + MsgTypeInteraction = 4 //互动消息
  51 + MsgTypeAudit = 8 //机会审核
  52 +)
  53 +
42 /*MessageCenter */ 54 /*MessageCenter */
43 type MessageCenterRequest struct { 55 type MessageCenterRequest struct {
44 MsgType int `json:"msgType" valid:"Required"` 56 MsgType int `json:"msgType" valid:"Required"`
@@ -23,4 +23,12 @@ func init() { @@ -23,4 +23,12 @@ func init() {
23 MethodParams: param.Make(), 23 MethodParams: param.Make(),
24 Params: nil}) 24 Params: nil})
25 25
  26 + beego.GlobalControllerRouter["opp/controllers:H5Controller"] = append(beego.GlobalControllerRouter["opp/controllers:H5Controller"],
  27 + beego.ControllerComments{
  28 + Method: "ChanceExample",
  29 + Router: `/chanceExample`,
  30 + AllowHTTPMethods: []string{"post"},
  31 + MethodParams: param.Make(),
  32 + Params: nil})
  33 +
26 } 34 }
@@ -57,6 +57,22 @@ func init() { @@ -57,6 +57,22 @@ func init() {
57 57
58 beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"], 58 beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
59 beego.ControllerComments{ 59 beego.ControllerComments{
  60 + Method: "ChanceApprove",
  61 + Router: `/approve`,
  62 + AllowHTTPMethods: []string{"post"},
  63 + MethodParams: param.Make(),
  64 + Params: nil})
  65 +
  66 + beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
  67 + beego.ControllerComments{
  68 + Method: "ChanceDetail",
  69 + Router: `/chanceDetail`,
  70 + AllowHTTPMethods: []string{"post"},
  71 + MethodParams: param.Make(),
  72 + Params: nil})
  73 +
  74 + beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
  75 + beego.ControllerComments{
60 Method: "ChanceType", 76 Method: "ChanceType",
61 Router: `/chanceType`, 77 Router: `/chanceType`,
62 AllowHTTPMethods: []string{"post"}, 78 AllowHTTPMethods: []string{"post"},
@@ -89,6 +105,14 @@ func init() { @@ -89,6 +105,14 @@ func init() {
89 105
90 beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"], 106 beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
91 beego.ControllerComments{ 107 beego.ControllerComments{
  108 + Method: "ChanceDelete",
  109 + Router: `/delete`,
  110 + AllowHTTPMethods: []string{"post"},
  111 + MethodParams: param.Make(),
  112 + Params: nil})
  113 +
  114 + beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
  115 + beego.ControllerComments{
92 Method: "Favorite", 116 Method: "Favorite",
93 Router: `/favorite`, 117 Router: `/favorite`,
94 AllowHTTPMethods: []string{"post"}, 118 AllowHTTPMethods: []string{"post"},
@@ -26,7 +26,7 @@ func GetUserBaseInfoAggregation(id int64, companyId int64) (v *protocol.UserBase @@ -26,7 +26,7 @@ func GetUserBaseInfoAggregation(id int64, companyId int64) (v *protocol.UserBase
26 return 26 return
27 } 27 }
28 if len(v.UserCompany.NickName) > 0 { 28 if len(v.UserCompany.NickName) > 0 {
29 - v.User.NickName = v.UserCompany.NickName //公司里面的用户名称 29 + v.User.NickName = v.User.NickName
30 } 30 }
31 wg.Add(3) 31 wg.Add(3)
32 go func() { 32 go func() {
  1 +package agg
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/mmm-go/gocomm/identity/idgen"
  6 + "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
  7 + "opp/models"
  8 + "opp/protocol"
  9 + "time"
  10 +)
  11 +
  12 +var (
  13 + MessageApproving = "提交了一条%v机会消息,需要您审核"
  14 + MessageApproveSuccess = "审核通过你提交的%v机会"
  15 + MessageApproveReject = "退回您了提交的%v机会"
  16 +)
  17 +
  18 +//发送审批消息
  19 +func SendApproveMsg(receiverId int64, name string, companyId int64, chanceId int64, chanceTypeId int, reviewStatus int) (err error) {
  20 + var (
  21 + userMsg *models.UserMsg
  22 + chanceType *models.ChanceType
  23 + format string
  24 + )
  25 + switch reviewStatus {
  26 + case protocol.ReviewStatusAuditging:
  27 + format = MessageApproving
  28 + break
  29 + case protocol.ReviewStatusReturn:
  30 + format = MessageApproveReject
  31 + break
  32 + case protocol.ReviewStatusPass:
  33 + format = MessageApproveSuccess
  34 + break
  35 + default:
  36 + format = MessageApproving
  37 + break
  38 + }
  39 + if chanceType, err = models.GetChanceTypeById(chanceTypeId); err != nil {
  40 + return
  41 + }
  42 + userMsg = &models.UserMsg{
  43 + Id: idgen.Next(),
  44 + CompanyId: companyId,
  45 + ReceiveUserId: receiverId,
  46 + MsgType: protocol.MsgTypeAudit,
  47 + Message: fmt.Sprintf(format, chanceType.Name),
  48 + SourceId: chanceId,
  49 + SourceType: protocol.SourceTypeChance,
  50 + IsPublic: 0,
  51 + CreateAt: time.Now(),
  52 + }
  53 + if _, err = models.AddUserMsg(userMsg); err != nil {
  54 + return
  55 + }
  56 + logMsg(userMsg, name)
  57 + return
  58 +}
  59 +
  60 +//发送审批消息
  61 +func SendApproveMsgByFormat(receiverId int64, name string, companyId int64, chanceId int64, chanceTypeId int, format string) (err error) {
  62 + var (
  63 + userMsg *models.UserMsg
  64 + chanceType *models.ChanceType
  65 + )
  66 + if chanceType, err = models.GetChanceTypeById(chanceTypeId); err != nil {
  67 + return
  68 + }
  69 + userMsg = &models.UserMsg{
  70 + Id: idgen.Next(),
  71 + CompanyId: companyId,
  72 + ReceiveUserId: receiverId,
  73 + MsgType: protocol.MsgTypeAudit,
  74 + Message: fmt.Sprintf(format, chanceType.Name),
  75 + SourceId: chanceId,
  76 + SourceType: protocol.SourceTypeChance,
  77 + IsPublic: 0,
  78 + CreateAt: time.Now(),
  79 + }
  80 + if _, err = models.AddUserMsg(userMsg); err != nil {
  81 + return
  82 + }
  83 + logMsg(userMsg, name)
  84 + return
  85 +}
  86 +
  87 +//打印消息日志
  88 +func logMsg(msg *models.UserMsg, name string) {
  89 + log.Info(fmt.Sprintf("发送消息 消息类型:%v Receiver:%v(%v) Message:%v SourceId:%v SourceType:%v",
  90 + msg.MsgType, msg.ReceiveUserId, name, msg.Message, msg.SourceId, msg.SourceType))
  91 +}
@@ -4,12 +4,16 @@ import ( @@ -4,12 +4,16 @@ import (
4 "fmt" 4 "fmt"
5 "github.com/astaxie/beego" 5 "github.com/astaxie/beego"
6 "github.com/astaxie/beego/httplib" 6 "github.com/astaxie/beego/httplib"
  7 + "github.com/astaxie/beego/orm"
7 "gitlab.fjmaimaimai.com/mmm-go/gocomm/common" 8 "gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
8 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log" 9 "gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
9 "io/ioutil" 10 "io/ioutil"
10 "net/http" 11 "net/http"
  12 + "opp/internal/utils"
11 "opp/models" 13 "opp/models"
12 "opp/protocol" 14 "opp/protocol"
  15 + "opp/services/agg"
  16 + "time"
13 17
14 "encoding/json" 18 "encoding/json"
15 ) 19 )
@@ -26,14 +30,15 @@ const ( @@ -26,14 +30,15 @@ const (
26 ApproveIntegrate = "/approve-processes/integrate" 30 ApproveIntegrate = "/approve-processes/integrate"
27 ) 31 )
28 32
  33 +//素加审批系统
29 type SuplusApprove struct { 34 type SuplusApprove struct {
30 } 35 }
31 36
32 //新增审批实例 37 //新增审批实例
33 -func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, process []*models.AuditFlowProcess) (err error) { 38 +func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, process []*models.AuditFlowProcess) (response NewApproveInstanceResponse, err error) {
34 var ( 39 var (
35 request NewApproveInstanceRequest 40 request NewApproveInstanceRequest
36 - response NewApproveInstanceResponse 41 + //response NewApproveInstanceResponse
37 mapApproves map[int]*Approve = make(map[int]*Approve) 42 mapApproves map[int]*Approve = make(map[int]*Approve)
38 relativeId int64 43 relativeId int64
39 userCompany *models.UserCompany 44 userCompany *models.UserCompany
@@ -54,14 +59,14 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces @@ -54,14 +59,14 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces
54 approve *Approve 59 approve *Approve
55 approveType int //审批类型 60 approveType int //审批类型
56 approveWay int //审批方式 61 approveWay int //审批方式
57 - approver *models.User 62 + //approver *models.User
58 ) 63 )
59 item := process[i] 64 item := process[i]
60 if relativeId == 0 { 65 if relativeId == 0 {
61 relativeId = item.ChanceId 66 relativeId = item.ChanceId
62 } 67 }
63 - if _, ok := mapApproves[i]; ok {  
64 - approve = mapApproves[i] 68 + if _, ok := mapApproves[item.Level]; ok {
  69 + approve = mapApproves[item.Level]
65 } else { 70 } else {
66 approveType = item.AuditFlowType 71 approveType = item.AuditFlowType
67 if approveType == protocol.AuditBySpecailUser { 72 if approveType == protocol.AuditBySpecailUser {
@@ -76,21 +81,19 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces @@ -76,21 +81,19 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces
76 ApproveType: item.AuditFlowType, 81 ApproveType: item.AuditFlowType,
77 ApproveWay: approveWay, 82 ApproveWay: approveWay,
78 } 83 }
79 - mapApproves[i] = approve  
80 - }  
81 - if approver, err = models.GetUserByUcid(item.Uid); err != nil {  
82 - log.Error(err)  
83 - return 84 + mapApproves[item.Level] = approve
84 } 85 }
  86 + //if approver, err = models.GetUserByUcid(item.Uid); err != nil {
  87 + // log.Error(err)
  88 + // return
  89 + //}
85 approve.ApproveUsers = append(approve.ApproveUsers, ApproveUsers{ 90 approve.ApproveUsers = append(approve.ApproveUsers, ApproveUsers{
86 Uid: item.Uid, 91 Uid: item.Uid,
87 - Name: approver.NickName,  
88 - //RoleId:5,  
89 - RoleId: 0, 92 + Name: item.UserName,
90 }) 93 })
91 } 94 }
92 request.RelativeId = relativeId 95 request.RelativeId = relativeId
93 - for i := 0; i < len(mapApproves); i++ { 96 + for i := 1; i <= len(mapApproves); i++ {
94 if v, ok := mapApproves[i]; ok { 97 if v, ok := mapApproves[i]; ok {
95 request.Approves = append(request.Approves, v) 98 request.Approves = append(request.Approves, v)
96 } 99 }
@@ -102,19 +105,20 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces @@ -102,19 +105,20 @@ func (s SuplusApprove) NewApproveInstance(header *protocol.RequestHeader, proces
102 } 105 }
103 106
104 //审批操作 107 //审批操作
105 -func (s SuplusApprove) ApproveItem(header *protocol.RequestHeader, approveType int, chanceId int64) (response ApproveItemResponse, err error) { 108 +func (s SuplusApprove) ApproveItem(header *protocol.RequestHeader, approveType int, chanceId int64, processId int64) (response ApproveItemResponse, err error) {
106 var ( 109 var (
107 request ApproveItemRequest = ApproveItemRequest{ 110 request ApproveItemRequest = ApproveItemRequest{
108 RelativeId: chanceId, 111 RelativeId: chanceId,
109 Type: approveType, 112 Type: approveType,
110 Suggestion: "", 113 Suggestion: "",
111 Sign: ApproveSign, 114 Sign: ApproveSign,
112 - ApproveType: 2, 115 + ApproveType: 2, //编辑
113 Uid: header.UserId, 116 Uid: header.UserId,
  117 + ExtendRelativeId: processId,
114 } 118 }
115 ) 119 )
116 - if s.DoRequest(ApproveItem, http.MethodPost, request, &response); err != nil {  
117 - log.Error(err) 120 + if err = s.DoRequest(ApproveItem, http.MethodPost, request, &response); err != nil {
  121 + return
118 } 122 }
119 log.Info(fmt.Sprintf("success request suplus-approve:%v request:%v response:%v", ApproveItem, common.AssertJson(request), common.AssertJson(response))) 123 log.Info(fmt.Sprintf("success request suplus-approve:%v request:%v response:%v", ApproveItem, common.AssertJson(request), common.AssertJson(response)))
120 return 124 return
@@ -178,7 +182,7 @@ func (s SuplusApprove) DoRequest(method string, methodType string, request inter @@ -178,7 +182,7 @@ func (s SuplusApprove) DoRequest(method string, methodType string, request inter
178 log.Error(e) 182 log.Error(e)
179 return 183 return
180 } 184 }
181 - log.Debug(fmt.Sprintf("request-%v request:%v rsp:%v", url, common.AssertJson(request), common.AssertJson(response))) 185 + log.Debug(fmt.Sprintf("request-%v request:%v rsp:%v", url, common.AssertJson(request), string(responseData)))
182 return 186 return
183 } 187 }
184 188
@@ -193,12 +197,17 @@ type NewApproveInstanceRequest struct { @@ -193,12 +197,17 @@ type NewApproveInstanceRequest struct {
193 RelativeId int64 `json:"relativeId"` //关联id 197 RelativeId int64 `json:"relativeId"` //关联id
194 198
195 } 199 }
196 -type NewApproveInstanceResponse interface{} 200 +type NewApproveInstanceResponse struct {
  201 + MessageData []MessageDataItem `json:"messageData"`
  202 +}
197 203
198 //审批节点 204 //审批节点
199 type Approve struct { 205 type Approve struct {
200 ApproveWay int `json:"approveWay"` //审批方式 1 会签 2 或签 3 发起人从角色成员中自选 206 ApproveWay int `json:"approveWay"` //审批方式 1 会签 2 或签 3 发起人从角色成员中自选
201 ApproveType int `json:"approveType"` //审批类型 1 业务区域负责人 2 指定成员 3 角色 207 ApproveType int `json:"approveType"` //审批类型 1 业务区域负责人 2 指定成员 3 角色
  208 + IsDefault int `json:"isDefault"` //1 是默认 0 不是
  209 + RoleName string `json:"roleName"` //角色名/负责人
  210 + RoleId int `json:"roleId"` //角色id
202 ApproveUsers []ApproveUsers `json:"approveUsers"` //审批人 211 ApproveUsers []ApproveUsers `json:"approveUsers"` //审批人
203 } 212 }
204 213
@@ -206,12 +215,25 @@ type Approve struct { @@ -206,12 +215,25 @@ type Approve struct {
206 type ApproveUsers struct { 215 type ApproveUsers struct {
207 Uid int64 `json:"uid"` //用户id 216 Uid int64 `json:"uid"` //用户id
208 Name string `json:"name"` //用户名 217 Name string `json:"name"` //用户名
209 - IsDefault int `json:"isDefault"` //1 是默认 0 不是  
210 - RoleName string `json:"roleName"` //角色名/负责人  
211 - RoleId int `json:"roleId"` //角色id  
212 ParentIds []int `json:"parentIds"` 218 ParentIds []int `json:"parentIds"`
213 } 219 }
214 220
  221 +//审批 消息列表
  222 +type MessageDataItem struct {
  223 + MessageContent contentItem `json:"messageContent"`
  224 + ReceiverInfo receiverInfo `json:"receiverInfo"`
  225 +}
  226 +type contentItem struct {
  227 + ApproveInstanceId int `json:"approveInstanceId"` //审批实例-id
  228 + ApproveProcessId int `json:"approveProcessId"` //审批进程节点-id
  229 + RelativeId int `json:"relativeId"` //机会编号
  230 + MsgApproveStatus int `json:"msgApproveStatus"` //审核状态
  231 +}
  232 +type receiverInfo struct {
  233 + ReceiverUid int64 `json:"receiverUid"` //用户id
  234 + ReceiverName string `json:"receiverName"` //接收人
  235 +}
  236 +
215 /*ApproveItem 审批操作*/ 237 /*ApproveItem 审批操作*/
216 type ApproveItemRequest struct { 238 type ApproveItemRequest struct {
217 RelativeId int64 `json:"relativeId"` //关联id 239 RelativeId int64 `json:"relativeId"` //关联id
@@ -220,11 +242,15 @@ type ApproveItemRequest struct { @@ -220,11 +242,15 @@ type ApproveItemRequest struct {
220 Sign string `json:"sign"` //CHANCE 242 Sign string `json:"sign"` //CHANCE
221 ApproveType int `json:"approveType"` //1-新增(订单用新增) 2-编辑 243 ApproveType int `json:"approveType"` //1-新增(订单用新增) 2-编辑
222 Uid int64 `json:"uid"` //用户id 244 Uid int64 `json:"uid"` //用户id
  245 + ExtendRelativeId int64 `json:"extendRelativeId"` //业务管理id
223 } 246 }
224 type ApproveItemResponse struct { 247 type ApproveItemResponse struct {
225 - Status int `json:"status"` //状态1-待确认2-已确认3-已驳回4-已撤回  
226 - ApproveStatus int `json:"approveStatus"` //审批状态0 待审批 1 审批中 2 同意 3 驳回 4 提交订单 5 已被其他人处理 (0这个状态不存在审批后)  
227 - IsApprove int `json:"isApprove"` //是否需要审批 1是 0 否 248 + MessageData ApproveMessageItem `json:"messageData"`
  249 + IsOver int `json:"isOver"` //是否结束1
  250 +}
  251 +type ApproveMessageItem struct {
  252 + ApproveMessage []MessageDataItem `json:"approveMessage"`
  253 + ApplyUserMessage []MessageDataItem `json:"applyUserMessage"`
228 } 254 }
229 255
230 /*ApproveIntegrate 审核列表*/ 256 /*ApproveIntegrate 审核列表*/
@@ -237,3 +263,218 @@ type AppproveProcess struct { @@ -237,3 +263,218 @@ type AppproveProcess struct {
237 ExtendRelativeId int64 `json:"extendRelativeId"` 263 ExtendRelativeId int64 `json:"extendRelativeId"`
238 Status int `json:"status"` 264 Status int `json:"status"`
239 } 265 }
  266 +
  267 +//机会审核
  268 +func ChanceApprove(header *protocol.RequestHeader, request *protocol.ChanceApproveRequest) (rsp *protocol.ChanceApproveResponse, err error) {
  269 + var (
  270 + process *models.AuditFlowProcess
  271 + chance *models.Chance
  272 + suplusApprove SuplusApprove
  273 + approveType int
  274 + approveItemResponse ApproveItemResponse
  275 + )
  276 + //TODO:测试注入
  277 + if request.Uid != 0 {
  278 + header.UserId = request.Uid
  279 + }
  280 + approveType = ConverReviewStatus(request.ReviewStatus)
  281 + if approveType == 0 {
  282 + log.Error("request.reviewStatus error :", request.ReviewStatus)
  283 + err = protocol.NewErrWithMessage(2)
  284 + return
  285 + }
  286 + if chance, err = models.GetChanceById(request.ChanceId); err != nil {
  287 + log.Error(err)
  288 + err = protocol.NewErrWithMessage(5101)
  289 + return
  290 + }
  291 + if process, err = models.GetAuditFlowProcessBy(request.ProcessId, header.UserId); err != nil {
  292 + log.Error(request.ProcessId, header.UserId, err)
  293 + err = protocol.NewErrWithMessage(5202)
  294 + return
  295 + }
  296 + if chance.ReviewStatus != protocol.ReviewStatusAuditging {
  297 + log.Error(fmt.Sprintf("机会已经被审核 chance_id:%v review_status:%v", chance.Id, chance.ReviewStatus))
  298 + err = protocol.NewErrWithMessage(5202)
  299 + return
  300 + }
  301 + log.Info(fmt.Sprintf("用户:%v 提交审核 机会编号:%v 审批流编号:%v 审批状态:%v", header.UserId, chance.Id, process.Id, request.ReviewStatus))
  302 + if approveItemResponse, err = suplusApprove.ApproveItem(header, approveType, chance.Id, process.Id); err != nil {
  303 + log.Error(err)
  304 + err = protocol.NewErrWithMessage(5203)
  305 + return
  306 + }
  307 + if err = utils.UpdateTableByMap(process, map[string]interface{}{
  308 + "ReviewStatus": int8(request.ReviewStatus), "ApproveTime": time.Now()}); err != nil {
  309 + log.Error("更新机会审核状态失败 process_id:", process.Id, err)
  310 + return
  311 + }
  312 + log.Info(fmt.Sprintf("用户%v 更新机会审核状态 process_id:%v 状态:%v", header.UserId, process.Id, request.ReviewStatus))
  313 + {
  314 + //更新下一批次的审核人
  315 + var nextApprovers []int64
  316 + if approveItemResponse.IsOver == 1 {
  317 + //结束审批
  318 + if err = utils.UpdateTableByMap(chance, map[string]interface{}{
  319 + "ReviewStatus": int8(request.ReviewStatus), "AuditLevel": chance.AuditLevel}); err != nil {
  320 + log.Error("更新机会审核状态失败 chance_id:", chance.Id, err)
  321 + return
  322 + }
  323 + //发送审核结果消息给提交人
  324 + for i := range approveItemResponse.MessageData.ApplyUserMessage {
  325 + message := approveItemResponse.MessageData.ApplyUserMessage[i]
  326 + nextApprovers = append(nextApprovers, message.ReceiverInfo.ReceiverUid)
  327 + if err = agg.SendApproveMsg(message.ReceiverInfo.ReceiverUid, message.ReceiverInfo.ReceiverName,
  328 + header.CompanyId, chance.Id, chance.ChanceTypeId, request.ReviewStatus); err != nil {
  329 + log.Error(err)
  330 + return
  331 + }
  332 + }
  333 + //更新同批次的为审核的状态置为无效
  334 + if err = models.UpdatetAuditFlowProcessNoApprove(chance.Id, chance.AuditLevel, protocol.ReviewStatusAuditging); err != nil {
  335 + log.Error(err)
  336 + return
  337 + }
  338 + } else {
  339 + //发送下一个消息给下一流程的审核人
  340 + for i := range approveItemResponse.MessageData.ApproveMessage {
  341 + message := approveItemResponse.MessageData.ApproveMessage[i]
  342 + nextApprovers = append(nextApprovers, message.ReceiverInfo.ReceiverUid)
  343 + if err = agg.SendApproveMsg(message.ReceiverInfo.ReceiverUid, message.ReceiverInfo.ReceiverName,
  344 + header.CompanyId, chance.Id, chance.ChanceTypeId, protocol.ReviewStatusAuditging); err != nil {
  345 + log.Error(err)
  346 + return
  347 + }
  348 + }
  349 + //更新下一批次的审核人 同批次的为审核的状态置为无效
  350 + if len(nextApprovers) != 0 {
  351 + if err = models.UpdatetAuditFlowProcessToNext(chance.Id, chance.AuditLevel+1, nextApprovers); err != nil {
  352 + log.Error(err)
  353 + log.Info(fmt.Sprintf("更新机会失败 chance_id:%v 下一批次审批人员:%v", chance.Id, nextApprovers))
  354 + return
  355 + }
  356 + log.Info(fmt.Sprintf("更新机会 chance_id:%v 下一批次审批人员:%v", chance.Id, nextApprovers))
  357 + if err = models.UpdatetAuditFlowProcessNoApprove(chance.Id, chance.AuditLevel, protocol.ReviewStatusAuditging); err != nil {
  358 + log.Error(err)
  359 + return
  360 + }
  361 + }
  362 + }
  363 + }
  364 + rsp = &protocol.ChanceApproveResponse{}
  365 + return
  366 +}
  367 +
  368 +/*ProcessIntegrate */
  369 +type ProcessIntegrateRequest struct {
  370 +}
  371 +type ProcessIntegrateResponse struct {
  372 +}
  373 +
  374 +func ProcessIntegrate(header *protocol.RequestHeader, request *ProcessIntegrateRequest) (rsp *ProcessIntegrateResponse, err error) {
  375 + var ()
  376 + rsp = &ProcessIntegrateResponse{}
  377 + return
  378 +}
  379 +
  380 +//系统审核状态转为审核类型 reviewStatus - > approveType
  381 +func ConverReviewStatus(reviewStatus int) (approveType int) {
  382 + if reviewStatus == protocol.ReviewStatusPass {
  383 + approveType = protocol.ApproveTypePass
  384 + } else if reviewStatus == protocol.ReviewStatusReturn {
  385 + approveType = protocol.ApproveTypeReject
  386 + }
  387 + return
  388 +}
  389 +
  390 +func ConverTypeToReviewStaus(approveType int) (reviewStatus int) {
  391 + if approveType == protocol.ApproveTypePass {
  392 + reviewStatus = protocol.ReviewStatusPass
  393 + } else if approveType == protocol.ApproveTypeReject {
  394 + reviewStatus = protocol.ReviewStatusReturn
  395 + }
  396 + return
  397 +}
  398 +
  399 +// 机会审核流程信息
  400 +func ChanceApproveProcess(header *protocol.RequestHeader, chance *models.Chance) (rsp *protocol.ChanceApproveProcessResponse, err error) {
  401 + var (
  402 + processList []*models.AuditFlowProcess
  403 + )
  404 + if processList, err = models.GetAuditFlowProcessList(chance.Id); err != nil {
  405 + log.Error(fmt.Sprintf("chance_id :%v 未查询到审核流信息", chance.Id), err)
  406 + if err == orm.ErrNoRows {
  407 + err = nil
  408 + return
  409 + }
  410 + return
  411 + }
  412 + rsp = &protocol.ChanceApproveProcessResponse{}
  413 + newProcessItem := func(process *models.AuditFlowProcess) *protocol.ProcessItem {
  414 + item := &protocol.ProcessItem{
  415 + Id: process.Id,
  416 + ReviewStatus: int(process.ReviewStatus),
  417 + ApproveWay: int(process.AuditFlowType),
  418 + Uid: process.Uid,
  419 + Name: process.UserName,
  420 + }
  421 + if item.ApproveWay == protocol.AuditBySpecailUser {
  422 + item.ApproveWay = protocol.AuditByUser
  423 + }
  424 + if item.ReviewStatus != protocol.ReviewStatusAuditging {
  425 + item.ApproveTime = process.ApproveTime.Unix() * 1000
  426 + }
  427 + switch item.ApproveWay {
  428 + case protocol.AuditByDepartmentor:
  429 + break
  430 + case protocol.AuditByUser:
  431 + //item.Uid=process.Uid
  432 + //item.Name=process.UserName
  433 + break
  434 + case protocol.AuditByRole:
  435 + item.Role = process.RoleId
  436 + item.RoleName = process.RoleName
  437 + break
  438 + }
  439 + return item
  440 + }
  441 + //检查审核权限
  442 + checkApprovePermission := func(process *models.AuditFlowProcess) {
  443 + if chance.ReviewStatus == protocol.ReviewStatusPass {
  444 + return
  445 + }
  446 + if process.ReviewStatus == protocol.ReviewStatusAuditging && process.Uid == header.UserId {
  447 + rsp.ApproveAccess = &protocol.ApproveAccess{
  448 + AllowApprove: 1,
  449 + AllowReject: 1,
  450 + ProcessId: process.Id,
  451 + }
  452 + }
  453 + }
  454 + for i := range processList {
  455 + p := processList[i]
  456 + item := newProcessItem(p)
  457 + checkApprovePermission(p)
  458 + //机会已经审核通过的直接添加到审核人列表
  459 + if chance.ReviewStatus == protocol.ReviewStatusPass {
  460 + rsp.ApproveProcess = append(rsp.ApproveProcess, item)
  461 + continue
  462 + }
  463 + //当前再审核的列表
  464 + if p.Level == chance.AuditLevel && item.ReviewStatus == protocol.ReviewStatusAuditging {
  465 + item = newProcessItem(p)
  466 + for j := i; j < len(processList); j++ {
  467 + p = processList[j]
  468 + checkApprovePermission(p)
  469 + item.ApproveUsers = append(item.ApproveUsers, protocol.UserItem{
  470 + Uid: p.Uid,
  471 + Name: p.UserName,
  472 + })
  473 + }
  474 + rsp.ApproveProcess = append(rsp.ApproveProcess, item)
  475 + break
  476 + }
  477 + rsp.ApproveProcess = append(rsp.ApproveProcess, item)
  478 + }
  479 + return
  480 +}
@@ -3,6 +3,7 @@ package chance @@ -3,6 +3,7 @@ package chance
3 import ( 3 import (
4 "encoding/json" 4 "encoding/json"
5 "fmt" 5 "fmt"
  6 + "github.com/astaxie/beego"
6 "github.com/astaxie/beego/orm" 7 "github.com/astaxie/beego/orm"
7 "gitlab.fjmaimaimai.com/mmm-go/gocomm/common" 8 "gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
8 "gitlab.fjmaimaimai.com/mmm-go/gocomm/identity/idgen" 9 "gitlab.fjmaimaimai.com/mmm-go/gocomm/identity/idgen"
@@ -190,6 +191,7 @@ func Templates(header *protocol.RequestHeader, request *protocol.TemplatesReques @@ -190,6 +191,7 @@ func Templates(header *protocol.RequestHeader, request *protocol.TemplatesReques
190 Icon: item.Icon, 191 Icon: item.Icon,
191 Doc: item.Doc, 192 Doc: item.Doc,
192 FormList: make([]*protocol.Form, len(forms)), 193 FormList: make([]*protocol.Form, len(forms)),
  194 + Link: fmt.Sprintf("%v/#/ability/opportunity?id=%v", beego.AppConfig.String("h5_host"), item.Id),
193 } 195 }
194 for j := range forms { 196 for j := range forms {
195 form := forms[j] 197 form := forms[j]
@@ -212,6 +214,20 @@ func checkTemplateIsVisible(header *protocol.RequestHeader, template *models.Aud @@ -212,6 +214,20 @@ func checkTemplateIsVisible(header *protocol.RequestHeader, template *models.Aud
212 return 214 return
213 } 215 }
214 216
  217 +//模板示例
  218 +func ChanceExample(header *protocol.RequestHeader, request *protocol.ChanceExampleRequest) (rsp *protocol.ChanceExampleResponse, err error) {
  219 + var (
  220 + example string
  221 + )
  222 + if example, err = models.GetAuditTemplateExample(int64(request.TemplateId)); err != nil {
  223 + log.Error(request.TemplateId, err)
  224 + err = protocol.NewErrWithMessage(5301) //模板不存在
  225 + return
  226 + }
  227 + rsp = &protocol.ChanceExampleResponse{example}
  228 + return
  229 +}
  230 +
215 //提交机会 231 //提交机会
216 func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmitRequest) (rsp *protocol.ChanceSubmitResponse, err error) { 232 func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmitRequest) (rsp *protocol.ChanceSubmitResponse, err error) {
217 var ( 233 var (
@@ -248,33 +264,52 @@ func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmit @@ -248,33 +264,52 @@ func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmit
248 ReviewStatus: protocol.ReviewStatusAuditging, 264 ReviewStatus: protocol.ReviewStatusAuditging,
249 DepartmentId: request.RelatedDepartment, 265 DepartmentId: request.RelatedDepartment,
250 } 266 }
251 - if _, err = orm.Insert(chance); err != nil { 267 + logAndRollBack := func(err error) {
252 log.Error(err) 268 log.Error(err)
253 orm.Rollback() 269 orm.Rollback()
254 return 270 return
255 } 271 }
  272 + if _, err = orm.Insert(chance); err != nil {
  273 + logAndRollBack(err)
  274 + return
  275 + }
256 276
  277 + //生成提交记录
  278 + if _, err = orm.Insert(GenAuditFlowProcess_Submit(header, chance.Id, template.Id)); err != nil {
  279 + logAndRollBack(err)
  280 + return
  281 + }
257 //4.查询审核配置 282 //4.查询审核配置
258 //5.生成审核流 283 //5.生成审核流
259 if auditFlows, err = GenAuditFlowProcess(header, chance.Id, template.Id, auditConfig); err != nil { 284 if auditFlows, err = GenAuditFlowProcess(header, chance.Id, template.Id, auditConfig); err != nil {
260 - log.Error(err)  
261 - orm.Rollback() 285 + logAndRollBack(err)
262 return 286 return
263 } 287 }
264 for i := 0; i < len(auditFlows); i++ { 288 for i := 0; i < len(auditFlows); i++ {
265 if _, err = orm.Insert(auditFlows[i]); err != nil { 289 if _, err = orm.Insert(auditFlows[i]); err != nil {
266 - log.Error(err)  
267 - orm.Rollback() 290 + logAndRollBack(err)
268 return 291 return
269 } 292 }
270 } 293 }
271 if len(auditFlows) > 0 { 294 if len(auditFlows) > 0 {
272 - if err = suplusApprove.NewApproveInstance(header, auditFlows); err != nil {  
273 - log.Error(fmt.Sprintf("uid:%v", header.UserId), "request suplus-approve.NewApproveInstance err", err) 295 + //7.发送审批实例给审批服务器
  296 + if m, e := suplusApprove.NewApproveInstance(header, auditFlows); e != nil {
  297 + log.Error(fmt.Sprintf("uid:%v", header.UserId), "request suplus-approve.NewApproveInstance err", e)
274 orm.Rollback() 298 orm.Rollback()
  299 + err = e
  300 + return
  301 + } else {
  302 + //7.发送消息通知给审核人(审核消息)
  303 + for i := range m.MessageData {
  304 + message := m.MessageData[i]
  305 + if err = agg.SendApproveMsg(message.ReceiverInfo.ReceiverUid, message.ReceiverInfo.ReceiverName,
  306 + header.CompanyId, chance.Id, chance.ChanceTypeId, protocol.ReviewStatusAuditging); err != nil {
  307 + logAndRollBack(err)
275 return 308 return
276 } 309 }
277 } 310 }
  311 + }
  312 + }
278 313
279 //6.文件 314 //6.文件
280 { 315 {
@@ -288,15 +323,12 @@ func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmit @@ -288,15 +323,12 @@ func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmit
288 UpdateAt: time.Now(), 323 UpdateAt: time.Now(),
289 } 324 }
290 if _, err = orm.Insert(data); err != nil { 325 if _, err = orm.Insert(data); err != nil {
291 - log.Error(err)  
292 - orm.Rollback() 326 + logAndRollBack(err)
293 return 327 return
294 } 328 }
295 } 329 }
296 orm.Commit() 330 orm.Commit()
297 331
298 - //6.激活审核流  
299 - //TODO:7.发送消息通知给审核人(审核消息)  
300 rsp = &protocol.ChanceSubmitResponse{} 332 rsp = &protocol.ChanceSubmitResponse{}
301 return 333 return
302 } 334 }
@@ -342,21 +374,6 @@ func ChanceUpdate(header *protocol.RequestHeader, request *protocol.ChanceSubmit @@ -342,21 +374,6 @@ func ChanceUpdate(header *protocol.RequestHeader, request *protocol.ChanceSubmit
342 } 374 }
343 } 375 }
344 376
345 - //4.查询审核配置  
346 - //5.生成审核流 删除旧的 生成新的  
347 - //if auditFlows, err = GenAuditFlowProcess(header, chance.Id, template.Id, auditConfig); err != nil {  
348 - // log.Error(err)  
349 - // orm.Rollback()  
350 - // return  
351 - //}  
352 - //for i := 0; i < len(auditFlows); i++ {  
353 - // if _, err = orm.Insert(auditFlows[i]); err != nil {  
354 - // log.Error(err)  
355 - // orm.Rollback()  
356 - // return  
357 - // }  
358 - //}  
359 -  
360 //6.更新文件 377 //6.更新文件
361 { 378 {
362 if chanceData, err = models.GetChanceDataByChanceId(chance.Id); err == nil { 379 if chanceData, err = models.GetChanceDataByChanceId(chance.Id); err == nil {
@@ -395,6 +412,27 @@ func ChanceUpdate(header *protocol.RequestHeader, request *protocol.ChanceSubmit @@ -395,6 +412,27 @@ func ChanceUpdate(header *protocol.RequestHeader, request *protocol.ChanceSubmit
395 return 412 return
396 } 413 }
397 414
  415 +//生成审批流-提交记录
  416 +func GenAuditFlowProcess_Submit(header *protocol.RequestHeader, chanceId int64, templateId int64) (v *models.AuditFlowProcess) {
  417 + v = &models.AuditFlowProcess{
  418 + Id: idgen.Next(),
  419 + ChanceId: chanceId,
  420 + Uid: header.UserId,
  421 + CreateAt: time.Now(),
  422 + UpdateAt: time.Now(),
  423 + ApproveTime: time.Now(),
  424 + EnableStatus: 1,
  425 + ReviewStatus: protocol.ReviewStatusSubmit,
  426 + }
  427 + if approver, err := models.GetUsersById(header.Uid); err != nil {
  428 + log.Error(err)
  429 + return
  430 + } else {
  431 + v.UserName = approver.NickName
  432 + }
  433 + return
  434 +}
  435 +
398 //生成审批流 436 //生成审批流
399 func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templateId int64, auditConfig *protocol.AuditConfig) (v []*models.AuditFlowProcess, err error) { 437 func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templateId int64, auditConfig *protocol.AuditConfig) (v []*models.AuditFlowProcess, err error) {
400 var ( 438 var (
@@ -403,6 +441,8 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat @@ -403,6 +441,8 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat
403 ids []int64 441 ids []int64
404 groupId int64 442 groupId int64
405 company *models.Company 443 company *models.Company
  444 + roleName string
  445 + approver *models.User
406 ) 446 )
407 if configs, err = models.GetAuditFlowConfigsLevel(templateId, 1); err != nil { 447 if configs, err = models.GetAuditFlowConfigsLevel(templateId, 1); err != nil {
408 if err == orm.ErrNoRows { 448 if err == orm.ErrNoRows {
@@ -464,7 +504,6 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat @@ -464,7 +504,6 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat
464 err = fmt.Errorf("GenAuditFlowProcess:company.admin is not set") 504 err = fmt.Errorf("GenAuditFlowProcess:company.admin is not set")
465 return 505 return
466 } 506 }
467 -  
468 //3.生成审核列表 507 //3.生成审核列表
469 for i := range configs { 508 for i := range configs {
470 config := configs[i] 509 config := configs[i]
@@ -481,7 +520,8 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat @@ -481,7 +520,8 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat
481 return 520 return
482 } 521 }
483 case protocol.AuditByRole: 522 case protocol.AuditByRole:
484 - 523 + //roleName="" //TODO:角色
  524 + return
485 } 525 }
486 if len(userIds) == 0 { //当前步骤没有用户 默认一个空审核人 526 if len(userIds) == 0 { //当前步骤没有用户 默认一个空审核人
487 userIds = append(userIds, 0) 527 userIds = append(userIds, 0)
@@ -495,6 +535,10 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat @@ -495,6 +535,10 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat
495 log.Info(fmt.Sprintf("生成机会审批流-转给管理员:chance_id:%v audit_level:%v audit_user:%v -> admin:%v", chanceId, config.Level, uid, company.AdminId)) 535 log.Info(fmt.Sprintf("生成机会审批流-转给管理员:chance_id:%v audit_level:%v audit_user:%v -> admin:%v", chanceId, config.Level, uid, company.AdminId))
496 uid = company.AdminId 536 uid = company.AdminId
497 } 537 }
  538 + if approver, err = models.GetUserByUcid(uid); err != nil {
  539 + log.Error(err)
  540 + return
  541 + }
498 item := &models.AuditFlowProcess{ 542 item := &models.AuditFlowProcess{
499 Id: idgen.Next(), 543 Id: idgen.Next(),
500 ChanceId: chanceId, 544 ChanceId: chanceId,
@@ -505,14 +549,13 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat @@ -505,14 +549,13 @@ func GenAuditFlowProcess(header *protocol.RequestHeader, chanceId int64, templat
505 AuditFlowType: config.AuditFlowType, 549 AuditFlowType: config.AuditFlowType,
506 FlowType: config.FlowType, 550 FlowType: config.FlowType,
507 ActionType: int(config.ActionType), 551 ActionType: int(config.ActionType),
508 - EnableStatus: 1, 552 + RoleName: roleName,
  553 + UserName: approver.NickName,
  554 + ReviewStatus: protocol.ReviewStatusAuditging,
509 } 555 }
510 - //if uid==0 && auditConfig.NoApprover==1{//审批人为空 自动通过  
511 - // item.  
512 - //}  
513 if config.Level == 1 { 556 if config.Level == 1 {
514 item.IsActive = 1 557 item.IsActive = 1
515 - //通知 user_msg 558 + item.EnableStatus = 1
516 } 559 }
517 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))) 560 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)))
518 v = append(v, item) 561 v = append(v, item)
@@ -655,20 +698,27 @@ func ChanceDetail(header *protocol.RequestHeader, request *protocol.ChanceDetail @@ -655,20 +698,27 @@ func ChanceDetail(header *protocol.RequestHeader, request *protocol.ChanceDetail
655 chance *models.Chance 698 chance *models.Chance
656 chanceData *models.ChanceData 699 chanceData *models.ChanceData
657 provider *protocol.BaseUserInfo 700 provider *protocol.BaseUserInfo
  701 + approveProcess *protocol.ChanceApproveProcessResponse
658 ) 702 )
659 - //检查是否可见  
660 - if provider, err = agg.GetUserBaseInfo(chance.UserId, header.CompanyId); err != nil { 703 + rsp = &protocol.ChanceDetailResponse{}
  704 + if chance, err = models.GetChanceById(request.Id); err != nil {
  705 + if err == orm.ErrNoRows {
  706 + err = protocol.NewErrWithMessage(5101)
  707 + return
  708 + }
661 log.Error(err) 709 log.Error(err)
662 return 710 return
663 } 711 }
664 - if chance, err = models.GetChanceById(request.Id); err != nil {  
665 - if err == orm.ErrNoRows { 712 + if chance.EnableStatus == 0 {
666 err = protocol.NewErrWithMessage(5101) 713 err = protocol.NewErrWithMessage(5101)
667 return 714 return
668 } 715 }
  716 + //用户信息
  717 + if provider, err = agg.GetUserBaseInfo(chance.UserId, header.CompanyId); err != nil {
669 log.Error(err) 718 log.Error(err)
670 return 719 return
671 } 720 }
  721 +
672 item := protocol.ChanceItem{ 722 item := protocol.ChanceItem{
673 Id: chance.Id, 723 Id: chance.Id,
674 Provider: provider, 724 Provider: provider,
@@ -680,7 +730,15 @@ func ChanceDetail(header *protocol.RequestHeader, request *protocol.ChanceDetail @@ -680,7 +730,15 @@ func ChanceDetail(header *protocol.RequestHeader, request *protocol.ChanceDetail
680 jsonUnmarshal(chanceData.Speechs, &item.Speechs) 730 jsonUnmarshal(chanceData.Speechs, &item.Speechs)
681 jsonUnmarshal(chanceData.Videos, &item.Videos) 731 jsonUnmarshal(chanceData.Videos, &item.Videos)
682 } 732 }
683 - rsp = &protocol.ChanceDetailResponse{} 733 + jsonUnmarshal(chance.PublishData, &rsp.PublicData)
  734 + rsp.ChanceDetail = item
  735 + if approveProcess, err = ChanceApproveProcess(header, chance); err != nil {
  736 + log.Error(err)
  737 + return
  738 + } else {
  739 + rsp.ApproveProcess = approveProcess.ApproveProcess
  740 + rsp.ApproveAccess = approveProcess.ApproveAccess
  741 + }
684 return 742 return
685 } 743 }
686 744
@@ -689,6 +747,7 @@ func ChanceDelete(header *protocol.RequestHeader, request *protocol.ChanceDelete @@ -689,6 +747,7 @@ func ChanceDelete(header *protocol.RequestHeader, request *protocol.ChanceDelete
689 var ( 747 var (
690 chance *models.Chance 748 chance *models.Chance
691 ) 749 )
  750 + rsp = &protocol.ChanceDeleteResponse{}
692 if chance, err = models.GetChanceById(request.Id); err != nil { 751 if chance, err = models.GetChanceById(request.Id); err != nil {
693 if err == orm.ErrNoRows { 752 if err == orm.ErrNoRows {
694 err = protocol.NewErrWithMessage(5101) 753 err = protocol.NewErrWithMessage(5101)
@@ -697,8 +756,24 @@ func ChanceDelete(header *protocol.RequestHeader, request *protocol.ChanceDelete @@ -697,8 +756,24 @@ func ChanceDelete(header *protocol.RequestHeader, request *protocol.ChanceDelete
697 log.Error(err) 756 log.Error(err)
698 return 757 return
699 } 758 }
700 - if chance != nil { 759 + if chance.ReviewStatus == protocol.ReviewStatusPass {
  760 + err = protocol.NewErrWithMessage(5202)
  761 + return
  762 + }
  763 + //被人审核过 公开状态数据不为空
  764 + if chance.ReviewStatus == protocol.ReviewStatusAuditging && len(chance.PublishData) != 0 {
  765 + err = protocol.NewErrWithMessage(5202)
  766 + return
  767 + }
  768 + if err = utils.UpdateTableByMap(chance, map[string]interface{}{
  769 + "EnableStatus": int8(0),
  770 + }); err != nil {
  771 + log.Error(err)
  772 + return
  773 + }
  774 + if err = models.CloseAuditFlowProcess(chance.Id); err != nil {
  775 + log.Error(err)
  776 + return
701 } 777 }
702 - rsp = &protocol.ChanceDeleteResponse{}  
703 return 778 return
704 } 779 }
@@ -105,7 +105,7 @@ func Announcements(header *protocol.RequestHeader, request *protocol.Announcemen @@ -105,7 +105,7 @@ func Announcements(header *protocol.RequestHeader, request *protocol.Announcemen
105 Title: bulletin.Title, 105 Title: bulletin.Title,
106 Control: int(bulletin.AllowClose), 106 Control: int(bulletin.AllowClose),
107 //link:'https://web-open.fjmaimaimai.com/#/ability/announcement?id='+announcementCfgData[i].id+'&uid='+param.uid 107 //link:'https://web-open.fjmaimaimai.com/#/ability/announcement?id='+announcementCfgData[i].id+'&uid='+param.uid
108 - Link: fmt.Sprintf("%v#/ability/announcement?id=%v&uid=%v", beego.AppConfig.String("h5_host"), bulletin.Id, msg.ReceiveUserId), 108 + Link: fmt.Sprintf("%v#/ability/announcement?id=%v&uid=%v&oppo", beego.AppConfig.String("h5_host"), bulletin.Id, msg.ReceiveUserId),
109 } 109 }
110 item.Cover = protocol.Cover{ 110 item.Cover = protocol.Cover{
111 Path: bulletin.Cover, 111 Path: bulletin.Cover,
@@ -2,6 +2,7 @@ package upload @@ -2,6 +2,7 @@ package upload
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
  5 + "github.com/disintegration/imaging"
5 "io" 6 "io"
6 "mime/multipart" 7 "mime/multipart"
7 "os" 8 "os"
@@ -69,8 +70,9 @@ func UploadFile(request *protocol.FileRequest) (rsp *protocol.FileResponse, err @@ -69,8 +70,9 @@ func UploadFile(request *protocol.FileRequest) (rsp *protocol.FileResponse, err
69 virtualPath = beego.AppConfig.String("source_host") + filepath.Join(virtualPath, request.FileType, date) 70 virtualPath = beego.AppConfig.String("source_host") + filepath.Join(virtualPath, request.FileType, date)
70 for i := range request.Files { 71 for i := range request.Files {
71 f := request.Files[i] 72 f := request.Files[i]
  73 + prefix := fmt.Sprintf("%v_%v", time.Now().Unix(), common.RandomString(32))
72 subfix := path.Ext(f.Filename) 74 subfix := path.Ext(f.Filename)
73 - filename = fmt.Sprintf("%v_%v%v", time.Now().Unix(), common.RandomString(32), subfix) 75 + filename = fmt.Sprintf("%v%v", prefix, subfix)
74 src, err = f.Open() 76 src, err = f.Open()
75 if err != nil { 77 if err != nil {
76 log.Error(err) 78 log.Error(err)
@@ -88,6 +90,35 @@ func UploadFile(request *protocol.FileRequest) (rsp *protocol.FileResponse, err @@ -88,6 +90,35 @@ func UploadFile(request *protocol.FileRequest) (rsp *protocol.FileResponse, err
88 return 90 return
89 } 91 }
90 rsp.Paths = append(rsp.Paths, filepath.Join(virtualPath, filename)) 92 rsp.Paths = append(rsp.Paths, filepath.Join(virtualPath, filename))
  93 + ResizeImage(request.FileType, sourcePath, prefix, subfix, f)
91 } 94 }
92 return 95 return
93 } 96 }
  97 +
  98 +func ResizeImage(fileType, sourcePath, prefix, subfix string, file *multipart.FileHeader) (err error) {
  99 + var (
  100 + src multipart.File
  101 + thumbName = "_thumb"
  102 + )
  103 + if fileType != protocol.FileImage {
  104 + return
  105 + }
  106 + filename := fmt.Sprintf("%v%v%v", prefix, thumbName, subfix)
  107 + filename = filepath.Join(sourcePath, filename)
  108 + if src, err = file.Open(); err != nil {
  109 + log.Error(err)
  110 + return
  111 + }
  112 + image, err := imaging.Decode(src)
  113 + if err != nil {
  114 + fmt.Println(err)
  115 + return
  116 + }
  117 + image = imaging.Resize(image, 0, 200, imaging.Lanczos)
  118 + err = imaging.Save(image, filename)
  119 + if err != nil {
  120 + log.Error(err)
  121 + }
  122 + log.Debug(fmt.Sprintf("resize iamge:%v", filename))
  123 + return
  124 +}