Browse Source

Merge branch 'master' of http://8.136.199.33:3000/hongze/hz_crm_api into crm/crm_14.7.1

xingzai 9 tháng trước cách đây
mục cha
commit
5d43ff159d
67 tập tin đã thay đổi với 3737 bổ sung530 xóa
  1. 3 1
      controllers/company_apply.go
  2. 8 8
      controllers/company_apply_v2.go
  3. 7 0
      controllers/company_user.go
  4. 51 4
      controllers/cygx/activity.go
  5. 5 0
      controllers/cygx/activity_signup.go
  6. 8 3
      controllers/cygx/activity_special_trip.go
  7. 5 5
      controllers/cygx/enter_score.go
  8. 3 3
      controllers/cygx/industrial_management.go
  9. 592 0
      controllers/cygx/order.go
  10. 34 10
      controllers/cygx/yanxuan_special.go
  11. 18 13
      controllers/day_new.go
  12. 16 379
      controllers/english_report/english_classify.go
  13. 290 0
      controllers/eta_business/eta_business.go
  14. 153 13
      controllers/roadshow/calendar.go
  15. 173 0
      controllers/roadshow/calendar_meeting_user.go
  16. 7 3
      controllers/roadshow/company.go
  17. 12 7
      controllers/roadshow/report.go
  18. 26 1
      controllers/yb/road_video.go
  19. 6 0
      controllers/yb_research_signup_statistics.go
  20. 1 0
      go.mod
  21. 3 0
      go.sum
  22. 16 8
      models/company/company_approval.go
  23. 8 0
      models/company/company_contract.go
  24. 10 1
      models/company/company_product.go
  25. 18 0
      models/cygx/activity_appointment.go
  26. 33 0
      models/cygx/activity_ask_email.go
  27. 17 0
      models/cygx/activity_help_ask.go
  28. 3 3
      models/cygx/chart_permission.go
  29. 47 1
      models/cygx/cygx_user_record.go
  30. 2 1
      models/cygx/cygx_yanxuan_special.go
  31. 138 0
      models/cygx/orde.go
  32. 90 0
      models/cygx/order_action.go
  33. 58 0
      models/cygx/order_refund.go
  34. 29 0
      models/cygx/user_business_card.go
  35. 5 1
      models/day_new/day_new_default.go
  36. 9 8
      models/day_new/wework_msg.go
  37. 9 5
      models/db.go
  38. 27 17
      models/english_report.go
  39. 12 0
      models/eta_business/eta_business.go
  40. 40 0
      models/eta_business/eta_business_contract.go
  41. 3 1
      models/eta_business/eta_business_operation_record.go
  42. 19 3
      models/permission.go
  43. 8 2
      models/roadshow/calendar.go
  44. 1 1
      models/roadshow/company.go
  45. 96 0
      models/roadshow/rs_calendar_meeting_user.go
  46. 1 1
      models/system/sys_admin.go
  47. 24 0
      models/user_record.go
  48. 11 0
      models/wx_user.go
  49. 81 0
      routers/commentsRouter.go
  50. 2 0
      routers/router.go
  51. 2 1
      services/company_apply/company_approval.go
  52. 18 0
      services/company_approval_message.go
  53. 61 0
      services/contract/contract.go
  54. 35 1
      services/cygx/acitvity.go
  55. 160 0
      services/cygx/activity_poster.go
  56. 2 0
      services/cygx/activity_power_check.go
  57. 37 1
      services/cygx/admin_power.go
  58. 18 4
      services/cygx/industry_fllow.go
  59. 39 0
      services/cygx/order.go
  60. 28 1
      services/cygx/research_summary.go
  61. 125 0
      services/cygx/wx_pay.go
  62. 27 11
      services/eta_business/eta_business.go
  63. 11 1
      services/roadshow/calendar.go
  64. 828 0
      services/wechat_send_category_template_msg.go
  65. 36 2
      utils/common.go
  66. 48 5
      utils/config.go
  67. 24 0
      utils/constants.go

+ 3 - 1
controllers/company_apply.go

