calendar.go 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  1. package roadshow
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/rdlucklib/rdluck_tools/http"
  7. "hongze/hz_crm_api/models/roadshow"
  8. "hongze/hz_crm_api/models/system"
  9. "hongze/hz_crm_api/services/alarm_msg"
  10. "hongze/hz_crm_api/utils"
  11. "io/ioutil"
  12. netHttp "net/http"
  13. "net/url"
  14. "strconv"
  15. "strings"
  16. "time"
  17. )
  18. // getAccessToken token内部请求接口
  19. func getAccessToken() (tokenData roadshow.TokenData, err error) {
  20. defer func() {
  21. if err != nil {
  22. go alarm_msg.SendAlarmMsg("更新上海的token失败;ERR:"+err.Error(), 3)
  23. //go utils.SendEmail(utils.APPNAME+"更新上海的token失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  24. }
  25. }()
  26. getUrl := fmt.Sprintf(utils.CRM_OPEN_API_URL+"/v1/auth/getAccessToken?app_key=%s&app_secret=%s", utils.CRM_OPEN_API_APP_KEY, utils.CRM_OPEN_API_APP_SECRET)
  27. body, err := http.Get(getUrl)
  28. if err != nil {
  29. err = errors.New("NewRequest Err:" + err.Error())
  30. return
  31. }
  32. var tokenResp roadshow.GetTokenResp
  33. err = json.Unmarshal(body, &tokenResp)
  34. if err != nil {
  35. err = errors.New("Unmarshal Err:" + err.Error())
  36. return
  37. }
  38. if tokenResp.Code != 1 {
  39. err = errors.New("getAccessToken err:" + tokenResp.Msg)
  40. return
  41. }
  42. tokenData = tokenResp.TokenData
  43. return
  44. }
  45. // refreshAccessToken 强制刷新获取accessToken
  46. func refreshAccessToken() (token string, err error) {
  47. defer func() {
  48. if err != nil {
  49. go alarm_msg.SendAlarmMsg("刷新上海的token失败;ERR:"+err.Error(), 3)
  50. //go utils.SendEmail(utils.APPNAME+"刷新上海的token失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  51. }
  52. }()
  53. tokenInfo, tmpErr := getAccessToken()
  54. if tmpErr != nil {
  55. err = tmpErr
  56. return
  57. }
  58. token = tokenInfo.AccessToken
  59. //token存入redis
  60. err = utils.Rc.Put("SH_ACCESS_TOKEN", token, time.Duration(tokenInfo.ExpireIn-600)*time.Second)
  61. if err != nil {
  62. go alarm_msg.SendAlarmMsg("获取上海的token失败;上海token存入redis失败,ERR:"+err.Error(), 3)
  63. //go utils.SendEmail(utils.APPNAME+"获取上海的token失败:"+time.Now().Format("2006-01-02 15:04:05"), "上海token存入redis失败:", utils.EmailSendToUsers)
  64. }
  65. return
  66. }
  67. // getCalendarFrom 获取上海方的路演活动列表
  68. func getCalendarFrom(userPhone, startDate, endDate string) (list []roadshow.UserCalendar, err error) {
  69. exUrl := utils.CRM_OPEN_API_URL + "/v1/calendar/userCalendarList"
  70. form := url.Values{
  71. "user_phone": {userPhone},
  72. "start_time": {startDate},
  73. "end_time": {endDate},
  74. }
  75. body, err := getCurl(exUrl, form, 0)
  76. if err != nil {
  77. err = errors.New("NewRequest Err:" + err.Error())
  78. return
  79. }
  80. var userCalendarList roadshow.UserCalendarList
  81. err = json.Unmarshal(body, &userCalendarList)
  82. if err != nil {
  83. err = errors.New("Unmarshal Err:" + err.Error())
  84. return
  85. }
  86. list = userCalendarList.Data
  87. //fmt.Println(response)
  88. //userCalendarList := response.([]interface{})
  89. //
  90. //for _, userCalendar := range userCalendarList {
  91. // fmt.Println(userCalendar)
  92. // fmt.Printf("type :%T;\n", userCalendar)
  93. // //list = append(list, userCalendar.(roadshow.UserCalendar))
  94. //}
  95. //fmt.Println(userCalendarList)
  96. //list = userCalendarList
  97. return
  98. }
  99. // creatSHCalendar 新增上海日历活动
  100. func creatSHCalendar(userPhone, toUserPhone, content, startTime, endTime string, calendarType int8, selfCalendarId int) (err error, errMsg string) {
  101. logMsg := ``
  102. defer func() {
  103. if err != nil {
  104. if logMsg != `` {
  105. errMsg = logMsg
  106. }
  107. }
  108. }()
  109. finalUrl := utils.CRM_OPEN_API_URL + "/v1/Calendar/create"
  110. form := url.Values{
  111. "user_phone": {userPhone},
  112. "to_user_phone": {toUserPhone},
  113. "content": {content},
  114. "start_time": {startTime},
  115. "end_time": {endTime},
  116. }
  117. //发送创建请求
  118. body, err, logMsg := postCurl(finalUrl, form, 0)
  119. if err != nil {
  120. err = errors.New("NewRequest Err:" + err.Error())
  121. return
  122. }
  123. var creatSHCalendarResp roadshow.CreatSHCalendarResp
  124. err = json.Unmarshal(body, &creatSHCalendarResp)
  125. if err != nil {
  126. err = errors.New("Unmarshal Err:" + err.Error())
  127. return
  128. }
  129. calendar := creatSHCalendarResp.Data
  130. //上海系统id
  131. sThirdId := calendar.CalendarID
  132. thirdId, err := strconv.Atoi(sThirdId)
  133. if err != nil {
  134. err = errors.New("string to int Err:" + err.Error())
  135. return
  136. }
  137. // 添加自系统与上海系统的路演关系
  138. relationItem := roadshow.RsCalendarRelation{
  139. UserPhone: userPhone,
  140. CalendarType: calendarType,
  141. SelfCalendarId: selfCalendarId,
  142. ThirdCalendarId: thirdId,
  143. Title: content,
  144. ResearcherMobile: toUserPhone,
  145. ModifyTime: time.Now(),
  146. CreateTime: time.Now(),
  147. }
  148. _, err = roadshow.AddRsCalendarRelation(&relationItem)
  149. if err != nil {
  150. err = errors.New("AddRsCalendarRelation Err:" + err.Error())
  151. fmt.Println(err)
  152. return
  153. }
  154. return
  155. }
  156. // updateSHCalendar 内部函数,只用于发送修改上海日历的http请求
  157. func updateSHCalendar(thirdCalendarId, researcherMobile, content, startTime, endTime string) (calendarResp roadshow.CreatSHCalendarResp, err error) {
  158. finalUrl := utils.CRM_OPEN_API_URL + "/v1/Calendar/update"
  159. form := url.Values{
  160. "calendar_id": {thirdCalendarId},
  161. "to_user_phone": {researcherMobile},
  162. "content": {content},
  163. "start_time": {startTime},
  164. "end_time": {endTime},
  165. }
  166. //发送创建请求
  167. _, err, _ = postCurl(finalUrl, form, 0)
  168. if err != nil {
  169. err = errors.New("NewRequest Err:" + err.Error())
  170. return
  171. }
  172. return
  173. }
  174. // deleteSHCalendar 删除上海方的路演
  175. func deleteSHCalendar(userPhone string, calendarId int) (err error) {
  176. finalUrl := utils.CRM_OPEN_API_URL + "/v1/Calendar/delete"
  177. form := url.Values{
  178. "user_phone": {userPhone},
  179. "calendar_id": {fmt.Sprintf("%v", calendarId)},
  180. }
  181. //发送创建请求
  182. _, err, _ = postCurl(finalUrl, form, 0)
  183. if err != nil {
  184. err = errors.New("NewRequest Err:" + err.Error())
  185. return
  186. }
  187. return
  188. }
  189. // ShResponse 上海数据返回结构体
  190. type ShResponse struct {
  191. Code int `json:"code" description:"1:正常返回;4001:token失效"`
  192. Msg string `json:"msg" description:"文字描述"`
  193. Time int `json:"time" description:"时间戳"`
  194. Data interface{} `json:"data" description:"业务数据"`
  195. }
  196. // getCurl get请求上海接口
  197. func getCurl(urlStr string, params url.Values, num int) (body []byte, err error) {
  198. if err != nil {
  199. go alarm_msg.SendAlarmMsg("get请求上海接口失败,ERR:"+err.Error(), 3)
  200. //go utils.SendEmail(utils.APPNAME+"get请求上海接口失败:"+time.Now().Format("2006-01-02 15:04:05"), "get请求上海接口失败:"+err.Error(), utils.EmailSendToUsers)
  201. }
  202. token, err := GetAccessToken(false)
  203. if err != nil {
  204. return
  205. }
  206. params.Add("access_token", token)
  207. getUrl := urlStr + "?" + params.Encode()
  208. body, err = http.Get(getUrl)
  209. if err != nil {
  210. utils.FileLog.Info(fmt.Sprint("get Err:", err.Error(), ";url:", getUrl, ";params:", params.Encode(), ";response:", string(body)))
  211. err = errors.New("NewRequest Err:" + err.Error())
  212. return
  213. }
  214. var response ShResponse
  215. err = json.Unmarshal(body, &response)
  216. if err != nil {
  217. utils.FileLog.Info(fmt.Sprint("get Err:", err.Error(), ";url:", getUrl, ";params:", params.Encode(), ";response:", string(body)))
  218. err = errors.New("Unmarshal Err:" + err.Error())
  219. return
  220. }
  221. //如果是token失效,同时只是第一次请求(没有尝试强制刷新token,那么重新请求)
  222. if response.Code == 4001 && num <= 0 {
  223. utils.FileLog.Info(fmt.Sprint("get data err", ";url:", getUrl, ";params:", params.Encode(), ";response:", string(body)))
  224. //token失效
  225. _, tmpErr := refreshAccessToken()
  226. if tmpErr != nil {
  227. err = tmpErr
  228. }
  229. num++
  230. params.Del("access_token")
  231. return getCurl(urlStr, params, num)
  232. } else if response.Code != 1 {
  233. utils.FileLog.Info(fmt.Sprint("get data err", ";url:", getUrl, ";params:", params.Encode(), ";response:", string(body)))
  234. err = errors.New(response.Msg)
  235. return
  236. }
  237. return
  238. }
  239. // postCurl post请求上海接口
  240. func postCurl(urlStr string, form url.Values, num int) (body []byte, err error, errMsg string) {
  241. logMsg := ``
  242. defer func() {
  243. if err != nil {
  244. if logMsg != `` {
  245. errMsg = logMsg
  246. go alarm_msg.SendAlarmMsg("post请求上海接口失败,ERR:"+err.Error()+";errMsg:"+errMsg, 3)
  247. //go utils.SendEmail(utils.APPNAME+"post请求上海接口失败:"+time.Now().Format("2006-01-02 15:04:05"), "post请求上海接口失败:"+errMsg, utils.EmailSendToUsers)
  248. }
  249. }
  250. }()
  251. token, err := GetAccessToken(false)
  252. if err != nil {
  253. return
  254. }
  255. finalUrl := urlStr + "?access_token=" + token
  256. //发送创建请求
  257. resp, err := netHttp.PostForm(finalUrl, form)
  258. if err != nil {
  259. err = errors.New("NewRequest Err:" + err.Error())
  260. return
  261. }
  262. defer resp.Body.Close()
  263. //解析resp并且存入关联表
  264. body, err = ioutil.ReadAll(resp.Body)
  265. if err != nil {
  266. logMsg = fmt.Sprint("post err; request:", form.Encode(), "; errMsg:", err.Error())
  267. utils.FileLog.Info(logMsg)
  268. return
  269. }
  270. logMsg = fmt.Sprint("post request:", form.Encode(), "; response:", string(body))
  271. utils.FileLog.Info(logMsg)
  272. var response ShResponse
  273. err = json.Unmarshal(body, &response)
  274. if err != nil {
  275. utils.FileLog.Info("post Err:", err.Error(), ";url:", finalUrl, ";params:", form.Encode(), ";response:", string(body))
  276. err = errors.New("Unmarshal Err:" + err.Error())
  277. return
  278. }
  279. utils.FileLog.Info(fmt.Sprint("post request url:", finalUrl, ";params:", form.Encode(), ";response:", string(body)))
  280. //如果是token失效,同时只是第一次请求(没有尝试强制刷新token,那么重新请求)
  281. if response.Code == 4001 && num <= 0 {
  282. //token失效
  283. _, tmpErr := refreshAccessToken()
  284. if tmpErr != nil {
  285. err = tmpErr
  286. }
  287. num++
  288. return postCurl(urlStr, form, num)
  289. } else if response.Code != 1 {
  290. utils.FileLog.Info(fmt.Sprint("post data err", ";url:", finalUrl, ";params:", form.Encode(), ";response:", string(body)))
  291. err = errors.New(response.Msg)
  292. return
  293. }
  294. return
  295. }
  296. // GetAccessToken 获取accessToken
  297. func GetAccessToken(isRefresh bool) (token string, err error) {
  298. defer func() {
  299. if err != nil {
  300. go alarm_msg.SendAlarmMsg("获取上海的token失败,ERR:"+err.Error(), 3)
  301. //go utils.SendEmail(utils.APPNAME+"获取上海的token失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  302. }
  303. }()
  304. token, redisErr := utils.Rc.RedisString("SH_ACCESS_TOKEN")
  305. //如果从redis中accessToken 获取失败或者token为空了,再或者需要强制刷新了,那么重新获取accessToken
  306. if redisErr != nil || token == `` || isRefresh {
  307. return refreshAccessToken()
  308. }
  309. return
  310. }
  311. // CalendarToSH 创建活动时同步上海的前置函数
  312. func CalendarToSH(rsCalendar roadshow.RsCalendar, researcher roadshow.RsCalendarResearcher) {
  313. var err error
  314. errMsg := ``
  315. defer func() {
  316. if err != nil {
  317. errMsg = err.Error() + ";" + errMsg
  318. go alarm_msg.SendAlarmMsg("新建上海研究员日历失败,ERR:"+err.Error()+";errMsg:"+errMsg, 3)
  319. //go utils.SendEmail(utils.APPNAME+"新建上海研究员日历失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  320. }
  321. }()
  322. //redis获取创建者及研究员信息
  323. userInfo, err := getAdminInfoById(rsCalendar.SysUserId)
  324. if err != nil {
  325. utils.FileLog.Info("getAdminInfoById err: " + err.Error())
  326. return
  327. }
  328. researcherInfo, err := getAdminInfoById(researcher.ResearcherId)
  329. if err != nil {
  330. utils.FileLog.Info("getAdminInfoById err: " + err.Error())
  331. return
  332. }
  333. sTime, _ := time.ParseInLocation(utils.FormatDateTime, researcher.StartDate+" "+researcher.StartTime, time.Now().Location())
  334. startTime := sTime.Format("2006-01-02 15:04")
  335. eTime, _ := time.ParseInLocation(utils.FormatDateTime, researcher.EndDate+" "+researcher.EndTime, time.Now().Location())
  336. endTime := eTime.Format("2006-01-02 15:04")
  337. // 创建上海路演日程
  338. err, errMsg = creatSHCalendar(userInfo.Mobile, researcherInfo.Mobile, rsCalendar.Title, startTime, endTime, 1, researcher.RsCalendarResearcherId)
  339. if err != nil {
  340. utils.FileLog.Info("CreatSHCalendar err: " + err.Error())
  341. fmt.Println(err)
  342. return
  343. }
  344. // 更新路演与研究员关系表的同步字段
  345. whereParams := make(map[string]interface{})
  346. updateParams := make(map[string]interface{})
  347. whereParams["rs_calendar_researcher_id"] = researcher.RsCalendarResearcherId
  348. updateParams["is_synced"] = 1
  349. updateParams["modify_time"] = time.Now()
  350. err = roadshow.UpdateCalendarResearcher(whereParams, updateParams)
  351. if err != nil {
  352. utils.FileLog.Info("UpdateCalendarResearcher err: " + err.Error())
  353. fmt.Println("UpdateCalendarResearcher err: " + err.Error())
  354. return
  355. }
  356. // 更新路演的同步字段
  357. calWhereParams := make(map[string]interface{})
  358. calWhereParams["rs_calendar_id"] = rsCalendar.RsCalendarId
  359. err = roadshow.UpdateRsCalendar(calWhereParams, updateParams)
  360. if err != nil {
  361. utils.FileLog.Info("UpdateRsCalendar err: " + err.Error())
  362. fmt.Println("UpdateRsCalendar err: " + err.Error())
  363. return
  364. }
  365. }
  366. // MatterToSH 创建事项时同步上海的前置函数
  367. func MatterToSH(matter roadshow.RsMatters) (err error) {
  368. errMsg := ``
  369. defer func() {
  370. if err != nil {
  371. errMsg = err.Error() + ";" + errMsg
  372. go alarm_msg.SendAlarmMsg("新建上海研究员事项失败,ERR:"+err.Error()+";errMsg:"+errMsg, 3)
  373. //go utils.SendEmail(utils.APPNAME+"新建上海研究员事项失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  374. }
  375. }()
  376. //获取研究员信息
  377. researcherInfo, err := getAdminInfoById(matter.SysUserId)
  378. if err != nil {
  379. //utils.FileLog.Info("getAdminInfoById err: " + err.Error())
  380. return
  381. }
  382. sTime, _ := time.ParseInLocation(utils.FormatDateTime, matter.StartDate+" "+matter.StartTime, time.Now().Location())
  383. startTime := sTime.Format("2006-01-02 15:04")
  384. eTime, _ := time.ParseInLocation(utils.FormatDateTime, matter.EndDate+" "+matter.EndTime, time.Now().Location())
  385. endTime := eTime.Format("2006-01-02 15:04")
  386. err, errMsg = creatSHCalendar(researcherInfo.Mobile, researcherInfo.Mobile, matter.MatterContent, startTime, endTime, 2, matter.RsMattersId)
  387. if err != nil {
  388. return
  389. }
  390. // 修改事项的同步字段
  391. updateParams := make(map[string]interface{})
  392. whereParams := make(map[string]interface{})
  393. updateParams["is_synced"] = 1
  394. whereParams["rs_matters_id"] = matter.RsMattersId
  395. err = roadshow.UpdateRsMatters(whereParams, updateParams)
  396. if err != nil {
  397. err = fmt.Errorf("UpdateRsMatters err: " + err.Error())
  398. }
  399. return
  400. }
  401. // UpdateSHCalendar 更新上海日历活动
  402. func UpdateSHCalendar(rsCalendarId, rsCalendarResearcherId int, activityType, roadshowType, activityCategory, roadshowPlatform, province, city string, calendarResearcherList []*roadshow.CalendarResearcher) (err error) {
  403. errMsg := ``
  404. defer func() {
  405. if errMsg != `` {
  406. if err != nil {
  407. errMsg = err.Error() + ";" + errMsg
  408. }
  409. go alarm_msg.SendAlarmMsg("更新上海日历活动失败,errMsg:"+errMsg, 3)
  410. //go utils.SendEmail(utils.APPNAME+"更新上海日历活动失败:"+time.Now().Format("2006-01-02 15:04:05"), errMsg, utils.EmailSendToUsers)
  411. }
  412. }()
  413. //查询关联表获取信息
  414. var condition string
  415. var pars []interface{}
  416. condition = ` AND self_calendar_id = ? and calendar_type = 1 `
  417. pars = append(pars, rsCalendarResearcherId)
  418. relationItem, err := roadshow.GetRelationByPars(condition, pars)
  419. if err != nil {
  420. err = errors.New("GetRelationByPars err:" + err.Error())
  421. fmt.Println(err)
  422. return
  423. }
  424. //需要同时修改创建人及研究员的日历(目前听说只有1个,先按一个处理吧)
  425. for _, researcher := range calendarResearcherList {
  426. sTime, _ := time.ParseInLocation(utils.FormatDateTime, researcher.StartDate+" "+researcher.StartTime, time.Now().Location())
  427. startTime := sTime.Format("2006-01-02 15:04")
  428. eTime, _ := time.ParseInLocation(utils.FormatDateTime, researcher.EndDate+" "+researcher.EndTime, time.Now().Location())
  429. endTime := eTime.Format("2006-01-02 15:04")
  430. title := getTitle(activityType, roadshowType, activityCategory, roadshowPlatform, province, city)
  431. //发送更新请求
  432. _, err = updateSHCalendar(fmt.Sprintf("%v", relationItem.ThirdCalendarId), relationItem.ResearcherMobile, title, startTime, endTime)
  433. if err != nil {
  434. errMsg += fmt.Sprint("更新研究员日历信息:", relationItem.ThirdCalendarId, ";err:"+err.Error(), ";")
  435. }
  436. //// 更新路演活动的信息
  437. //calWhereParams := make(map[string]interface{})
  438. //calWhereParams["rs_calendar_id"] = rsCalendarId
  439. //err = roadshow.UpdateRsCalendarRelation(calWhereParams, updateParams)
  440. //if err != nil {
  441. // errMsg += fmt.Sprint("UpdateRsCalendar:", relationItem.ThirdCalendarId, ";err:"+err.Error(), ";")
  442. // return
  443. //}
  444. }
  445. // 更新路演活动中 研究员的信息
  446. whereParams := make(map[string]interface{})
  447. updateParams := make(map[string]interface{})
  448. whereParams["rs_calendar_researcher_id"] = rsCalendarResearcherId
  449. updateParams["is_synced"] = 1
  450. updateParams["modify_time"] = time.Now()
  451. err = roadshow.UpdateCalendarResearcher(whereParams, updateParams)
  452. if err != nil {
  453. errMsg += fmt.Sprint("UpdateCalendarResearcher:", relationItem.ThirdCalendarId, ";err:"+err.Error(), ";")
  454. return
  455. }
  456. // 更新路演活动的信息
  457. calWhereParams := make(map[string]interface{})
  458. calWhereParams["rs_calendar_id"] = rsCalendarId
  459. err = roadshow.UpdateRsCalendar(calWhereParams, updateParams)
  460. if err != nil {
  461. errMsg += fmt.Sprint("UpdateRsCalendar:", relationItem.ThirdCalendarId, ";err:"+err.Error(), ";")
  462. return
  463. }
  464. return
  465. }
  466. // UpdateSHCalendarByMatter 更新上海日历活动
  467. func UpdateSHCalendarByMatter(req roadshow.UpdateMattersReq) (err error) {
  468. defer func() {
  469. if err != nil {
  470. go alarm_msg.SendAlarmMsg("更新上海日历活动失败,Err:"+err.Error(), 3)
  471. //go utils.SendEmail(utils.APPNAME+"更新上海日历活动失败:"+time.Now().Format("2006-01-02 15:04:05"), err.Error(), utils.EmailSendToUsers)
  472. }
  473. }()
  474. if err != nil {
  475. return
  476. }
  477. //需要同时修改创建人及研究员的日历
  478. //查询关联表获取信息
  479. var condition string
  480. var pars []interface{}
  481. condition = ` AND self_calendar_id = ? and calendar_type = 2 `
  482. pars = append(pars, req.RsMattersId)
  483. relationItem, err := roadshow.GetRelationByPars(condition, pars)
  484. if err != nil {
  485. err = errors.New("GetRelationByPars err:" + err.Error())
  486. fmt.Println(err)
  487. }
  488. sTime, _ := time.ParseInLocation(utils.FormatDateTime, req.StartDate+" "+req.StartTime, time.Now().Location())
  489. startTime := sTime.Format("2006-01-02 15:04")
  490. eTime, _ := time.ParseInLocation(utils.FormatDateTime, req.EndDate+" "+req.EndTime, time.Now().Location())
  491. endTime := eTime.Format("2006-01-02 15:04")
  492. //发送更新请求
  493. _, err = updateSHCalendar(fmt.Sprintf("%v", relationItem.ThirdCalendarId), relationItem.ResearcherMobile, req.MatterContent, startTime, endTime)
  494. if err == nil {
  495. updateParams := make(map[string]interface{})
  496. whereParams := make(map[string]interface{})
  497. updateParams["is_synced"] = 1
  498. whereParams["rs_matters_id"] = req.RsMattersId
  499. err = roadshow.UpdateRsMatters(whereParams, updateParams)
  500. if err != nil {
  501. utils.FileLog.Info("UpdateRsMatters err: " + err.Error())
  502. fmt.Println("UpdateRsMatters err: " + err.Error())
  503. return
  504. }
  505. }
  506. return
  507. }
  508. // DeleteSHCalendar 删除上海日历活动
  509. func DeleteSHCalendar(rsCalendarResearcherId int) (err error) {
  510. defer func() {
  511. if err != nil {
  512. go alarm_msg.SendAlarmMsg(fmt.Sprint("删除上海日历活动失败,关系id:", rsCalendarResearcherId, ";err:", err.Error()), 3)
  513. //go utils.SendEmail(utils.APPNAME+"删除上海日历活动失败:"+time.Now().Format("2006-01-02 15:04:05"), fmt.Sprint("关系id:", rsCalendarResearcherId, ";err:", err.Error()), utils.EmailSendToUsers)
  514. }
  515. }()
  516. var condition string
  517. var pars []interface{}
  518. condition = ` AND self_calendar_id = ? and calendar_type = 1 `
  519. pars = append(pars, rsCalendarResearcherId)
  520. relationItem, err := roadshow.GetRelationByPars(condition, pars)
  521. if err != nil {
  522. logInfo := fmt.Sprint("删除上海日历活动失败;rsCalendarResearcherId:,", rsCalendarResearcherId, " ;GetRelationByPars err"+err.Error())
  523. err = errors.New(logInfo)
  524. utils.FileLog.Info(logInfo)
  525. if err.Error() == utils.ErrNoRow() {
  526. err = nil
  527. return
  528. }
  529. return
  530. }
  531. //删除上海方的路演
  532. err = deleteSHCalendar(relationItem.UserPhone, relationItem.ThirdCalendarId)
  533. if err != nil {
  534. return
  535. }
  536. //删除活动表及事项表
  537. err = roadshow.DeleteRsCalendarRelation(relationItem.RelationId)
  538. if err != nil {
  539. err = errors.New("DeleteRsCalendarRelation err:" + err.Error())
  540. return
  541. }
  542. return
  543. }
  544. // DeleteSHMatter 删除上海日历事项
  545. func DeleteSHMatter(matterId int) (err error) {
  546. defer func() {
  547. if err != nil {
  548. go alarm_msg.SendAlarmMsg("删除上海研究员日历失败;ERR:"+err.Error(), 3)
  549. //go utils.SendEmail(utils.APPNAME+"删除上海日历事项失败:", "删除上海研究员日历失败 "+err.Error(), utils.EmailSendToUsers)
  550. }
  551. }()
  552. var condition string
  553. var pars []interface{}
  554. condition = ` AND self_calendar_id = ? and calendar_type = 2 `
  555. pars = append(pars, matterId)
  556. relationItem, err := roadshow.GetRelationByPars(condition, pars)
  557. if err != nil {
  558. err = errors.New(fmt.Sprint("删除上海日历事项失败;matterId:,", matterId, " ;GetRelationByPars err"+err.Error()))
  559. utils.FileLog.Info(err.Error())
  560. if err.Error() == utils.ErrNoRow() {
  561. err = nil
  562. return
  563. }
  564. return
  565. }
  566. //删除上海方的路演
  567. err = deleteSHCalendar(relationItem.UserPhone, relationItem.ThirdCalendarId)
  568. //删除活动表及事项表
  569. err = roadshow.DeleteRsCalendarRelation(relationItem.RelationId)
  570. if err != nil {
  571. err = errors.New("DeleteRsCalendarRelation err:" + err.Error())
  572. return
  573. }
  574. return
  575. }
  576. // SyncCalendarFromShanghai 上海路演数据同步到自系统
  577. func SyncCalendarFromShanghai(userPhone, startDate, endDate string) (err error) {
  578. errMsgList := make([]string, 0)
  579. defer func() {
  580. if len(errMsgList) > 0 {
  581. //fmt.Println("err:", errMsg)
  582. if err != nil {
  583. errMsgList = append(errMsgList, fmt.Sprint("ERR:"+err.Error(), ";"))
  584. }
  585. go alarm_msg.SendAlarmMsg("上海路演数据同步到自系统失败;errMsg:"+strings.Join(errMsgList, "\n"), 3)
  586. //go utils.SendEmail(utils.APPNAME+"上海路演数据同步到自系统失败:"+time.Now().Format("2006-01-02 15:04:05"), errMsg, utils.EmailSendToUsers)
  587. }
  588. }()
  589. //fmt.Println(userPhone, startDate, endDate)
  590. endDateTime, err := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  591. if err != nil {
  592. errMsgList = append(errMsgList, `结束日期转time类型失败,err:`+err.Error())
  593. return
  594. }
  595. //往后延迟一天,避免截止到当天
  596. endDate = endDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)
  597. currDay := time.Now().Format(utils.FormatDate)
  598. nowDateTime, _ := time.ParseInLocation(utils.FormatDate, currDay, time.Local)
  599. //如果传入的结束日期早于当前日期,那么就不去查询了
  600. if endDateTime.Before(nowDateTime) {
  601. return
  602. }
  603. //获取当前研究员信息
  604. userPhoneInfo, err := getAdminInfo(userPhone)
  605. if err != nil {
  606. errMsgList = append(errMsgList, fmt.Sprint("获取手机号信息失败:手机号:", userPhone, ";err:"+err.Error(), ";"))
  607. return
  608. }
  609. //根据研究员和开始/结束日期获取上海的活动路演
  610. rsCalendarResearcherList, err := roadshow.GetRsCalendarResearcherInfoIByResearcherIdAndDate(userPhoneInfo.AdminId, currDay, endDate)
  611. if err != nil {
  612. errMsgList = append(errMsgList, fmt.Sprint("获取研究员日程信息失败:手机号:", userPhone, ";err:"+err.Error(), ";"))
  613. return
  614. }
  615. //待删除的活动路演
  616. deleteRsCalendarResearcherMap := make(map[int][]*roadshow.RsCalendarResearcherRelationInfo)
  617. for _, v := range rsCalendarResearcherList {
  618. tmpList, ok := deleteRsCalendarResearcherMap[v.ThirdCalendarId]
  619. if !ok {
  620. tmpList = make([]*roadshow.RsCalendarResearcherRelationInfo, 0)
  621. }
  622. tmpList = append(tmpList, v)
  623. deleteRsCalendarResearcherMap[v.ThirdCalendarId] = tmpList
  624. }
  625. //以当前日期作为起始日期去同步
  626. list, err := getCalendarFrom(userPhone, currDay, endDate)
  627. if err != nil {
  628. errMsgList = append(errMsgList, fmt.Sprint("获取第三方路演日历数据失败,", "userPhone:", userPhone, ";currDay:", currDay, ";endDate:", endDate, ";err:"+err.Error()))
  629. return
  630. }
  631. thirdIdList := make([]int, 0)
  632. if len(list) > 0 {
  633. for _, v := range list {
  634. thirdIdList = append(thirdIdList, v.ID)
  635. //移除还存在的活动,保留不存在的活动
  636. delete(deleteRsCalendarResearcherMap, v.ID)
  637. }
  638. rsCalendarRelationList, tmpErr := roadshow.GetRsCalendarRelationListByThirdIds(thirdIdList)
  639. if tmpErr != nil {
  640. err = tmpErr
  641. errMsgList = append(errMsgList, "获取关联列表失败,err:"+tmpErr.Error())
  642. return
  643. }
  644. rsCalendarRelationMap := make(map[int]*roadshow.RsCalendarRelation)
  645. for _, rsCalendarRelation := range rsCalendarRelationList {
  646. rsCalendarRelationMap[rsCalendarRelation.ThirdCalendarId] = rsCalendarRelation
  647. }
  648. for _, v := range list {
  649. if rsCalendarRelation, ok := rsCalendarRelationMap[v.ID]; ok {
  650. //存在的话,那么就去查找对应的信息
  651. if rsCalendarRelation.CalendarType == 1 {
  652. //路演
  653. rsCalendarResearcherInfo, tmpErr := roadshow.GetRsCalendarResearcherById(rsCalendarRelation.SelfCalendarId)
  654. if tmpErr != nil {
  655. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "获取路演研究员信息失败;err:"+tmpErr.Error(), ";"))
  656. continue
  657. }
  658. rsCalendarInfo, tmpErr := roadshow.GetRsCalendarById(rsCalendarResearcherInfo.RsCalendarId)
  659. if tmpErr != nil {
  660. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "获取路演信息失败;err:"+tmpErr.Error(), ";"))
  661. continue
  662. }
  663. if rsCalendarInfo.Source == 0 { //自系统创建的路演活动,不需要依靠上海方来修改
  664. continue
  665. }
  666. //是否去同步变更数据库
  667. isUpdateSync := false
  668. //是否变更
  669. isUpdate := false
  670. if v.StartTime != rsCalendarRelation.StartTime {
  671. isUpdate = true
  672. }
  673. if v.EndTime != rsCalendarRelation.EndTime {
  674. isUpdate = true
  675. }
  676. if v.Title != rsCalendarRelation.Title {
  677. isUpdate = true
  678. }
  679. if rsCalendarResearcherInfo.Status == 4 { // 被删除了,现在是需要更新
  680. isUpdate = true
  681. }
  682. researcherList := make([]system.AdminItem, 0)
  683. researcherMap := make(map[int]system.AdminItem)
  684. addResearcherList := make([]system.AdminItem, 0) // 需要新增的研究员
  685. delResearcherIdList := make([]int, 0) //需要删除的路演活动与研究员的关系id
  686. updateResearcherList := make([]*roadshow.RsCalendarResearcher, 0) //待更新的路演活动中研究员信息
  687. if v.ResearcherMobile != rsCalendarRelation.ResearcherMobile {
  688. //研究员变更了,需要去改表
  689. isUpdateSync = true
  690. researcherMobileList := strings.Split(v.ResearcherMobile, ",")
  691. if len(researcherMobileList) > 0 {
  692. for _, mobile := range researcherMobileList {
  693. researcherInfo, tmpErr := getAdminInfo(mobile)
  694. if tmpErr != nil {
  695. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "获取研究员失败,研究员手机号:", mobile, ";err:"+tmpErr.Error(), ";"))
  696. continue
  697. }
  698. if researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_RESEARCHR ||
  699. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RESEARCHR ||
  700. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_RESEARCHR ||
  701. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_DEPARTMENT ||
  702. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_DEPARTMENT {
  703. researcherList = append(researcherList, researcherInfo)
  704. researcherMap[researcherInfo.AdminId] = researcherInfo
  705. }
  706. }
  707. }
  708. //没有研究员
  709. if len(researcherList) <= 0 {
  710. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, ";对方研究员信息失败;"))
  711. continue
  712. }
  713. rsCalendarResearcherList, tmpErr := roadshow.GetRsCalendarResearcherListByRsCalendarId(rsCalendarInfo.RsCalendarId)
  714. if tmpErr != nil {
  715. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "获取路演活动中的研究员列表失败,路演活动ID:", rsCalendarInfo.RsCalendarId, ";err:"+tmpErr.Error(), ";"))
  716. continue
  717. }
  718. //现有活动中的研究员
  719. rsCalendarResearcherMap := make(map[int]*roadshow.RsCalendarResearcher)
  720. for _, rsCalendarResearcher := range rsCalendarResearcherList {
  721. if _, ok := researcherMap[rsCalendarResearcher.ResearcherId]; ok {
  722. if isUpdate {
  723. updateResearcherList = append(updateResearcherList, rsCalendarResearcher)
  724. }
  725. } else {
  726. delResearcherIdList = append(delResearcherIdList, rsCalendarResearcher.RsCalendarResearcherId)
  727. }
  728. rsCalendarResearcherMap[rsCalendarResearcher.ResearcherId] = rsCalendarResearcher
  729. }
  730. //校验是否需要新增研究员
  731. for adminId, researcherInfo := range researcherMap {
  732. //如果
  733. if _, ok := rsCalendarResearcherMap[adminId]; !ok {
  734. addResearcherList = append(addResearcherList, researcherInfo)
  735. }
  736. }
  737. } else if isUpdate { //如果有字段更新,那么需要将所有的研究员信息更新
  738. isUpdateSync = true
  739. rsCalendarResearcherList, tmpErr := roadshow.GetRsCalendarResearcherListByRsCalendarId(rsCalendarInfo.RsCalendarId)
  740. if tmpErr != nil {
  741. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "获取路演活动中的研究员列表失败,路演活动ID:", rsCalendarInfo.RsCalendarId, ";err:"+tmpErr.Error(), ";"))
  742. continue
  743. }
  744. for _, rsCalendarResearcher := range rsCalendarResearcherList {
  745. updateResearcherList = append(updateResearcherList, rsCalendarResearcher)
  746. }
  747. }
  748. if isUpdateSync {
  749. tmpErr = roadshow.UpdateSyncRsCalendarRelation(v, rsCalendarInfo, rsCalendarRelation, updateResearcherList, delResearcherIdList, addResearcherList)
  750. if tmpErr != nil {
  751. err = tmpErr
  752. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "修改关联关系失败;err:"+tmpErr.Error(), ";"))
  753. return
  754. }
  755. }
  756. } else {
  757. //事项
  758. //事项都是由自系统创建的,不需要依靠上海方来修改
  759. }
  760. } else {
  761. //数据不存在
  762. createUser, tmpErr := getAdminInfo(v.UserPhone)
  763. if tmpErr != nil {
  764. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "获取创建人失败,创建人手机号:", v.UserPhone, ";err:"+tmpErr.Error(), ";"))
  765. continue
  766. }
  767. //研究员列表
  768. researcherList := make([]system.AdminItem, 0)
  769. researcherMobileList := strings.Split(v.ResearcherMobile, ",")
  770. if len(researcherMobileList) > 0 {
  771. for _, mobile := range researcherMobileList {
  772. researcherInfo, tmpErr := getAdminInfo(mobile)
  773. if tmpErr != nil {
  774. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "获取研究员失败,研究员手机号:", mobile, ";err:"+tmpErr.Error(), ";"))
  775. continue
  776. }
  777. if researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_RESEARCHR ||
  778. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RESEARCHR ||
  779. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_RESEARCHR ||
  780. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_DEPARTMENT ||
  781. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_DEPARTMENT ||
  782. researcherInfo.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN {
  783. researcherList = append(researcherList, researcherInfo)
  784. }
  785. }
  786. }
  787. //没有研究员
  788. if len(researcherList) <= 0 {
  789. continue
  790. }
  791. //数据入库
  792. tmpErr = roadshow.SyncRsCalendarRelation(v, createUser, researcherList)
  793. if tmpErr != nil {
  794. err = tmpErr
  795. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", v.ID, "绑定关联关系失败;err:"+tmpErr.Error(), ";"))
  796. continue
  797. }
  798. //fmt.Println("createUser:", createUser)
  799. }
  800. }
  801. }
  802. //上海那边已经删除了路演,这边也要同步删除
  803. for _, deleteRsCalendarResearcherList := range deleteRsCalendarResearcherMap {
  804. for _, deleteRsCalendarResearcher := range deleteRsCalendarResearcherList {
  805. // 更新路演与研究员关系表的状态字段
  806. whereParams := make(map[string]interface{})
  807. updateParams := make(map[string]interface{})
  808. whereParams["rs_calendar_researcher_id"] = deleteRsCalendarResearcher.RsCalendarResearcherId
  809. updateParams["status"] = 4
  810. updateParams["modify_time"] = time.Now()
  811. tmpErr := roadshow.UpdateCalendarResearcher(whereParams, updateParams)
  812. if tmpErr != nil {
  813. err = tmpErr
  814. errMsgList = append(errMsgList, fmt.Sprint("第三方日历ID:", deleteRsCalendarResearcher.ThirdCalendarId, "删除关联关系失败;err:"+tmpErr.Error(), ";"))
  815. continue
  816. }
  817. // 更新路演的同步字段
  818. //calWhereParams := make(map[string]interface{})
  819. //calUpdateParams := make(map[string]interface{})
  820. //calWhereParams["rs_calendar_id"] = deleteRsCalendarResearcher.RsCalendarId
  821. //updateParams["is_synced"] = 1
  822. //err = roadshow.UpdateRsCalendar(calWhereParams, calUpdateParams)
  823. }
  824. }
  825. return
  826. }
  827. // CreateOaUser 新增系统用户
  828. func CreateOaUser(mobile, username string, groupId int) (err error) {
  829. defer func() {
  830. if err != nil {
  831. errMsg := fmt.Sprint("手机号:", mobile, ";username:", username, ";分组id:", groupId, ";err:", err.Error())
  832. go alarm_msg.SendAlarmMsg("系统用户同步到上海失败;ERR:"+err.Error()+";errMsg:"+errMsg, 3)
  833. //go utils.SendEmail(utils.APPNAME+"系统用户同步到上海失败:"+time.Now().Format("2006-01-02 15:04:05"), errMsg, utils.EmailSendToUsers)
  834. }
  835. }()
  836. finalUrl := utils.CRM_OPEN_API_URL + "/v1/OaUser/create"
  837. //发送创建请求
  838. form := url.Values{}
  839. form.Add("mobile", mobile)
  840. form.Add("username", username)
  841. form.Add("group_id", fmt.Sprint(groupId))
  842. //发送创建请求
  843. _, err, _ = postCurl(finalUrl, form, 0)
  844. if err != nil {
  845. err = errors.New("NewRequest Err:" + err.Error())
  846. return
  847. }
  848. return
  849. }
  850. // getAdminInfo 通过手机号获取用户信息
  851. func getAdminInfo(mobile string) (adminInfo system.AdminItem, err error) {
  852. adminMap := make(map[string]system.AdminItem)
  853. redisAdminData, redisErr := utils.Rc.RedisString(utils.CACHE_KEY_ADMIN)
  854. if redisErr != nil {
  855. list, err := system.GetSysuserList("", []interface{}{}, 0, 1000)
  856. // GetSysuserList
  857. for _, tmpAdminInfo := range list {
  858. adminMap[tmpAdminInfo.Mobile] = *tmpAdminInfo
  859. }
  860. //入缓存
  861. redisJsonData, err := json.Marshal(adminMap)
  862. if err == nil {
  863. _ = utils.Rc.Put(utils.CACHE_KEY_ADMIN, string(redisJsonData), time.Minute*30)
  864. }
  865. } else {
  866. err := json.Unmarshal([]byte(redisAdminData), &adminMap)
  867. if err != nil {
  868. fmt.Println("用户数据,json转换失败:", err)
  869. }
  870. }
  871. adminInfo, ok := adminMap[mobile]
  872. if !ok {
  873. err = fmt.Errorf("找不到该手机号用户,mobile:" + mobile)
  874. }
  875. return
  876. }
  877. // getAdminInfoById 通过用户id获取用户信息
  878. func getAdminInfoById(sysId int) (adminInfo system.AdminItem, err error) {
  879. adminMap := make(map[int]system.AdminItem)
  880. redisAdminData, redisErr := utils.Rc.RedisString(utils.CACHE_KEY_ADMIN_ID)
  881. if redisErr != nil {
  882. list, err := system.GetSysuserList("", []interface{}{}, 0, 1000)
  883. // GetSysuserList
  884. for _, tmpAdminInfo := range list {
  885. adminMap[tmpAdminInfo.AdminId] = *tmpAdminInfo
  886. }
  887. //入缓存
  888. redisJsonData, err := json.Marshal(adminMap)
  889. if err == nil {
  890. _ = utils.Rc.Put(utils.CACHE_KEY_ADMIN_ID, string(redisJsonData), time.Minute*30)
  891. }
  892. } else {
  893. err := json.Unmarshal([]byte(redisAdminData), &adminMap)
  894. if err != nil {
  895. fmt.Println("用户数据,json转换失败:", err)
  896. }
  897. }
  898. adminInfo, ok := adminMap[sysId]
  899. if !ok {
  900. err = fmt.Errorf("找不到该用户id,sysId:" + fmt.Sprint(sysId))
  901. }
  902. return
  903. }
  904. func getTitle(activityType, roadshowType, activityCategory, roadshowPlatform, province, city string) string {
  905. var title string
  906. switch activityType {
  907. case "内部会议":
  908. title = "内部会议"
  909. case "公开会议", "路演":
  910. if roadshowType == "线上" {
  911. title = roadshowType + activityType + roadshowPlatform
  912. } else {
  913. title = roadshowType + activityType + province + city
  914. }
  915. case "报告电话会":
  916. title = activityCategory + "电话会"
  917. }
  918. return title
  919. }
  920. // GetCalendarFrom 获取上海方的路演活动列表
  921. func GetCalendarFrom(userPhone, startDate, endDate string) (list []roadshow.UserCalendar, err error) {
  922. list, err = getCalendarFrom(userPhone, startDate, endDate)
  923. return
  924. }