作者 yangfu

发布机会

... ... @@ -207,7 +207,7 @@ func (this *ChanceController) Templates() {
}
//ChanceSubmit
//@router /chanceSubmit [post]
//@router /submit [post]
func (this *ChanceController) ChanceSubmit() {
var msg *protocol.ResponseMessage
defer func() {
... ... @@ -224,5 +224,9 @@ func (this *ChanceController) ChanceSubmit() {
return
}
header := controllers.GetRequestHeader(this.Ctx)
if request.Id>0{
msg = protocol.NewReturnResponse(chance.ChanceUpdate(header, request))
return
}
msg = protocol.NewReturnResponse(chance.ChanceSubmit(header, request))
}
... ...
... ... @@ -34,6 +34,8 @@ func SetStructValueByType(s interface{}, columnType string, columnValue interfac
setValue.SetFloat(float64(columnValueV.Float()))
case reflect.String:
setValue.SetString(columnValueV.String())
case reflect.Struct:
setValue.Set(columnValueV)
default:
return errors.New("columnValue err for:" + columnType)
}
... ...
... ... @@ -30,8 +30,8 @@ func init() {
//})
err := redis.InitWithDb(100, beego.AppConfig.String("redis_add_port"), beego.AppConfig.String("redis_auth"), "0")
if err != nil {
log.Fatal(err, beego.AppConfig.String("redis_add_port"), beego.AppConfig.String("redis_auth"))
//panic(err)
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",
beego.AppConfig.String("mysql_user"),
... ...
... ... @@ -10,7 +10,7 @@ import (
type AuditTemplate struct {
Id int64 `orm:"column(id);pk" description:"唯一编号"`
CompanyId int `orm:"column(company_id)" description:"公司id"`
ChanceType int `orm:"column(chance_type)" description:"机会类型"`
ChanceTypeId int `orm:"column(chance_type_id)" description:"机会类型编号"`
Name string `orm:"column(name);size(20)" description:"子分类名称"`
Doc string `orm:"column(doc);size(255)" description:"说明"`
Icon string `orm:"column(icon);size(255)" description:"图标"`
... ... @@ -82,7 +82,7 @@ func DeleteAuditTemplate(id int64) (err error) {
func GetAuditTemplates(companyId int64, chanceType int) (v []*AuditTemplate, err error) {
o := orm.NewOrm()
sql := "select * from audit_template where company_id=? and chance_type=? and enable_status=1"
sql := "select * from audit_template where company_id=? and chance_type_id=? and enable_status=1"
if _, err = o.Raw(sql, companyId, chanceType).QueryRows(&v); err == nil {
return
}
... ...
... ... @@ -15,7 +15,7 @@ type Chance struct {
UserId int64 `orm:"column(user_id)" description:"表user.id 用户id"`
CompanyId int64 `orm:"column(company_id)" description:"表company.id 公司id"`
DepartmentId int64 `orm:"column(department_id)" description:"表department.id 部门id"`
ChanceType int `orm:"column(chance_type)" description:"表chance_type.id 机会类型 "`
ChanceTypeId int `orm:"column(chance_type_id)" description:"表chance_type.id 机会类型 "`
AuditTemplateId int64 `orm:"column(audit_template_id)" description:"表audit_template.id 所属审批模板编号"`
AuditTemplateConfig string `orm:"column(audit_template_config);size(255);null" description:"模板配置 (存旧的配置信息,对新改动的不影响)"`
Content string `orm:"column(content)" description:"格式化后的文本内容"`
... ...
package models
import (
"fmt"
"time"
"github.com/astaxie/beego/orm"
)
type ChanceData struct {
Id int64 `orm:"column(id)" description:"唯一编号"`
ChanceId int64 `orm:"column(chance_id);null" description:"表chance.id 机会编号"`
Images string `orm:"column(images);size(1000);null" description:"图片 json"`
Speechs string `orm:"column(speechs);size(1000);null" description:"语音 json"`
Videos string `orm:"column(videos);size(1000);null" description:"视频 json"`
CreateAt time.Time `orm:"column(create_at);type(timestamp);null" description:"创建时间"`
UpdateAt time.Time `orm:"column(update_at);type(timestamp);null" description:"更新时间"`
}
func (t *ChanceData) TableName() string {
return "chance_data"
}
func init() {
orm.RegisterModel(new(ChanceData))
}
// AddChanceData insert a new ChanceData into database and returns
// last inserted Id on success.
func AddChanceData(m *ChanceData) (id int64, err error) {
o := orm.NewOrm()
id, err = o.Insert(m)
return
}
// GetChanceDataById retrieves ChanceData by Id. Returns error if
// Id doesn't exist
func GetChanceDataById(id int64) (v *ChanceData, err error) {
o := orm.NewOrm()
v = &ChanceData{Id: id}
if err = o.Read(v); err == nil {
return v, nil
}
return nil, err
}
// UpdateChanceData updates ChanceData by Id and returns error if
// the record to be updated doesn't exist
func UpdateChanceDataById(m *ChanceData) (err error) {
o := orm.NewOrm()
v := ChanceData{Id: m.Id}
// ascertain id exists in the database
if err = o.Read(&v); err == nil {
var num int64
if num, err = o.Update(m); err == nil {
fmt.Println("Number of records updated in database:", num)
}
}
return
}
// DeleteChanceData deletes ChanceData by Id and returns error if
// the record to be deleted doesn't exist
func DeleteChanceData(id int64) (err error) {
o := orm.NewOrm()
v := ChanceData{Id: id}
// ascertain id exists in the database
if err = o.Read(&v); err == nil {
var num int64
if num, err = o.Delete(&ChanceData{Id: id}); err == nil {
fmt.Println("Number of records deleted in database:", num)
}
}
return
}
func GetChanceDataByChanceId(chanceId int64) (v *ChanceData, err error) {
o := orm.NewOrm()
sql :=`select * from chance_data where chance_id=?`
if err = o.Raw(sql,chanceId).QueryRow(&v); err == nil {
return v, nil
}
return nil, err
}
\ No newline at end of file
... ...
... ... @@ -154,3 +154,15 @@ func DeleteCompany(id int64) (err error) {
}
return
}
func GetCompanyByPermission(uid int64) (v []*Company, err error) {
o := orm.NewOrm()
sql := `select * from company where id in(
select company_id from user_company where user_id=? and enable=1
) and enable=1` //
if _,err = o.Raw(sql, uid).QueryRows(&v); err == nil {
return v, nil
}
return nil, err
}
... ...
... ... @@ -7,6 +7,10 @@ const (
LoginTypeSmdcode = "signInCaptcha"
)
const(
DeviceType =1
)
const TokenExpire = 3600
const SmscodeDayLimitTime = 10 //短信验证码每天最多发10次
... ...
... ... @@ -88,7 +88,7 @@ type ChanceTypeResponse struct {
/*Templates */
type TemplatesRequest struct {
ChanceType int `json:"chance_type" valid:"Required"`
ChanceTypeId int `json:"chanceTypeId" valid:"Required"`
}
type TemplatesResponse struct {
Templates []*Template `json:"list"`
... ... @@ -99,26 +99,27 @@ type Template struct {
Name string `json:"name"`
Doc string `json:"doc"`
Icon string `json:"icon"`
FormList []*Form `json:"form_list"`
FormList []*Form `json:"formList"`
}
type Form struct {
Id int `json:"id"`
Lable string `json:"name"`
InputType string `json:"input_type"`
SectionType int8 `json:"section_type"`
InputType string `json:"inputType"`
SectionType int8 `json:"sectionType"`
Value string `json:"value"`
Required int8 `json:"required"`
}
type ChanceSubmitRequest struct {
AuditTemplateId int64 `json:"audit_template_id" valid:"Required"`
Id int64 `json:"id"` // = 0添加 >0 编辑
AuditTemplateId int64 `json:"auditTemplateId" valid:"Required"`
Content string `json:"content" valid:"Required"`
FormList []*Form `json:"form_list" valid:"Required"`
FormList []*Form `json:"formList" valid:"Required"`
Speechs []Speech `json:"speechs"`
Pictures []Picture `json:"pictures"`
Videos []Video `json:"videos"`
RelatedDepartment int64 `json:"related_departments" valid:"Required"`
RelatedDepartment int64 `json:"relatedDepartments" valid:"Required"`
}
type ChanceSubmitResponse struct {
... ...
... ... @@ -3,13 +3,14 @@ package protocol
import "time"
const (
DepartmentAll = iota + 1 //公司所有部门
DepartmentUser //用户所有部门
DepartmentUser = iota //用户所有部门
DepartmentAll //公司所有部门
)
/*Departments */
type DepartmentsRequest struct {
Type int `json:"type" valid:"Required"` //1:公司所有部门 2:用户所在部门
//Type int `json:"type" valid:"Required"` //1:公司所有部门 2:用户所在部门
Type int `json:"type"` //0:用户所在部门 1:公司所有部门
}
type DepartmentsResponse struct {
Departments []*Department `json:"departments,omitempty"`
... ...
... ... @@ -26,7 +26,7 @@ var errmessge ErrorMap = map[int]string{
4140: "refreshToken过期,需要重新登录授权",
4141: "accessToken过期或无效,需要进行重新获取令牌",
4142: "Uuid已存在,请求失败",
4201: "无该公司",
5000: "繁忙,请稍后再试",
}
... ...
... ... @@ -36,11 +36,12 @@ type ChangePasswordResponse struct {
type UserCompanysRequest struct {
}
type UserCompanysResponse struct {
Companys []Company `json:"companys"`
}
/*SwitchCompany */
type SwitchCompanyRequest struct {
CompanyId int64 `json:"company_id" valid:"Required"`
CompanyId int64 `json:"companyId" valid:"Required"`
}
type SwitchCompanyResponse struct {
}
... ... @@ -103,3 +104,9 @@ type User struct {
CompanyId int `json:"companyId"`
Company string `json:"company"` //公司名称
}
type Company struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
\ No newline at end of file
... ...
... ... @@ -57,14 +57,6 @@ func init() {
beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
beego.ControllerComments{
Method: "ChanceSubmit",
Router: `/chanceSubmit`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
beego.ControllerComments{
Method: "ChanceType",
Router: `/chanceType`,
AllowHTTPMethods: []string{"post"},
... ... @@ -121,6 +113,14 @@ func init() {
beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
beego.ControllerComments{
Method: "ChanceSubmit",
Router: `/submit`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"] = append(beego.GlobalControllerRouter["opp/controllers/v1:ChanceController"],
beego.ControllerComments{
Method: "SympathyAction",
Router: `/sympathyAction`,
AllowHTTPMethods: []string{"post"},
... ...
... ... @@ -147,7 +147,7 @@ func GetChance(chanceId int64, companyId int64) (v *protocol.ChanceDetail, err e
Provider: baseUserInfo,
Content: c.Content,
ChanceType: c.ChanceType,
ChanceType: c.ChanceTypeId,
ViewTotal: c.ViewTotal,
CommentTotal: c.CommentTotal,
ZanTotal: c.ZanTotal,
... ...
... ... @@ -76,7 +76,7 @@ func SympathyAction(header *protocol.RequestHeader, request *protocol.SympathyAc
log.Error("机会不存在", err)
return
}
chanceType = chance.ChanceType
chanceType = chance.ChanceTypeId
table = "chance"
}
if chanceFavoirte != nil {
... ... @@ -159,7 +159,7 @@ func Templates(header *protocol.RequestHeader, request *protocol.TemplatesReques
forms []*models.AuditForm
)
rsp = &protocol.TemplatesResponse{}
if templates, err = models.GetAuditTemplates(header.CompanyId, request.ChanceType); err != nil {
if templates, err = models.GetAuditTemplates(header.CompanyId, request.ChanceTypeId); err != nil {
log.Error(err)
return
}
... ... @@ -225,7 +225,7 @@ func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmit
Id: idgen.Next(),
UserId: header.Uid,
CompanyId: header.CompanyId,
ChanceType: template.ChanceType,
ChanceTypeId: template.ChanceTypeId,
AuditTemplateId: template.Id,
AuditTemplateConfig: common.AssertJson(auditConfig),
Content: request.Content,
... ... @@ -255,30 +255,119 @@ func ChanceSubmit(header *protocol.RequestHeader, request *protocol.ChanceSubmit
orm.Rollback()
return
}
}
//6.文件
for _, v := range GenSpeechs(chance.Id, request.Speechs) {
if _, err = orm.Insert(v); err != nil {
{
data :=&models.ChanceData{
Id:idgen.Next(),
ChanceId:chance.Id,
Speechs:common.AssertJson(request.Speechs),
Images:common.AssertJson(request.Pictures),
Videos:common.AssertJson(request.Videos),
CreateAt:time.Now(),
UpdateAt:time.Now(),
}
if _, err = orm.Insert(data); err != nil {
log.Error(err)
orm.Rollback()
return
}
}
for _, v := range GenVideos(chance.Id, request.Videos) {
if _, err = orm.Insert(v); err != nil {
orm.Commit()
//6.激活审核流
//TODO:7.发送消息通知给审核人(审核消息)
rsp = &protocol.ChanceSubmitResponse{}
return
}
func ChanceUpdate(header *protocol.RequestHeader, request *protocol.ChanceSubmitRequest) (rsp *protocol.ChanceSubmitResponse, err error) {
var (
template *models.AuditTemplate
chance *models.Chance
auditConfig *protocol.AuditConfig
chanceData *models.ChanceData
//auditFlows []*models.AuditFlowProcess
updateMap =make(map[string]interface{})
)
if chance,err =models.GetChanceById(request.Id);err!=nil{
log.Error(err)
return
}
//TODO:非本人 1.需要验证角色权限,是否是审核人
if chance.UserId!=header.Uid{
err = protocol.NewErrWithMessage(1)
log.Error(fmt.Sprintf("user:%v 无权限操作机会 chance:%v",header.Uid,chance.Id))
return
}
//TODO:验证机会当前是否在审核中
//1.模板是否存在
if template, err = models.GetAuditTemplateById(request.AuditTemplateId); err != nil {
log.Error("模板不存在:", request.AuditTemplateId, err)
return
}
auditConfig = &protocol.AuditConfig{NoApprover: template.NoApprover}
orm := orm.NewOrm()
orm.Begin()
{
updateMap["AuditTemplateConfig"] = common.AssertJson(auditConfig)
updateMap["Content"] = request.Content
updateMap["SourceContent"] = common.AssertJson(request.FormList)
updateMap["DepartmentId"] = request.RelatedDepartment
if err = utils.UpdateTableByMapWithOrmer(orm,&models.Chance{Id:chance.Id},updateMap); err != nil {
log.Error(err)
orm.Rollback()
return
}
}
for _, v := range GenImages(chance.Id, request.Pictures) {
if _, err = orm.Insert(v); err != nil {
//4.查询审核配置
//5.生成审核流 删除旧的 生成新的
//if auditFlows, err = GenAuditFlowProcess(header, chance.Id, template.Id, auditConfig); err != nil {
// log.Error(err)
// orm.Rollback()
// return
//}
//for i := 0; i < len(auditFlows); i++ {
// if _, err = orm.Insert(auditFlows[i]); err != nil {
// log.Error(err)
// orm.Rollback()
// return
// }
//}
//6.更新文件
{
if chanceData,err = models.GetChanceDataByChanceId(chance.Id);err==nil{
if err = utils.UpdateTableByMapWithOrmer(orm,chanceData,map[string]interface{}{
"Speechs":common.AssertJson(request.Speechs),
"Images":common.AssertJson(request.Pictures),
"Videos":common.AssertJson(request.Videos),
"UpdateAt":time.Now(),
});err!=nil{
log.Error(err)
orm.Rollback()
return
}
}else{
data :=&models.ChanceData{
Id:idgen.Next(),
ChanceId:chance.Id,
Speechs:common.AssertJson(request.Speechs),
Images:common.AssertJson(request.Pictures),
Videos:common.AssertJson(request.Videos),
CreateAt:time.Now(),
UpdateAt:time.Now(),
}
if _, err = orm.Insert(data); err != nil {
log.Error(err)
orm.Rollback()
return
}
}
}
orm.Commit()
//6.激活审核流
... ...
... ... @@ -179,8 +179,21 @@ func ChangePassword(header *protocol.RequestHeader, request *protocol.ChangePass
//用户公司
func UserCompanys(header *protocol.RequestHeader, request *protocol.UserCompanysRequest) (rsp *protocol.UserCompanysResponse, err error) {
var ()
var (
companys []*models.Company
)
rsp = &protocol.UserCompanysResponse{}
if companys,err =models.GetCompanyByPermission(header.Uid);err!=nil{
log.Error(err)
err = protocol.NewErrWithMessage(4201) //找不到这家公司
return
}
for i:=range companys{
rsp.Companys =append(rsp.Companys,protocol.Company{
Id:companys[i].Id,
Name:companys[i].Name,
})
}
return
}
... ... @@ -193,12 +206,17 @@ func SwitchCompany(header *protocol.RequestHeader, request *protocol.SwitchCompa
rsp = &protocol.SwitchCompanyResponse{}
if company, err = repository.UserCompany.GetUserCompanyByUserId(header.Uid, int64(request.CompanyId)); err != nil {
log.Error(err)
err = protocol.NewErrWithMessage(4201) //找不到这家公司
return
}
if auth, err = repository.UserAuth.GetUserAuthByUserId(header.Uid, header.DeviceType); err != nil {
if auth, err = repository.UserAuth.GetUserAuthByUserId(header.Uid, protocol.DeviceType); err != nil {
log.Error(err)
return
}
if auth.CurrentCompanyId == request.CompanyId{
log.Error(fmt.Sprintf("uid:%v 当前公司已经是:%v",header.Uid,request.CompanyId))
return
}
if err = utils.UpdateTableByMap(&models.UserAuth{Id: auth.Id}, map[string]interface{}{"CurrentCompanyId": company.CompanyId}); err != nil {
log.Error(err)
return
... ...
... ... @@ -271,3 +271,327 @@
}
}
```
### 公司列表
* URL: /v1/user/userCompanys
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
}
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {
"companys": [
{
"id": 1,
"name": "test_company"
},
{
"id": 2,
"name": "dyt_company"
}
]
}
}
```
### 切换公司
* URL: /v1/user/switchCompany
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
"companyId":1
}
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {}
}
```
## 机会
### 机会类型
* URL: /v1/chance/chanceType
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
}
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {
"list": [
{
"id": 1,
"name": "产品",
"icon": ""
},
{
"id": 2,
"name": "渠道",
"icon": ""
},
{
"id": 3,
"name": "客户",
"icon": ""
},
{
"id": 4,
"name": "区域",
"icon": ""
},
{
"id": 5,
"name": "其他",
"icon": ""
}
]
}
}
```
### 机会模板
* URL: /v1/chance/templates
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
"chanceTypeId":1
}
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {
"list": [
{
"id": 1,
"name": "产品-1",
"doc": "新型产品1",
"icon": "",
"formList": [
{
"id": 1,
"name": "产品名称",
"inputType": "text",
"sectionType": 1,
"value": "",
"required": 0
},
{
"id": 2,
"name": "竞品",
"inputType": "text",
"sectionType": 2,
"value": "",
"required": 0
}
]
}
]
}
}
```
### 提交机会
* URL: /v1/chance/submit
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
"id":279802775016046593,
"auditTemplateId": 1,
"content": "是否素:是\n 出厂价格:¥100 \n",
"formList": [{
"lable": "是否素食",
"inputType": "text",
"section": 1,
"value": ""
},
{
"lable": "竞品",
"inputType": "text",
"section": 2,
"value": ""
}
],
"speechs": [{
"path": "www.xx.com/file/xx/xx...",
"duration": 60
},
{
"path": "www.xx.com/file/xx/xx...",
"duration": 30
}
],
"pictures": [{
"path": "www.xx.com/file/xx/xx...",
"w": 600,
"h": 600
},
{
"path": "www.xx.com/file/xx/xx...",
"w": 600,
"h": 600
}
],
"videos": [{
"path": "www.xx.com/file/xx/xx...",
"cover": "www.xx.com/file/xx/xx...",
"duration": 60
},
{
"path": "www.xx.com/file/xx/xx...",
"cover": "www.xx.com/file/xx/xx...",
"duration": 30
}
],
"relatedDepartments": 1
}
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {}
}
```
## 文件上传
### 上传图片
* URL: /v1/upload/image
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
}
```
```
form-data: file
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {
"paths": [
"http:/192.168.139.137:8080/file/opp/image/20191214/1576290273_H7WDQpksZyXaGxmwKQDC5T6mhQBMTF3M.png"
]
}
}
```
### 上传语音
* URL: /v1/upload/voice
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
}
```
```
form-data: file
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {
"paths": [
"http:/192.168.139.137:8080/file/opp/voice/20191214/1576290273_H7WDQpksZyXaGxmwKQDC5T6mhQBMTF3M.wav"
]
}
}
```
### 上传视频
* URL: /v1/upload/video
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
}
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {
"paths": [
"http:/192.168.139.137:8080/file/opp/video/20191214/1576290351_R3h4nQxxcMJ7ympktMsYBBQ6bAcFC6xj.mp3"
]
}
}
```
## 部门统计
### 部门列表
* URL: /v1/department/departments
* 格式: JSON
* HTTP请求方式: POST
* 请求示例
```json
{
"type": 0
}
```
* 应答示例
```json
{
"code": 0,
"msg": "成功",
"data": {
"departments": [
{
"id": 1,
"name": "部门1"
}
]
}
}
```
\ No newline at end of file
... ...