@@ -2089,6 +2089,7 @@ func (this *CompanyApplyController) ApplyContract() {
 		//mapChartPermissionId := make(map[int]int)
 		mapChartPermissionName := make(map[string]string) // 行业主客观防止重复写入Items用的
 		filterPermissionName := []string{}
+		mapPermissionNameUpgrade := make(map[string]bool) //升级权限重复
 		if totalForever == 0 {
 			filterPermissionName = []string{"专家", "路演服务"} // 需要过滤不展示的行业
 		} else {
@@ -2160,13 +2161,14 @@ func (this *CompanyApplyController) ApplyContract() {
 
 			plist.Items = append(plist.Items, n)
 
-			if totalForever == 0 {
+			if totalForever == 0 && !mapPermissionNameUpgrade[n.PermissionName] {
 				t := new(company.PermissionLookItem)
 				t.ChartPermissionId = n.ChartPermissionId + utils.PERMISSION_ID_UPGRADE
 				t.PermissionName = n.PermissionName + "(升级)"
 				t.PermissionType = n.PermissionType
 				t.Checked = n.Checked
 				plist.Items = append(plist.Items, t)
+				mapPermissionNameUpgrade[n.PermissionName] = true
 			}
 		}
 		//}

+ 8 - 8
controllers/company_apply_v2.go

@@ -101,9 +101,9 @@ func (this *CompanyApplyController) ApplyServiceUpdate() {
 		//权益的新签合同重新定义,如果合同起始时间在新签合同起始日期 1年之内的,仍为新签合同。
 		raicontractType = req.ContractType
 		if raicontractType != "新签合同" {
-			startDateTime, _ := time.Parse(utils.FormatDate, req.StartDate)
-			startDateTime = startDateTime.AddDate(-1, 0, 0)
-			totalLastYear, err := company.GetCompanyContractCountRaiByLastYear(req.CompanyId, startDateTime.Format(utils.FormatDate))
+			//startDateTime, _ := time.Parse(utils.FormatDate, req.StartDate)
+			//startDateTime = startDateTime.AddDate(-1, 0, 0)
+			totalLastYear, err := contractService.GetCompanyContractCountRaiByLastYear(req.CompanyId, req.StartDate)
 			if err != nil {
 				br.Msg = "获取合同信息失败"
 				br.ErrMsg = "获取合同信息失败,Err:" + err.Error()
@@ -617,9 +617,9 @@ func (this *CompanyApplyController) ApplyTurnPositive() {
 			//权益的新签合同重新定义,如果合同起始时间在新签合同起始日期 1年之内的,仍为新签合同。
 			raicontractType = contractType
 			if raicontractType != "新签合同" {
-				startDateTime, _ := time.Parse(utils.FormatDate, req.StartDate)
-				startDateTime = startDateTime.AddDate(-1, 0, 0)
-				totalLastYear, err := company.GetCompanyContractCountRaiByLastYear(req.CompanyId, startDateTime.Format(utils.FormatDate))
+				//startDateTime, _ := time.Parse(utils.FormatDate, req.StartDate)
+				//startDateTime = startDateTime.AddDate(-1, 0, 0)
+				totalLastYear, err := contractService.GetCompanyContractCountRaiByLastYear(req.CompanyId, req.StartDate)
 				if err != nil {
 					br.Msg = "获取合同信息失败"
 					br.ErrMsg = "获取合同信息失败,Err:" + err.Error()
@@ -1142,8 +1142,8 @@ func (this *CompanyApplyController) ApplyBySystemContract() {
 		//权益的新签合同重新定义,如果合同起始时间在新签合同起始日期 1年之内的,仍为新签合同。
 		raicontractType = contractType
 		if raicontractType != "新签合同" {
-			startDateTime := contractDetail.StartDate.AddDate(-1, 0, 0)
-			totalLastYear, err := company.GetCompanyContractCountRaiByLastYear(req.CompanyId, startDateTime.Format(utils.FormatDate))
+			//startDateTime := contractDetail.StartDate.AddDate(-1, 0, 0)
+			totalLastYear, err := contractService.GetCompanyContractCountRaiByLastYear(req.CompanyId, contractDetail.StartDate.Format(utils.FormatDate))
 			if err != nil {
 				br.Msg = "获取合同信息失败"
 				br.ErrMsg = "获取合同信息失败,Err:" + err.Error()

+ 7 - 0
controllers/company_user.go

@@ -2805,6 +2805,13 @@ func (this *CompanyController) UserMove() {
 	//联系人信息
 	originalUserInfo, _ := json.Marshal(oldWxUser)
 	userInfo, _ := json.Marshal(wxUser)
+	{
+		// 最新的联系人信息
+		newWxUser, err := models.GetWxUserByUserId(req.UserId)
+		if err == nil {
+			userInfo, _ = json.Marshal(newWxUser)
+		}
+	}
 	go services.AddWxUserOpLog(company.WxUserOpLog{
 		LogType:                "move",
 		UserId:                 int(wxUser.UserId),

+ 51 - 4
controllers/cygx/activity.go

@@ -728,21 +728,43 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 				errAct = err
 				if activityInfo.PublishStatus == 1 && activityInfo.ActivityTimeText != item.ActivityTimeText {
 					go services.SendWxMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.ActivityTimeText, item.ActivityTimeText, "timeType")
+					if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+						activityTime, err := time.Parse(utils.FormatDateTime, item.ActivityTime)
+						if err != nil {
+							br.Msg = "转换失败"
+							br.ErrMsg = "转换失败,Err:" + err.Error()
+							return
+						}
+						activityTimeStr := activityTime.Format(utils.FormatDateTimeMinute2)
+						go services.SendWxCategoryMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.ActivityTimeText, activityTimeStr, "timeType")
+					}
 				}
 				oldExpert, _ := cygx.GetReportContentTextSub(activityInfo.Expert)
 				newExpert, _ := cygx.GetReportContentTextSub(item.Expert)
 				if activityInfo.PublishStatus == 1 && oldExpert != newExpert {
 					go services.SendWxMsgWithCygxActivityUpdateTime(req.ActivityId, oldExpert, newExpert, "expertType")
+					if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+						go services.SendWxCategoryMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.ActivityTimeText, newExpert, "expertType")
+					}
 				}
 				if activityInfo.PublishStatus == 1 && activityInfo.Address != item.Address {
 					go services.SendWxMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.Address, item.Address, "addressType")
+					if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+						go services.SendWxCategoryMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.ActivityTimeText, item.Address, "addressType")
+					}
 				}
 				if activityInfo.PublishStatus == 1 && activityInfo.ParticipationCode != item.ParticipationCode {
 					go services.SendWxMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.ParticipationCode, item.ParticipationCode, "participationCode")
+					if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+						go services.SendWxCategoryMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.ActivityTimeText, item.ParticipationCode, "participationCode")
+					}
 				}
 
 				if activityInfo.PublishStatus == 1 && activityInfo.Theme != item.Theme {
 					go services.SendWxMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.Theme, item.Theme, "Theme")
+					if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+						go services.SendWxCategoryMsgWithCygxActivityUpdateTime(req.ActivityId, activityInfo.ActivityTimeText, item.Theme, "Theme")
+					}
 				}
 
 				//对于限制人数的活动,如果修改改了可见范围,对于新增的那一部分做新的推送
@@ -766,6 +788,9 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 				//修改活动人数限制之后,对于因为人数已满而失败的用户,推送模板消息
 				if activityInfo.PublishStatus == 1 && activityInfo.IsLimitPeople != 0 && activityInfo.LimitPeopleNum != strconv.Itoa(req.LimitPeopleNum) {
 					go cygxService.SendWxMsgWithCygxActivityUpdateLimitPeople(req.ActivityId)
+					if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+						go services.SendWxCategoryMsgWithCygxActivityUpdateLimitPeople(activityId)
+					}
 				}
 				go cygxService.YiDongSaveRoadshowDetail(activityId)
 
@@ -1290,6 +1315,9 @@ func (this *ActivityCoAntroller) PublishAndCancel() {
 		go services.SendWxMsgWithCygxActivity(req.ActivityId)
 		//同步活动到最新数据表
 		//go cygxService.UpdateResourceData(req.ActivityId, "activity", "delete", "")
+		if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+			go services.SendWxCategoryMsgWithCygxActivity(req.ActivityId)
+		}
 	}
 	item.ActivityId = req.ActivityId
 	if item.PublishStatus == 1 {
@@ -1415,10 +1443,29 @@ func (this *ActivityCoAntroller) ChartPermissionListAct() {
 		br.Ret = 408
 		return
 	}
-	//数据库新加行业分类,与之前的项目权限部分冲突太多,故采用自定义而不去数据库查找
-	resp := new(cygx.ChartPermissionRepMoreList)
-	// 查研观向7.4-策略后面新增一个宏观
-	resp.List = cygxService.GetActChartPermissionList()
+
+	resp := new(cygx.ChartPermissionResp)
+	list, err := cygx.GetChartPermissionAll()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+
+	for _, v := range list {
+		if v.PermissionName == utils.CHART_PERMISSION_NAME_MF_YANXUAN || v.PermissionName == utils.YAN_XUAN_KOU_DIAN_BAO_NAME {
+			continue
+		}
+		resp.List = append(resp.List, v)
+	}
+
+	// 查研观向7.4-新增一个宏观
+	macro := &cygx.ChartPermission{
+		ChartPermissionId: 1,
+		PermissionName:    "宏观",
+	}
+	resp.List = append(resp.List, macro)
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"

+ 5 - 0
controllers/cygx/activity_signup.go

@@ -939,6 +939,7 @@ func (this *ActivitySignupCoAntroller) SalonSignupEdit() {
 	//销售或后台管理员给用户添加报名之后,进行模版消息推送
 	if doFailType == 0 {
 		go cygxService.SendWxMsgWithCygxActivitySignUpBySell(itemsSendWxMsg)
+		go services.SendWxCategoryMsgWithCygxActivitySignUpBySell(itemsSendWxMsg)
 	}
 	//添加操作日志记录
 	br.Ret = 200
@@ -2055,6 +2056,7 @@ func (this *ActivitySignupCoAntroller) AddSignuUser() {
 	//销售或后台管理员给用户添加报名之后,进行模版消息推送
 	if len(itemsSendWxMsg) > 0 {
 		go cygxService.SendWxMsgWithCygxActivitySignUpBySell(itemsSendWxMsg)
+		go services.SendWxCategoryMsgWithCygxActivitySignUpBySell(itemsSendWxMsg)
 	}
 	if len(items) > 0 {
 		//1用户报名添加到处理研选扣点
@@ -2480,6 +2482,9 @@ func (this *ActivitySignupCoAntroller) SignupCancel() {
 		return
 	}
 	go cygxService.YanXuanActivityPointsBillSignupCancel(detail.ActivityId, detail.UserId, adminInfo.AdminId)
+	if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN{
+		go services.SendWxCategoryMsgWithYxActivityCancelSignUpBySell(detail.UserId, activityInfo.ActivityId)
+	}
 	//添加操作日志记录
 	br.IsAddLog = true
 	br.Ret = 200

+ 8 - 3
controllers/cygx/activity_special_trip.go

@@ -135,6 +135,9 @@ func (this *ActivitySpecialTripCoAntroller) AddUser() {
 				br.ErrMsg = "获取日程数量信息失败,Err:" + err.Error()
 				return
 			}
+			if totalAll > 0 {
+				continue
+			}
 			//流水记录表
 			itemBill := new(cygx.CygxActivitySpecialTripBill)
 			itemBill.UserId = infoUser.UserId
@@ -153,8 +156,9 @@ func (this *ActivitySpecialTripCoAntroller) AddUser() {
 			itemBill.ChartPermissionName = activityInfo.ChartPermissionName
 			itemBill.AdminId = AdminUser.AdminId
 
-			if activityInfo.ChartPermissionName == utils.CE_LUE_NAME || activityInfo.ChartPermissionName == utils.GU_SHOU_NAME {
-				//如果是策略、固收行业,把代扣行业信息放入流水表,取消报名的时候,返点使用
+			//if activityInfo.ChartPermissionName == utils.CE_LUE_NAME || activityInfo.ChartPermissionName == utils.GU_SHOU_NAME {
+			if utils.InArrayByStr(utils.ACTIVITY_SPECIAL_TRIP_PERMISSION_NAME_OTHER, activityInfo.ChartPermissionName) {
+				//如果是策略、固收、周期行业,把代扣行业信息放入流水表,取消报名的时候,返点使用
 				maxChartPermissionId, maxChartPermissionName, err := cygxService.GetSpecialBillMaxChartPermissionId(infoUser)
 				if err != nil {
 					br.Msg = "操作失败"
@@ -568,7 +572,8 @@ func (this *ActivitySpecialTripCoAntroller) TripCancel() {
 	itemBill.ChartPermissionName = activityInfo.ChartPermissionName
 	itemBill.AdminId = sysUser.AdminId
 
-	if activityInfo.ChartPermissionName == utils.CE_LUE_NAME || activityInfo.ChartPermissionName == utils.GU_SHOU_NAME {
+	//if activityInfo.ChartPermissionName == utils.CE_LUE_NAME || activityInfo.ChartPermissionName == utils.GU_SHOU_NAME {
+	if utils.InArrayByStr(utils.ACTIVITY_SPECIAL_TRIP_PERMISSION_NAME_OTHER, activityInfo.ChartPermissionName) {
 		//如果是策略、固收行业,把代扣行业信息放入流水表,取消报名的时候,返点使用
 		lastTripBill, err := cygx.GetCygxActivitySpecialTripBillLastDetialByActivityId(activityInfo.ActivityId, userId)
 		if err != nil {

+ 5 - 5
controllers/cygx/enter_score.go

@@ -59,7 +59,7 @@ func (this *EnterScoreController) CompanySearchList() {
 	}
 
 	//权益申请销售只能看到自己名下的客户的申请
-	companyIds, err := cygxService.GetAdminLookUserCompanyIdsBySelf(sysUser)
+	companyIds, err := cygxService.GetAdminLookUserCompanyIdsByResearcher(sysUser)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,GetAdminLookUserCompanyIds Err:" + err.Error()
@@ -169,7 +169,7 @@ func (this *EnterScoreController) EnterScoreDetail() {
 			mapFiccUser[v.GroupName] = append(mapFiccUser[v.GroupName], item)
 		}
 
-		permissionFiccNameArr := []string{"宏观组", "建材组", "有色组", "能化组"}
+		permissionFiccNameArr := []string{"宏观组", "建材组", "有色组", "能化组", "海外组"}
 		for _, v := range permissionFiccNameArr {
 			item := new(cygx.EnterScorePermissionListResp)
 			item.ChartPermissionName = v
@@ -541,7 +541,7 @@ func (this *EnterScoreController) EnterScoreList() {
 	var condition string
 	var pars []interface{}
 	//如果不是权益管理员和admin,就做可见权限限制
-	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_RAI_ADMIN && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_RAI_ADMIN && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_RAI_RESEARCHR {
 		var conditionAdmin string
 		var parsAdmin []interface{}
 		conditionAdmin = "  AND product_id = 2  AND   status = '永续'  AND seller_id =  ?  "
@@ -826,7 +826,7 @@ func (this *EnterScoreController) EnterScoreScoreOverview() {
 	}
 
 	//权益申请销售只能看到自己名下的客户的申请
-	companyIds, err := cygxService.GetAdminLookUserCompanyIdsBySelf(AdminUser)
+	companyIds, err := cygxService.GetAdminLookUserCompanyIdsByResearcher(AdminUser)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,GetAdminLookUserCompanyIds Err:" + err.Error()
@@ -1347,7 +1347,7 @@ func (this *EnterScoreController) EnterScoreRankingOverview() {
 	}
 
 	//权益申请销售只能看到自己名下的客户的申请
-	companyIds, err := cygxService.GetAdminLookUserCompanyIdsBySelf(AdminUser)
+	companyIds, err := cygxService.GetAdminLookUserCompanyIdsByResearcher(AdminUser)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,GetAdminLookUserCompanyIdsBySelf Err:" + err.Error()

+ 3 - 3
controllers/cygx/industrial_management.go

@@ -188,7 +188,7 @@ func (this *IndustrialManagementController) ChartPermissionFirstProduct() {
 	}
 	//医药消费科技制造策略
 	for _, v := range list {
-		if v.PermissionName == utils.YI_YAO_NAME || v.PermissionName == utils.XIAO_FEI_NAME || v.PermissionName == utils.KE_JI_NAME || v.PermissionName == utils.ZHI_ZAO_NAME || v.PermissionName == utils.CE_LUE_NAME || v.PermissionName == utils.GU_SHOU_NAME {
+		if v.PermissionName == utils.YI_YAO_NAME || v.PermissionName == utils.XIAO_FEI_NAME || v.PermissionName == utils.KE_JI_NAME || v.PermissionName == utils.ZHI_ZAO_NAME || v.PermissionName == utils.CE_LUE_NAME || v.PermissionName == utils.GU_SHOU_NAME || v.PermissionName == utils.ZHOU_QI_NAME {
 			resp.List = append(resp.List, v)
 		}
 	}
@@ -215,9 +215,9 @@ func (this *IndustrialManagementController) ChartPermissionListActivitySpecial()
 		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
 		return
 	}
-	//医药、消费、科技、制造、策略,固收
+	//医药、消费、科技、制造、策略,固收,周期
 	for _, v := range list {
-		if v.PermissionName == utils.YI_YAO_NAME || v.PermissionName == utils.XIAO_FEI_NAME || v.PermissionName == utils.KE_JI_NAME || v.PermissionName == utils.ZHI_ZAO_NAME || v.PermissionName == utils.CE_LUE_NAME || v.PermissionName == utils.GU_SHOU_NAME {
+		if v.PermissionName == utils.YI_YAO_NAME || v.PermissionName == utils.XIAO_FEI_NAME || v.PermissionName == utils.KE_JI_NAME || v.PermissionName == utils.ZHI_ZAO_NAME || v.PermissionName == utils.CE_LUE_NAME || v.PermissionName == utils.GU_SHOU_NAME || v.PermissionName == utils.ZHOU_QI_NAME {
 			resp.List = append(resp.List, v)
 		}
 	}

+ 592 - 0
controllers/cygx/order.go

@@ -0,0 +1,592 @@
+package cygx
+
+import (
+	"encoding/json"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hz_crm_api/controllers"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/cygx"
+	cygxService "hongze/hz_crm_api/services/cygx"
+	"hongze/hz_crm_api/utils"
+	"strconv"
+	"time"
+)
+
+// 产品内测
+type OrderController struct {
+	controllers.BaseAuthController
+}
+
+// @Title 列表
+// @Description 列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   StartDate   query   string  false       "开始时间 ,列如2021-03-06 "
+// @Param   EndDate   query   string  false       "结束时间,列如2021-03-06 "
+// @Param   AdminId   query   string  false       "销售ID "
+// @Param   ShareId   query   string  false       "推荐人ID "
+// @Param   PaymentType   query   string  false       "支付渠道  取值范围:1微信小程序,2微信扫码支付,3微信H5支付。 "
+// @Param   OrderType   query   int  false       "订单类型 1:畅读卡订单,2:单场付费订单"
+// @Param   OrderStatus   query   int  false       "订单状态,0:已取消、1:待支付、2:已支付、3:退款成功、4:退款处理中、5:退款异常、6:退款关闭"
+// @Param   PaymentProject   query   string  false       "付款项目"
+// @Param   UserCardType   query   string  false       "会员卡类型 ,日卡、月卡"
+// @Param   OrderCode   query   string  false       "订单编号"
+// @Param   KeyWord   query   string  false       "搜索关键词"
+// @Success Ret=200 {object} cygx.GetCygxTacticsTimeLineResp
+// @router /order/list [get]
+func (this *OrderController) OrderList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	resp := new(cygx.UserOrderListResp)
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	orderType, _ := this.GetInt("OrderType", 1)
+	orderStatus, _ := this.GetInt("OrderStatus", -1)
+	startDate := this.GetString("StartDate")
+	endDate := this.GetString("EndDate")
+	adminId := this.GetString("AdminId")
+	shareId := this.GetString("ShareId")
+	paymentType, _ := this.GetInt("PaymentType")
+	orderCode := this.GetString("OrderCode")
+	keyWord := this.GetString("KeyWord")
+	paymentProject := this.GetString("PaymentProject")
+	userCardType := this.GetString("UserCardType")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	var condition string
+	var pars []interface{}
+	if orderType > 0 { //订单类型 1:畅读卡订单,2:单场付费订单
+		condition += `  AND order_type =   ? `
+		pars = append(pars, orderType)
+	}
+
+	if startDate != "" && endDate != "" { //时间范围
+		condition += ` 	AND create_time  BETWEEN ?   AND  ? `
+		pars = append(pars, startDate+" 00:00:01", endDate+" 23:59:59")
+	}
+
+	if adminId != "" { //所属销售筛选
+		condition += ` 	AND seller_id IN (` + adminId + `) `
+	}
+
+	if shareId != "" { //推荐人ID
+		condition += ` 	AND share_id IN (` + shareId + `) `
+	}
+
+	if paymentType > 0 { // 支付渠道
+		var tradeType string
+		switch paymentType {
+		case 1:
+			tradeType = "JSAPI"
+		case 2:
+			tradeType = "NATIVE"
+		case 3:
+			tradeType = "MWEB"
+		}
+		condition += ` 	AND trade_type  = ?  `
+		pars = append(pars, tradeType)
+	}
+
+	if orderStatus > -1 { //订单状态
+		condition += ` 	AND order_status  = ?  `
+		pars = append(pars, orderStatus)
+	}
+
+	if orderCode != "" { //订单编号
+		orderCode = "%" + orderCode + "%"
+		condition += ` 	AND order_code LIKE ? `
+		pars = append(pars, orderCode)
+	}
+
+	if paymentProject != "" { //付款项目
+		condition += ` 	AND goods_name =  ? `
+		pars = append(pars, paymentProject)
+	}
+
+	if userCardType != "" { //日卡月卡, 前端不好区分这里用了两个字段
+		condition += ` 	AND goods_name =  ? `
+		pars = append(pars, userCardType)
+	}
+
+	if keyWord != "" { //用户姓名,手机号
+		keyWord = "%" + keyWord + "%"
+		condition += ` 	AND (mobile LIKE ?  OR  real_name LIKE ? ) `
+		pars = append(pars, keyWord, keyWord)
+	}
+
+	total, err := cygx.GetCygxOrderCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	condition += "	ORDER BY order_id  DESC "
+	list, err := cygx.GetCygxOrderList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	var mobiles []string
+	for _, v := range list {
+		mobiles = append(mobiles, v.Mobile)
+	}
+	inviteNameMap := cygxService.GetCygxUserBusinessCardMap(mobiles) // 根据手机号获取邀请人
+
+	for _, v := range list {
+		item := new(cygx.OrderListResp)
+		item.OrderCode = v.OrderCode
+		item.OrderMoney = v.OrderMoney
+		item.SourceId = v.SourceId
+		item.Source = v.Source
+		item.SourceTitle = v.SourceTitle
+		switch v.Source {
+		case utils.CYGX_OBJ_ARTICLE: //文章详情
+			item.HttpUrl = utils.CYGX_MFYX_URL + "/material/info/" + strconv.Itoa(v.SourceId)
+		case utils.CYGX_OBJ_ACTIVITY: //活动详情
+			item.HttpUrl = utils.CYGX_MFYX_URL + "/activity/detail/" + strconv.Itoa(v.SourceId)
+		case utils.CYGX_OBJ_YANXUANSPECIAL: //专栏详情
+			item.HttpUrl = utils.CYGX_MFYX_URL + "/column/detail/" + strconv.Itoa(v.SourceId)
+		}
+		item.OrderStatus = v.OrderStatus
+
+		switch item.OrderStatus {
+		case 0:
+			item.OrderStatusText = "已取消"
+		case 1:
+			item.OrderStatusText = "待支付"
+		case 2:
+			item.OrderStatusText = "已支付"
+		case 3:
+			item.OrderStatusText = "退款成功"
+		case 4:
+			item.OrderStatusText = "退款处理中"
+		case 5:
+			item.OrderStatusText = "退款异常"
+		case 6:
+			item.OrderStatusText = "退款关闭"
+		}
+
+		//TradeType        string    `comment:"交易类型,枚举值:JSAPI:公众号支付 、 NATIVE:扫码支付 、 App:App支付 、 MICROPAY:付款码支付 、 MWEB:H5支付 、 FACEPAY:刷脸支付"`
+		switch v.TradeType {
+		case "JSAPI":
+			item.PaymentTypeText = "小程序"
+		case "NATIVE":
+			item.PaymentTypeText = "PC"
+		case "MWEB":
+			item.PaymentTypeText = "H5"
+		}
+
+		item.UserId = v.UserId
+		item.RealName = v.RealName
+		item.Mobile = v.Mobile
+		item.Email = v.Email
+		item.CompanyId = v.CompanyId
+		item.CompanyName = v.CompanyName
+		item.SellerName = v.SellerName
+		if v.ShareName != "" {
+			item.InviteName = v.ShareName
+		} else {
+			item.InviteName = inviteNameMap[v.Mobile]
+		}
+		item.PaymentProject = v.GoodsName
+		if v.OrderStatus != 0 && v.OrderStatus != 1 {
+			item.PayTime = v.PayTime.Format(utils.FormatDateTime)
+		}
+		if orderType == 1 && v.OrderStatus != 0 && v.OrderStatus != 1 {
+			if v.GoodsId == 1 {
+				item.StartDate = v.StartDate.Format(utils.FormatDateTime)
+				item.EndDate = v.EndDate.Format(utils.FormatDateTime)
+			} else {
+				item.StartDate = v.StartDate.Format(utils.FormatDate)
+				item.EndDate = v.EndDate.Format(utils.FormatDate)
+			}
+		}
+		item.CreateTime = v.CreateTime.Format(utils.FormatDateTime)
+		resp.List = append(resp.List, item)
+	}
+	if len(resp.List) == 0 {
+		resp.List = make([]*cygx.OrderListResp, 0)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 退款
+// @Description 退款接口
+// @Param	request	body cygx.UserRemarAddReq true "type json string"
+// @Success 200 操作成功
+// @router /order/refund [post]
+func (this *UserController) OrderRefund() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req cygx.CygxOrderRefundReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	orderCode := req.OrderCode
+	remark := req.Remark
+
+	if remark == "" {
+		br.Msg = "请填写退款原因"
+		return
+	}
+	orderDetail, err := cygx.GetCygxOrderDetailByOrderCode(orderCode)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败, Err:" + err.Error()
+		return
+	}
+	if orderDetail.OrderStatus != 2 {
+		br.Msg = "订单状态异常!"
+		br.ErrMsg = "订单状态异常,orderCode:" + orderCode
+		return
+	}
+	//订单状态,0:已取消、1:待支付、2:已支付、3:退款成功、4:退款处理中、5:退款异常、6:退款关闭
+	statusCode, err := cygxService.RefundsApiService(orderDetail)
+	var orderStatus int
+	if statusCode == 200 && err == nil {
+		orderStatus = 4
+	} else {
+		orderStatus = 5
+	}
+	item := new(cygx.CygxOrderRefund)
+	item.OrderCode = orderCode
+	item.RefundMoney = orderDetail.OrderMoney
+	item.RefundWay = 1
+	item.Remark = remark
+	item.CreateTime = time.Now()
+	item.RefundTime = time.Now()
+	item.AdminId = sysUser.AdminId
+	item.AdminName = sysUser.RealName
+	err = cygx.AddCygxOrderRefund(item, orderStatus)
+	if err != nil {
+		br.Msg = "新增失败."
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "已提交退款,请到退款记录页面查看"
+}
+
+// @Title 退款记录列表
+// @Description 退款记录列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   StartDate   query   string  false       "开始时间 ,列如2021-03-06 "
+// @Param   EndDate   query   string  false       "结束时间,列如2021-03-06 "
+// @Param   AdminId   query   string  false       "销售ID "
+// @Param   ShareId   query   string  false       "推荐人ID "
+// @Param   PaymentType   query   string  false       "支付渠道  取值范围:1微信小程序,2微信扫码支付,3微信H5支付。 "
+// @Param   OrderType   query   int  false       "订单类型 1:畅读卡订单,2:单场付费订单"
+// @Param   OrderStatus   query   int  false       "订单状态,0:已取消、1:待支付、2:已支付、3:退款成功、4:退款处理中、5:退款异常、6:退款关闭"
+// @Param   PaymentProject   query   string  false       "付款项目"
+// @Param   UserCardType   query   string  false       "会员卡类型 ,日卡、月卡"
+// @Param   OrderCode   query   string  false       "订单编号"
+// @Param   KeyWord   query   string  false       "搜索关键词"
+// @Success Ret=200 {object} cygx.GetCygxTacticsTimeLineResp
+// @router /order/refund/list [get]
+func (this *OrderController) OrderRefundList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	resp := new(cygx.UserOrderListResp)
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	orderType, _ := this.GetInt("OrderType", 1)
+	orderStatus, _ := this.GetInt("OrderStatus", -1)
+	startDate := this.GetString("StartDate")
+	endDate := this.GetString("EndDate")
+	adminId := this.GetString("AdminId")
+	shareId := this.GetString("ShareId")
+	paymentType, _ := this.GetInt("PaymentType")
+	orderCode := this.GetString("OrderCode")
+	keyWord := this.GetString("KeyWord")
+	paymentProject := this.GetString("PaymentProject")
+	userCardType := this.GetString("UserCardType")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	var condition string
+	var pars []interface{}
+	condition += `  AND order_status  IN  (3,4,5,6) `
+	if orderType > 0 { //订单类型 1:畅读卡订单,2:单场付费订单
+		condition += `  AND order_type =   ? `
+		pars = append(pars, orderType)
+	}
+
+	if startDate != "" && endDate != "" { //时间范围
+		condition += ` 	AND create_time  BETWEEN ?   AND  ? `
+		pars = append(pars, startDate+" 00:00:01", endDate+" 23:59:59")
+	}
+
+	if adminId != "" { //所属销售筛选
+		condition += ` 	AND seller_id IN (` + adminId + `) `
+	}
+
+	if shareId != "" { //推荐人ID
+		condition += ` 	AND share_id IN (` + shareId + `) `
+	}
+
+	if paymentType > 0 { // 支付渠道
+		var tradeType string
+		switch paymentType {
+		case 1:
+			tradeType = "JSAPI"
+		case 2:
+			tradeType = "NATIVE"
+		case 3:
+			tradeType = "MWEB"
+		}
+		condition += ` 	AND trade_type  = ?  `
+		pars = append(pars, tradeType)
+	}
+
+	if orderStatus > -1 { //订单状态
+		condition += ` 	AND order_status  = ?  `
+		pars = append(pars, orderStatus)
+	}
+
+	if orderCode != "" { //订单编号
+		orderCode = "%" + orderCode + "%"
+		condition += ` 	AND order_code LIKE ? `
+		pars = append(pars, orderCode)
+	}
+
+	if paymentProject != "" { //付款项目
+		condition += ` 	AND goods_name =  ? `
+		pars = append(pars, paymentProject)
+	}
+
+	if userCardType != "" { //日卡月卡, 前端不好区分这里用了两个字段
+		condition += ` 	AND goods_name =  ? `
+		pars = append(pars, userCardType)
+	}
+
+	if keyWord != "" { //用户姓名,手机号
+		keyWord = "%" + keyWord + "%"
+		condition += ` 	AND (mobile LIKE ?  OR  real_name LIKE ? ) `
+		pars = append(pars, keyWord, keyWord)
+	}
+
+	total, err := cygx.GetCygxOrderCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	condition += "	ORDER BY order_id  DESC "
+	list, err := cygx.GetCygxOrderList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	var mobiles []string
+	for _, v := range list {
+		mobiles = append(mobiles, v.Mobile)
+	}
+	inviteNameMap := cygxService.GetCygxUserBusinessCardMap(mobiles) // 根据手机号获取邀请人
+	for _, v := range list {
+		item := new(cygx.OrderListResp)
+		item.OrderCode = v.OrderCode
+		item.OrderMoney = v.OrderMoney
+		item.SourceId = v.SourceId
+		item.Source = v.Source
+		item.SourceTitle = v.SourceTitle
+		switch v.Source {
+		case utils.CYGX_OBJ_ARTICLE: //文章详情
+			item.HttpUrl = utils.CYGX_MFYX_URL + "/material/info/" + strconv.Itoa(v.SourceId)
+		case utils.CYGX_OBJ_ACTIVITY: //活动详情
+			item.HttpUrl = utils.CYGX_MFYX_URL + "/activity/detail/" + strconv.Itoa(v.SourceId)
+		case utils.CYGX_OBJ_YANXUANSPECIAL: //专栏详情
+			item.HttpUrl = utils.CYGX_MFYX_URL + "/column/detail/" + strconv.Itoa(v.SourceId)
+		}
+		//OrderStatus      int       `comment:"订单状态,0:已取消、1:待支付、2:已支付、3:退款成功、4:退款处理中、5:退款异常、6:退款关闭"`
+		item.OrderStatus = v.OrderStatus
+		switch item.OrderStatus {
+		case 3:
+			item.OrderStatusText = "退款成功"
+		case 4:
+			item.OrderStatusText = "退款处理中"
+		case 5:
+			item.OrderStatusText = "退款异常"
+		case 6:
+			item.OrderStatusText = "退款关闭"
+		}
+
+		//TradeType        string    `comment:"交易类型,枚举值:JSAPI:公众号支付 、 NATIVE:扫码支付 、 App:App支付 、 MICROPAY:付款码支付 、 MWEB:H5支付 、 FACEPAY:刷脸支付"`
+		switch v.TradeType {
+		case "JSAPI":
+			item.PaymentTypeText = "小程序"
+		case "NATIVE":
+			item.PaymentTypeText = "PC"
+		case "MWEB":
+			item.PaymentTypeText = "H5"
+		}
+
+		item.UserId = v.UserId
+		item.RealName = v.RealName
+		item.Mobile = v.Mobile
+		item.Email = v.Email
+		item.CompanyId = v.CompanyId
+		item.CompanyName = v.CompanyName
+		item.SellerName = v.SellerName
+		if v.ShareName != "" {
+			item.InviteName = v.ShareName
+		} else {
+			item.InviteName = inviteNameMap[v.Mobile]
+		}
+
+		item.PaymentProject = v.GoodsName
+		switch v.GoodsId {
+		case 1:
+			item.PaymentProject = "日卡"
+		case 2:
+			item.PaymentProject = "月卡"
+		}
+
+		item.RefundTime = v.RefundTime.Format(utils.FormatDateTime)
+		item.RefundRemark = v.RefundRemark
+
+		//if v.OrderStatus == 2 {
+		item.PayTime = v.PayTime.Format(utils.FormatDateTime)
+		//}
+		if orderType == 1 {
+			if v.GoodsId == 1 {
+				item.StartDate = v.StartDate.Format(utils.FormatDateTime)
+				item.EndDate = v.EndDate.Format(utils.FormatDateTime)
+			} else {
+				item.StartDate = v.StartDate.Format(utils.FormatDate)
+				item.EndDate = v.EndDate.Format(utils.FormatDate)
+			}
+		}
+		item.CreateTime = v.CreateTime.Format(utils.FormatDateTime)
+		resp.List = append(resp.List, item)
+	}
+	if len(resp.List) == 0 {
+		resp.List = make([]*cygx.OrderListResp, 0)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 退款撤销
+// @Description 退款撤销接口
+// @Param	request	body cygx.UserRemarAddReq true "type json string"
+// @Success 200 操作成功
+// @router /order/refund_revoke [post]
+func (this *UserController) OrderRefundRevoke() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req cygx.CygxOrderRefundReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	orderCode := req.OrderCode
+	orderDetail, err := cygx.GetCygxOrderDetailByOrderCode(orderCode)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败, Err:" + err.Error()
+		return
+	}
+	if orderDetail.OrderStatus != 4 {
+		br.Msg = "订单状态异常!"
+		br.ErrMsg = "订单状态异常,orderCode:" + orderCode
+		return
+	}
+
+	item := new(cygx.CygxOrderAction)
+	item.Action = "关闭退款"
+	item.OrderStatus = 6
+	item.OrderStatusText = "关闭退款"
+	item.OrderCode = orderDetail.OrderCode
+	item.UserId = orderDetail.UserId
+	item.RealName = orderDetail.RealName
+	item.Mobile = orderDetail.Mobile
+	item.Email = orderDetail.Email
+	item.CompanyId = orderDetail.CompanyId
+	item.CompanyName = orderDetail.CompanyName
+	item.SellerName = orderDetail.SellerName
+	item.CreateTime = time.Now()
+	item.ModifyTime = time.Now()
+	item.AdminId = sysUser.AdminId
+	item.AdminName = sysUser.RealName
+
+	err = cygx.AddCygxOrderRefundRevoke(item)
+	if err != nil {
+		br.Msg = "新增失败."
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 34 - 10
controllers/cygx/yanxuan_special.go

@@ -9,6 +9,7 @@ import (
 	"hongze/hz_crm_api/models"
 	"hongze/hz_crm_api/models/company"
 	"hongze/hz_crm_api/models/cygx"
+	"hongze/hz_crm_api/services"
 	cygxService "hongze/hz_crm_api/services/cygx"
 	"hongze/hz_crm_api/services/elastic"
 	"hongze/hz_crm_api/utils"
@@ -536,10 +537,12 @@ func (this *YanxuanSpecialController) Enable() {
 	}
 	if req.Status == 1 {
 		go cygxService.SendWxMsgSpecialFollow(req.Id)
+		go services.SendWxCategoryMsgSpecialFollow(req.Id)
 	}
-	go cygxService.SendWxMsgSpecialAuthor(req.Id, req.Status) // 研选专栏审核完成时,给提交人发送模板消息
-	go cygxService.UpdateYanxuanSpecialResourceData(req.Id)   //  写入首页最新  cygx_resource_data 表
-	go elastic.EsAddYanxuanSpecial(req.Id)                    //  写入es 综合搜索
+	go cygxService.SendWxMsgSpecialAuthor(req.Id, req.Status)      // 研选专栏审核完成时,给提交人发送模板消息
+	go services.SendWxCategoryMsgSpecialAuthor(req.Id, req.Status) // 研选专栏审核完成时,给提交人发送模板消息
+	go cygxService.UpdateYanxuanSpecialResourceData(req.Id)        //  写入首页最新  cygx_resource_data 表
+	go elastic.EsAddYanxuanSpecial(req.Id)                         //  写入es 综合搜索
 	br.Msg = "审批成功"
 	br.Ret = 200
 	br.Success = true
@@ -798,25 +801,46 @@ func (this *YanxuanSpecialController) ShowButton() {
 	}
 
 	resp := new(cygx.CygxYanxuanSpecialShowButton)
-	configCode := utils.TPL_MSG_NEI_RONG_ZU
-	cnfNeiRong, err := cygx.GetConfigByCode(configCode)
+	//configCode := utils.TPL_MSG_NEI_RONG_ZU
+	//cnfNeiRong, err := cygx.GetConfigByCode(configCode)
+	//if err != nil {
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = "获取失败,Err:" + err.Error()
+	//	return
+	//}
+	////汪洋王芳手机号
+	//configCode = utils.TPL_MSG_WANG_FANG_WANG_YANG
+	//cnfWang, err := cygx.GetConfigByCode(configCode)
+	//if err != nil {
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = "获取失败,Err:" + err.Error()
+	//	return
+	//}
+
+	//文章管理专栏是否可见
+	cnfArticle, err := cygx.GetConfigByCode(utils.YANXUAN_SPECIAL_ARTICLE_BUTTON_MOBILE)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-	//汪洋王芳手机号
-	configCode = utils.TPL_MSG_WANG_FANG_WANG_YANG
-	cnfWang, err := cygx.GetConfigByCode(configCode)
+	articleMobileSlice := strings.Split(cnfArticle.ConfigValue, ",")
+	if utils.InArrayByStr(articleMobileSlice, sysUser.Mobile) || sysUser.Role == utils.ROLE_TYPE_CODE_ADMIN {
+		resp.IsShowYanXuanSpecial = true
+	}
+
+	//作者管理专栏是否可见
+	cnfAuthor, err := cygx.GetConfigByCode(utils.YANXUAN_SPECIAL_AUTHOR_BUTTON_MOBILE)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-	//作者管理栏,只有内容组、汪洋、王芳、超管可见
-	if strings.Contains(cnfNeiRong.ConfigValue, sysUser.Mobile) || strings.Contains(cnfWang.ConfigValue, sysUser.Mobile) || sysUser.Role == utils.ROLE_TYPE_CODE_ADMIN {
+	authorMobileSlice := strings.Split(cnfAuthor.ConfigValue, ",")
+	if utils.InArrayByStr(authorMobileSlice, sysUser.Mobile) || sysUser.Role == utils.ROLE_TYPE_CODE_ADMIN {
 		resp.IsShowSpecialAuthor = true
 	}
+
 	br.Data = resp
 	br.Ret = 200
 	br.Success = true

+ 18 - 13
controllers/day_new.go

@@ -378,7 +378,7 @@ func (this *DayNewController) AddReport() {
 		}
 	}
 
-	maxStage, err := models.GetEnglishReportStage(dayNewDefault.ClassifyIdFirst, dayNewDefault.ClassifyIdSecond)
+	maxStage, err := models.GetEnglishReportStage(dayNewDefault.ClassifyIdSecond, dayNewDefault.ClassifyIdThird)
 	if err != nil {
 		br.Msg = "期数获取失败!"
 		br.ErrMsg = "期数获取失败,Err:" + err.Error()
@@ -386,11 +386,11 @@ func (this *DayNewController) AddReport() {
 	}
 
 	item := new(models.EnglishReport)
-	item.AddType = 1 //新增方式:1:新增报告,2:继承报告
-	item.ClassifyIdFirst = dayNewDefault.ClassifyIdFirst
-	item.ClassifyNameFirst = dayNewDefault.ClassifyNameFirst
-	item.ClassifyIdSecond = dayNewDefault.ClassifyIdSecond
-	item.ClassifyNameSecond = dayNewDefault.ClassifyNameSecond
+	item.AddType = 1                                      // 新增方式:1:新增报告,2:继承报告
+	item.ClassifyIdFirst = dayNewDefault.ClassifyIdSecond // 报告表中的id_first实际为二级ID
+	item.ClassifyNameFirst = dayNewDefault.ClassifyNameSecond
+	item.ClassifyIdSecond = dayNewDefault.ClassifyIdThird // 报告表中的id_second实际为三级ID
+	item.ClassifyNameSecond = dayNewDefault.ClassifyNameThird
 	item.Title = dayNewDefault.Title
 	item.Abstract = dayNewDefault.Abstract
 	item.Author = dayNewDefault.Author
@@ -433,9 +433,9 @@ func (this *DayNewController) AddReport() {
 	br.Msg = "生成成功"
 }
 
-// List
-// @Title 每日资讯列表
-// @Description 每日资讯列表
+// ReportDefault
+// @Title 转报告默认设置
+// @Description 转报告默认设置
 // @Success 200 {object} models.WeworkMsgListResp
 // @router /day_new/report_default [get]
 func (this *DayNewController) ReportDefault() {
@@ -464,6 +464,8 @@ func (this *DayNewController) ReportDefault() {
 		ClassifyNameFirst:  dayNewDefault.ClassifyNameFirst,
 		ClassifyIdSecond:   dayNewDefault.ClassifyIdSecond,
 		ClassifyNameSecond: dayNewDefault.ClassifyNameSecond,
+		ClassifyIdThird:    dayNewDefault.ClassifyIdThird,
+		ClassifyNameThird:  dayNewDefault.ClassifyNameThird,
 		Title:              dayNewDefault.Title,
 		Abstract:           dayNewDefault.Abstract,
 		Author:             dayNewDefault.Author,
@@ -477,9 +479,10 @@ func (this *DayNewController) ReportDefault() {
 	br.Data = defaultReport
 }
 
-// @Title 新增英文报告接口
-// @Description 新增英文报告接口
-// @Param	request	body day_new.AddEnglishReportReq true "type json string"
+// ReportDefaultSave
+// @Title 保存-转报告默认设置
+// @Description 保存-转报告默认设置
+// @Param	request	body day_new.EnglishReportDefaultSaveReq true "type json string"
 // @Success 200 {object}
 // @router /day_new/report_default/save [post]
 func (this *DayNewController) ReportDefaultSave() {
@@ -533,6 +536,8 @@ func (this *DayNewController) ReportDefaultSave() {
 	item.ClassifyNameFirst = req.ClassifyNameFirst
 	item.ClassifyIdSecond = req.ClassifyIdSecond
 	item.ClassifyNameSecond = req.ClassifyNameSecond
+	item.ClassifyIdThird = req.ClassifyIdThird
+	item.ClassifyNameThird = req.ClassifyNameThird
 	item.Title = req.Title
 	item.Abstract = req.Abstract
 	item.Author = req.Author
@@ -557,7 +562,7 @@ func (this *DayNewController) ReportDefaultSave() {
 		}
 	} else {
 		item.Id = exist.Id
-		ups := []string{"ClassifyIdFirst", "ClassifyNameFirst", "ClassifyIdSecond", "ClassifyNameSecond", "Title", "Abstract", "Author", "Frequency", "Overview", "ModifyTime"}
+		ups := []string{"ClassifyIdFirst", "ClassifyNameFirst", "ClassifyIdSecond", "ClassifyNameSecond", "Title", "Abstract", "Author", "Frequency", "Overview", "ModifyTime", "ClassifyIdThird", "ClassifyNameThird"}
 		err = item.Update(ups)
 		if err != nil {
 			br.Msg = "保存失败"

+ 16 - 379
controllers/english_report/english_classify.go

@@ -2,17 +2,11 @@ package english_report
 
 import (
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"hongze/hz_crm_api/models"
 	"hongze/hz_crm_api/utils"
 	"sort"
 )
 
-// EnglishClassifyController 英文分类
-//type EnglishClassifyController struct {
-//	controllers.BaseAuthController
-//}
-
 // ListClassify
 // @Title 获取分类列表
 // @Description 获取分类列表
@@ -28,46 +22,24 @@ func (this *EnglishReportController) ListClassify() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	pageSize, _ := this.GetInt("PageSize")
-	currentIndex, _ := this.GetInt("CurrentIndex")
-	keyWord := this.GetString("KeyWord")
 
-	var startSize int
-	if pageSize <= 0 {
-		pageSize = utils.PageSize20
-	}
-	if currentIndex <= 0 {
-		currentIndex = 1
+	keyWord := this.GetString("KeyWord")
+	reqEnabled, _ := this.GetInt("Enabled", -1)
+	enabled := -1
+	if reqEnabled == 1 {
+		enabled = reqEnabled
 	}
-
-	startSize = utils.StartIndex(currentIndex, pageSize)
-
-	page := paging.GetPaging(currentIndex, pageSize, 0)
 	resp := new(models.EnglishClassifyListResp)
 
 	// 处理一级分类分页的情况
-	rootList, err := models.GetEnglishClassifyRootId(startSize, pageSize, keyWord)
+	rootList, err := models.GetEnglishClassifyRootId(keyWord, enabled)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-	var ids []int
-	var rootIds []int
-	rootMap := make(map[int]struct{}, 0)
-	for _, v := range rootList {
-		rootIds = append(rootIds, v.Id)
-		rootMap[v.Id] = struct{}{}
-	}
-	total, err := models.GetEnglishClassifyListCount(keyWord)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-	if total == 0 {
+	if len(rootList) == 0 {
 		resp.List = make([]*models.EnglishClassifyList, 0)
-		resp.Paging = page
 
 		br.Data = resp
 		br.Ret = 200
@@ -75,10 +47,16 @@ func (this *EnglishReportController) ListClassify() {
 		br.Msg = "获取成功"
 		return
 	}
-	page = paging.GetPaging(currentIndex, pageSize, total)
+	var ids []int
+	var rootIds []int
+	rootMap := make(map[int]struct{}, 0)
+	for _, v := range rootList {
+		rootIds = append(rootIds, v.Id)
+		rootMap[v.Id] = struct{}{}
+	}
 
 	//获取相关的分类ID
-	idList, err := models.GetEnglishClassifyListByRootId(rootIds, keyWord)
+	idList, err := models.GetEnglishClassifyListByRootId(rootIds, keyWord, enabled)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
@@ -100,7 +78,7 @@ func (this *EnglishReportController) ListClassify() {
 			}
 			if _, ok := childIdMap[v.Id]; !ok {
 				ids = append(ids, v.Id)
-				childIdMap[v.ParentId] = struct{}{}
+				childIdMap[v.Id] = struct{}{}
 			}
 		}
 		tmpList, err := models.GetEnglishClassifyChildByIds(ids)
@@ -172,350 +150,9 @@ func (this *EnglishReportController) ListClassify() {
 	sort.Sort(sortList)
 
 	resp.List = sortList
-	resp.Paging = page
 
 	br.Data = resp
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
 }
-
-//// @Title 新增分类
-//// @Description 新增分类接口
-//// @Param   ClassifyName   int  true       "分类名称"
-//// @Param   ParentId   query   int  true       "父级Id 添加父级时为0"
-//// @Param   Sort   query   string  false       "排序"
-//// @Success 200 新增成功
-//// @router /classify/add [get]
-//func (this *EnglishReportController) AddClassify() {
-//	br := new(models.BaseResponse).Init()
-//	defer func() {
-//		this.Data["json"] = br
-//		this.ServeJSON()
-//	}()
-//	classifyName := this.GetString("ClassifyName")
-//	parentId, _ := this.GetInt("ParentId")
-//	classifyType, _ := this.GetInt("ClassifyType", 0)
-//	sort, _ := this.GetInt("Sort")
-//
-//	item := &models.EnglishClassify{
-//		ClassifyName: classifyName,
-//		Sort:         sort,
-//		ParentId:     parentId,
-//		CreateTime:   time.Now(),
-//		ModifyTime:   time.Now(),
-//		ClassifyType: classifyType,
-//		IsShow:       1,
-//	}
-//	counts, err := models.GetEnglishClassifyCountsByName(classifyName, parentId, classifyType)
-//	if err != nil {
-//		br.Msg = "查询失败"
-//		br.ErrMsg = "查询失败,Err:" + err.Error()
-//		return
-//	}
-//	if counts > 0 {
-//		br.Msg = "该名称已存在"
-//		br.ErrMsg = "该名称已存在!"
-//		return
-//	}
-//	_, err = models.AddEnglishClassify(item)
-//	if err != nil {
-//		br.Msg = "保存失败"
-//		br.ErrMsg = "保存失败,Err:" + err.Error()
-//		return
-//	}
-//
-//	br.Ret = 200
-//	br.Success = true
-//	br.Msg = "新增成功"
-//}
-//
-//// @Title 编辑分类
-//// @Description 编辑分类接口
-//// @Param   ClassifyId   int  true       "分类Id"
-//// @Param   ClassifyName   string  true       "分类名称"
-//// @Param   ParentId   query   int  true       "父级Id 添加父级时为0"
-//// @Param   Sort   query   string  false       "排序"
-//// @Success 200 保存成功
-//// @router /classify/edit [get]
-//func (this *EnglishReportController) EditClassify() {
-//	br := new(models.BaseResponse).Init()
-//	defer func() {
-//		this.Data["json"] = br
-//		this.ServeJSON()
-//	}()
-//	classifyId, _ := this.GetInt("ClassifyId")
-//	classifyName := this.GetString("ClassifyName")
-//	parentId, _ := this.GetInt("ParentId")
-//	sort, _ := this.GetInt("Sort")
-//
-//	if parentId == classifyId {
-//		br.Msg = "上级分类不能选择自己"
-//		return
-//	}
-//	if classifyId <= 0 {
-//		br.Msg = "参数错误"
-//		return
-//	}
-//	if classifyName == "" {
-//		br.Msg = "分类名称不可为空"
-//		return
-//	}
-//
-//	oldItem, err := models.GetEnglishReportClassifyById(classifyId)
-//	if err != nil && err.Error() != utils.ErrNoRow() {
-//		br.Msg = "获取信息失败"
-//		br.ErrMsg = "获取信息失败,Err:" + err.Error()
-//		return
-//	}
-//	parent, err := models.GetEnglishReportClassifyById(parentId)
-//	if err != nil && err.Error() != utils.ErrNoRow() {
-//		br.Msg = "获取信息失败"
-//		br.ErrMsg = "获取信息失败,Err:" + err.Error()
-//		return
-//	}
-//
-//	if oldItem.ParentId == 0 && parentId > 0 {
-//		// 一级分类变更为二级分类,禁止
-//		br.Msg = "一级分类不允许更改为二级分类"
-//		return
-//	}
-//
-//	//判断是否已存在同个名称的分类
-//	existItem, e := models.GetEnglishClassifyByClassifyNameParentId(classifyName, parentId, oldItem.ClassifyType)
-//	if e != nil {
-//		if e.Error() != utils.ErrNoRow() {
-//			br.Msg = "查询已存在的分类出错"
-//			br.ErrMsg = "查询已存在的分类出错, Err:" + e.Error()
-//			return
-//		}
-//	}
-//	if e == nil && existItem.Id != oldItem.Id {
-//		br.Msg = "分类名称:" + classifyName + "已存在"
-//		return
-//	}
-//	if err != nil && err.Error() != utils.ErrNoRow() {
-//		br.Msg = "获取信息失败"
-//		br.ErrMsg = "获取信息失败,Err:" + err.Error()
-//		return
-//	}
-//
-//	//oldParentId := item.ParentId
-//	item := &models.EnglishClassify{
-//		Id:           oldItem.Id,
-//		ClassifyName: classifyName,
-//		Sort:         sort,
-//		ParentId:     parentId,
-//		ModifyTime:   time.Now(),
-//		ClassifyType: oldItem.ClassifyType,
-//		IsShow:       1,
-//	}
-//	if oldItem.ClassifyType == 1 {
-//		err = services.UpdateEnglishVideoClassifyId(oldItem, item, parent, classifyId)
-//		if err != nil {
-//			br.Msg = err.Error()
-//			return
-//		}
-//	} else {
-//		// 更新研报里的分类名称
-//		err = services.UpdateEnglishReportClassifyId(oldItem, item, parent, classifyId)
-//		if err != nil {
-//			br.Msg = err.Error()
-//			return
-//		}
-//	}
-//
-//	err = models.ModifyEnglishClassify(item)
-//	if err != nil {
-//		br.Msg = "保存失败"
-//		br.ErrMsg = "保存失败,Err:" + err.Error()
-//		return
-//	}
-//
-//	br.Ret = 200
-//	br.Success = true
-//	br.Msg = "保存成功"
-//}
-//
-//// @Title 删除分类列表
-//// @Description 删除分类列表
-//// @Param   ClassifyId   int  true       "分类名称"
-//// @Param   ParentId   query   int  true   "父级Id"
-//// @Success 200 保存成功
-//// @router /classify/delete [get]
-//func (this *EnglishReportController) DelClassify() {
-//	br := new(models.BaseResponse).Init()
-//	defer func() {
-//		this.Data["json"] = br
-//		this.ServeJSON()
-//	}()
-//	classifyId, _ := this.GetInt("ClassifyId")
-//	//parentId, _ := this.GetInt("ParentId")
-//
-//	classifyInfo, err := models.GetEnglishReportClassifyById(classifyId)
-//	if err != nil {
-//		if err.Error() == utils.ErrNoRow() {
-//			br.Msg = "当前分类不存在"
-//			br.ErrMsg = "当前分类不存在"
-//			return
-//		}
-//		br.Msg = "获取分类信息失败"
-//		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
-//		return
-//	}
-//
-//	count, err := models.GetEnglishClassifyChildCounts(classifyId)
-//	if err != nil && err.Error() != utils.ErrNoRow() {
-//		br.Msg = "获取信息失败"
-//		br.ErrMsg = "获取失败,Err:" + err.Error()
-//		return
-//	}
-//
-//	if count > 0 {
-//		br.Msg = "请先删除该分类下关联分类"
-//		br.Ret = 403
-//		return
-//	}
-//
-//	if classifyInfo.ClassifyType == 0 {
-//		reportCount, e := models.GetEnglishReportCounts(classifyId, classifyInfo.ParentId)
-//		if e != nil && e.Error() != utils.ErrNoRow() {
-//			br.Msg = "获取信息失败"
-//			br.ErrMsg = "获取失败,Err:" + e.Error()
-//			return
-//		}
-//
-//		if reportCount > 0 {
-//			br.Msg = "该分类有关联报告,不允许删除"
-//			br.Ret = 403
-//			return
-//		}
-//	} else {
-//		videoCount, e := models.GetEnglishVideoCounts(classifyId, classifyInfo.ParentId)
-//		if e != nil && e.Error() != utils.ErrNoRow() {
-//			br.Msg = "获取信息失败"
-//			br.ErrMsg = "获取失败,Err:" + e.Error()
-//			return
-//		}
-//
-//		if videoCount > 0 {
-//			br.Msg = "该分类有关联的路演视频,不允许删除"
-//			br.Ret = 403
-//			return
-//		}
-//	}
-//
-//	if err = models.DeleteEnglishClassify(classifyId); err != nil {
-//		br.Msg = "删除失败"
-//		br.ErrMsg = "删除报告失败, Err: " + err.Error()
-//		return
-//	}
-//
-//	br.Ret = 200
-//	br.Success = true
-//	br.Msg = "删除成功"
-//}
-//
-//// @Title 获取一级分类列表
-//// @Description 获取一级分类列表
-//// @Param   PageSize   query   int  true       "每页数据条数"
-//// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
-//// @Param   CompanyType   query   string  false       "产品类型,枚举值:'ficc','权益';不传默认返回全部"
-//// @Success 200 {object} models.EnglishClassifyListResp
-//// @router /classify/first/list [get]
-//func (this *EnglishReportController) FistListClassify() {
-//	br := new(models.BaseResponse).Init()
-//	defer func() {
-//		this.Data["json"] = br
-//		this.ServeJSON()
-//	}()
-//	pageSize, _ := this.GetInt("PageSize")
-//	currentIndex, _ := this.GetInt("CurrentIndex")
-//	classifyType, _ := this.GetInt("ClassifyType", 0)
-//
-//	var startSize int
-//	if pageSize <= 0 {
-//		pageSize = utils.PageSize20
-//	}
-//	if currentIndex <= 0 {
-//		currentIndex = 1
-//	}
-//
-//	startSize = utils.StartIndex(currentIndex, pageSize)
-//	list, err := models.GetEnglishFirstClassifyList(classifyType, startSize, pageSize)
-//	if err != nil {
-//		br.Msg = "获取失败"
-//		br.ErrMsg = "获取失败,Err:" + err.Error()
-//		return
-//	}
-//	total, err := models.GetEnglishFirstClassifyListCount(classifyType)
-//	if err != nil {
-//		br.Msg = "获取失败"
-//		br.ErrMsg = "获取失败,Err:" + err.Error()
-//		return
-//	}
-//
-//	page := paging.GetPaging(currentIndex, pageSize, total)
-//	resp := new(models.EnglishClassifyListResp)
-//	resp.List = list
-//	resp.Paging = page
-//
-//	br.Data = resp
-//	br.Ret = 200
-//	br.Success = true
-//	br.Msg = "获取成功"
-//}
-//
-//// PermissionEdit
-//// @Title 编辑品种权限
-//// @Description 编辑品种权限
-//// @Param	request	body models.EnPermissionAddReq true "type json string"
-//// @Success 200 Ret=200 操作成功
-//// @router /permission/edit [post]
-//func (this *EnglishClassifyController) PermissionEdit() {
-//	br := new(models.BaseResponse).Init()
-//	defer func() {
-//		if br.ErrMsg == "" {
-//			br.IsSendEmail = false
-//		}
-//		this.Data["json"] = br
-//		this.ServeJSON()
-//	}()
-//	sysUser := this.SysUser
-//	if sysUser == nil {
-//		br.Msg = "请登录"
-//		br.ErrMsg = "请登录,SysUser Is Empty"
-//		br.Ret = 408
-//		return
-//	}
-//	var req models.EnClassifyPermissionEditReq
-//	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
-//		br.Msg = "参数解析异常!"
-//		br.ErrMsg = "参数解析失败,Err:" + e.Error()
-//		return
-//	}
-//	if req.ClassifyId <= 0 {
-//		br.Msg = "参数有误"
-//		return
-//	}
-//
-//	// 更新品种权限
-//	nowTime := time.Now().Local()
-//	permissions := make([]*models.EnClassifyPermission, 0)
-//	for _, p := range req.EnPermissions {
-//		v := new(models.EnClassifyPermission)
-//		v.EnPermissionId = p
-//		v.EnClassifyId = req.ClassifyId
-//		v.CreateTime = nowTime
-//		permissions = append(permissions, v)
-//	}
-//	if e := models.ClearAndCreateEnClassifyPermissions(req.ClassifyId, permissions); e != nil {
-//		br.Msg = "保存失败"
-//		br.ErrMsg = "更新分类品种权限失败, Err: " + e.Error()
-//		return
-//	}
-//
-//	br.Ret = 200
-//	br.Success = true
-//	br.Msg = "操作成功"
-//}

+ 290 - 0
controllers/eta_business/eta_business.go

@@ -1222,3 +1222,293 @@ func (this *EtaBusinessController) OperateRecordList() {
 	br.Success = true
 	br.Msg = "获取成功"
 }
+
+// EditSign
+// @Title 编辑签约
+// @Description 编辑签约
+// @Param	request	body eta_business.EtaBusinessEditSignReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /edit_sign [post]
+func (this *EtaBusinessController) EditSign() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req eta_business.EtaBusinessEditSignReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.EtaBusinessContractId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家签约ID为空"
+		return
+	}
+	if req.SigningTime == "" {
+		br.Msg = "签约时间不可为空"
+		return
+	}
+	if req.ExpiredTime == "" {
+		br.Msg = "到期时间不可为空"
+		return
+	}
+	signTime, e := time.ParseInLocation(utils.FormatDate, req.SigningTime, time.Local)
+	if e != nil {
+		br.Msg = "签约时间格式有误"
+		br.ErrMsg = "签约时间格式有误, Err: " + e.Error()
+		return
+	}
+	expiredTime, e := time.ParseInLocation(utils.FormatDate, req.ExpiredTime, time.Local)
+	if e != nil {
+		br.Msg = "到期时间格式有误"
+		br.ErrMsg = "到期时间格式有误, Err: " + e.Error()
+		return
+	}
+	if !expiredTime.After(signTime) {
+		br.Msg = "到期时间不得早于签约时间"
+		return
+	}
+
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	contractOb := new(eta_business.EtaBusinessContract)
+	contract, e := contractOb.GetItemById(req.EtaBusinessContractId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "签约信息不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家签约信息失败, Err: " + e.Error()
+		return
+	}
+	businessOb := new(eta_business.EtaBusiness)
+	business, e := businessOb.GetItemById(contract.EtaBusinessId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "商家不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家信息失败, Err: " + e.Error()
+		return
+	}
+
+	// 续约不可早于当前生效合约的到期时间
+	if business.ContractId > 0 && business.ContractId != req.EtaBusinessContractId {
+		{
+			ob := new(eta_business.EtaBusinessContract)
+			item, e := ob.GetItemById(business.ContractId)
+			if e != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取商家当前合同失败, Err: " + e.Error()
+				return
+			}
+			if !signTime.After(item.ExpiredTime) {
+				br.Msg = "签约时间不可早于当前合同的到期时间"
+				return
+			}
+		}
+	}
+
+	// 获取历史签约, 签约日期不可交叠
+	cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessContractColumns.EtaBusinessId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, contract.EtaBusinessId)
+	contracts, e := contractOb.GetItemsByCondition(cond, pars, []string{}, "signing_time ASC")
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家签约列表失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验签约时间是否重叠
+	isFirst := true      // 是否为首次签约
+	changeFirst := false // 是否需要更新首次签约合同
+	if len(contracts) > 0 {
+		isFirst = false
+		for k, c := range contracts {
+			if c.EtaBusinessContractId == req.EtaBusinessContractId {
+				continue
+			}
+			pass := false
+			if expiredTime.Before(c.SigningTime) {
+				pass = true
+			}
+			if signTime.After(c.ExpiredTime) {
+				pass = true
+			}
+			if !pass {
+				br.Msg = "签约时间在存续期内, 请检查"
+				return
+			}
+			// 若该合同签约时间早于第一份合同(业务上未限制所以可能会出现这种情况, contracts已排序), 则更新为首次签约合同
+			if k == 0 && signTime.Before(c.SigningTime) {
+				changeFirst = true
+				isFirst = true
+			}
+		}
+	}
+
+	// 新增签约
+	contract.SigningTime = signTime
+	contract.ExpiredTime = expiredTime
+	contract.ModifyTime = time.Now().Local()
+	if isFirst {
+		contract.IsFirst = 1
+	}
+	updateCols := []string{"SigningTime", "ExpiredTime", "ModifyTime"}
+	if e = contract.UpdateMaybeUpdateFirst(contract, changeFirst, updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "编辑签约失败, Err: " + e.Error()
+		return
+	}
+
+	// 签约后续操作
+	go func() {
+		_ = etaBusinessService.UpdateEtaBusinessAfterSigning(business.EtaBusinessId)
+	}()
+
+	// 续约操作日志
+	if !isFirst {
+		go func() {
+			recordOb := new(eta_business.EtaBusinessOperationRecord)
+			recordOb.EtaBusinessId = business.EtaBusinessId
+			recordOb.SellerId = business.SellerId
+			recordOb.SysUserId = sysUser.AdminId
+			recordOb.SysRealName = sysUser.RealName
+			recordOb.OperationType = eta_business.EtaBusinessOperationTypeEditContract
+			recordOb.OperationRemark = fmt.Sprintf("%s编辑续约", sysUser.RealName)
+			recordOb.CreateTime = time.Now().Local()
+			_ = recordOb.Create()
+		}()
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// RemoveSign
+// @Title 删除签约
+// @Description 删除签约
+// @Param	request	body eta_business.EtaBusinessRemoveSignReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /remove_sign [post]
+func (this *EtaBusinessController) RemoveSign() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req eta_business.EtaBusinessRemoveSignReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.EtaBusinessContractId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家签约ID为空"
+		return
+	}
+
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	// 获取商家信息
+	contractOb := new(eta_business.EtaBusinessContract)
+	contract, e := contractOb.GetItemById(req.EtaBusinessContractId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "签约信息不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家签约信息失败, Err: " + e.Error()
+		return
+	}
+
+	// 获取商家信息
+	businessOb := new(eta_business.EtaBusiness)
+	business, e := businessOb.GetItemById(contract.EtaBusinessId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "商家不存在, 请检查"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家信息失败, Err: " + e.Error()
+		return
+	}
+
+	// 删除签约
+	if e = contract.Del(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除签约失败, Err: " + e.Error()
+		return
+	}
+
+	// 签约后续操作
+	go func() {
+		_ = etaBusinessService.UpdateEtaBusinessAfterSigning(business.EtaBusinessId)
+	}()
+
+	// 操作日志
+	go func() {
+		recordOb := new(eta_business.EtaBusinessOperationRecord)
+		recordOb.EtaBusinessId = business.EtaBusinessId
+		recordOb.SellerId = business.SellerId
+		recordOb.SysUserId = sysUser.AdminId
+		recordOb.SysRealName = sysUser.RealName
+		recordOb.OperationType = eta_business.EtaBusinessOperationTypeRemoveContract
+		recordOb.OperationRemark = fmt.Sprintf("%s删除签约", sysUser.RealName)
+		recordOb.CreateTime = time.Now().Local()
+		_ = recordOb.Create()
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 153 - 13
controllers/roadshow/calendar.go

@@ -6,6 +6,7 @@ import (
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"hongze/hz_crm_api/controllers"
 	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/cygx"
 	"hongze/hz_crm_api/models/roadshow"
 	"hongze/hz_crm_api/models/system"
 	"hongze/hz_crm_api/services"
@@ -173,6 +174,16 @@ func (this *CalendarController) Add() {
 		br.IsSendEmail = false
 		return
 	}
+	sysUserList, err := cygx.GetAskEmailList()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,GetAskEmailList Err: " + err.Error()
+		return
+	}
+	raiAskadminMap := make(map[int]bool, 0)
+	for _, v := range sysUserList {
+		raiAskadminMap[v.AdminId] = true
+	}
 
 	rsCalendar := new(roadshow.RsCalendar)
 	rsCalendar.SysUserId = sysUser.AdminId
@@ -186,6 +197,7 @@ func (this *CalendarController) Add() {
 	rsCalendar.ProvinceCode = req.ProvinceCode
 	rsCalendar.City = req.City
 	rsCalendar.CityCode = req.CityCode
+	rsCalendar.District = req.District
 	rsCalendar.Theme = req.Theme
 	rsCalendar.CooperationName = req.CooperationName
 	rsCalendar.CreateTime = time.Now()
@@ -220,6 +232,12 @@ func (this *CalendarController) Add() {
 		} else {
 			researcher.Status = 2
 		}
+
+		//CRM15.5 权益研究员直接通过
+		if raiAskadminMap[v.ResearcherId] {
+			researcher.Status = 2
+		}
+
 		rsCalendarResearcherId, err := roadshow.AddRsCalendarResearcher(researcher)
 		if err != nil {
 			br.Msg = "保存失败!"
@@ -559,6 +577,10 @@ func (this *CalendarController) Edit() {
 		calendarUpdateParams["city"] = req.City
 	}
 
+	if req.District != "" {
+		calendarUpdateParams["district"] = req.District
+	}
+
 	calendarUpdateParams["english_company"] = req.EnglishCompany
 
 	calendarUpdateParams["modify_time"] = time.Now()
@@ -582,7 +604,16 @@ func (this *CalendarController) Edit() {
 	for _, ev := range existList {
 		existResearcherMap[ev.ResearcherId] = ev.ResearcherName
 	}
-
+	sysUserList, err := cygx.GetAskEmailList()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,GetAskEmailList Err: " + err.Error()
+		return
+	}
+	raiAskadminMap := make(map[int]bool, 0)
+	for _, v := range sysUserList {
+		raiAskadminMap[v.AdminId] = true
+	}
 	if rsCalendarItem.ActivityType == "路演" || rsCalendarItem.ActivityType == "公开会议" {
 		// 更新研究员信息
 		//go roadshowService.UpdateSHCalendar(req.RsCalendarId, req.RsCalendarResearcherId, req.ActivityType, req.RoadshowType, req.ActivityCategory, req.RoadshowPlatform, req.Province, req.City, req.ResearcherList)
@@ -609,6 +640,11 @@ func (this *CalendarController) Edit() {
 				calendarResearcherUpdateParams["status"] = 1
 				rsCalendarResearcherItem.Status = 1
 			}
+			//CRM15.5 权益研究员直接通过
+			if raiAskadminMap[v.ResearcherId] {
+				calendarResearcherUpdateParams["status"] = 2
+				rsCalendarResearcherItem.Status = 2
+			}
 			calendarResearcherUpdateParams["start_date"] = v.StartDate
 			rsCalendarResearcherItem.StartDate = v.StartDate
 			calendarResearcherUpdateParams["end_date"] = v.EndDate
@@ -727,6 +763,10 @@ func (this *CalendarController) Edit() {
 			} else {
 				researcher.Status = 2
 			}
+			//CRM15.5 权益研究员直接通过
+			if raiAskadminMap[v.ResearcherId] {
+				researcher.Status = 2
+			}
 			rsCalendarResearcherId, err := roadshow.AddRsCalendarResearcher(researcher)
 			if err != nil {
 				br.Msg = "保存失败!"
@@ -975,16 +1015,18 @@ func (this *CalendarController) ResearcherList() {
 	researcherList, err := roadshow.GetResearcher()
 	groupMap := make(map[int][]*roadshow.ResearcherGroup)
 	for _, v := range researcherList {
-		//if v.RoleTypeCode == "ficc_admin" {
-		//	findItems := groupMap[1]
-		//	findItems = append(findItems, v)
-		//	groupMap[1] = findItems
-		//} else {
+		item := &roadshow.ResearcherGroup{
+			GroupId:      v.GroupId,
+			GroupName:    v.GroupName,
+			AdminId:      v.AdminId,
+			RealName:     v.RealName,
+			RoleTypeCode: v.RoleTypeCode,
+		}
 		if findItems, ok := groupMap[v.GroupId]; ok {
-			findItems = append(findItems, v)
+			findItems = append(findItems, item)
 			groupMap[v.GroupId] = findItems
 		} else {
-			findItems = append(findItems, v)
+			findItems = append(findItems, item)
 			groupMap[v.GroupId] = findItems
 		}
 		//}
@@ -992,14 +1034,72 @@ func (this *CalendarController) ResearcherList() {
 	for _, v := range group {
 		v.ResearcherList = groupMap[v.GroupId]
 	}
-	//allGroup := new(roadshow.ResearcherGroup)
-	//allGroup.GroupId = 99
-	//allGroup.GroupName = "ficc全体"
-	//group = append(group, allGroup)
+
+	ficcGroup := new(roadshow.ResearcherGroup)
+	ficcGroup.GroupId = 999
+	ficcGroup.GroupName = "ficc"
+	ficcGroup.ResearcherList = group
+
+	sysUserList, err := system.GetAdminList()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取admin列表失败, Err:" + err.Error()
+		return
+	}
+	adminMap := make(map[int]*system.Admin, 0)
+	for _, v := range sysUserList {
+		adminMap[v.AdminId] = v
+	}
+	askUserList, err := cygx.GetAskEmailList()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,GetAskEmailList Err: " + err.Error()
+		return
+	}
+	mapPermissionUser := make(map[string][]*roadshow.ResearcherGroup)
+	listPermission, err := cygx.GetChartPermissionAll()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	mapPermissionId := make(map[string]int)
+	for _, v := range listPermission {
+		mapPermissionId[v.PermissionName] = v.ChartPermissionId
+	}
+	for _, v := range askUserList {
+		if admin, ok := adminMap[v.AdminId]; ok {
+			item := &roadshow.ResearcherGroup{
+				AdminId:      v.AdminId,
+				RealName:     v.Name,
+				GroupId:      admin.GroupId,
+				GroupName:    admin.GroupName,
+				RoleTypeCode: admin.RoleTypeCode,
+			}
+			mapPermissionUser[v.ChartPermissionName] = append(mapPermissionUser[v.ChartPermissionName], item)
+		}
+	}
+	raiList := make([]*roadshow.ResearcherGroup, 0)
+	for k, v := range mapPermissionUser {
+		respItem := new(roadshow.ResearcherGroup)
+		respItem.GroupName = k + "组"
+		respItem.GroupId = mapPermissionId[k]
+		respItem.ResearcherList = v
+		raiList = append(raiList, respItem)
+	}
+
+	raiGroup := new(roadshow.ResearcherGroup)
+	raiGroup.GroupId = 888
+	raiGroup.GroupName = "权益"
+	raiGroup.ResearcherList = raiList
+
+	var resp []*roadshow.ResearcherGroup
+	resp = append(resp, ficcGroup, raiGroup)
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
-	br.Data = group
+	br.Data = resp
 }
 
 // CalendarList
@@ -1115,10 +1215,17 @@ func (this *CalendarController) CalendarList() {
 
 	// 英文客户的国家以及点击量
 	englishIds := make([]int, 0)
+	adminIds := make([]int, 0)     // 管理员ID
+	rsCalendarId := make([]int, 0) //路演ID
 	for i := range dataList {
 		if dataList[i].EnglishCompany == 1 {
 			englishIds = append(englishIds, dataList[i].CompanyId)
 		}
+
+		if calendarType == 2 {
+			adminIds = append(adminIds, dataList[i].SysUserId)
+			rsCalendarId = append(rsCalendarId, dataList[i].RsCalendarId)
+		}
 	}
 	englishMap := make(map[int]*models.EnglishCompany)
 	if len(englishIds) > 0 {
@@ -1135,6 +1242,31 @@ func (this *CalendarController) CalendarList() {
 			englishMap[englishList[i].CompanyId] = englishList[i]
 		}
 	}
+	mapRaiSllerId := make(map[int]bool)  // 是否为权益销售
+	mapMeetingCount := make(map[int]int) // 路演参会人员数量
+	if len(adminIds) > 0 {
+		listAdmin, e := system.GetAdminListByIdListWithoutEnable(adminIds)
+		if e != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取管理员信息失败, Err:" + e.Error()
+			return
+		}
+		for _, v := range listAdmin { //权益销售与权益销售组长
+			if v.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_SELLER || v.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_GROUP {
+				mapRaiSllerId[v.AdminId] = true
+			}
+		}
+		listMeetingCount, e := roadshow.GetRsCalendarMeetingUserListCount(rsCalendarId)
+		if e != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取路演参会人员数量信息失败, Err:" + e.Error()
+			return
+		}
+		for _, v := range listMeetingCount {
+			mapMeetingCount[v.RsCalendarId] = v.Total
+		}
+	}
+
 	for i := range dataList {
 		if dataList[i].EnglishCompany == 1 {
 			en := englishMap[dataList[i].CompanyId]
@@ -1143,6 +1275,14 @@ func (this *CalendarController) CalendarList() {
 				dataList[i].EnglishViewTotal = en.ViewTotal
 			}
 		}
+		//如果是已结束的权益销售添加的活动,就行进行按钮展示
+		if mapRaiSllerId[dataList[i].SysUserId] && utils.InArrayByInt([]int{2, 6}, dataList[i].Status) {
+			if mapMeetingCount[dataList[i].RsCalendarId] == 0 {
+				dataList[i].SubmitButton = true
+			} else {
+				dataList[i].ViewButton = true
+			}
+		}
 	}
 
 	resp.Paging = page

+ 173 - 0
controllers/roadshow/calendar_meeting_user.go

@@ -0,0 +1,173 @@
+package roadshow
+
+import (
+	"encoding/json"
+	"hongze/hz_crm_api/controllers"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/roadshow"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// 日历参会名单
+type CalendarMeetingUserController struct {
+	controllers.BaseAuthController
+}
+
+// @Title 新增路演活动参会名单接口
+// @Description 新增路演活动参会名单接口
+// @Param	request	body roadshow.AddRsCalendarMeetingUserReq true "type json string"
+// @Success Ret=200 保存成功
+// @router /rs_calendar_meeting_user/add [post]
+func (this *CalendarMeetingUserController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var req roadshow.AddRsCalendarMeetingUserReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	rsCalendarId := req.RsCalendarId
+	userIds := req.UserId
+
+	if rsCalendarId == 0 {
+		br.Msg = "路演信息错误!"
+		return
+	}
+	if len(userIds) == 0 {
+		br.Msg = "参会人不能为空!"
+		return
+	}
+	var userIdsStr []string
+	for _, v := range userIds {
+		userIdsStr = append(userIdsStr, strconv.Itoa(v))
+	}
+
+	listUser, err := models.GetWxUserListByUserIdsHaveCompany(strings.Join(userIdsStr, ","))
+	if err != nil {
+		br.Msg = "获取用户信息失败!"
+		br.ErrMsg = "获取用户信息失败-GetWxUserListByUserIdsHaveCompany!Err:" + err.Error()
+		return
+	}
+
+	var items []*roadshow.RsCalendarMeetingUser
+	for _, v := range listUser {
+		item := new(roadshow.RsCalendarMeetingUser)
+		item.RsCalendarId = rsCalendarId
+		item.UserId = v.UserId
+		item.Mobile = v.Mobile
+		item.Email = v.Email
+		item.CompanyId = v.CompanyId
+		item.CompanyName = v.CompanyName
+		item.RealName = v.RealName
+		item.Position = v.Position
+		item.AdminId = sysUser.AdminId
+		item.AdminName = sysUser.RealName
+		item.CreateTime = time.Now()
+		item.ModifyTime = time.Now()
+		items = append(items, item)
+	}
+	err = roadshow.MultiAddRsCalendarMeetingUser(items)
+	if err != nil {
+		br.Msg = "操作失败!"
+		br.ErrMsg = "操作失败-MultiAddRsCalendarMeetingUser!Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "添加成功"
+	br.IsAddLog = true
+}
+
+// @Title 路演活动参会名单列表接口
+// @Description 路演活动参会名单列表接口
+// @Param   RsCalendarId   query   int  true       "路演活动id"
+// @Success 200 {object} roadshow.CalendarListResp
+// @router /rs_calendar_meeting_user/list [get]
+func (this *CalendarMeetingUserController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	rsCalendarId, _ := this.GetInt("RsCalendarId")
+	resp := new(roadshow.RsCalendarMeetingUserListResp)
+	list, err := roadshow.GetRsCalendarMeetingUserListByRsCalendarId(rsCalendarId)
+	if err != nil {
+		br.Msg = "获取失败!"
+		br.ErrMsg = "操作失败-GetRsCalendarMeetingUserListByRsCalendarId!Err:" + err.Error()
+		return
+	}
+	if len(list) == 0 {
+		list = make([]*roadshow.RsCalendarMeetingUserResp, 0)
+	}
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+	br.Msg = "获取成功"
+}
+
+// @Title 路演活动参会删除接口
+// @Description 路演活动参会删除接口
+// @Param   RsCalendarMeetingUserId   query   int  true       "参会名单主键ID"
+// @Success Ret=200 删除成功
+// @router /rs_calendar_meeting_user/delete [post]
+func (this *CalendarMeetingUserController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req roadshow.DeleteRsCalendarMeetingUserReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	rsCalendarMeetingUserId := req.RsCalendarMeetingUserId
+	err = roadshow.DeleteRsCalendarMeetingUser(rsCalendarMeetingUserId)
+	if err != nil {
+		br.Msg = "删除失败!"
+		br.ErrMsg = "删除失败-DeleteRsCalendarMeetingUser!Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+	br.IsAddLog = true
+}

+ 7 - 3
controllers/roadshow/company.go

@@ -4,6 +4,7 @@ import (
 	"hongze/hz_crm_api/models"
 	"hongze/hz_crm_api/models/company"
 	"hongze/hz_crm_api/models/roadshow"
+	"hongze/hz_crm_api/services"
 	"hongze/hz_crm_api/utils"
 	"strings"
 )
@@ -76,10 +77,13 @@ func (this *CalendarController) CompanyDetail() {
 		return
 	}
 	englishCompany, _ := this.GetInt("EnglishCompany")
-
+	productId := services.GetProductId(sysUser.RoleTypeCode)
+	if productId == 0 {
+		productId = 1
+	}
 	detailView := new(roadshow.CompanyDetailView)
 	if englishCompany == 0 {
-		companyProductItem, err := company.GetCompanyProductByCompanyIdAndProductId(companyId, 1)
+		companyProductItem, err := company.GetCompanyProductByCompanyIdAndProductId(companyId, productId)
 		if err != nil {
 			if err.Error() == utils.ErrNoRow() {
 				br.Msg = "该客户已被删除"
@@ -89,7 +93,7 @@ func (this *CalendarController) CompanyDetail() {
 			br.ErrMsg = "搜索客户失败!Err:" + err.Error()
 			return
 		}
-		permissionList, err := company.GetCompanyProductReportPermissionList(companyId, 1)
+		permissionList, err := company.GetCompanyProductReportPermissionList(companyId, productId)
 		if err != nil {
 			br.Msg = "搜索客户权限失败!"
 			br.ErrMsg = "搜索客户权限失败!Err:" + err.Error()

+ 12 - 7
controllers/roadshow/report.go

@@ -87,20 +87,25 @@ func (this *CalendarController) ResearcherReportList() {
 	}
 	groupMap := make(map[int][]*roadshow.ResearcherGroup)
 	for _, v := range researcherList {
-		//if v.RoleTypeCode == "ficc_admin" {
-		//	findItems := groupMap[1]
-		//	findItems = append(findItems, v)
-		//	groupMap[1] = findItems
-		//} else {
+		item := &roadshow.ResearcherGroup{
+			GroupId:      v.GroupId,
+			GroupName:    v.GroupName,
+			AdminId:      v.AdminId,
+			RealName:     v.RealName,
+			RoleTypeCode: v.RoleTypeCode,
+		}
 		if findItems, ok := groupMap[v.GroupId]; ok {
-			findItems = append(findItems, v)
+			findItems = append(findItems, item)
 			groupMap[v.GroupId] = findItems
 		} else {
-			findItems = append(findItems, v)
+			findItems = append(findItems, item)
 			groupMap[v.GroupId] = findItems
 		}
 		//}
 	}
+	for _, v := range group {
+		v.ResearcherList = groupMap[v.GroupId]
+	}
 
 	groupReportRecordList := make([]roadshow.GroupReportRecord, 0)
 	rsAllReportRecordNumList := make([]roadshow.RsReportRecordNum, 0)

+ 26 - 1
controllers/yb/road_video.go

@@ -527,7 +527,7 @@ func (r *RoadVideoController) SimpleReportList() {
 		cond += ` AND title LIKE ?`
 		pars = append(pars, kw)
 	}
-	fieldArr := []string{"id", "title", "publish_time"}
+	fieldArr := []string{"id", "classify_id_second", "title", "publish_time"}
 	orderRule := ` ORDER BY publish_time DESC, id DESC`
 	reports, e := models.GetReportByCondition(cond, pars, fieldArr, orderRule, true, 0, 5)
 	if e != nil {
@@ -536,12 +536,36 @@ func (r *RoadVideoController) SimpleReportList() {
 		return
 	}
 
+	// 查询报告权限
+	classifyPermissions := make(map[int][]int, 0)
+	{
+		classifyIds := make([]int, 0)
+		for _, v := range reports {
+			if utils.InArrayByInt(classifyIds, v.ClassifyIdSecond) {
+				continue
+			}
+			classifyIds = append(classifyIds, v.ClassifyIdSecond)
+		}
+		if len(classifyIds) > 0 {
+			classifyIdsPermissions, e := models.GetPermissionsByClassifyIds(classifyIds)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取分类权限失败, Err: " + e.Error()
+				return
+			}
+			for _, v := range classifyIdsPermissions {
+				classifyPermissions[v.ClassifyId] = append(classifyPermissions[v.ClassifyId], v.ChartPermissionId)
+			}
+		}
+	}
+
 	type SimpleReportListResp struct {
 		ReportId       int
 		Title          string
 		PublishTime    string
 		BindVideo      int
 		BindVideoTitle string
+		PermissionIds  []int
 	}
 	respList := make([]*SimpleReportListResp, 0)
 	if len(reports) > 0 {
@@ -570,6 +594,7 @@ func (r *RoadVideoController) SimpleReportList() {
 				PublishTime:    reports[i].PublishTime.Format(utils.FormatDateTime),
 				BindVideo:      bindMap[reports[i].Id],
 				BindVideoTitle: bindTitleMap[reports[i].Id],
+				PermissionIds:  classifyPermissions[reports[i].ClassifyIdSecond],
 			})
 		}
 	}

+ 6 - 0
controllers/yb_research_signup_statistics.go

@@ -65,6 +65,12 @@ func (this *BannerController) StatisticsItem() {
 		br.ErrMsg = "GetYbResearchSignupStatisticsItemsById,Err:" + err.Error()
 		return
 	}
+	if len(list) == 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
 	resp.List = list
 	for _, v := range list {
 		resp.Total += v.Count

+ 1 - 0
go.mod

@@ -97,6 +97,7 @@ require (
 	github.com/tidwall/match v1.1.1 // indirect
 	github.com/tidwall/pretty v1.2.0 // indirect
 	github.com/tjfoc/gmsm v1.3.2 // indirect
+	github.com/wechatpay-apiv3/wechatpay-go v0.2.18 // indirect
 	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
 	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
 	golang.org/x/crypto v0.5.0 // indirect

+ 3 - 0
go.sum

@@ -13,6 +13,7 @@ github.com/SebastiaanKlippert/go-wkhtmltopdf v1.7.2 h1:LORAatv6KuKheYq8HXehiwx3f
 github.com/SebastiaanKlippert/go-wkhtmltopdf v1.7.2/go.mod h1:TY8r0gmwEL1c5Lbd66NgQCkL4ZjGDJCMVqvbbFvUx20=
 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -416,6 +417,8 @@ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso
 github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
 github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
 github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
+github.com/wechatpay-apiv3/wechatpay-go v0.2.18 h1:vj5tvSmnEIz3ZsnFNNUzg+3Z46xgNMJbrO4aD4wP15w=
+github.com/wechatpay-apiv3/wechatpay-go v0.2.18/go.mod h1:A254AUBVB6R+EqQFo3yTgeh7HtyqRRtN2w9hQSOrd4Q=
 github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=

+ 16 - 8
models/company/company_approval.go

@@ -523,18 +523,19 @@ func FreezeToTryOutXClassRai(companyId, productId, sellerId, companyApprovalId,
 			err = to.Commit()
 		}
 	}()
+
 	startDate = time.Now().Format(utils.FormatDate)
-	endDate = time.Now().AddDate(0, 3, 0).Format(utils.FormatDate)
+	endDate = time.Now().AddDate(0, 2, 0).Format(utils.FormatDate)
 
-	sellerItem, err := system.GetSysAdminById(applyUserId)
-	if err != nil {
-		return
-	}
+	//sellerItem, err := system.GetSysAdminById(applyUserId)
+	//if err != nil {
+	//	return
+	//}
 
 	//更新用户产品状态
 	sql := `UPDATE company_product SET status='永续',is_suspend=0,approve_status='已审批',freeze_start_date=null,freeze_end_date=null,
-            start_date=?,end_date=?,seller_id=?,seller_name=?,group_id=?,department_id=?,modify_time=NOW(),try_stage=1 WHERE company_id=? AND product_id=? `
-	_, err = to.Raw(sql, startDate, endDate, sellerItem.AdminId, sellerItem.RealName, sellerItem.GroupId, sellerItem.DepartmentId, companyId, productId).Exec()
+            start_date=?,end_date=?,modify_time=NOW(),try_stage=1 WHERE company_id=?  `
+	_, err = to.Raw(sql, startDate, endDate, companyId).Exec()
 	if err != nil {
 		return
 	}
@@ -578,6 +579,13 @@ func FreezeToTryOutXClassRai(companyId, productId, sellerId, companyApprovalId,
 			return
 		}
 	}
+
+	sql = `UPDATE company_report_permission SET  status='永续',start_date=?,end_date=? WHERE  company_id=?  ` // 更改权限的开始时间结束时间
+	_, err = to.Raw(sql, startDate, endDate, companyId).Exec()
+	if err != nil {
+		return
+	}
+
 	//获取需要试用的权限
 	delayPermissionItems, tmpErr := GetDelayPermissionItems(companyId, companyApprovalId)
 	if tmpErr != nil {
@@ -594,7 +602,7 @@ func FreezeToTryOutXClassRai(companyId, productId, sellerId, companyApprovalId,
 			LastUpdatedTime:    time.Now(),
 			ChartPermissionId:  v.ChartPermissionId,
 			StartDate:          v.StartDate,
-			EndDate:            v.EndDate,
+			EndDate:            endDate,
 			ProductId:          productId,
 			ProductName:        productName,
 			//CompanyContractId:         companyContractId,

+ 8 - 0
models/company/company_contract.go

@@ -330,3 +330,11 @@ func UpdateCompanyContractCompanyAscribeId(companyAscribId, companyContractId in
 	_, err = o.Raw(sql, companyAscribId, companyContractId).Exec()
 	return
 }
+
+// GetFirstContractRai 权益获取第一份合同
+func GetFirstContractRai(companyId int) (item *CompanyContract, err error) {
+	o := orm.NewOrm()
+	sql := " SELECT * FROM company_contract WHERE company_id = ?  AND product_id= 2  AND status = 1   ORDER BY   start_date  ASC  LIMIT  1  "
+	err = o.Raw(sql, companyId).QueryRow(&item)
+	return
+}

+ 10 - 1
models/company/company_product.go

@@ -103,6 +103,7 @@ type CompanyProductDetail struct {
 	ShareSeller      string    `description:"共享销售员"`
 	ShareSellerId    int       `description:"共享销售员id"`
 	PermissionList   []*PermissionLookList
+	ViewTotal        int `description:"总阅读次数"`
 }
 
 func GetCompanyProductsByCompanyId(companyId int) (items []*CompanyProductDetail, err error) {
@@ -496,7 +497,7 @@ func GetCompanyProductByCompanyIdAndSellerId(companyId, sellerId int) (item *Com
 
 // GetCompanyProductsByCompanyIds 根据客户id集合字符串获取所有客户产品列表
 func GetCompanyProductsBySellerId(sellerId string) (items []*CompanyProduct, err error) {
-	sql := `SELECT * FROM company_product WHERE seller_id in (` + sellerId + `) `
+	sql := `SELECT * FROM company_product WHERE (seller_id in (` + sellerId + `) OR share_seller_id IN  (` + sellerId + `) )`
 	o := orm.NewOrm()
 	_, err = o.Raw(sql).QueryRows(&items)
 	return
@@ -674,3 +675,11 @@ func GetCompanyProductRaiForeverCount(companyId int) (count int, err error) {
 	err = o.Raw(sqlCount, companyId).QueryRow(&count)
 	return
 }
+
+// 根据共享销售id查被共享的公司销售id
+func GetCompanyProductSellerIdByShareSellerId(shareSellerId int) (sellerId int, err error) {
+	sqlCount := ` SELECT seller_id FROM company_product WHERE share_seller_id = ? AND product_id = 2 `
+	o := orm.NewOrm()
+	err = o.Raw(sqlCount, shareSellerId).QueryRow(&sellerId)
+	return
+}

+ 18 - 0
models/cygx/activity_appointment.go

@@ -197,3 +197,21 @@ func GetActivityAppointmentOpenIdList(activityId int) (items []*OpenIdList, err
 	_, err = o.Raw(sql, activityId).QueryRows(&items)
 	return
 }
+
+
+// 获取预约活动纪要的的用户的openID
+func GetMfyxActivityAppointmentOpenIdList(activityId int) (items []*OpenIdList, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	var sql string
+	sql = `SELECT DISTINCT
+				u.open_id,
+				u.cygx_user_id AS user_id 
+			FROM
+				cygx_activity_appointment AS m
+				INNER JOIN cygx_mfyx_gzh_user_record AS u ON u.cygx_bind_account = m.mobile 
+				AND u.cygx_user_id = m.user_id 
+			WHERE
+				m.activity_id = ? `
+	_, err = o.Raw(sql, activityId).QueryRows(&items)
+	return
+}

+ 33 - 0
models/cygx/activity_ask_email.go

@@ -2,6 +2,7 @@ package cygx
 
 import (
 	"github.com/beego/beego/v2/client/orm"
+	"hongze/hz_crm_api/models/system"
 )
 
 type AskEmailRep struct {
@@ -9,6 +10,7 @@ type AskEmailRep struct {
 	Email               string `description:"邮箱"`
 	Mobile              string `description:"手机号"`
 	ChartPermissionName string `description:"权限名称"`
+	AdminId             int
 }
 
 func GetAskEmail() (item []*AskEmailRep, err error) {
@@ -24,3 +26,34 @@ func GetAskEmailList() (item []*AskEmailRep, err error) {
 	_, err = o.Raw(sql).QueryRows(&item)
 	return
 }
+
+func UpdateAskEmail(item *AskEmailRep) (err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sql := `UPDATE cygx_activity_ask_email SET admin_id=? where mobile=?`
+	_, err = o.Raw(sql, item.AdminId, item.Mobile).Exec()
+	return
+}
+
+func InitSyncActivityAskEmailAdminId() {
+	list, err := GetAskEmailList()
+	if err != nil {
+		return
+	}
+	sysUserList, err := system.GetAdminList()
+	if err != nil {
+		return
+	}
+	adminMap := make(map[string]*system.Admin, 0)
+	for _, v := range sysUserList {
+		adminMap[v.Mobile] = v
+	}
+	for _, v := range list {
+		if admin, ok := adminMap[v.Mobile]; ok {
+			v.AdminId = admin.AdminId
+			err = UpdateAskEmail(v)
+			if err != nil {
+				return
+			}
+		}
+	}
+}

+ 17 - 0
models/cygx/activity_help_ask.go

@@ -46,3 +46,20 @@ func GetActivityHelpAskOpenIdList(activityId int) (items []*OpenIdList, err erro
 	_, err = o.Raw(sql, activityId).QueryRows(&items)
 	return
 }
+
+// 获取活动带问的用户的openID
+func GetMfyxActivityHelpAskOpenIdList(activityId int) (items []*OpenIdList, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	var sql string
+	sql = `SELECT DISTINCT
+				u.open_id,
+				u.cygx_user_id AS user_id 
+			FROM
+				cygx_activity_help_ask AS m
+				INNER JOIN cygx_mfyx_gzh_user_record AS u ON u.cygx_bind_account = m.mobile 
+				AND u.cygx_user_id = m.user_id 
+			WHERE
+				m.activity_id = ? `
+	_, err = o.Raw(sql, activityId).QueryRows(&items)
+	return
+}

+ 3 - 3
models/cygx/chart_permission.go

@@ -113,9 +113,9 @@ func GetCategoryInfoById(chartPermissionId int) (item *ChartPermission, err erro
 
 // 通过名称获取分类详情
 func GetCategoryInfoByName(name string) (item *ChartPermission, err error) {
-	if name == "宏观" {
-		name = "宏观经济"
-	}
+	//if name == "宏观" {
+	//	name = "宏观经济"
+	//}
 	o := orm.NewOrm()
 	sql := `SELECT * FROM chart_permission WHERE permission_name=? AND parent_id>0`
 	err = o.Raw(sql, name).QueryRow(&item)

+ 47 - 1
models/cygx/cygx_user_record.go

@@ -143,7 +143,7 @@ func GetCygxUserFllowDepartmentOpenid(articleId int) (items []*OpenIdList, err e
 			cr.cygx_user_id  as user_id 
 		FROM
 			cygx_article_department_follow AS f
-			INNER JOIN cygx_user_record AS cr ON cr.cygx_user_id = f.user_id 
+			INNER JOIN cygx_user_record AS cr ON cr.cygx_bind_account = f.mobile 
 			INNER JOIN cygx_article AS a ON a.department_id = f.department_id 
 		WHERE
 			 1=1   
@@ -465,3 +465,49 @@ func GetCygxUserIndustryFllowOpneidByActivityIds(activityId int) (items []*OpenI
 	_, err = o.Raw(sql, activityId).QueryRows(&items)
 	return
 }
+
+// 获取预约活动的用户的openID
+func GetMfyxActivityOpenIdList(activityId int) (items []*OpenIdList, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sql := `SELECT DISTINCT cr.open_id,cr.cygx_user_id as  user_id
+			FROM
+			cygx_my_schedule AS m
+			INNER JOIN cygx_mfyx_gzh_user_record AS cr ON cr.cygx_bind_account = m.mobile 
+			WHERE m.activity_id = ?  `
+	_, err = o.Raw(sql, activityId).QueryRows(&items)
+	return
+}
+
+
+// 根据手机号获取用户的openid
+func GetMfyxUserRecordListByMobileArr(bindAccount []string) (items []*OpenIdList, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	lenarr := len(bindAccount)
+	if lenarr == 0 {
+		return
+	}
+	var condition string
+	var pars []interface{}
+	condition = ` AND u.cygx_bind_account IN (` + utils.GetOrmInReplace(lenarr) + `)`
+	pars = append(pars, bindAccount)
+	sql := `SELECT
+			u.open_id,
+			u.cygx_user_id AS user_id 
+		FROM
+			cygx_mfyx_gzh_user_record AS u 
+		WHERE
+			1 = 1  ` + condition
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// 获取单个用户openid
+func GetMfyxUserRecordOpenidByMobile(bindAccount string) (item *OpenIdList, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	var sql string
+	sql = `SELECT cr.open_id,cr.cygx_user_id as  user_id
+			FROM cygx_mfyx_gzh_user_record AS cr 
+			WHERE cr.cygx_bind_account = ?`
+	err = o.Raw(sql, bindAccount).QueryRow(&item)
+	return
+}

+ 2 - 1
models/cygx/cygx_yanxuan_special.go

@@ -188,7 +188,8 @@ func GetCygxYanxuanSpecialCount(condition string, pars []interface{}) (count int
 }
 
 type CygxYanxuanSpecialShowButton struct {
-	IsShowSpecialAuthor bool // 作者管理的按钮是否
+	IsShowYanXuanSpecial bool // 研选专栏文章管理按钮是否展示
+	IsShowSpecialAuthor  bool // 作者管理的按钮是否展示
 }
 
 func GetYanxuanSpecialBySpecialId(specialId int) (item *CygxYanxuanSpecialItem, err error) {

+ 138 - 0
models/cygx/orde.go

@@ -0,0 +1,138 @@
+package cygx
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+type CygxOrder struct {
+	OrderId          int       `orm:"column(order_id);pk";comment:"订单id"`
+	OrderCode        string    `comment:"订单编号"`
+	OutTradeCode     string    `comment:"外部交易号"`
+	PaymentType      int       `comment:"支付类型。支付类型。取值范围:1微信小程序,2微信扫码支付,3微信H5支付。"`
+	GoodsName        string    `comment:"商品名称"`
+	GoodsId          int       `comment:"商品ID"`
+	BuyerInvoice     string    `comment:"买家发票信息"`
+	GoodsMoney       float64   `comment:"商品总价"`
+	OrderMoney       float64   `comment:"订单总价"`
+	Point            int       `comment:"订单消耗积分"`
+	PointMoney       float64   `comment:"订单消耗积分抵多少钱"`
+	PayMoney         float64   `comment:"订单实付金额"`
+	RefundMoney      float64   `comment:"订单退款金额"`
+	RefundTime       time.Time `description:"退款时间"`
+	RefundRemark     string    `description:"退款原因说明"`
+	OrderStatus      int       `comment:"订单状态,0:已取消、1:待支付、2:已支付、3:退款成功、4:退款处理中、5:退款异常、6:退款关闭"`
+	PayTime          time.Time `comment:"订单付款时间"`
+	SourceId         int       `comment:"来源ID"`
+	Source           string    `comment:"来源\n报告 :article\n活动 :activity"`
+	SourceTitle      string    `comment:"来源名称,活动或者报告标题"`
+	UserId           int       `comment:"用户ID"`
+	Mobile           string    `comment:"手机号"`
+	Email            string    `comment:"邮箱"`
+	CompanyId        int       `comment:"公司ID"`
+	CompanyName      string    `comment:"公司名称"`
+	RealName         string    `comment:"用户实际名称"`
+	SellerName       string    `comment:"所属销售"`
+	CreateTime       time.Time `comment:"创建时间"`
+	ModifyTime       time.Time `comment:"修改时间"`
+	RegisterPlatform int       `comment:"来源 1小程序,2:网页"`
+}
+
+type CygxOrderResp struct {
+	OrderId          int       `orm:"column(order_id);pk";comment:"订单id"`
+	OrderCode        string    `comment:"订单编号"`
+	OutTradeNo       string    `comment:"【商户订单号】 商户系统内部订单号"`
+	OutTradeCode     string    `comment:"外部交易号"`
+	PaymentType      int       `comment:"支付类型。取值范围:1微信支付,2支付宝支付。"`
+	TradeType        string    `comment:"交易类型,枚举值:JSAPI:公众号支付 、 NATIVE:扫码支付 、 App:App支付 、 MICROPAY:付款码支付 、 MWEB:H5支付 、 FACEPAY:刷脸支付"`
+	GoodsName        string    `comment:"商品名称"`
+	GoodsId          int       `comment:"商品ID"`
+	BuyerInvoice     string    `comment:"买家发票信息"`
+	GoodsMoney       float64   `comment:"商品总价"`
+	OrderMoney       float64   `comment:"订单总价"`
+	Point            int       `comment:"订单消耗积分"`
+	PointMoney       float64   `comment:"订单消耗积分抵多少钱"`
+	PayMoney         float64   `comment:"订单实付金额"`
+	RefundMoney      float64   `comment:"订单退款金额"`
+	RefundTime       time.Time `comment:"退款时间"`
+	RefundRemark     string    `comment:"退款原因说明"`
+	OrderStatus      int       `comment:"订单状态,0:已取消、1:待支付、2:已支付、3:退款成功、4:退款处理中、5:退款异常、6:退款关闭"`
+	PayTime          time.Time `comment:"订单付款时间"`
+	SourceId         int       `comment:"来源ID"`
+	Source           string    `comment:"来源\n报告 :article\n活动 :activity"`
+	SourceTitle      string    `comment:"来源名称,活动或者报告标题"`
+	UserId           int       `comment:"用户ID"`
+	Mobile           string    `comment:"手机号"`
+	Email            string    `comment:"邮箱"`
+	CompanyId        int       `comment:"公司ID"`
+	CompanyName      string    `comment:"公司名称"`
+	RealName         string    `comment:"用户实际名称"`
+	SellerName       string    `comment:"所属销售"`
+	StartDate        time.Time `comment:"开始日期"`
+	EndDate          time.Time `comment:"结束日期"`
+	CreateTime       time.Time `comment:"创建时间"`
+	ModifyTime       time.Time `comment:"修改时间"`
+	RegisterPlatform int       `comment:"来源 1小程序,2:网页"`
+	ShareId          int       `comment:"分享人ID"`
+	ShareName        string    `comment:"分享人姓名"`
+}
+
+func GetCygxOrderList(condition string, pars []interface{}, startSize, pageSize int) (items []*CygxOrderResp, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sql := `SELECT *
+			FROM
+			cygx_order
+			WHERE 1 = 1 ` + condition
+	sql += ` LIMIT ?,?  `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// 获取数量
+func GetCygxOrderCount(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sqlCount := ` SELECT COUNT(1) AS count  FROM cygx_order WHERE   1= 1  ` + condition
+	err = o.Raw(sqlCount, pars).QueryRow(&count)
+	return
+}
+
+// 根据订单编号获取订单详情
+func GetCygxOrderDetailByOrderCode(orderCode string) (item *CygxOrderResp, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sql := `SELECT * FROM cygx_order WHERE order_code = ? `
+	err = o.Raw(sql, orderCode).QueryRow(&item)
+	return
+}
+
+type OrderListResp struct {
+	OrderCode       string  `comment:"订单编号"`
+	UserId          int     `comment:"用户ID"`
+	Mobile          string  `comment:"手机号"`
+	Email           string  `comment:"邮箱"`
+	CompanyId       int     `comment:"公司ID"`
+	CompanyName     string  `comment:"公司名称"`
+	RealName        string  `comment:"用户实际名称"`
+	SellerName      string  `comment:"所属销售"`
+	OrderMoney      float64 `comment:"订单总价"`
+	CreateTime      string  `comment:"创建时间"`
+	SourceId        int     `comment:"来源ID"`
+	Source          string  `comment:"来源\n报告 :article\n活动 :activity"`
+	SourceTitle     string  `comment:"来源名称,活动或者报告标题"`
+	OrderStatus     int     `comment:"订单状态码"`
+	OrderStatusText string  `comment:"订单状态描述"`
+	PaymentTypeText string  `comment:"支付类型。取值范围:1微信小程序,2微信扫码支付,3微信H5支付。"`
+	StartDate       string  `comment:"开始日期"`
+	EndDate         string  `comment:"结束日期"`
+	InviteName      string  `description:"邀请人"`
+	PayTime         string  `comment:"订单付款时间"`
+	RefundTime      string  `comment:"订单退款时间"`
+	RefundRemark    string  `description:"退款原因说明"`
+	PaymentProject  string  `comment:"付款项目"`
+	HttpUrl         string  `description:"跳转地址"`
+}
+
+type UserOrderListResp struct {
+	Paging *paging.PagingItem `description:"分页数据"`
+	List   []*OrderListResp
+}

+ 90 - 0
models/cygx/order_action.go

@@ -0,0 +1,90 @@
+package cygx
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// /订单操作表
+type CygxOrderAction struct {
+	ActionId         int       `orm:"column(action_id);pk";comment:"动作id"`
+	Action           string    `comment:"动作内容"`
+	OrderStatus      int       `comment:"订单状态,0:已取消、1:待支付、2:已支付、3:已退款"`
+	OrderStatusText  string    `comment:"订单状态名称"`
+	OrderCode        string    `comment:"订单编号"`
+	UserId           int       `comment:"用户ID"`
+	Mobile           string    `comment:"手机号"`
+	Email            string    `comment:"邮箱"`
+	CompanyId        int       `comment:"公司ID"`
+	CompanyName      string    `comment:"公司名称"`
+	RealName         string    `comment:"用户实际名称"`
+	SellerName       string    `comment:"所属销售"`
+	CreateTime       time.Time `comment:"创建时间"`
+	ModifyTime       time.Time `comment:"修改时间"`
+	RegisterPlatform int       `comment:"来源 1小程序,2:网页"`
+	AdminId          int       `comment:"管理员ID"`
+	AdminName        string    `comment:"管理员姓名"`
+}
+
+func AddCygxOrderRefundRevoke(item *CygxOrderAction) (err error) {
+	to := orm.NewOrmUsingDB("hz_cygx")
+	o, err := to.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+	updateParams := make(map[string]interface{})
+	updateParams["OrderStatus"] = 6 //退款关闭
+	ptrStructOrTableName := "cygx_order"
+	whereParam := map[string]interface{}{"order_code": item.OrderCode}
+	qs := o.QueryTable(ptrStructOrTableName)
+	for expr, exprV := range whereParam {
+		qs = qs.Filter(expr, exprV)
+	}
+	_, err = qs.Update(updateParams)
+	if err != nil {
+		return
+	}
+
+	_, err = o.Insert(item)
+	return
+}
+
+//// 添加CygxOrderRefund
+//func AddCygxOrderRefundRevoke(item *CygxOrderRefund) (err error) {
+//	to := orm.NewOrmUsingDB("hz_cygx")
+//	o, err := to.Begin()
+//	if err != nil {
+//		return
+//	}
+//	defer func() {
+//		if err != nil {
+//			_ = o.Rollback()
+//		} else {
+//			_ = o.Commit()
+//		}
+//	}()
+//	updateParams := make(map[string]interface{})
+//	updateParams["OrderStatus"] = 3
+//	updateParams["RefundMoney"] = item.RefundMoney
+//	updateParams["RefundRemark"] = item.Remark
+//	updateParams["RefundTime"] = time.Now()
+//	ptrStructOrTableName := "cygx_order"
+//	whereParam := map[string]interface{}{"order_code": item.OrderCode}
+//	qs := o.QueryTable(ptrStructOrTableName)
+//	for expr, exprV := range whereParam {
+//		qs = qs.Filter(expr, exprV)
+//	}
+//	_, err = qs.Update(updateParams)
+//	if err != nil {
+//		return
+//	}
+//	_, err = o.Insert(item)
+//	return
+//}

+ 58 - 0
models/cygx/order_refund.go

@@ -0,0 +1,58 @@
+package cygx
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxOrderRefund struct {
+	//OrderRefundID   uint64    `description:"主键id"`
+	OrderRefundId   int       `orm:"column(order_refund_id);pk";comment:"主键id"`
+	OrderCode       string    `description:"订单编号"`
+	RefundTradeCode string    `description:"退款交易号"`
+	RefundMoney     float64   `description:"退款金额"`
+	RefundWay       int       `description:"退款方式(1:微信商户,2:支付宝商户,3:线下)"`
+	RefundTime      time.Time `description:"退款时间"`
+	Remark          string    `description:"备注"`
+	CreateTime      time.Time `description:"创建时间"`
+	AdminId         int       `description:"管理员ID"`
+	AdminName       string    `description:"管理员姓名"`
+}
+
+type CygxOrderRefundReq struct {
+	OrderCode string `description:"订单编号"`
+	Remark    string `description:"备注"`
+}
+
+// 添加CygxOrderRefund
+func AddCygxOrderRefund(item *CygxOrderRefund, orderStatus int) (err error) {
+	to := orm.NewOrmUsingDB("hz_cygx")
+	o, err := to.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+	updateParams := make(map[string]interface{})
+	updateParams["OrderStatus"] = orderStatus
+	updateParams["RefundMoney"] = item.RefundMoney
+	updateParams["RefundRemark"] = item.Remark
+	updateParams["RefundTime"] = time.Now()
+	ptrStructOrTableName := "cygx_order"
+	whereParam := map[string]interface{}{"order_code": item.OrderCode}
+	qs := o.QueryTable(ptrStructOrTableName)
+	for expr, exprV := range whereParam {
+		qs = qs.Filter(expr, exprV)
+	}
+	_, err = qs.Update(updateParams)
+	if err != nil {
+		return
+	}
+	_, err = o.Insert(item)
+	return
+}

+ 29 - 0
models/cygx/user_business_card.go

@@ -0,0 +1,29 @@
+package cygx
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxUserBusinessCard struct {
+	UserId           int       `comment:"用户ID"`
+	Mobile           string    `comment:"手机号"`
+	Email            string    `comment:"邮箱"`
+	CompanyName      string    `comment:"公司名称"`
+	RealName         string    `comment:"用户实际名称"`
+	InviteName       string    `comment:"用户实际名称"`
+	CreateTime       time.Time `comment:"创建时间"`
+	ModifyTime       time.Time `comment:"修改时间"`
+	RegisterPlatform int       `comment:"来源 1小程序,2:网页"`
+}
+
+func GetCygxUserBusinessCardList(condition string, pars []interface{}, startSize, pageSize int) (items []*CygxUserBusinessCard, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sql := `SELECT *
+			FROM
+			cygx_user_business_card
+			WHERE 1 = 1 ` + condition
+	sql += ` LIMIT ?,?  `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}

+ 5 - 1
models/day_new/day_new_default.go

@@ -10,6 +10,8 @@ type DayNewDefault struct {
 	ClassifyNameFirst  string `description:"一级分类名称"`
 	ClassifyIdSecond   int    `description:"二级分类id"`
 	ClassifyNameSecond string `description:"二级分类名称"`
+	ClassifyIdThird    int    `description:"三级分类ID"`
+	ClassifyNameThird  string `description:"三级分类名称"`
 	Title              string `description:"标题"`
 	Abstract           string `description:"摘要"`
 	Author             string `description:"作者"`
@@ -24,6 +26,8 @@ type EnglishReportDefaultSaveReq struct {
 	ClassifyNameFirst  string `description:"一级分类名称"`
 	ClassifyIdSecond   int    `description:"二级分类id"`
 	ClassifyNameSecond string `description:"二级分类名称"`
+	ClassifyIdThird    int    `description:"三级分类ID"`
+	ClassifyNameThird  string `description:"三级分类名称"`
 	Title              string `description:"标题"`
 	Abstract           string `description:"摘要"`
 	Author             string `description:"作者"`
@@ -51,4 +55,4 @@ func (item *DayNewDefault) Update(cols []string) (err error) {
 	o := orm.NewOrm()
 	_, err = o.Update(item, cols...)
 	return
-}
+}

+ 9 - 8
models/day_new/wework_msg.go

@@ -45,7 +45,7 @@ type WeworkMsgListResp struct {
 }
 
 type DeleteWeworkMsgReq struct {
-	MsgId      string `description:"企业微信消息id"`
+	MsgId string `description:"企业微信消息id"`
 }
 
 type EditWeworkMsgContentReq struct {
@@ -59,6 +59,8 @@ type DayNewReportDefaultResp struct {
 	ClassifyNameFirst  string `description:"一级分类名称"`
 	ClassifyIdSecond   int    `description:"二级分类id"`
 	ClassifyNameSecond string `description:"二级分类名称"`
+	ClassifyIdThird    int    `description:"三级分类ID"`
+	ClassifyNameThird  string `description:"三级分类名称"`
 	Title              string `description:"标题"`
 	Abstract           string `description:"摘要"`
 	Author             string `description:"作者"`
@@ -115,7 +117,7 @@ func GetWeworkMsgByConditionLimit(condition string, pars []interface{}, limit in
 	return
 }
 
-func UpdateContentEnByMsgId(contentEn, msgId string) (err error)  {
+func UpdateContentEnByMsgId(contentEn, msgId string) (err error) {
 	o := orm.NewOrm()
 	sql := `UPDATE wework_msg 
 SET modify_time=NOW(), content_en = ?
@@ -126,7 +128,7 @@ WHERE
 }
 
 // DeleteWeworkMsgByMsgId 删除消息
-func DeleteWeworkMsgByMsgId(msgId string) (err error)  {
+func DeleteWeworkMsgByMsgId(msgId string) (err error) {
 	o := orm.NewOrm()
 	sql := `UPDATE wework_msg 
 SET modify_time=NOW(), is_delete = 1
@@ -137,7 +139,7 @@ WHERE
 }
 
 // GetWeworkMsgByMsgId 根据消息Id查询
-func GetWeworkMsgByMsgId(msgId string) (item *WeworkMsg, err error)  {
+func GetWeworkMsgByMsgId(msgId string) (item *WeworkMsg, err error) {
 	o := orm.NewOrm()
 	sql := `select * from wework_msg where msg_id = ?`
 	err = o.Raw(sql, msgId).QueryRow(&item)
@@ -155,14 +157,13 @@ type AddEnglishReportReq struct {
 	Frequency          string `description:"频度"`
 }
 
-
 // UpdateWeworkMsgIsAdd 更新消息状态为已加入报告
-func UpdateWeworkMsgIsAdd(msgIds string, reportId int64) (err error)  {
+func UpdateWeworkMsgIsAdd(msgIds string, reportId int64) (err error) {
 	o := orm.NewOrm()
 	sql := `UPDATE wework_msg 
 SET modify_time=NOW(), is_add = 1, report_id= ?
 WHERE 
-	 msg_id in (`+msgIds+`) and is_delete = 0 and is_add = 0`
+	 msg_id in (` + msgIds + `) and is_delete = 0 and is_add = 0`
 	_, err = o.Raw(sql, reportId).Exec()
 	return
 }
@@ -173,4 +174,4 @@ func GetWeworkMsgReportIdByLimit(limit int) (list []*WeworkMsg, err error) {
 	sql := `SELECT * FROM wework_msg WHERE is_add = 1 and report_id > 0 GROUP BY report_id ORDER BY report_id desc LIMIT ?`
 	_, err = o.Raw(sql, limit).QueryRows(&list)
 	return
-}
+}

+ 9 - 5
models/db.go

@@ -378,11 +378,12 @@ func initYb() {
 func initRoadShow() {
 	//注册对象
 	orm.RegisterModel(
-		new(roadshow.RsCalendar),           //路演主表
-		new(roadshow.RsCalendarResearcher), //路演研究员信息表
-		new(roadshow.RsMatters),            //公开会议表
-		new(roadshow.RsCalendarRelation),   //路演关系表(与上海的路演日历关系)
-		new(roadshow.RsReportRecord),       //路演统计表
+		new(roadshow.RsCalendar),            //路演主表
+		new(roadshow.RsCalendarResearcher),  //路演研究员信息表
+		new(roadshow.RsMatters),             //公开会议表
+		new(roadshow.RsCalendarRelation),    //路演关系表(与上海的路演日历关系)
+		new(roadshow.RsReportRecord),        //路演统计表
+		new(roadshow.RsCalendarMeetingUser), //路演参会名单表
 	)
 }
 
@@ -476,6 +477,9 @@ func initCygx() {
 		new(cygx.CygxEnterScoreGroup),
 		new(cygx.CygxEnterScorePermission),
 		new(cygx.CygxEnterScoreResearcher),
+		new(cygx.CygxOrderRefund),
+		new(cygx.CygxOrder),
+		new(cygx.CygxOrderAction),
 	)
 }
 

+ 27 - 17
models/english_report.go

@@ -2,7 +2,6 @@ package models
 
 import (
 	"github.com/beego/beego/v2/client/orm"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"hongze/hz_crm_api/utils"
 	"strings"
 	"time"
@@ -108,33 +107,36 @@ type EnglishClassifyList struct {
 	IsShow        int       `description:"是否在小程序显示:1-显示 0-隐藏"`
 	//ClassifyType  int       `description:"分类类型:0英文报告,1英文线上路演"`
 	EnPermissions []int `description:"英文权限IDs"`
+	Enabled       int   `description:"是否可用,1可用,0禁用"`
 	Child         []*EnglishClassifyList
 }
 
 type EnglishClassifyListResp struct {
-	List   []*EnglishClassifyList
-	Paging *paging.PagingItem `description:"分页数据"`
+	List []*EnglishClassifyList
 }
 
 // GetEnglishClassifyRootId 获取一级分类列表
-func GetEnglishClassifyRootId(startSize, pageSize int, keyWord string) (items []*EnglishClassifyList, err error) {
+func GetEnglishClassifyRootId(keyword string, enabled int) (items []*EnglishClassifyList, err error) {
 	sql := ``
 	o := orm.NewOrmUsingDB("rddp")
-	if keyWord != "" {
+	cond := ""
+	if enabled == 1 {
+		cond = " AND enabled=1 "
+	}
+	if keyword != "" {
 		sql = `SELECT * FROM (
 			                   SELECT * FROM english_classify
-                   WHERE parent_id=0 AND classify_name LIKE '%` + keyWord + `%'
+                   WHERE parent_id=0 ` + cond + ` AND classify_name LIKE ? 
                    UNION
                    SELECT * FROM english_classify
                    WHERE id IN(SELECT parent_id FROM english_classify
-                   WHERE parent_id>0 AND classify_name LIKE '%` + keyWord + `%')
+                   WHERE parent_id>0 ` + cond + ` AND classify_name LIKE ? )
                    )AS t
-                   ORDER BY sort ASC,create_time ASC
-                   LIMIT ?,? `
-		_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+                   ORDER BY sort ASC,create_time ASC`
+		_, err = o.Raw(sql, utils.GetLikeKeyword(keyword), utils.GetLikeKeyword(keyword)).QueryRows(&items)
 	} else {
-		sql = `SELECT * FROM english_classify WHERE parent_id=0 ORDER BY sort ASC,create_time ASC LIMIT ?,? `
-		_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+		sql = `SELECT * FROM english_classify WHERE parent_id=0 ` + cond + ` ORDER BY sort ASC,create_time ASC `
+		_, err = o.Raw(sql).QueryRows(&items)
 	}
 	return
 }
@@ -160,20 +162,28 @@ func GetEnglishClassifyListCount(keyWord string) (count int, err error) {
 	return
 }
 
-func GetEnglishClassifyListByRootId(rootIds []int, keyWord string) (items []*EnglishClassifyList, err error) {
+func GetEnglishClassifyListByRootId(rootIds []int, keyword string, enabled int) (items []*EnglishClassifyList, err error) {
 	sql := ``
+	pars := make([]interface{}, 0)
+
 	o := orm.NewOrmUsingDB("rddp")
-	if keyWord != "" {
+	cond := ""
+	if enabled == 1 {
+		cond = " AND enabled=1 "
+	}
+	if keyword != "" {
 		sql = `SELECT
 	a.*
 FROM
 	english_classify a
 	LEFT JOIN english_classify b ON a.root_id = b.id
 	LEFT JOIN english_classify c ON a.parent_id = c.id
-	WHERE a.parent_id > 0 and a.classify_name LIKE '%` + keyWord + `%' and a.root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `)`
-		_, err = o.Raw(sql, rootIds).QueryRows(&items)
+	WHERE a.parent_id>0  ` + cond + ` and a.classify_name LIKE ? and a.root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `)`
+		pars = append(pars, utils.GetLikeKeyword(keyword))
+		pars = append(pars, rootIds)
+		_, err = o.Raw(sql, pars).QueryRows(&items)
 	} else {
-		sql = `SELECT * FROM english_classify WHERE parent_id > 0 and root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `) `
+		sql = `SELECT * FROM english_classify WHERE parent_id>0  ` + cond + ` and root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `) `
 		_, err = o.Raw(sql, rootIds).QueryRows(&items)
 	}
 	return

+ 12 - 0
models/eta_business/eta_business.go

@@ -330,3 +330,15 @@ type EtaBusinessItem struct {
 	ModifyTime       string `description:"更新时间"`
 	Nation           string `description:"所属国家"`
 }
+
+// EtaBusinessEditSignReq 编辑商家签约请求体
+type EtaBusinessEditSignReq struct {
+	EtaBusinessContractId int    `description:"商家合约ID"`
+	SigningTime           string `description:"当前合约的签约时间"`
+	ExpiredTime           string `description:"当前合约的到期时间"`
+}
+
+// EtaBusinessRemoveSignReq 删除商家签约请求体
+type EtaBusinessRemoveSignReq struct {
+	EtaBusinessContractId int `description:"商家合约ID"`
+}

+ 40 - 0
models/eta_business/eta_business_contract.go

@@ -154,6 +154,46 @@ func (m *EtaBusinessContract) CreateMaybeUpdateFirst(item *EtaBusinessContract,
 	return
 }
 
+// UpdateMaybeUpdateFirst 编辑签约合同, 或同时更新首次签约合同
+func (m *EtaBusinessContract) UpdateMaybeUpdateFirst(item *EtaBusinessContract, changeFirst bool, updateCols []string) (err error) {
+	// 无需修改首次签约则直接更新
+	o := orm.NewOrm()
+	if !changeFirst {
+		e := item.Update(updateCols)
+		if e != nil {
+			return e
+		}
+		return
+	}
+
+	// 更新首次签约合同
+	tx, e := o.Begin()
+	if e != nil {
+		return e
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	_, e = tx.Update(item, updateCols...)
+	if e != nil {
+		err = fmt.Errorf("contract update err: %s", e.Error())
+		return
+	}
+
+	sql := fmt.Sprintf(`UPDATE %s SET %s = 0 WHERE %s = ? AND %s <> ?`, m.TableName(), EtaBusinessContractColumns.IsFirst, EtaBusinessContractColumns.EtaBusinessId, EtaBusinessContractColumns.EtaBusinessContractId)
+	_, e = tx.Raw(sql, item.EtaBusinessId, item.EtaBusinessContractId).Exec()
+	if e != nil {
+		err = fmt.Errorf("update first contract err: %s", e.Error())
+		return
+	}
+	return
+}
+
 // EtaBusinessContractItem 商家签约信息
 type EtaBusinessContractItem struct {
 	EtaBusinessContractId int

+ 3 - 1
models/eta_business/eta_business_operation_record.go

@@ -15,6 +15,8 @@ const (
 	EtaBusinessOperationTypeEnable
 	EtaBusinessOperationTypeMoveSeller
 	EtaBusinessOperationTypeRenewalContract
+	EtaBusinessOperationTypeEditContract
+	EtaBusinessOperationTypeRemoveContract
 )
 
 // EtaBusinessOperationRecord ETA商家操作日志表
@@ -24,7 +26,7 @@ type EtaBusinessOperationRecord struct {
 	SellerId        int       `description:"操作时所对应的销售ID"`
 	SysUserId       int       `description:"操作人ID"`
 	SysRealName     string    `description:"操作人姓名"`
-	OperationType   int       `description:"操作类型:1-新增;2-编辑;3-禁用;4-启用;5-移动销售;6-添加续约"`
+	OperationType   int       `description:"操作类型:1-新增;2-编辑;3-禁用;4-启用;5-移动销售;6-添加续约;7-编辑签约;8-删除签约"`
 	OperationRemark string    `description:"操作内容"`
 	CreateTime      time.Time `description:"创建时间"`
 }

+ 19 - 3
models/permission.go

@@ -1,6 +1,10 @@
 package models
 
-import "github.com/beego/beego/v2/client/orm"
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hz_crm_api/utils"
+)
 
 // ChartPermissionSearchKeyWordMapping 权限相关
 type ChartPermissionSearchKeyWordMapping struct {
@@ -10,6 +14,7 @@ type ChartPermissionSearchKeyWordMapping struct {
 	From               string `description:"类型标识" json:"-"`
 	TacticType         string `description:"策略表type字段值" json:"-"`
 	TeleconferenceSort int    `description:"电话会类型排序" json:"-"`
+	ClassifyId         int    `description:"分类ID"`
 }
 
 func GetPermission(classifyNameSecond string) (items []*ChartPermissionSearchKeyWordMapping, err error) {
@@ -65,7 +70,7 @@ func AddChartPermissionSearchKeyWordMappingMulti(chartPermissionSearchKeyWordMap
 
 func AddChartPermissionChapterMapping(chartPermissionId int, reportId int64) (err error) {
 	sql := `INSERT INTO chart_permission_chapter_mapping (chart_permission_id, report_chapter_type_id,research_type)
-           VALUES(?,?,?)`
+          VALUES(?,?,?)`
 	o := orm.NewOrm()
 	_, err = o.Raw(sql, chartPermissionId, reportId, "rddp").Exec()
 	return
@@ -97,4 +102,15 @@ func UpdateChartPermissionNameFromMappingByKeyword(newKeyword, keyword, source s
 	sql := " UPDATE chart_permission_search_key_word_mapping SET key_word = ? WHERE key_word = ? AND `from` = ? "
 	_, err = o.Raw(sql, newKeyword, keyword, source).Exec()
 	return
-}
+}
+
+// GetPermissionsByClassifyIds 根据分类IDs获取权限IDs
+func GetPermissionsByClassifyIds(classifyIds []int) (items []*ChartPermissionSearchKeyWordMapping, err error) {
+	if len(classifyIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM chart_permission_search_key_word_mapping AS a WHERE a.from='rddp' AND a.classify_id IN (%s)`, utils.GetOrmInReplace(len(classifyIds)))
+	_, err = o.Raw(sql, classifyIds).QueryRows(&items)
+	return
+}

+ 8 - 2
models/roadshow/calendar.go

@@ -21,6 +21,7 @@ type AddActivityReq struct {
 	ProvinceCode     string `description:"省编码"`
 	City             string `description:"市"`
 	CityCode         string `description:"市编码"`
+	District         string `description:"区"`
 	Theme            string `description:"会议主题"`
 	CooperationName  string `description:"合作方名称"`
 	ActivityCategory string `description:"活动类别"`
@@ -52,6 +53,7 @@ type RsCalendar struct {
 	ProvinceCode     string `description:"省编码"`
 	City             string `description:"市"`
 	CityCode         string `description:"市编码"`
+	District         string `description:"区"`
 	Theme            string `description:"会议主题"`
 	CooperationName  string `description:"合作方名称"`
 	Title            string `description:"展示在日历的标题"`
@@ -273,6 +275,7 @@ type CalendarListView struct {
 	ProvinceCode           string `description:"省编码"`
 	City                   string `description:"市"`
 	CityCode               string `description:"市编码"`
+	District               string `description:"区"`
 	Theme                  string `description:"会议主题"`
 	CooperationName        string `description:"合作方名称"`
 	ActivityCategory       string `description:"活动类别"`
@@ -283,6 +286,8 @@ type CalendarListView struct {
 	EnglishCompany         int    `description:"是否为英文客户: 0-否; 1-是"`
 	EnglishCountry         string `description:"英文客户-国家"`
 	EnglishViewTotal       int    `description:"英文客户-累计点击量"`
+	SubmitButton           bool   `description:"提交按钮是否展示"`
+	ViewButton             bool   `description:"查看按钮是否展示"`
 }
 
 type CalendarListResp struct {
@@ -317,7 +322,7 @@ func GetCalendarListCount(condition string, pars []interface{}, calendarType int
 func GetCalendarList(condition string, pars []interface{}, startSize, pageSize, calendarType int) (list []*CalendarListView, err error) {
 	o := orm.NewOrm()
 	if calendarType == 3 || calendarType == 4 {
-		sql := ` SELECT a.rs_calendar_id,a.activity_type,a.roadshow_type,a.activity_category,a.roadshow_platform,b.create_time,
+		sql := ` SELECT a.rs_calendar_id,a.activity_type,a.roadshow_type,a.activity_category,a.roadshow_platform,b.create_time,a.district,
 				b.modify_time,GROUP_CONCAT(b.researcher_id ORDER BY researcher_sort ASC) AS researcher_id,GROUP_CONCAT(b.researcher_name ORDER BY researcher_sort ASC) AS researcher_name,
 				b.rs_calendar_researcher_id,b.start_date,
 				b.end_date,b.start_time,b.end_time,b.start_week,b.end_week,b.status,b.refuse_reason,b.refuse_time,
@@ -340,7 +345,7 @@ func GetCalendarList(condition string, pars []interface{}, startSize, pageSize,
 
 		_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&list)
 	} else {
-		sql := `SELECT a.rs_calendar_id,a.activity_type,a.roadshow_type,a.activity_category,a.roadshow_platform,b.create_time,
+		sql := `SELECT a.rs_calendar_id,a.activity_type,a.roadshow_type,a.activity_category,a.roadshow_platform,b.create_time,a.district,a.sys_user_id,
 				b.modify_time,b.researcher_id,b.researcher_name,
 				b.rs_calendar_researcher_id,b.start_date,
 				b.end_date,b.start_time,b.end_time,b.start_week,b.end_week,b.status,b.refuse_reason,b.refuse_time,
@@ -537,6 +542,7 @@ type EditActivityReq struct {
 	ProvinceCode           string `description:"省编码"`
 	City                   string `description:"市"`
 	CityCode               string `description:"市编码"`
+	District               string `description:"区"`
 	Theme                  string `description:"会议主题"`
 	CooperationName        string `description:"合作方名称"`
 	ActivityCategory       string `description:"活动类别"`

+ 1 - 1
models/roadshow/company.go

@@ -37,7 +37,7 @@ func CompanySearchV2(sellerId int, keyWord string) (list []*CompanySearchView, e
 				0 AS english_company
 			FROM
 				company AS a
-			INNER JOIN company_product AS b ON a.company_id = b.company_id AND b.product_id = 1
+			INNER JOIN company_product AS b ON a.company_id = b.company_id 
 			WHERE
 				b.status IN ('正式', '试用') AND (b.seller_id = ? OR b.share_seller_id = ?) AND a.company_name LIKE ?
 			GROUP BY

+ 96 - 0
models/roadshow/rs_calendar_meeting_user.go

@@ -0,0 +1,96 @@
+package roadshow
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hz_crm_api/utils"
+	"time"
+)
+
+type AddRsCalendarMeetingUserReq struct {
+	RsCalendarId int   `description:"日程ID"`
+	UserId       []int // 用户ID
+}
+
+type RsCalendarMeetingUser struct {
+	RsCalendarMeetingUserId int       `orm:"column(rs_calendar_meeting_user_id);pk" description:"主键ID"`
+	RsCalendarId            int       `description:"日程ID"`
+	UserId                  int       `description:"用户ID"`
+	Mobile                  string    `description:"手机号"`
+	Email                   string    `description:"邮箱"`
+	CompanyId               int       `description:"公司ID"`
+	CompanyName             string    `description:"公司名称"`
+	RealName                string    `description:"用户实际名称"`
+	Position                string    `description:"职位"`
+	AdminId                 int       `description:"管理员ID"`
+	AdminName               string    `description:"管理员姓名"`
+	CreateTime              time.Time `description:"创建时间"`
+	ModifyTime              time.Time `description:"修改时间"`
+}
+
+type RsCalendarMeetingUserResp struct {
+	RsCalendarMeetingUserId int    `description:"参会名单主键ID"`
+	RealName                string `description:"用户实际名称"`
+	Position                string `description:"职位"`
+}
+
+type DeleteRsCalendarMeetingUserReq struct {
+	RsCalendarMeetingUserId int `description:"参会名单主键ID"`
+}
+
+type RsCalendarMeetingUserListResp struct {
+	List []*RsCalendarMeetingUserResp
+}
+
+// MultiAddRsCalendarMeetingUser 批量添加RsCalendarMeetingUser
+func MultiAddRsCalendarMeetingUser(items []*RsCalendarMeetingUser) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+// 删除
+func DeleteRsCalendarMeetingUser(rsCalendarMeetingUserID int) (err error) {
+	o := orm.NewOrm()
+	sql := ` DELETE FROM rs_calendar_meeting_user WHERE rs_calendar_meeting_user_id=? `
+	_, err = o.Raw(sql, rsCalendarMeetingUserID).Exec()
+	return err
+}
+
+// 列表
+func GetRsCalendarMeetingUserList(condition string, pars []interface{}) (items *RsCalendarMeetingUserResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM rs_calendar_meeting_user WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&items)
+	return
+}
+
+// 通过路演ID获取参会人员列表
+func GetRsCalendarMeetingUserListByRsCalendarId(rsCalendarId int) (items []*RsCalendarMeetingUserResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM rs_calendar_meeting_user WHERE  rs_calendar_id = ?  `
+	_, err = o.Raw(sql, rsCalendarId).QueryRows(&items)
+	return
+}
+
+type RsCalendarMeetingUserCountResp struct {
+	RsCalendarId int `description:"日程ID"`
+	Total        int `description:"数量"`
+}
+
+// 路演参会人员数量
+func GetRsCalendarMeetingUserListCount(rsCalendarIds []int) (items []*RsCalendarMeetingUserCountResp, err error) {
+	lenNum := len(rsCalendarIds)
+	if lenNum <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := `SELECT  rs_calendar_id ,COUNT(1) as total  FROM rs_calendar_meeting_user WHERE  rs_calendar_id IN ( ` + utils.GetOrmInReplace(lenNum) + `)   GROUP BY rs_calendar_id  `
+	_, err = o.Raw(sql, rsCalendarIds).QueryRows(&items)
+	return
+}

+ 1 - 1
models/system/sys_admin.go

@@ -515,7 +515,7 @@ func GetRaiAdmin() (items []*AdminItem, err error) {
 // GetFiccEnterScoreAdmin 获取Ficc需要录分的研究员
 func GetFiccEnterScoreAdmin() (items []*AdminItem, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT   *  FROM admin WHERE group_name  IN('宏观组','建材组','有色组','能化组')  AND enabled = 1 `
+	sql := `SELECT   *  FROM admin_cygx WHERE group_name  IN('宏观组','建材组','有色组','能化组','海外组')  AND enabled = 1 `
 	_, err = o.Raw(sql).QueryRows(&items)
 	return
 }

+ 24 - 0
models/user_record.go

@@ -106,3 +106,27 @@ func GetUserRecordRegisterByUserIdsMyfx(userIds string) (items []*UserRecordRegi
 	_, err = o.Raw(sql).QueryRows(&items)
 	return
 }
+
+// 根据手机号获取用户的openid
+func GeCygxtUserRecordListByMobile(bindAccount string) (items []*OpenIdList, err error) {
+	var sql string
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sql = `SELECT
+			cr.open_id,
+			cr.cygx_user_id as  user_id 
+		FROM
+		  cygx_user_record  as cr 
+		WHERE 1= 1	AND cygx_bind_account IN (` + bindAccount + `)`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+func GetWxOpenIdByMobileList(mobile string) (items []*OpenIdList, err error) {
+	o := orm.NewOrmUsingDB("hz_cygx")
+	sql := ` SELECT
+				union_id,open_id,
+				cygx_user_id AS user_id
+				FROM cygx_user_record	WHERE	1 = 1	AND cygx_bind_account IN (` + mobile + `)`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 11 - 0
models/wx_user.go

@@ -455,6 +455,7 @@ type WxUserItem struct {
 	IsMsgOutboundMobile int       `description:"是否弹窗过绑定外呼手机号区号"`
 	IsMaker             int       `description:"是否是决策人"`
 	Source              int
+	Position            string `description:"职位"`
 }
 
 // GetWxUserListByUserIds 根据用户ID集合获取用户有公司名称
@@ -625,3 +626,13 @@ func GetCompanyFollowCount(companyId int) (count int, err error) {
 	err = o.Raw(sql, companyId).QueryRow(&count)
 	return
 }
+
+// 根据用户ID获取相关信息
+func GetWxUserItemByUserId(userId int) (item *WxUserItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT a.*,b.company_name FROM wx_user AS a
+			LEFT JOIN company AS b on a.company_id=b.company_id
+			WHERE a.user_id=? `
+	err = o.Raw(sql, userId).QueryRow(&item)
+	return
+}

+ 81 - 0
routers/commentsRouter.go

@@ -2158,6 +2158,24 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:OrderController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:OrderController"],
+        beego.ControllerComments{
+            Method: "OrderList",
+            Router: `/order/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:OrderController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:OrderController"],
+        beego.ControllerComments{
+            Method: "OrderRefundList",
+            Router: `/order/refund/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:ProductInteriorController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:ProductInteriorController"],
         beego.ControllerComments{
             Method: "PvExport",
@@ -2950,6 +2968,24 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:UserController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:UserController"],
+        beego.ControllerComments{
+            Method: "OrderRefund",
+            Router: `/order/refund`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:UserController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:UserController"],
+        beego.ControllerComments{
+            Method: "OrderRefundRevoke",
+            Router: `/order/refund_revoke`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:UserController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/cygx:UserController"],
         beego.ControllerComments{
             Method: "Add",
@@ -6928,6 +6964,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "EditSign",
+            Router: `/edit_sign`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
         beego.ControllerComments{
             Method: "Enable",
@@ -6964,6 +7009,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "RemoveSign",
+            Router: `/remove_sign`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
         beego.ControllerComments{
             Method: "Signing",
@@ -7666,6 +7720,33 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarMeetingUserController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarMeetingUserController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/rs_calendar_meeting_user/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarMeetingUserController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarMeetingUserController"],
+        beego.ControllerComments{
+            Method: "Delete",
+            Router: `/rs_calendar_meeting_user/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarMeetingUserController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarMeetingUserController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/rs_calendar_meeting_user/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/seal:SealApprovalController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/seal:SealApprovalController"],
         beego.ControllerComments{
             Method: "Apply",

+ 2 - 0
routers/router.go

@@ -161,6 +161,7 @@ func init() {
 				&cygx.AskserieVideoController{},
 				&cygx.UserAdminShareHistoryController{},
 				&cygx.EnterScoreController{},
+				&cygx.OrderController{},
 			),
 		),
 		web.NSNamespace("/advisory",
@@ -232,6 +233,7 @@ func init() {
 		web.NSNamespace("/roadshow",
 			web.NSInclude(
 				&roadshow.CalendarController{},
+				&roadshow.CalendarMeetingUserController{},
 			),
 		),
 		web.NSNamespace("/taglib",

+ 2 - 1
services/company_apply/company_approval.go

@@ -855,10 +855,11 @@ func afterApproved(companyApprovalId int, opUserId int, opUserName string) (err
 		remark := "审批"
 		operation := "approve"
 		approveContent := "审批通过"
-		if companyProduct.Status == utils.COMPANY_STATUS_FOREVER && companyProduct.ProductId == 2 { //权益永续客户申请内容做变更
+		if companyProduct.InitStatus == utils.COMPANY_STATUS_FOREVER && companyProduct.ProductId == 2 { //权益永续客户申请内容做变更
 			//123月份申请转正通过时,将试用期限延长(更新)至4.30。456月份申请转正通过时,将试用期限延长至7.31。789月份申请转正通过时,将试用期限延长至10.31。101112月份申请转正通过时,将试用期限延长至次年1.31。
 			endDateContent := utils.GetLastDayOfQuarter(time.Now()).Format(utils.FormatDate)
 			approveContent += ",试用延期至" + endDateContent
+
 		}
 		services.AddCompanyOperationRecord(recodeInfo.CompanyId, companyProduct.SellerId, opUserId, recodeInfo.ProductId, opUserId, companyProduct.CompanyName,
 			companyProduct.ProductName, opUserName, remark, operation, approveContent, opUserName, "", companyProduct.Status)

+ 18 - 0
services/company_approval_message.go

@@ -215,6 +215,22 @@ func AddCompanyApprovalMessageRai(companyId, companyContractId int, applyRealNam
 		return
 	}
 	go SendWxMsgWithRaiSell(first, keyword1, keyword2, keyword3, keyword4, openIdList)
+
+	list, e := company.GetCompanyContractPermissionByCompanyContractId(companyContractId)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("GetCompanyContractPermissionByCompanyContractId, Err: " + e.Error())
+		return
+	}
+
+	if len(list) == 0 {
+		return
+	}
+
+	for _, v := range list {
+		if v.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN || v.ChartPermissionId == utils.YAN_XUAN_KOU_DIAN_BAO_ID {
+			go SendWxCategoryMsgWithRaiSell(companyName, "销售:"+applyRealName, "已签约研选", time.Now().Format(utils.FormatDateTimeMinute2), openIdList)
+		}
+	}
 	return
 }
 
@@ -267,6 +283,7 @@ func AddCompanyApprovalMessageWangYang(companyId, companyContractId int, applyRe
 		keyword2 = time.Now().Format(utils.FormatDateTime)
 		keyword3 = "签约【研选订阅】"
 		go SendWxMsgWithRaiWangYang(keyword1, keyword2, keyword3, keyword4, openIdList)
+		go SendWxCategoryMsgWithRaiWangYang(companyName, "销售:"+applyRealName, keyword3, time.Now().Format(utils.FormatDateTimeMinute2), openIdList)
 	}
 
 	if points > 0 {
@@ -274,6 +291,7 @@ func AddCompanyApprovalMessageWangYang(companyId, companyContractId int, applyRe
 		keyword2 = time.Now().Format(utils.FormatDateTime)
 		keyword3 = "签约【研选扣点包(" + fmt.Sprint(points) + "个点)】"
 		go SendWxMsgWithRaiWangYang(keyword1, keyword2, keyword3, keyword4, openIdList)
+		go SendWxCategoryMsgWithRaiWangYang(companyName, "销售:"+applyRealName, keyword3, time.Now().Format(utils.FormatDateTimeMinute2), openIdList)
 	}
 
 	return

+ 61 - 0
services/contract/contract.go

@@ -1763,3 +1763,64 @@ func handleRaiContractModifyContentByServices(originService []*contract.Contract
 	tips = fmt.Sprint("原服务内容:", oldStr, "</n>现服务内容:", newStr)
 	return
 }
+
+// 获取权益近一年是否有新签合同
+func GetCompanyContractCountRaiByLastYear(companyId int, startDate string) (total int, err error) {
+	firstContractRai, err := company.GetFirstContractRai(companyId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return
+	}
+	//没有合同这第一份合同就属于新签合同
+	if firstContractRai == nil {
+		err = nil
+		total = 1
+		return
+	}
+	//判断是否是在一年以内
+	startDateTime, _ := time.Parse(utils.FormatDate, startDate)
+	startDateTime = startDateTime.AddDate(-1, 0, 0)
+	startDateTimeFirst, _ := time.Parse(utils.FormatDate, firstContractRai.StartDate)
+	if startDateTime.Before(startDateTimeFirst) {
+		total = 1
+	}
+	return
+}
+
+func initCRM15_5() {
+	var condition string
+	var pars []interface{}
+
+	condition = " AND  rai_contract_type  = '新签合同'  AND  product_id = 2 "
+	companyContractList, e := company.GetCompanyContractList(condition, pars)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		fmt.Println(e)
+		return
+	}
+	var CompanyContractIdS []int
+	for k, v := range companyContractList {
+		fmt.Println(k)
+		firstContractRai, err := company.GetFirstContractRai(v.CompanyId)
+		if err != nil {
+			fmt.Println(err)
+			continue
+		}
+
+		if firstContractRai.CompanyContractId == v.CompanyContractId {
+			continue
+		}
+		//判断是否是在一年以内
+		startDateTime, _ := time.Parse(utils.FormatDate, v.StartDate)
+		startDateTime = startDateTime.AddDate(-1, 0, 0)
+		startDateTimeFirst, _ := time.Parse(utils.FormatDate, firstContractRai.StartDate)
+		if !startDateTime.Before(startDateTimeFirst) {
+			CompanyContractIdS = append(CompanyContractIdS, v.CompanyContractId)
+		}
+	}
+	fmt.Println("companyContractIds", len(CompanyContractIdS))
+	fmt.Println("companyContractIds", (CompanyContractIdS))
+	//
+	//fmt.Println(strings.Join(companyContractIds, ","))
+	//err := company.UpdateCompanyContractRaiContractTypeInit(strings.Join(companyContractIds, ","))
+	//fmt.Println(err)
+	return
+}

+ 35 - 1
services/cygx/acitvity.go

@@ -854,7 +854,10 @@ func DoActivityOnenIdWxTemplateMsg(activityId int) (err error) {
 	if err != nil {
 		return
 	}
-
+	industrialList, err := cygx.GetIndustrialActivityGroupManagementList(activityId, 1)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return
+	}
 	if activityInfo.VisibleRange == 1 {
 		return //只要是仅对本组可见的活动,发布时,模板消息统一不发送, p2_876
 	}
@@ -1299,6 +1302,36 @@ func DoActivityOnenIdWxTemplateMsg(activityId int) (err error) {
 		err = errors.New("SendTemplateMsg, Err: " + e.Error())
 		return
 	}
+
+	industrialName := ""
+	for _, v := range industrialList {
+		industrialName += v.IndustryName + ","
+	}
+	industrialName = strings.TrimRight(industrialName, ",")
+	// 发类目模版消息
+	if activityInfo.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+		actTime, _ := time.Parse(utils.FormatDateTime, activityInfo.ActivityTime)
+		first := industrialName
+		keyword1 := "发布了新活动"
+		keyword2 := utils.TruncateActivityNameString(activityInfo.ActivityName)
+		keyword3 := actTime.Format(utils.FormatDateTimeMinute2)
+
+		redirectUrl := utils.WX_MSG_PATH_YX_ACTIVITY_DETAIL + strconv.Itoa(activityId)
+		sendInfo := new(services.SendWxCategoryTemplate)
+		sendInfo.Keywords = []string{first, keyword1, keyword2, keyword3}
+
+		sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityPublishApply
+		sendInfo.RedirectUrl = redirectUrl
+		sendInfo.RedirectTarget = 3
+		sendInfo.Resource = strconv.Itoa(activityId)
+		sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ACTIVITY_LIMIT_PEOPLE
+		sendInfo.OpenIdArr = openIdArr
+		e := services.SendCategoryTemplateMsg(sendInfo)
+		if e != nil {
+			err = errors.New("SendTemplateMsg, Err: " + e.Error())
+			return
+		}
+	}
 	return
 }
 
@@ -1368,6 +1401,7 @@ func GetActChartPermissionList() []*cygx.ChartPermissionRepMore {
 		{PermissionName: "智造"},
 		{PermissionName: "策略"},
 		{PermissionName: "固收"},
+		{PermissionName: "周期"},
 		{PermissionName: "宏观"},
 		//{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN},
 		//{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(医药)"},

+ 160 - 0
services/cygx/activity_poster.go

@@ -405,3 +405,163 @@ func MakeActivityMomentsImg(activityId int) {
 		return
 	}
 }
+
+// MakeMfyxActivitySigninImg 生成mfyx太阳码并上传OSS
+//func MakeMfyxActivitySigninImg(activityId int) (imgUrl string, err error) {
+//	var msg string
+//	defer func() {
+//		if err != nil || msg != "" {
+//			fmt.Println(err)
+//			utils.FileLog.Info("MakeMfyxActivitySigninImg Err:", err.Error())
+//			go alarm_msg.SendAlarmMsg("扫码签到日志记录,失败,活动ID:"+strconv.Itoa(activityId)+err.Error()+";msg:"+msg, 3)
+//		}
+//	}()
+//	activityInfo, e := cygx.GetAddActivityInfoById(activityId)
+//	if e != nil {
+//		err = errors.New("活动不存在, Err: " + e.Error())
+//		return
+//	}
+//	if activityInfo == nil {
+//		return
+//	}
+//	if activityInfo.ActivityTypeId != 5 && activityInfo.ActivityTypeId != 6 && activityInfo.ActivityTypeId != 8 {
+//		return
+//	}
+//	itemToken, err := models.GetWxToken(utils.WxMfyxAppId, utils.WxMfyxAppSecret)
+//	if err != nil {
+//		return
+//	}
+//	if itemToken.AccessToken == "" {
+//		msg = "accessToken is empty"
+//		return
+//	}
+//	var envVersion string
+//	var resourceUrl string
+//	if utils.RunMode == "release" {
+//		envVersion = "release"
+//	} else {
+//		envVersion = "trial"
+//	}
+//	url := "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + itemToken.AccessToken
+//	method := "POST"
+//	payload := strings.NewReader(`{
+//		"page":"` + utils.WX_MSG_PATH_ACTIVITY_SIGNIN + `",
+//		"scene":"` + strconv.Itoa(activityId) + `",
+//		"env_version":"` + envVersion + `",
+//		"check_path":false,
+//		"auto_color":true
+//				}`)
+//	client := &http.Client{}
+//	req, err := http.NewRequest(method, url, payload)
+//	if err != nil {
+//		msg = "获取微信二维码失败,Err:" + err.Error()
+//		return
+//	}
+//	req.Header.Add("Content-Type", "application/json")
+//	postBody, err := client.Do(req)
+//	if err != nil {
+//		msg = "获取微信二维码失败,Err:" + err.Error()
+//		return
+//	}
+//	defer postBody.Body.Close()
+//	uploadDir := "static/img/share/"
+//	uuid := utils.GetRandStringNoSpecialChar(28)
+//	if !utils.FileIsExist(uploadDir) {
+//		err = os.MkdirAll(uploadDir, 0755)
+//		if err != nil {
+//			msg = "生成文件夹失败,Err:" + err.Error()
+//			return
+//		}
+//	}
+//	imagePath := uploadDir + uuid + ".jpg"
+//	switch header := postBody.Header.Get("Content-Type"); {
+//	case strings.HasPrefix(header, "application/json"):
+//		tokenResp := ReturnBodyRule{}
+//		decoder := json.NewDecoder(postBody.Body)
+//		if decodeErr := decoder.Decode(&tokenResp); decodeErr != nil {
+//			msg = "获取微信二维码失败,Err:" + decodeErr.Error()
+//			return
+//		}
+//	case strings.HasPrefix(header, "image"):
+//		reply, e := ioutil.ReadAll(postBody.Body)
+//		if e != nil {
+//			err = e
+//			msg = "获取微信二维码失败,Err:" + err.Error()
+//			return
+//		}
+//		imageContent, e := os.Create(imagePath)
+//		if e != nil {
+//			err = e
+//			msg = "获取微信二维码失败,Err:" + err.Error()
+//			return
+//		}
+//		writeStringRes, e := io.WriteString(imageContent, string(reply))
+//		if e != nil {
+//			err = e
+//			fmt.Println(writeStringRes)
+//			return
+//		}
+//		closeErr := imageContent.Close()
+//		if closeErr != nil {
+//			err = closeErr
+//			return
+//		}
+//		randStr := utils.GetRandStringNoSpecialChar(28)
+//		fileName := randStr + ".jpg"
+//		savePath := uploadDir + time.Now().Format("200601/20060102/")
+//		savePath += fileName
+//		//上传到阿里云
+//		err = services.UploadFileToAliyun(fileName, imagePath, savePath)
+//		if err != nil {
+//			fmt.Println("文件上传失败,Err:" + err.Error())
+//			return
+//		}
+//		fileHost := "https://hzstatic.hzinsights.com/"
+//		resourceUrl = fileHost + savePath
+//		defer func() {
+//			os.Remove(imagePath)
+//		}()
+//	default:
+//		msg = "生成二维码失败"
+//		return
+//	}
+//
+//	detailConfig, e := cygx.GetCygxConfigDetailByCode(Cygx_activity_sigin_html)
+//	if e != nil {
+//		err = errors.New("GetCygxConfigDetailByCode 获取配置签到码格式信息失败, Err: " + e.Error())
+//		return
+//	}
+//	configValue := detailConfig.ConfigValue
+//	configValue = strings.Replace(configValue, "{{TITLE}}", activityInfo.ActivityName, -1)
+//	configValue = strings.Replace(configValue, "{{IMG}}", resourceUrl, -1)
+//	configValue = strings.Replace(configValue, "{{PLEASE}}", "请扫码确认签到", -1)
+//	configValue = strings.Replace(configValue, "{{SHOWTEXT}}", "将签到成功页面出示给接待人员", -1)
+//	htm2ImgReq := make(map[string]interface{})
+//	htm2ImgReq["html_content"] = configValue
+//	htm2ImgReq["width"] = 1364
+//	htm2ImgReq["height"] = 2060
+//	res, err := postHtml2Img(htm2ImgReq)
+//	if err != nil || res == nil {
+//		msg = "html转图片请求失败"
+//		return
+//	}
+//	if res.Code != 200 {
+//		msg = "html转图片请求失败"
+//		err = errors.New("html转图片失败: " + res.Msg)
+//		return
+//	}
+//	imgUrl = res.Data
+//	// 记录海报信息
+//
+//	err = cygx.UpdateCygxActivitySigninImg(imgUrl, activityId)
+//	if err != nil {
+//		return
+//	}
+//	item := new(cygx.CygxActivityPoster)
+//	item.ActivityId = activityId
+//	item.ImgXcx = resourceUrl
+//	item.ImgPoster = imgUrl
+//	item.CreateTime = time.Now()
+//	err = cygx.AddCygxActivityPoster(item)
+//	return
+//}

+ 2 - 0
services/cygx/activity_power_check.go

@@ -282,6 +282,8 @@ func GetActivityDetailUserPower(user *models.WxUser, adminInfo *system.Admin, ac
 	//如果权限不包含那么直接返回
 	if !strings.Contains(permissionStr, activityInfo.ChartPermissionName) {
 		return
+	} else {
+		havePower = true
 	}
 
 	//处理决策人可见权限

+ 37 - 1
services/cygx/admin_power.go

@@ -12,13 +12,23 @@ import (
 
 // 获取这个销售所能查看的手机号权限
 func GetAdminLookUserMobile(adminInfo *system.Admin) (mapMobile map[string]string, err error) {
+
+	sellerId, e := company.GetCompanyProductSellerIdByShareSellerId(adminInfo.AdminId)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("GetCompanyProductSellerIdByShareSellerId 根据共享销售id查被共享的公司销售id, Err: " + e.Error())
+		return
+	}
 	var conditionMobile string
 	if adminInfo.RoleTypeCode == "rai_group" {
 		//组长查看本组所有组员
 		conditionMobile = ` SELECT mobile FROM user_seller_relation WHERE seller_id IN (SELECT  admin_id FROM admin WHERE group_id = (SELECT group_id FROM admin WHERE admin_id = ` + strconv.Itoa(adminInfo.AdminId) + ` )) `
 	} else {
 		//组员查看自己
-		conditionMobile = ` SELECT mobile FROM user_seller_relation WHERE seller_id  = ` + strconv.Itoa(adminInfo.AdminId)
+		if sellerId != 0 {
+			conditionMobile = ` SELECT mobile FROM user_seller_relation WHERE seller_id  IN ( ` + strconv.Itoa(adminInfo.AdminId) + `,` + strconv.Itoa(sellerId) + ` ) `
+		} else {
+			conditionMobile = ` SELECT mobile FROM user_seller_relation WHERE seller_id  IN ( ` + strconv.Itoa(adminInfo.AdminId) + ` ) `
+		}
 	}
 	mobileList, e := cygx.GetSellerUserMobile(conditionMobile)
 	if e != nil {
@@ -131,3 +141,29 @@ func GetAdminLookUserCompanyIdsBySelf(sysUser *system.Admin) (companyIds []int,
 	}
 	return
 }
+
+// 获取这个销售所能查看的公司权限(研究员)
+func GetAdminLookUserCompanyIdsByResearcher(sysUser *system.Admin) (companyIds []int, err error) {
+	//如果不是管理员,权益管理员那么就对可见权限范围做处理
+	adminIds := make([]int, 0)
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_RAI_ADMIN && sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_RAI_RESEARCHR {
+
+		adminIds = append(adminIds, sysUser.AdminId)
+		var adminIdGroup string
+		for _, v := range adminIds {
+			adminIdGroup += strconv.Itoa(v) + ","
+		}
+		adminIdGroup = strings.TrimRight(adminIdGroup, ",")
+		companyProductList, e := company.GetCompanyProductsBySellerId(adminIdGroup)
+		if e != nil {
+			err = errors.New("GetCompanyProductsBySellerId , Err: " + e.Error())
+			return
+		}
+
+		for _, v := range companyProductList {
+			companyIds = append(companyIds, v.CompanyId)
+		}
+		companyIds = append(companyIds, 0) //添加潜在客户
+	}
+	return
+}

+ 18 - 4
services/cygx/industry_fllow.go

@@ -6,12 +6,13 @@ import (
 	"hongze/hz_crm_api/models"
 	"hongze/hz_crm_api/models/cygx"
 	"hongze/hz_crm_api/services/alarm_msg"
+	"hongze/hz_crm_api/utils"
 	"strconv"
 	"time"
 )
 
 //func init() {
-//	AddUserFllowCompanyLossToTryOut(1431)
+//	AddUserFllowCompanyLossToTryOut(12841)
 //}
 
 // 流失客户转试用给下面的用户自动添加产业关注
@@ -30,6 +31,10 @@ func AddUserFllowCompanyLossToTryOut(companyId int) {
 		err = errors.New("GetWxUserListByUserMobileHaveCompany" + e.Error())
 		return
 	}
+
+	if len(userList) == 0 {
+		return
+	}
 	var condition string
 	var pars []interface{}
 	//所有的产业
@@ -38,8 +43,15 @@ func AddUserFllowCompanyLossToTryOut(companyId int) {
 		err = errors.New("GetTopOneMonthArtReadNumIndustryAll, Err: " + e.Error())
 		return
 	}
-	condition = " AND company_id =  ? "
-	pars = append(pars, companyId)
+
+	var userIds []int
+
+	for _, v := range userList {
+		userIds = append(userIds, v.UserId)
+	}
+
+	condition = " AND user_id IN  (" + utils.GetOrmInReplace(len(userIds)) + ")  "
+	pars = append(pars, userIds)
 	userFllowList, e := cygx.GetCygxIndustryFllowList(condition, pars, 0, 0)
 	if e != nil {
 		err = errors.New("GetCygxIndustryFllowList, Err: " + e.Error())
@@ -75,7 +87,7 @@ func AddUserFllowCompanyLossToTryOut(companyId int) {
 			Items = append(Items, item)
 		}
 	}
-
+	//fmt.Println("Items", len(Items))
 	//如果小于五千条就直接插入,大于五千条就批量插入
 	if len(Items) < 5000 {
 		e = cygx.AddCygxIndustryFllowMulti(Items)
@@ -118,5 +130,7 @@ func AddUserFllowCompanyLossToTryOut(companyId int) {
 			}
 		}
 	}
+
+	//fmt.Println("AddUserFllowCompanyLossToTryOut end")
 	return
 }

+ 39 - 0
services/cygx/order.go

@@ -0,0 +1,39 @@
+package cygx
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hz_crm_api/models/cygx"
+	"hongze/hz_crm_api/services/alarm_msg"
+	"hongze/hz_crm_api/utils"
+)
+
+// GetCygxUserBusinessCardMap 获取手机号对应的邀请人
+func GetCygxUserBusinessCardMap(mobileArr []string) (mapResp map[string]string) {
+	lenArr := len(mobileArr)
+	if lenArr == 0 {
+		return
+	}
+	var err error
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+			go alarm_msg.SendAlarmMsg("获取手机号对应的邀请人,信息失败,GetCygxUserBusinessCardMap Err:"+err.Error(), 3)
+		}
+	}()
+	var condition string
+	var pars []interface{}
+
+	condition = ` AND  mobile IN (` + utils.GetOrmInReplace(lenArr) + `)`
+	pars = append(pars, mobileArr)
+	list, e := cygx.GetCygxUserBusinessCardList(condition, pars, 0, lenArr)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("GetArticlList, Err: " + e.Error())
+		return
+	}
+	mapResp = make(map[string]string, 0)
+	for _, v := range list {
+		mapResp[v.Mobile] = v.InviteName
+	}
+	return
+}

+ 28 - 1
services/cygx/research_summary.go

@@ -356,6 +356,10 @@ func DoArticleOnenIdWxTemplateMsg(articleId int, source int) (err error) {
 							if err != nil && err.Error() != utils.ErrNoRow() {
 								return err
 							}
+							//mfyxOpenIditem, err := cygx.GetMfyxUserRecordOpenidByMobile(k)
+							if err != nil && err.Error() != utils.ErrNoRow() {
+								return err
+							}
 							//如果没有权限或者没有获取到 openID的就不推送
 							if openIditem == nil || mapOpenidPower[openIditem.UserId] == "" {
 								continue
@@ -367,14 +371,17 @@ func DoArticleOnenIdWxTemplateMsg(articleId int, source int) (err error) {
 							if mapUserIdChooseSend[openIditem.UserId] == 0 {
 								services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
 								mapOpenidPushed[openIditem.UserId] = openIditem.OpenId
+								// 研选发类目模板消息
+								go services.SendWxCategoryMsgWithCygxActivityAppointmentNew("您预约的调研,有新报告发布", "已发布", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 							}
 
 							//如果小助手勾选了对应的权限信息 就做正常推送
 							if mapUserIdChooseSend[openIditem.UserId] != 0 && mapOpenidFllow[openIditem.UserId] != "" {
 								services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
 								mapOpenidPushed[openIditem.UserId] = openIditem.OpenId
+								// 研选发类目模板消息
+								go services.SendWxCategoryMsgWithCygxActivityAppointmentNew("您预约的调研,有新报告发布", "已发布", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 							}
-
 						}
 					}
 				}
@@ -402,11 +409,15 @@ func DoArticleOnenIdWxTemplateMsg(articleId int, source int) (err error) {
 			if mapUserIdChooseSend[openIditem.UserId] == 0 {
 				services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
 				mapOpenidPushed[openIditem.UserId] = openIditem.OpenId
+				// 研选发类目模板消息
+				go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(articleInfo.NickName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 			}
 			//如果小助手勾选了对应的权限信息 就做正常推送
 			if mapUserIdChooseSend[openIditem.UserId] != 0 && mapOpenidDepartmentFllow[openIditem.UserId] != "" {
 				services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
 				mapOpenidPushed[openIditem.UserId] = openIditem.OpenId
+				// 研选发类目模板消息
+				go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(articleInfo.NickName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 			}
 		}
 		//优先推送3: 关注产业
@@ -430,11 +441,15 @@ func DoArticleOnenIdWxTemplateMsg(articleId int, source int) (err error) {
 			if mapUserIdChooseSend[openIditem.UserId] == 0 {
 				services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
 				mapOpenidPushed[openIditem.UserId] = openIditem.OpenId
+				// 研选发类目模板消息
+				go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 			}
 			//如果小助手勾选了对应的权限信息 就做正常推送
 			if mapUserIdChooseSend[openIditem.UserId] != 0 && mapOpenidFllow[openIditem.UserId] != "" {
 				services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
 				mapOpenidPushed[openIditem.UserId] = openIditem.OpenId
+				// 研选发类目模板消息
+				go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 			}
 		}
 		//针对哪些没有关注作者,没有关注产业,没有预约纪要的人的推送
@@ -452,10 +467,14 @@ func DoArticleOnenIdWxTemplateMsg(articleId int, source int) (err error) {
 			//如果有权限而且小助手没有提交过信息的 就做正常推送
 			if mapUserIdChooseSend[openIditem.UserId] == 0 {
 				services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
+				// 研选发类目模板消息
+				go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 			}
 			//如果小助手勾选了对应的权限信息 就做正常推送
 			if mapUserIdChooseSend[openIditem.UserId] != 0 && mapOpenidFllow[openIditem.UserId] != "" {
 				services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
+				// 研选发类目模板消息
+				go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 			}
 		}
 
@@ -489,10 +508,14 @@ func DoArticleOnenIdWxTemplateMsg(articleId int, source int) (err error) {
 				//如果有权限而且小助手没有提交过信息的 就做正常推送
 				if mapUserIdChooseSend[openIditem.UserId] == 0 {
 					services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
+					// 研选发类目模板消息
+					go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 				}
 				//如果小助手勾选了对应的权限信息 就做正常推送
 				if mapUserIdChooseSend[openIditem.UserId] != 0 && mapUserFllowCeLue[openIditem.UserId] != "" {
 					services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
+					// 研选发类目模板消息
+					go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 				}
 			}
 		} else {
@@ -505,10 +528,14 @@ func DoArticleOnenIdWxTemplateMsg(articleId int, source int) (err error) {
 				//如果有权限而且小助手没有提交过信息的 就做正常推送
 				if mapUserIdChooseSend[openIditem.UserId] == 0 {
 					services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
+					// 研选发类目模板消息
+					go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 				}
 				//如果小助手勾选了对应的权限信息 就做正常推送
 				if mapUserIdChooseSend[openIditem.UserId] != 0 && mapOpenidFllow[openIditem.UserId] != "" {
 					services.SendWxMsgWithCygxActivityAppointmentNew(first, keyword1, keyword2, keyword3, keyword4, openIditem, articleId)
+					// 研选发类目模板消息
+					go services.SendWxCategoryMsgWithCygxActivityAppointmentNew(industryName, "发布了新报告", utils.TruncateActivityNameString(articleInfo.Title), articleInfo.PublishDate.Format(utils.FormatDateTimeMinute2), openIditem, articleId)
 				}
 			}
 		}

+ 125 - 0
services/cygx/wx_pay.go

@@ -0,0 +1,125 @@
+package cygx
+
+import (
+	"context"
+	"fmt"
+	"github.com/wechatpay-apiv3/wechatpay-go/core"
+	"github.com/wechatpay-apiv3/wechatpay-go/core/option"
+	"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
+	payUtils "github.com/wechatpay-apiv3/wechatpay-go/utils"
+	"hongze/hz_crm_api/models/cygx"
+	"hongze/hz_crm_api/services/alarm_msg"
+	"hongze/hz_crm_api/utils"
+)
+
+const (
+	//MchPKFileName              = "./utils/cert/apiclient_key.pem"
+	//MchPKFileName              = "../hongze_mfyx/utils/cert/apiclient_key.pem"
+	MchPKFileName              = "/home/code/wechat_cert/cygx/apiclient_key.pem"
+	Mchid                      = "1624495680"
+	MchCertificateSerialNumber = "5ED2719CFAE5205763034AD80BF4B8A33533C418"
+	MchAPIv3Key                = "W1tbnzQrzQ7yRRNuQCIHjis8dgdasKVX"
+)
+
+// 微信商户建立连接
+//func getWechatClient() (context.Context, *core.Client, error) {
+//	var err error
+//	defer func() {
+//		if err != nil {
+//			fmt.Println(err)
+//			go alarm_msg.SendAlarmMsg(fmt.Sprint("微信商户建立连接失败 getWechatClient, err:", err.Error()), 2)
+//		}
+//	}()
+//	// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
+//	mchPrivateKey, err := payUtils.LoadPrivateKeyWithPath(MchPKFileName)
+//	if err != nil {
+//		log.Print("load merchant private key error")
+//		return nil, nil, err
+//	}
+//	ctx := context.Background()
+//	// 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
+//	opts := []core.ClientOption{
+//		option.WithWechatPayAutoAuthCipher(Mchid, MchCertificateSerialNumber, mchPrivateKey, MchAPIv3Key),
+//	}
+//	client, err := core.NewClient(ctx, opts...)
+//	if err != nil {
+//		log.Printf("new wechat pay client err:%s", err)
+//		return nil, nil, err
+//	}
+//	return ctx, client, nil
+//}
+
+var WechatCertClient *core.Client
+
+// 微信商户建立连接(全局)
+func init() {
+	if !utils.FileIsExist(MchPKFileName) {
+		//fmt.Println("商户私钥文件不存在")
+		go alarm_msg.SendAlarmMsg("微信商户链接失败 商户私钥文件不存在", 2)
+		return
+	}
+	// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
+	mchPrivateKey, err := payUtils.LoadPrivateKeyWithPath(MchPKFileName)
+	if err != nil {
+		fmt.Println(err)
+		go alarm_msg.SendAlarmMsg("微信商户链接失败 LoadPrivateKeyWithPath"+err.Error(), 2)
+	}
+	ctx := context.Background()
+	// 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
+	opts := []core.ClientOption{
+		option.WithWechatPayAutoAuthCipher(Mchid, MchCertificateSerialNumber, mchPrivateKey, MchAPIv3Key),
+	}
+
+	client, err := core.NewClient(ctx, opts...)
+	if err != nil {
+		fmt.Println(err)
+		go alarm_msg.SendAlarmMsg("微信商户链接失败 NewClient"+err.Error(), 2)
+	}
+	WechatCertClient = client
+	return
+}
+
+// 微信商户退款
+func RefundsApiService(orderDetail *cygx.CygxOrderResp) (statusCode int, err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+			go alarm_msg.SendAlarmMsg(fmt.Sprint("微信商户退款失败 RefundsApiService, err:", err.Error()), 2)
+		}
+	}()
+	//ctx, client, err := getWechatClient()
+	//if err != nil {
+	//	//log.Printf("getWechatClientt err:%s", err)
+	//	return
+	//}
+	ctx := context.Background()
+	svc := refunddomestic.RefundsApiService{Client: WechatCertClient}
+	resp, result, err := svc.Create(ctx,
+		refunddomestic.CreateRequest{
+			//SubMchid:      core.String(Mchid),
+			TransactionId: core.String(orderDetail.OutTradeCode),
+			OutTradeNo:    core.String(orderDetail.OutTradeNo),
+			OutRefundNo:   core.String("RE" + orderDetail.OrderCode),
+			Reason:        core.String("退款"),
+			NotifyUrl:     core.String(utils.Wx_MFYX_Refund_NotifyUrl),
+			FundsAccount:  refunddomestic.REQFUNDSACCOUNT_AVAILABLE.Ptr(),
+			Amount: &refunddomestic.AmountReq{
+				Currency: core.String("CNY"),
+				//From: []refunddomestic.FundsFromItem{refunddomestic.FundsFromItem{
+				//	Account: refunddomestic.ACCOUNT_AVAILABLE.Ptr(),
+				//	Amount:  core.Int64(444),
+				//}},
+				Refund: core.Int64(int64(orderDetail.PayMoney * 100)),
+				Total:  core.Int64(int64(orderDetail.PayMoney * 100)),
+			},
+		},
+	)
+	if err != nil {
+		return
+	} else {
+		utils.FileLogCygx.Info("status=%d resp=%s", result.Response.StatusCode, resp)
+	}
+	statusCode = result.Response.StatusCode
+
+	return
+}

+ 27 - 11
services/eta_business/eta_business.go

@@ -45,6 +45,9 @@ func UpdateEtaBusinessAfterSigning(businessId int) (err error) {
 	businessOb := new(eta_business.EtaBusiness)
 	business, e := businessOb.GetItemById(businessId)
 	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			return
+		}
 		err = fmt.Errorf("获取商家信息失败, Err: %s", e.Error())
 		return
 	}
@@ -55,7 +58,8 @@ func UpdateEtaBusinessAfterSigning(businessId int) (err error) {
 		cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessContractColumns.EtaBusinessId)
 		pars := make([]interface{}, 0)
 		pars = append(pars, businessId)
-		list, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
+		// 按签约时间倒序
+		list, e := ob.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s DESC", eta_business.EtaBusinessContractColumns.SigningTime))
 		if e != nil {
 			err = fmt.Errorf("获取商家合同列表失败, Err: " + e.Error())
 			return
@@ -63,6 +67,16 @@ func UpdateEtaBusinessAfterSigning(businessId int) (err error) {
 		contracts = list
 	}
 	if len(contracts) == 0 {
+		// 重置签约信息
+		cols := []string{"ContractId", "SigningStatus", "SigningTime", "ExpiredTime", "ModifyTime"}
+		business.ContractId = 0
+		business.SigningStatus = eta_business.EtaBusinessSigningStatusWait
+		business.SigningTime = time.Time{}
+		business.ExpiredTime = time.Time{}
+		business.ModifyTime = time.Now().Local()
+		if e = business.Update(cols); e != nil {
+			err = fmt.Errorf("更新商家信息失败, Err: %s", e.Error())
+		}
 		return
 	}
 
@@ -86,18 +100,20 @@ func UpdateEtaBusinessAfterSigning(businessId int) (err error) {
 			break
 		}
 	}
-	// 不存在任一合同期内, 当前合同不变, 更新状态
-	if !using {
-		business.SigningStatus = eta_business.EtaBusinessSigningStatusTerminate
-		business.ModifyTime = time.Now().Local()
-		cols := []string{"SigningStatus", "ModifyTime"}
-		if e = business.Update(cols); e != nil {
-			err = fmt.Errorf("更新商家信息失败, Err: %s", e.Error())
-			return
+
+	// 不存在任一合同期内, 取签约时间最后的合同(已按时间排序)
+	if !using && len(contracts) > 0 {
+		business.ContractId = contracts[0].EtaBusinessContractId
+		business.SigningTime = contracts[0].SigningTime
+		business.ExpiredTime = contracts[0].ExpiredTime
+		if contracts[0].IsFirst == 1 {
+			business.SigningStatus = eta_business.EtaBusinessSigningStatusFirst
+		} else {
+			business.SigningStatus = eta_business.EtaBusinessSigningStatusTerminate
 		}
-		return
+		business.ModifyTime = time.Now().Local()
 	}
-	// 合同期内
+
 	cols := []string{"ContractId", "SigningStatus", "SigningTime", "ExpiredTime", "ModifyTime"}
 	if e = business.Update(cols); e != nil {
 		err = fmt.Errorf("更新商家信息失败, Err: %s", e.Error())

+ 11 - 1
services/roadshow/calendar.go

@@ -709,6 +709,12 @@ func SyncCalendarFromShanghai(userPhone, startDate, endDate string) (err error)
 		}
 
 		for _, v := range list {
+			//展示优先级:1、customer_name 2、project_name 3、title 需求池953
+			if v.CustomerName != "" {
+				v.Title = v.CustomerName
+			} else if v.ProjectName != "" {
+				v.Title = v.ProjectName
+			}
 			if rsCalendarRelation, ok := rsCalendarRelationMap[v.ID]; ok {
 				//存在的话,那么就去查找对应的信息
 				if rsCalendarRelation.CalendarType == 1 {
@@ -768,7 +774,9 @@ func SyncCalendarFromShanghai(userPhone, startDate, endDate string) (err error)
 									researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RESEARCHR ||
 									researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_RESEARCHR ||
 									researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_DEPARTMENT ||
-									researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_DEPARTMENT {
+									researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_DEPARTMENT ||
+									researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_SELLER ||
+									researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_ADMIN {
 
 									researcherList = append(researcherList, researcherInfo)
 									researcherMap[researcherInfo.AdminId] = researcherInfo
@@ -857,6 +865,8 @@ func SyncCalendarFromShanghai(userPhone, startDate, endDate string) (err error)
 							researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_RESEARCHR ||
 							researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_DEPARTMENT ||
 							researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_DEPARTMENT ||
+							researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_SELLER ||
+							researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_ADMIN ||
 							researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN {
 							researcherList = append(researcherList, researcherInfo)
 						}

+ 828 - 0
services/wechat_send_category_template_msg.go

@@ -0,0 +1,828 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/cygx"
+	"hongze/hz_crm_api/services/alarm_msg"
+	"hongze/hz_crm_api/utils"
+	"html"
+	"io/ioutil"
+	"net/http"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type SendWxCategoryTemplate struct {
+	WxAppId        string   `description:"公众号appId"`
+	Keywords       []string `description:"模板消息keyword字段"`
+	TemplateId     string   `description:"模板id"`
+	RedirectUrl    string   `description:"跳转地址"`
+	RedirectTarget int      `description:"小程序跳转目标:1:弘则研报小程序,2:随手办公小程序,3:查研观向,4:买方研选"`
+	Resource       string   `description:"资源唯一标识"`
+	SendType       int      `description:"发送的消息类型:1:报告,2:指标更新提醒,3:审批通知,4:销售领取客户通知,5:活动取消通知,6活动更改时间通知,7:关注的作者发布报告通知,8:发送日报(周报、双周报、月报)模板消息,9:活动预约/报名时间通知"`
+	OpenIdArr      []string `description:"消息接收者openid"`
+}
+
+// 推送类目模板消息
+func SendCategoryTemplateMsg(sendInfo *SendWxCategoryTemplate) (err error) {
+	postData, err := json.Marshal(sendInfo)
+	if err != nil {
+		alarm_msg.SendAlarmMsg("SendCategoryTemplateMsg json.Marshal Err:"+err.Error(), 1)
+		return err
+	}
+	body := ioutil.NopCloser(strings.NewReader(string(postData)))
+	client := &http.Client{}
+	req, err := http.NewRequest("POST", utils.SendWxCategoryTemplateMsgUrl, body)
+	if err != nil {
+		alarm_msg.SendAlarmMsg("SendCategoryTemplateMsg http.NewRequest Err:"+err.Error(), 1)
+		return err
+	}
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", utils.SendTemplateMsgAuthorization)
+	resp, err := client.Do(req)
+	if err != nil {
+		fmt.Println("http client.Do Err:" + err.Error())
+		return err
+	}
+	defer resp.Body.Close()
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
+	result := new(models.BaseResponse)
+	err = json.Unmarshal(b, &result)
+	if err != nil {
+		return err
+	}
+	if result.Ret != 200 {
+		err = errors.New(string(b))
+		return err
+	}
+	return
+}
+
+// 活动更改时间消息通知
+func SendWxCategoryMsgWithCygxActivityUpdateTime(activityId int, oldStr, newStr, strType string) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("发送类目模版消息失败,Err:"+err.Error()+";msg:"+msg, 3)
+			utils.FileLogCygx.Info(fmt.Sprintf("发送类目模版消息失败,Err:%s,%s", err.Error(), msg))
+		}
+		if msg != "" {
+			utils.FileLogCygx.Info("发送类目模版消息失败,msg:%s", msg)
+		}
+	}()
+
+	activityInfo, err := cygx.GetAddActivityInfoById(activityId)
+	if err != nil {
+		msg = "GetReportInfo Err:" + err.Error()
+		return
+	}
+	if activityInfo == nil {
+		utils.FileLogCygx.Info("活动信息不存在")
+		return
+	}
+
+	var openIdList []*cygx.OpenIdList
+
+	openIdList, err = cygx.GetMfyxActivityOpenIdList(activityId)
+	if err != nil {
+		msg = "get openIdList err:" + err.Error()
+		return
+	}
+
+	mapOpenid := make(map[int]string)
+	for _, v := range openIdList {
+		mapOpenid[v.UserId] = v.OpenId
+	}
+	//添加预约纪要的openid
+	openIdListAppointment, err := cygx.GetMfyxActivityAppointmentOpenIdList(activityId)
+	if err != nil {
+		msg = "GetActivityAppointmentOpenIdList err:" + err.Error()
+		return
+	}
+	if len(openIdListAppointment) > 0 {
+		for _, v := range openIdListAppointment {
+			if _, ok := mapOpenid[v.UserId]; !ok {
+				item := new(cygx.OpenIdList)
+				item.UserId = v.UserId
+				item.OpenId = v.OpenId
+				openIdList = append(openIdList, item)
+			}
+			mapOpenid[v.UserId] = v.OpenId
+
+		}
+	}
+
+	//添加带问的openid
+	openIdListActivityHelpAsk, err := cygx.GetMfyxActivityHelpAskOpenIdList(activityId)
+	if err != nil {
+		msg = "openIdListActivityHelpAsk err:" + err.Error()
+		return
+	}
+	if len(openIdListActivityHelpAsk) > 0 {
+		for _, v := range openIdListActivityHelpAsk {
+			if _, ok := mapOpenid[v.UserId]; !ok {
+				item := new(cygx.OpenIdList)
+				item.UserId = v.UserId
+				item.OpenId = v.OpenId
+				openIdList = append(openIdList, item)
+			}
+			mapOpenid[v.UserId] = v.OpenId
+		}
+	}
+
+	if len(openIdList) == 0 {
+		return err
+	}
+	//sendMap := make(map[string]interface{})
+	//sendData := make(map[string]interface{})
+	var keyword1, keyword2, keyword3, redirectUrl string
+
+	activityInfo.ActivityTypeName = strings.Replace(activityInfo.ActivityTypeName, "(C类)", "", -1)
+	if strType == "timeType" {
+		//first = "您有一场【" + activityInfo.ActivityTypeName + "】发生了时间变更"
+		//keyword2 = "时间变更为-- " + newStr
+		keyword2 = "时间变更为"
+	} else if strType == "expertType" {
+		//first = "您有一场【" + activityInfo.ActivityTypeName + "】发生了专家变更"
+		//keyword2 = "专家变更为--" + newStr
+		keyword2 = "专家变更"
+	} else if strType == "addressType" {
+		//first = "您有一场【" + activityInfo.ActivityTypeName + "】发生了地址变更"
+		//keyword2 = "地点变更为--" + newStr
+		keyword2 = "地点变更"
+	} else if strType == "participationCode" {
+		//first = "您有一场【" + activityInfo.ActivityTypeName + "】公布了拨入密码"
+		//keyword2 = "拨入密码为--" + newStr
+		keyword2 = "拨入密码"
+	} else if strType == "Theme" {
+		//first = "您有一场【" + activityInfo.ActivityTypeName + "】更新了活动主题"
+		newStr = strings.Replace(newStr, "</p><p>", "\n", -1)
+		newStr = html.EscapeString(newStr)
+		newStrHtml, _ := cygx.GetReportContentTextSub(newStr)
+		newStr = newStrHtml
+		//keyword2 = "主题变更为--" + newStr
+		keyword2 = "主题变更"
+	}
+
+	keyword1 = utils.TruncateActivityNameString(activityInfo.ActivityName)
+	openIdArr := make([]string, len(openIdList))
+	for i, v := range openIdList {
+		openIdArr[i] = v.OpenId
+	}
+
+	keyword3 = utils.TruncateActivityNameString(newStr)
+
+	redirectUrl = utils.WX_MSG_PATH_YX_ACTIVITY_DETAIL + strconv.Itoa(activityId) + "&IsSendWx=1"
+	sendInfo := new(SendWxCategoryTemplate)
+	//sendInfo.WxAppId = utils.WxAppId
+	sendInfo.Keywords = []string{keyword1, keyword2, keyword3}
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityChangeApply
+	sendInfo.RedirectUrl = redirectUrl
+	sendInfo.RedirectTarget = 4
+	sendInfo.Resource = strconv.Itoa(activityId)
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ACTIVITY_UPDATE
+	sendInfo.OpenIdArr = openIdArr
+	e := SendCategoryTemplateMsg(sendInfo)
+	if e != nil {
+		err = errors.New("推送模板消息失败" + e.Error())
+		return
+	}
+	return
+}
+
+// 活动取消消息通知
+func SendWxCategoryMsgWithCygxActivity(activityId int) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("发送类目模版消息失败,Err:"+err.Error()+";msg:"+msg, 3)
+			utils.FileLogCygx.Info(fmt.Sprintf("发送类目模版消息失败,Err:%s,%s", err.Error(), msg))
+		}
+		if msg != "" {
+			utils.FileLogCygx.Info("发送类目模版消息失败,msg:%s", msg)
+		}
+	}()
+	activityInfo, err := cygx.GetAddActivityInfoById(activityId)
+	if err != nil {
+		msg = "GetReportInfo Err:" + err.Error()
+		return
+	}
+	var openIdList []*cygx.OpenIdList
+	openIdList, err = cygx.GetMfyxActivityOpenIdList(activityId)
+	if err != nil {
+		msg = "get GetActivityOpenIdList err:" + err.Error()
+		return
+	}
+	mapOpenid := make(map[int]string)
+	for _, v := range openIdList {
+		mapOpenid[v.UserId] = v.OpenId
+	}
+	//添加预约纪要的openid
+	openIdListAppointment, err := cygx.GetActivityAppointmentOpenIdList(activityId)
+	if err != nil {
+		msg = "GetActivityAppointmentOpenIdList err:" + err.Error()
+		return
+	}
+	if len(openIdListAppointment) > 0 {
+		for _, v := range openIdListAppointment {
+			if _, ok := mapOpenid[v.UserId]; !ok {
+				item := new(cygx.OpenIdList)
+				item.UserId = v.UserId
+				item.OpenId = v.OpenId
+				openIdList = append(openIdList, item)
+			}
+			mapOpenid[v.UserId] = v.OpenId
+
+		}
+	}
+
+	//添加带问的openid
+	openIdListActivityHelpAsk, err := cygx.GetMfyxActivityHelpAskOpenIdList(activityId)
+	if err != nil {
+		msg = "openIdListActivityHelpAsk err:" + err.Error()
+		return
+	}
+	if len(openIdListActivityHelpAsk) > 0 {
+		for _, v := range openIdListActivityHelpAsk {
+			if _, ok := mapOpenid[v.UserId]; !ok {
+				item := new(cygx.OpenIdList)
+				item.UserId = v.UserId
+				item.OpenId = v.OpenId
+				openIdList = append(openIdList, item)
+			}
+			mapOpenid[v.UserId] = v.OpenId
+		}
+	}
+	activityInfo.ActivityTypeName = strings.Replace(activityInfo.ActivityTypeName, "(C类)", "", -1)
+	if len(openIdList) == 0 {
+		return err
+	}
+	var keyword1, keyword2, keyword3, redirectUrl string
+	keyword1 = utils.TruncateActivityNameString(activityInfo.ActivityName)
+	keyword2 = "活动已取消"
+	keyword3 = time.Now().Format(utils.FormatDateTimeMinute)
+
+	openIdArr := make([]string, len(openIdList))
+	for i, v := range openIdList {
+		openIdArr[i] = v.OpenId
+	}
+	redirectUrl = utils.WX_MSG_PATH_YX_ACTIVITY_DETAIL + strconv.Itoa(activityId) + "&IsSendWx=1"
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = append(sendInfo.Keywords, keyword1, keyword2, keyword3)
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityCancleApply
+	sendInfo.RedirectUrl = redirectUrl
+	sendInfo.RedirectTarget = 4
+	sendInfo.Resource = strconv.Itoa(activityId)
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ACTIVITY_CACLE
+	sendInfo.OpenIdArr = openIdArr
+	err = SendCategoryTemplateMsg(sendInfo)
+	return
+}
+
+// 修改活动人数限制之后,对于因为人数已满而失败的用户,推送模板消息
+func SendWxCategoryMsgWithCygxActivityUpdateLimitPeople(activityId int) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+			go alarm_msg.SendAlarmMsg("修改活动人数限制之后,对于因为人数已满而失败的用户,推送模板消息,发送模版消息失败,Err:"+err.Error()+";msg:"+msg, 3)
+			utils.FileLogCygx.Info(fmt.Sprintf("发送类目模版消息失败,Err:%s,%s", err.Error(), msg))
+		}
+	}()
+	activityInfo, e := cygx.GetAddActivityInfoById(activityId)
+	if e != nil {
+		err = errors.New("活动不存在, Err: " + e.Error())
+		return
+	}
+	if activityInfo == nil {
+		return
+	}
+	//已经推送过的不做二次推送
+	listSendOpendId, err := models.GeUserTemplateRecordListBysendType(utils.TEMPLATE_MSG_CYGX_ACTIVITY_LIMIT_PEOPLE, strconv.Itoa(activityId))
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return err
+	}
+	mapSendOpenid := make(map[string]int)
+	for _, v := range listSendOpendId {
+		mapSendOpenid[v.OpenId] = v.UserId
+	}
+
+	var condition string
+	var pars []interface{}
+
+	condition = ` AND do_fail_type = 1 AND  activity_id = ?  `
+	pars = append(pars, activityId)
+	listSignup, e := cygx.GetActivitySignupList(condition, pars)
+	if e != nil {
+		err = errors.New("GetResourceDataList, Err: " + e.Error())
+		return
+	}
+	var mobileArr []string
+	for _, v := range listSignup {
+		if v.Mobile != "" {
+			mobileArr = append(mobileArr, v.Mobile)
+		}
+	}
+	mobileLen := len(mobileArr)
+	if mobileLen == 0 {
+		return
+	}
+	//condition = ""
+	//pars = make([]interface{}, 0)
+	//condition += ` AND u.mobile IN (` + utils.GetOrmInReplace(mobileLen) + `)`
+	//pars = append(pars, mobileArr)
+
+	openIdList, e := cygx.GetMfyxUserRecordListByMobileArr(mobileArr)
+	if e != nil {
+		err = errors.New("GetWxOpenIdBList, Err: " + e.Error())
+		return
+	}
+	if len(openIdList) == 0 {
+		return
+	}
+	openIdArr := make([]string, len(openIdList))
+	for i, v := range openIdList {
+		if mapSendOpenid[v.OpenId] > 0 {
+			continue
+		}
+		openIdArr[i] = v.OpenId
+	}
+	keyword1 := utils.TruncateActivityNameString(activityInfo.ActivityName)
+	keyword2 := "活动名额增加"
+	keyword3 := "名额增至" + activityInfo.LimitPeopleNum + "人,欢迎报名"
+
+	redirectUrl := utils.WX_MSG_PATH_YX_ACTIVITY_DETAIL + strconv.Itoa(activityId)
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = []string{keyword1, keyword2, keyword3}
+
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityChangeApply
+	sendInfo.RedirectUrl = redirectUrl
+	sendInfo.RedirectTarget = 4
+	sendInfo.Resource = strconv.Itoa(activityId)
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ACTIVITY_LIMIT_PEOPLE
+	sendInfo.OpenIdArr = openIdArr
+	e = SendCategoryTemplateMsg(sendInfo)
+	if e != nil {
+		err = errors.New("SendTemplateMsg, Err: " + e.Error())
+		return
+	}
+	return
+}
+
+// 推送预约研选的纪要活动、策略报告、研选报告
+func SendWxCategoryMsgWithCygxActivityAppointmentNew(keyword1, keyword2, keyword3, keyword4 string, item *cygx.OpenIdList, articleId int) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			fmt.Println("err:", err)
+			go alarm_msg.SendAlarmMsg("查研观向,推送预约研选的纪要活动、策略报告、研选报告,Err:"+err.Error()+";msg:"+msg, 3)
+			utils.FileLog.Info(fmt.Sprintf("发送类目模版消息失败,Err:%s,%s", err.Error(), msg))
+		}
+		if msg != "" {
+			utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
+		}
+	}()
+
+	var openIdList []*cygx.OpenIdList
+	openIdList = append(openIdList, item)
+	openIdArr := make([]string, len(openIdList))
+	for i, v := range openIdList {
+		openIdArr[i] = v.OpenId
+	}
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = []string{keyword1, keyword2, keyword3, keyword4}
+
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityPublishApply
+	sendInfo.RedirectUrl = utils.WX_MSG_PATH_YX_ARTICLE_DETAIL + strconv.Itoa(articleId)
+	sendInfo.RedirectTarget = 4
+	sendInfo.Resource = strconv.Itoa(articleId)
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ARTICLE
+	sendInfo.OpenIdArr = openIdArr
+	err = SendCategoryTemplateMsg(sendInfo)
+	return
+}
+
+// SendWxCategoryMsgWithRaiSell 权益销售客户申请转正后,消息群发给所有销售
+func SendWxCategoryMsgWithRaiSell(keyword1, keyword2, keyword3, keyword4 string, openIdList []*cygx.OpenIdList) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			fmt.Println("err:", err)
+			go alarm_msg.SendAlarmMsg("权益销售客户申请转正后,消息群发给所有销售,Err:"+err.Error()+";msg:"+msg, 3)
+		}
+		if msg != "" {
+			utils.FileLog.Info("发送类目模版消息失败,msg:%s", msg)
+		}
+	}()
+	openIdArr := make([]string, len(openIdList))
+	for i, v := range openIdList {
+		openIdArr[i] = v.OpenId
+	}
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = []string{keyword1, keyword2, keyword3, keyword4}
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdCompanyApprovalMessageRai
+	sendInfo.RedirectUrl = ""
+	sendInfo.RedirectTarget = 4
+	sendInfo.SendType = utils.TEMPLATE_MSG_APPLY
+	sendInfo.OpenIdArr = openIdArr
+	fmt.Println(sendInfo)
+	err = SendCategoryTemplateMsg(sendInfo)
+	return
+}
+
+// SendWxCategoryMsgWithRaiWangYang 客户研选行业转正时(王芳审批通过),模板消息提醒 董衡、高亦文、吴昂迪和沈涛
+func SendWxCategoryMsgWithRaiWangYang(keyword1, keyword2, keyword3, keyword4 string, openIdList []*cygx.OpenIdList) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			fmt.Println("err:", err)
+			go alarm_msg.SendAlarmMsg("客户研选行业转正时(王芳审批通过),类目模板消息提醒汪洋,Err:"+err.Error()+";msg:"+msg, 3)
+		}
+		if msg != "" {
+			utils.FileLog.Info("发送类目模版消息失败,msg:%s", msg)
+		}
+	}()
+	openIdArr := make([]string, len(openIdList))
+	for i, v := range openIdList {
+		openIdArr[i] = v.OpenId
+	}
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = []string{keyword1, keyword2, keyword3, keyword4}
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdCompanyApprovalMessageRai
+	sendInfo.RedirectUrl = ""
+	sendInfo.RedirectTarget = 4
+	sendInfo.SendType = utils.TEMPLATE_MSG_APPLY
+	sendInfo.OpenIdArr = openIdArr
+	err = SendCategoryTemplateMsg(sendInfo)
+	return
+}
+
+// 销售或后台管理员给用户添加报名之后,进行模版消息推送-研选类目模版
+func SendWxCategoryMsgWithCygxActivitySignUpBySell(items []*cygx.CygxSignupUser) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+			go alarm_msg.SendAlarmMsg("修改活动人数限制之后,对于因为人数已满而失败的用户,推送模板消息,发送类目模版消息失败,Err:"+err.Error()+";msg:"+msg, 3)
+			utils.FileLogCygx.Info(fmt.Sprintf("发送类目模版消息失败,Err:%s,%s", err.Error(), msg))
+		}
+	}()
+
+	if len(items) == 0 {
+		return
+	}
+	//var condition string
+	//var pars []interface{}
+
+	for _, v := range items {
+		activityId := v.ActivityId
+		uid := v.UserId
+		activityInfo, e := cygx.GetAddActivityInfoById(activityId)
+		if e != nil {
+			err = errors.New("活动不存在, Err: " + e.Error())
+			return
+		}
+		//只发研选的
+		if activityInfo.ChartPermissionId != utils.CHART_PERMISSION_ID_YANXUAN {
+			continue
+		}
+		if activityInfo == nil {
+			return
+		}
+		wxUser, e := models.GetWxUserItemByUserId(uid)
+		if e != nil {
+			err = errors.New("查询用户信息失败, Err: " + e.Error())
+			return
+		}
+		var mobileArr []string
+		mobileArr = append(mobileArr, wxUser.Mobile)
+		mobileLen := len(mobileArr)
+		if mobileLen == 0 {
+			return
+		}
+		//condition = ""
+		//pars = make([]interface{}, 0)
+		//condition += ` AND u.mobile IN (` + utils.GetOrmInReplace(mobileLen) + `)`
+		//pars = append(pars, mobileArr)
+
+		openIdList, e := cygx.GetUserRecordListByMobileArr(mobileArr)
+		if e != nil {
+			err = errors.New("GetWxOpenIdBList, Err: " + e.Error())
+			return
+		}
+		if len(openIdList) == 0 {
+			return
+		}
+		openIdArr := make([]string, len(openIdList))
+		for i, v := range openIdList {
+			fmt.Println(v.OpenId)
+			openIdArr[i] = v.OpenId
+		}
+		resultTime := utils.StrTimeToTime(activityInfo.ActivityTime)
+
+		keyword1 := "销售已为您报名"
+		keyword2 := "报名成功"
+		keyword3 := utils.TruncateActivityNameString(activityInfo.ActivityName)
+		keyword4 := resultTime.Format(utils.FormatDateTimeMinute2)
+
+		sendInfo := new(SendWxCategoryTemplate)
+		sendInfo.Keywords = []string{keyword1, keyword2, keyword3, keyword4}
+		sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityPublishApply
+		sendInfo.RedirectUrl = utils.WX_MSG_PATH_YX_ACTIVITY_DETAIL + strconv.Itoa(activityId)
+		sendInfo.RedirectTarget = 4
+		sendInfo.SendType = utils.TEMPLATE_MSG_APPLY
+		sendInfo.OpenIdArr = openIdArr
+		err = SendCategoryTemplateMsg(sendInfo)
+		if e != nil {
+			err = errors.New("SendCategoryTemplateMsg, Err: " + e.Error())
+			return
+		}
+
+		if activityInfo.ActivityTypeId == 5 {
+			sellerItem, tmpErr := cygx.GetSellerByCompanyIdCheckFicc(wxUser.CompanyId, 2)
+			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+				err = errors.New("GetSellerByCompanyIdCheckFicc, Err: " + e.Error())
+				return
+			}
+			configCode := utils.TPL_MSG_NEI_RONG_ZU
+			cnfNeiRong, tmpErr := cygx.GetConfigByCode(configCode)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			mobileArr = append(mobileArr, sellerItem.Mobile, utils.MobileShenTao)
+			cnfNeiRongArr := strings.Split(cnfNeiRong.ConfigValue, ",")
+			for _, v := range cnfNeiRongArr {
+				mobileArr = append(mobileArr, v)
+			}
+			openIdList, e = cygx.GetUserRecordListByMobileArr(mobileArr)
+			if e != nil {
+				err = errors.New("GetWxOpenIdBList, Err: " + e.Error())
+				return
+			}
+			openIdArr := make([]string, len(openIdList))
+			for i, v := range openIdList {
+				fmt.Println(v.OpenId)
+				openIdArr[i] = v.OpenId
+			}
+			// 专家线下沙龙再发一条给口销售和内容组4人(高:15000123056,董:15216736473,冯:18652179672,吴:18701809782)和沈涛
+			keyword1 := wxUser.RealName
+			keyword2 := wxUser.CompanyName
+			keyword3 := sellerItem.RealName
+			keyword4 := resultTime.Format(utils.FormatDateTimeMinute2)
+			keyword5 := utils.TruncateActivityNameString("报名:"+activityInfo.ActivityName)
+
+			sendInfo := new(SendWxCategoryTemplate)
+			sendInfo.Keywords = []string{keyword1, keyword2, keyword3, keyword4, keyword5}
+			sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityApply
+			sendInfo.RedirectUrl = utils.WX_MSG_PATH_YX_ACTIVITY_DETAIL + strconv.Itoa(activityId)
+			sendInfo.RedirectTarget = 4
+			sendInfo.SendType = utils.TEMPLATE_MSG_APPLY
+			sendInfo.OpenIdArr = openIdArr
+			err = SendCategoryTemplateMsg(sendInfo)
+			if e != nil {
+				err = errors.New("SendCategoryTemplateMsg, Err: " + e.Error())
+				return
+			}
+		}
+	}
+	return
+}
+
+// 研选专栏审核完成时,给提交人发送类目模板消息
+func SendWxCategoryMsgSpecialAuthor(specialId, status int) (err error) {
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg(fmt.Sprint("研选专栏审核完成时,给提交人发送类目模板消息 specialId:", specialId, err.Error()), 2)
+		}
+	}()
+	var keyword1 string
+	var keyword2 string
+	var keyword3 string
+	var keyword4 string
+	var redirectUrl string
+
+	specialItem, e := cygx.GetYanxuanSpecialItemById(specialId)
+	if e != nil {
+		err = errors.New("GetYanxuanSpecialFollowUserById, Err: " + e.Error())
+		return
+	}
+	user, e := models.GetWxUserItemByUserId(specialItem.UserId)
+	if e != nil {
+		err = errors.New("GetWxUserItemByUserId, Err: " + e.Error())
+		return err
+	}
+
+	openIdList, err := models.GeCygxtUserRecordListByMobile(user.Mobile)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return err
+	}
+
+	keyword1 = specialItem.Title
+	keyword2 = specialItem.NickName
+	if status == 1 {
+		keyword3 = "文章已通过审核,点击查看详情"
+		redirectUrl = utils.WX_MSG_PATH_YX_SPECIAL_DETAIL + strconv.Itoa(specialId)
+	} else {
+		keyword3 = "文章未通过审核,点击查看驳回原因"
+		redirectUrl = utils.WX_MSG_PATH_YX_SPECIAL_CENTER
+	}
+	keyword4 = time.Now().Format(utils.FormatDateTimeMinute2)
+	openIdArr := make([]string, 0)
+	for _, v := range openIdList {
+		openIdArr = append(openIdArr, v.OpenId)
+	}
+
+	keywords := []string{keyword1, keyword2, keyword3, keyword4}
+
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = keywords
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdCompanyApprovalMessageRai
+	sendInfo.RedirectTarget = 4
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ARTICLE_ADD
+	sendInfo.OpenIdArr = openIdArr
+	sendInfo.RedirectUrl = redirectUrl
+	err = SendCategoryTemplateMsg(sendInfo)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// 研选专栏有新内容审核通过时,给关注此专栏的客户发送模板消息
+func SendWxCategoryMsgSpecialFollow(specialId int) (err error) {
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg(fmt.Sprint("研选专栏审核完成时,给提交人发送类目模板消息 specialId:", specialId, err.Error()), 2)
+		}
+	}()
+	var keyword1 string
+	var keyword2 string
+	var keyword3 string
+	var keyword4 string
+
+	followers, e := cygx.GetYanxuanSpecialFollowUserById(specialId)
+	if e != nil {
+		err = errors.New("GetYanxuanSpecialFollowUserById, Err: " + e.Error())
+		return
+	}
+	if len(followers) == 0 {
+		return
+	}
+	specialItem, e := cygx.GetYanxuanSpecialItemById(specialId)
+	if e != nil {
+		err = errors.New("GetYanxuanSpecialFollowUserById, Err: " + e.Error())
+		return
+	}
+	specialAuthor, e := cygx.GetCygxYanxuanSpecialAuthorByUserId(specialItem.UserId)
+	if e != nil {
+		err = errors.New("GetCygxYanxuanSpecialAuthorByUserId, Err: " + e.Error())
+		return
+	}
+	var allInUserId string
+	for _, v := range followers {
+		allInUserId += strconv.Itoa(v) + ","
+	}
+
+	allInUserId = strings.TrimRight(allInUserId, ",")
+
+	userList, err := models.GetWxUserListByUserIds(allInUserId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return err
+	}
+
+	mobile := ``
+
+	for _, v := range userList {
+		mobile += v.Mobile + ","
+	}
+
+	mobile = strings.TrimRight(mobile, ",")
+
+	openIdList, e := models.GetWxOpenIdByMobileList(mobile)
+	if e != nil {
+		err = errors.New("GetSellerByAdminId, Err: " + e.Error())
+		return
+	}
+	if len(openIdList) == 0 {
+		return
+	}
+
+	keyword1 = specialAuthor.NickName
+	keyword2 = "发布了新报告"
+	keyword3 = specialItem.Title
+	keyword4 = time.Now().Format(utils.FormatDateTimeMinute2)
+	openIdArr := make([]string, 0)
+	for _, v := range openIdList {
+		openIdArr = append(openIdArr, v.OpenId)
+	}
+	redirectUrl := ""
+	redirectUrl = utils.WX_MSG_PATH_YX_SPECIAL_DETAIL + strconv.Itoa(specialId)
+	keywords := []string{keyword1, keyword2, keyword3, keyword4}
+
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = keywords
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityPublishApply
+	sendInfo.RedirectTarget = 4
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_ARTICLE_ADD
+	sendInfo.OpenIdArr = openIdArr
+	sendInfo.RedirectUrl = redirectUrl
+	err = SendCategoryTemplateMsg(sendInfo)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// 销售或后台管理员给用户取消报名之后,进行模版消息推送-研选类目模版
+func SendWxCategoryMsgWithYxActivityCancelSignUpBySell(uid, activityId int) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+			go alarm_msg.SendAlarmMsg("销售或后台管理员给用户取消报名之后,进行模版消息推送-研选类目模版,Err:"+err.Error()+";msg:"+msg, 3)
+			utils.FileLogCygx.Info(fmt.Sprintf("发送类目模版消息失败,Err:%s,%s", err.Error(), msg))
+		}
+	}()
+
+	//var condition string
+	//var pars []interface{}
+
+	activityInfo, e := cygx.GetAddActivityInfoById(activityId)
+	if e != nil {
+		err = errors.New("活动不存在, Err: " + e.Error())
+		return
+	}
+
+	wxUser, e := models.GetWxUserItemByUserId(uid)
+	if e != nil {
+		err = errors.New("查询用户信息失败, Err: " + e.Error())
+		return
+	}
+	var mobileArr []string
+	mobileArr = append(mobileArr, wxUser.Mobile)
+	mobileLen := len(mobileArr)
+	if mobileLen == 0 {
+		return
+	}
+	//condition = ""
+	//pars = make([]interface{}, 0)
+	//condition += ` AND u.mobile IN (` + utils.GetOrmInReplace(mobileLen) + `)`
+	//pars = append(pars, mobileArr)
+	sellerItem, e := cygx.GetSellerByCompanyIdCheckFicc(wxUser.CompanyId, 2)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("GetSellerByCompanyIdCheckFicc, Err: " + e.Error())
+		return
+	}
+	configCode := utils.TPL_MSG_NEI_RONG_ZU
+	cnfNeiRong, err := cygx.GetConfigByCode(configCode)
+	if err != nil {
+		return
+	}
+	mobileArr = append(mobileArr, sellerItem.Mobile, utils.MobileShenTao)
+	cnfNeiRongArr := strings.Split(cnfNeiRong.ConfigValue, ",")
+	for _, v := range cnfNeiRongArr {
+		mobileArr = append(mobileArr, v)
+	}
+	openIdList, e := cygx.GetUserRecordListByMobileArr(mobileArr)
+	if e != nil {
+		err = errors.New("GetWxOpenIdBList, Err: " + e.Error())
+		return
+	}
+	if len(openIdList) == 0 {
+		return
+	}
+	openIdArr := make([]string, len(openIdList))
+	for i, v := range openIdList {
+		fmt.Println(v.OpenId)
+		openIdArr[i] = v.OpenId
+	}
+	resultTime := utils.StrTimeToTime(activityInfo.ActivityTime)
+	keyword1 := wxUser.RealName
+	keyword2 := wxUser.CompanyName
+	keyword3 := sellerItem.RealName
+	keyword4 := resultTime.Format(utils.FormatDateTimeMinute2)
+	keyword5 := utils.TruncateActivityNameString("取消报名:"+activityInfo.ActivityName)
+
+	sendInfo := new(SendWxCategoryTemplate)
+	sendInfo.Keywords = []string{keyword1, keyword2, keyword3, keyword4, keyword5}
+	sendInfo.TemplateId = utils.WxMsgCategoryTemplateIdActivityApply
+	sendInfo.RedirectUrl = utils.WX_MSG_PATH_YX_ACTIVITY_DETAIL + strconv.Itoa(activityId)
+	sendInfo.RedirectTarget = 4
+	sendInfo.SendType = utils.TEMPLATE_MSG_APPLY
+	sendInfo.OpenIdArr = openIdArr
+	err = SendCategoryTemplateMsg(sendInfo)
+	if e != nil {
+		err = errors.New("SendCategoryTemplateMsg, Err: " + e.Error())
+		return
+	}
+	return
+}

+ 36 - 2
utils/common.go

@@ -29,6 +29,7 @@ import (
 	"strings"
 	"time"
 	"unicode"
+	"unicode/utf8"
 )
 
 // 随机数种子
@@ -2306,9 +2307,9 @@ func GetQuarterStrStartDatesInRangeHaveYear(startTimeStr, endTimeStr string) (qu
 	return quartersStar, nil
 }
 
-// 获取当前时间所属季度的最后一天,并往后推个月
+// 获取当前时间所属季度的最后一天,并往后推个月
 func GetLastDayOfQuarter(t time.Time) time.Time {
-	month := (t.Month()-1)/3*3 + 1 // 计算当前季度的第一个月份
+	month := (t.Month()-1)/3*3 + 2 // 计算当前季度的第一个月份
 	nextQuarter := month + 3
 	year := t.Year()
 	if nextQuarter > 12 {
@@ -2319,3 +2320,36 @@ func GetLastDayOfQuarter(t time.Time) time.Time {
 	lastDay := time.Date(year, time.Month(nextQuarter), 1, 0, 0, 0, 0, time.UTC).AddDate(0, 1, 0).Add(-time.Second)
 	return lastDay
 }
+
+// 处理活动名称
+func TruncateActivityNameString(s string) string {
+	// 计算字符串总字数(按汉字、数字、字母和特殊符号计算)
+	totalCharCount := utf8.RuneCountInString(s)
+	// 如果总字数不超过18,则直接返回整个字符串
+	if totalCharCount <= 18 {
+		return s
+	}
+	// 计算前15个汉字所需的字节位置
+	hanziCount := 0
+	byteIndex := 0
+	for byteIndex < len(s) && hanziCount < 15 {
+		r, size := utf8.DecodeRuneInString(s[byteIndex:])
+		if r != utf8.RuneError {
+			hanziCount++
+		}
+		byteIndex += size
+	}
+	// 截取前15个汉字,并添加省略号
+	return s[:byteIndex] + "…"
+}
+
+// GetLikeKeyword
+//
+//	@Description: 获取sql查询中的like查询字段
+//	@author: Roc
+//	@datetime2023-10-23 14:46:32
+//	@param keyword string
+//	@return string
+func GetLikeKeyword(keyword string) string {
+	return `%` + keyword + `%`
+}

+ 48 - 5
utils/config.go

@@ -31,10 +31,11 @@ var (
 
 // 微信配置信息
 var (
-	WxId                string //微信原始ID
-	WxAppId             string
-	WxAppSecret         string
-	TemplateIdByProduct string //产品运行报告通知-模板ID
+	WxId                     string //微信原始ID
+	WxAppId                  string
+	WxAppSecret              string
+	TemplateIdByProduct      string //产品运行报告通知-模板ID
+	Wx_MFYX_Refund_NotifyUrl string //买方研选微信商户退款回调地址
 
 	TemplateRedirectUrl                      string //模板消息跳转地址
 	DayReportTemplateRedirectUrl             string //模板消息跳转地址(晨报、周报)
@@ -63,6 +64,14 @@ var (
 	WxMsgTemplateIdWithRoadshowDeleteNotice  string //路演->研究员收到活动删除通知
 	CYGX_WEB_URL                             string //查研观向web端网址
 	CYGX_MFYX_URL                            string //查研观向web端网址
+	WxMfyxAppId                              string //买方研选小程序APPID
+	WxMfyxAppSecret                          string //买方研选小程序 秘钥
+
+	WxMsgCategoryTemplateIdActivityChangeApply       string //买方研选活动变更通知-类目模板ID
+	WxMsgCategoryTemplateIdActivityCancleApply       string //买方研选活动取消通知-类目模板ID
+	WxMsgCategoryTemplateIdActivityPublishApply      string //买方研选关注的产业下,单个活动/研选报告发布通知-类目模板ID
+	WxMsgCategoryTemplateIdCompanyApprovalMessageRai string //权益销售签约成功通知买方研选类目模版消息
+	WxMsgCategoryTemplateIdActivityApply             string //后台研选活动给客户报名或取消报名模版消息
 
 	WxMsgTemplateIdWithYbCommunityQuestion string // 研报小程序->问答社区回复通知
 	WxMsgTemplateIdWithSealApplyFinished   string // 用印申请-已签回通知
@@ -138,7 +147,8 @@ var (
 // 公共api内部服务调用
 var (
 	// SendWxTemplateMsgUrl 模板消息推送
-	SendWxTemplateMsgUrl string
+	SendWxTemplateMsgUrl         string
+	SendWxCategoryTemplateMsgUrl string
 	// HandleVideoDecibelUrl 处理音频分贝的url
 	HandleVideoDecibelUrl string
 )
@@ -230,6 +240,10 @@ func init() {
 	AdminWxAppId = "wx1392111da5426e9e"
 	AdminWxAppSecret = "30eceb7cf29bf2f046031155ab55d7b4"
 
+	// 买方研选
+	WxMfyxAppId = "wx5e3240ab90c247ac"
+	WxMfyxAppSecret = "6b1316b46dc9c63429f5c1df6f51b4ac"
+
 	THS_PubKey = `-----BEGIN PUBLIC KEY-----
 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqugglfCboOEfWtHlGBOW
 40a4Y3xOs0MPBwjTOzHgcaWzx5XCc20VftGVXkWlpjs8u4dza/Bp1SV7SJ5Y7U95
@@ -273,6 +287,7 @@ ZwIDAQAB
 		WxRelease()
 
 		SendWxTemplateMsgUrl = "http://127.0.0.1:8086/v1/wechat/send_template_msg"
+		SendWxCategoryTemplateMsgUrl = "http://127.0.0.1:8086/v1/wechat/send_category_template_msg"
 		HandleVideoDecibelUrl = "http://172.19.173.232:8086/v1/report/handle_video_decibel"
 		HongzeOpenApiHost = "http://127.0.0.1:8609"
 		EnglishShareUrl = "https://ybpcen.hzinsights.com"
@@ -319,6 +334,7 @@ ZwIDAQAB
 
 		WxDebug()
 		SendWxTemplateMsgUrl = "http://127.0.0.1:8086/v1/wechat/send_template_msg"
+		SendWxCategoryTemplateMsgUrl = "http://127.0.0.1:8086/v1/wechat/send_category_template_msg"
 		HandleVideoDecibelUrl = "http://127.0.0.1:8086/v1/report/handle_video_decibel"
 		HongzeOpenApiHost = "http://127.0.0.1:8608"
 		EnglishShareUrl = "http://8.136.199.33:8301"
@@ -358,6 +374,9 @@ ZwIDAQAB
 
 	// 初始化内部服务配置
 	initSystemServer()
+
+	//微信商户内部配置
+	WxPayConfig()
 }
 
 // 测试环境模板消息
@@ -385,6 +404,13 @@ func WxDebug() {
 		WxMsgTemplateIdWithYbCommunityQuestion = "rciDm9ThigRBGi1SZ4TFd74XA4aoAxSz_ugdv_tZ450" // 研报小程序->问答社区回复通知
 		WxMsgTemplateIdWithSealApplyFinished = "rciDm9ThigRBGi1SZ4TFd74XA4aoAxSz_ugdv_tZ450"   // 用印申请-已签回通知
 		UserTemplateIdByProduct = "-YjuPOB7Fqd-S3ilabYa6wvjDY9aXmeEfPN6DCiy-EY"
+
+		// 买方研选小程序
+		WxMsgCategoryTemplateIdActivityChangeApply = "M975oDGwJXSX5rv4brhF4mbhl8LLoXcY_HzSKzQOtQs"       //买方研选活动变更通知-类目模板ID
+		WxMsgCategoryTemplateIdActivityCancleApply = "NdnEwNmqTy8LSVGJNGSAEkTdG9U17Vk7dveqwroiTLM"       //买方研选活动取消通知-类目模板ID
+		WxMsgCategoryTemplateIdActivityPublishApply = "wLeV7tVK4ZJBoAvsmfXkHveVW8yefGAkwnVKQWRi8uQ"      //买方研选活动报告发布通知-类目模板ID
+		WxMsgCategoryTemplateIdCompanyApprovalMessageRai = "wU4x_c5XruwuA44VZelyklRNOfq4XrU9ILckTtDs6hg" //权益销售签约成功通知买方研选类目模版消息通知-类目模板ID
+		WxMsgCategoryTemplateIdActivityApply = "IemWOTzbnLBqJ2ozSiFqm13WjaotoC3V4uXaxTij08I"             //后台研选活动给客户报名或取消报名模版消息
 	}
 
 	//查研观向小助手
@@ -423,6 +449,14 @@ func WxRelease() {
 		WxMsgTemplateIdWithYbCommunityQuestion = "rciDm9ThigRBGi1SZ4TFd74XA4aoAxSz_ugdv_tZ450" // 研报小程序->问答社区回复通知
 		WxMsgTemplateIdWithSealApplyFinished = "rciDm9ThigRBGi1SZ4TFd74XA4aoAxSz_ugdv_tZ450"   // 用印申请-已签回通知
 		UserTemplateIdByProduct = "Cp2wF8gvBtxyWV4DeYuI172oqwyYXVRSm3AyJO42d84"                //用户产品允许通知模版
+
+		// 买方研选小程序
+		WxMsgCategoryTemplateIdActivityChangeApply = "mpaOZ8xGABHJE40KaK53vzMtn30Pe9nhYK54Vvl6f0E"       //买方研选活动变更通知-类目模板ID
+		WxMsgCategoryTemplateIdActivityCancleApply = "N1oPORd3cHUJKAX6IZysZPQfemXv-ARf8iTYp0w0IvA"       //买方研选活动取消通知-类目模板ID
+		WxMsgCategoryTemplateIdActivityPublishApply = "IBMqiE61lVgUfFM4rsH0XCH57R_G3PbWvRbnzg9JHPI"      //买方研选活动报告发布通知-类目模板ID
+		WxMsgCategoryTemplateIdCompanyApprovalMessageRai = "t1CcxcOkoZkWZrDRs6zYUlceBGYMV3mhkBYUa8a6Mx0" //权益销售签约成功通知买方研选类目模版消息通知-类目模板ID
+		WxMsgCategoryTemplateIdActivityApply = "HKD03oZfSv8LJgeoHz0pynai3G2Ls4h8zZ6BfOpZmIA"             //后台研选活动给客户报名或取消报名模版消息
+
 	}
 
 	//查研观向小助手
@@ -503,6 +537,15 @@ func initSystemServer() {
 
 }
 
+// WxPayConfig 微信商户内部配置
+func WxPayConfig() {
+	if RunMode == "release" {
+		Wx_MFYX_Refund_NotifyUrl = "https://mfyx.hzinsights.com/api/wechat/wxpay/refunds/notify/" //买方研选微信商户退款回调地址
+	} else {
+		Wx_MFYX_Refund_NotifyUrl = "https://testmfyx.hzinsights.com/api/wechat/wxpay/refunds/notify" //买方研选微信商户退款回调地址
+	}
+}
+
 //http://adminapi.brilliantstart.cn/admin/
 //http://adminapi.brilliantstart.cn/swagger/
 //http://8.136.199.33:8602/swagger/

+ 24 - 0
utils/constants.go

@@ -15,6 +15,7 @@ const (
 	FormatDateTime             = "2006-01-02 15:04:05"     //完整时间格式
 	HlbFormatDateTime          = "2006-01-02_15:04:05.999" //完整时间格式
 	FormatDateTimeMinute       = "2006/01/02 15:04"        //时间格式 年/月/日 时:分
+	FormatDateTimeMinute2      = "2006-01-02 15:04"        //时间格式 年-月-日 时:分
 	FormatDateTimeUnSpace      = "20060102150405"          //完整时间格式
 	FormatShortDateTimeUnSpace = "060102150405"            //省去开头两位年份的时间格式
 	EmptyDateTimeStr           = "0000-00-00 00:00:00"     //DateTime零值字符串
@@ -393,6 +394,7 @@ const (
 	ZHI_ZAO_NAME                            string = "智造"
 	ZHI_ZAO_ID                              int    = 19
 	GU_SHOU_NAME                            string = "固收"
+	ZHOU_QI_NAME                            string = "周期"
 	GU_SHOU_ID                              int    = 100000 // 自定义权限类型ID ,十万起步
 	YI_DONG_NAME                            string = "(易董)"
 	YI_DONG_NAME_TWO                        string = "--易董"
@@ -421,11 +423,19 @@ const (
 	HONG_GUAN_NAME                          string = "宏观"
 )
 
+// 权益cygx_config配置主键以后放这里
+const (
+	YANXUAN_SPECIAL_ARTICLE_BUTTON_MOBILE string = "yanxuan_special_article_button_mobile" //CRM研选专栏模块文章管理可以查看的手机号
+	YANXUAN_SPECIAL_AUTHOR_BUTTON_MOBILE  string = "yanxuan_special_author_button_mobile"  //CRM研选专栏模块作者管理可以查看的手机号
+)
+
 var CYGX_REGISTER_PLATFORM_MAP = map[string]string{
 	"1": "小程序",
 	"2": "网页版",
 }
 
+var ACTIVITY_SPECIAL_TRIP_PERMISSION_NAME_OTHER = []string{"策略", "固收", "周期"} //专项调研活动带扣点的行业
+
 const (
 	CYGX_OBJ_ARTICLE            string = "article"            // 对象类型:文章
 	CYGX_OBJ_ACTIVITY           string = "activity"           // 对象类型:活动
@@ -584,3 +594,17 @@ const (
 const (
 	TelAreaCodeHome = "86" // 大陆区号
 )
+
+const (
+	MobileShenTao       = "18767183922" //沈涛手机号18767183922
+	MobileZhangChuanXin = "15557270714" // 张传星手机号
+	MobileWangFang      = "18621268829" // 王芳手机号
+	MobileWuAngDi       = "18701809782" // 吴昂迪手机号
+)
+
+// 买方研选小程序 模版消息路由
+const (
+	WX_MSG_PATH_YX_ACTIVITY_DETAIL = "pages-activity/activityDetail/activityDetail?id=" //研选活动详情
+	WX_MSG_PATH_YX_ARTICLE_DETAIL  = "pages-user/reportDetail/reportDetail?id="         //研选纪要详情
+
+)