plat_schedule.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package plat
  2. import (
  3. "context"
  4. "dashoo.cn/micro/app/service/dingtalk_log"
  5. "dashoo.cn/opms_libary/myerrors"
  6. "database/sql"
  7. "fmt"
  8. "github.com/gogf/gf/errors/gerror"
  9. "github.com/gogf/gf/os/gtime"
  10. "github.com/gogf/gf/util/gconv"
  11. "strings"
  12. "dashoo.cn/micro/app/dao/plat"
  13. model "dashoo.cn/micro/app/model/plat"
  14. "dashoo.cn/micro/app/service"
  15. libary_dingtalk "dashoo.cn/opms_libary/plugin/dingtalk"
  16. "dashoo.cn/opms_libary/plugin/dingtalk/calendar"
  17. "dashoo.cn/opms_libary/plugin/dingtalk/message"
  18. )
  19. type scheduleService struct {
  20. *service.ContextService
  21. Dao *plat.PlatScheduleDao
  22. }
  23. func NewScheduleService(ctx context.Context) (svc *scheduleService, err error) {
  24. svc = new(scheduleService)
  25. if svc.ContextService, err = svc.Init(ctx); err != nil {
  26. return nil, err
  27. }
  28. svc.Dao = plat.NewPlatScheduleDao(svc.Tenant)
  29. return svc, nil
  30. }
  31. // GetList 日程列表 // 数据类型:(前后端约定)10 查询参与者,其他 查询组织者
  32. func (s *scheduleService) GetList(req *model.ScheduleSearchReq) (total int, scheduleList []*model.GetScheduleRes, err error) {
  33. Model := s.Dao.M.InnerJoin("plat_schedule_attendee", "plat_schedule.id=plat_schedule_attendee.sch_id")
  34. where := ""
  35. if req.DataType == "10" {
  36. where = fmt.Sprintf("plat_schedule_attendee.user_id=%v", s.GetCxtUserId())
  37. Model = Model.Where("plat_schedule_attendee.user_id = ", s.GetCxtUserId())
  38. } else {
  39. where = fmt.Sprintf("plat_schedule.user_id=%v", s.GetCxtUserId())
  40. Model = Model.Where("plat_schedule.user_id = ", s.GetCxtUserId())
  41. }
  42. if req.SchDate != nil {
  43. schDate := gconv.String(req.SchDate)
  44. begin := strings.Split(schDate, " ")[0] + " 00:00:00"
  45. end := strings.Split(schDate, " ")[0] + " 23:59:59"
  46. Model = Model.Where("plat_schedule.sch_date >= ? AND plat_schedule.sch_date <= ? ", begin, end)
  47. where += fmt.Sprintf(" AND plat_schedule.sch_date >= %v AND plat_schedule.sch_date <= %v", begin, end)
  48. }
  49. total, err = Model.Count()
  50. if err != nil {
  51. err = myerrors.DbError("获取总行数失败")
  52. return
  53. }
  54. err = Model.Page(req.GetPage()).Order("plat_schedule.id desc").Group("plat_schedule.id").Fields("plat_schedule.*").Scan(&scheduleList)
  55. if err != nil {
  56. return
  57. }
  58. // 获取参与者信息
  59. var attendees []*model.PlatScheduleAttendee
  60. err = s.Dao.M.InnerJoin("plat_schedule_attendee", "plat_schedule.id=plat_schedule_attendee.sch_id").Order("plat_schedule_attendee.id ASC").Where(where).Fields("plat_schedule_attendee.*").Scan(&attendees)
  61. if err == sql.ErrNoRows {
  62. return total, scheduleList, nil
  63. } else if err != nil {
  64. return
  65. }
  66. // 组合参与者信息
  67. for index, att := range attendees {
  68. for schIndex, sch := range scheduleList {
  69. if att.SchId == sch.Id {
  70. scheduleList[schIndex].Attendees = append(scheduleList[schIndex].Attendees, attendees[index])
  71. break
  72. }
  73. }
  74. }
  75. return
  76. }
  77. // GetUserBusyStatus 获取用户忙闲信息
  78. func (s *scheduleService) GetUserBusyStatus(req *model.UserBusyStatusReq) (UserBusyInfo interface{}, err error) {
  79. // 构造请求参数
  80. var param calendar.DingIsUserBusyParams
  81. param.BeginTime = fmt.Sprintf("%vT%v+08:00", req.BeginTime.Format("Y-m-d"), req.BeginTime.Format("H:i:s"))
  82. param.EndTime = fmt.Sprintf("%vT%v+08:00", req.EndTime.Format("Y-m-d"), req.EndTime.Format("H:i:s"))
  83. param.UserIds = req.UserIds
  84. param.UserId = s.GetCxtUserDingtalkId()
  85. // 记录日志
  86. dingtalk_log.Create(s.Ctx, "10", gconv.String(&param))
  87. // 调用钉钉接口
  88. client := libary_dingtalk.NewClient()
  89. cal := client.GetCalendar()
  90. returnData, err := cal.GetUserBusyStatus(&param)
  91. if err != nil {
  92. return 0, err
  93. }
  94. UserBusyInfo = returnData
  95. return
  96. }
  97. //Create 创建日程信息
  98. func (s *scheduleService) Create(req *model.AddScheduleSeq) (insertId int64, err error) {
  99. schedule := new(model.PlatSchedule)
  100. if err = gconv.Struct(req, schedule); err != nil {
  101. return
  102. }
  103. service.SetCreatedInfo(schedule, s.GetCxtUserId(), s.GetCxtUserName())
  104. schedule.UserId = s.GetCxtUserId()
  105. schedule.UserName = s.GetCxtUserName()
  106. // 构造请求参数
  107. var param calendar.DingAddScheduleParams
  108. param.Summary = schedule.SchTitle
  109. param.Description = schedule.SchContent
  110. param.BeginTime = fmt.Sprintf("%vT%v+08:00", req.SchDate.Format("Y-m-d"), req.SchDate.Format("H:i:s"))
  111. param.EndTime = fmt.Sprintf("%vT%v+08:00", req.SchDateEnd.Format("Y-m-d"), req.SchDateEnd.Format("H:i:s"))
  112. param.UserIds = req.UserIds
  113. param.UserId = s.GetCxtUserDingtalkId()
  114. // 记录日志
  115. dingtalk_log.Create(s.Ctx, "10", gconv.String(&param))
  116. // 调用钉钉接口
  117. client := libary_dingtalk.NewClient()
  118. cal := client.GetCalendar()
  119. returnData, err := cal.CreateSchedule(&param)
  120. if err != nil {
  121. return 0, err
  122. }
  123. // 将钉钉日程回填到系统中
  124. schedule.DingScheduleId = *returnData.Id
  125. insertId, err = s.Dao.InsertAndGetId(schedule)
  126. if err != nil {
  127. return 0, err
  128. }
  129. // 回填 日程参与人的信息 到系统中
  130. var attendees []*model.PlatScheduleAttendee
  131. for _, att := range returnData.Attendees {
  132. attendee := &model.PlatScheduleAttendee{
  133. SchId: int(insertId),
  134. DingScheduleId: schedule.DingScheduleId,
  135. UserId: 0, // TODO 用户id需要关联到此处
  136. UserUnionId: *att.Id,
  137. UserName: *att.DisplayName,
  138. }
  139. service.SetCreatedInfo(attendee, s.GetCxtUserId(), s.GetCxtUserName())
  140. attendees = append(attendees, attendee)
  141. }
  142. _, err = s.Dao.DB.Model("plat_schedule_attendee").Save(attendees)
  143. return
  144. }
  145. // SaveByDingEvent 保存日程信息
  146. func (s *scheduleService) SaveByDingEvent(msg *message.MixMessage) (err error) {
  147. if msg.ChangeType == "cancelled" || msg.ChangeType == "deleteView" {
  148. // 钉钉日程删除或者取消,本地日程需要删除
  149. _, err = s.Dao.Delete("ding_schedule_id", msg.CalendarEventId)
  150. return err
  151. } else {
  152. // 构造请求参数
  153. var param calendar.DingGetScheduleParams
  154. param.EventId = msg.CalendarEventId
  155. param.UserId = msg.UnionIdList[0]
  156. // 记录日志
  157. dingtalk_log.Create(s.Ctx, "10", gconv.String(&param))
  158. // 获取日程详情
  159. // 调用钉钉接口
  160. client := libary_dingtalk.NewClient()
  161. cal := client.GetCalendar()
  162. returnData, err := cal.GetScheduleByEventId(&param)
  163. if err != nil {
  164. return err
  165. }
  166. // 将日程数据回填
  167. // 新建日程
  168. if msg.ChangeType == "created" {
  169. err = s.addScheduleByDing(returnData)
  170. return err
  171. } else if msg.ChangeType == "updated" {
  172. // 获取系统中日程数据
  173. schedule, err := s.Dao.Where("ding_schedule_id", msg.CalendarEventId).FindOne()
  174. if err != nil {
  175. // 查询不到数据时
  176. if err == sql.ErrNoRows {
  177. err = s.addScheduleByDing(returnData)
  178. return err
  179. } else {
  180. return err
  181. }
  182. }
  183. // 查询不到数据时
  184. if schedule == nil {
  185. err = s.addScheduleByDing(returnData)
  186. return err
  187. } else {
  188. // 能查询到数据,则更新数据
  189. updateScheduleByDing(returnData, schedule)
  190. // 获取日程参与者
  191. var attendees []*model.PlatScheduleAttendee
  192. var saveAttendees []*model.PlatScheduleAttendee
  193. err = s.Dao.DB.Model("plat_schedule_attendee").Where("sch_id", schedule.Id).Scan(&attendees)
  194. if err != nil && err != sql.ErrNoRows {
  195. return err
  196. }
  197. now := gtime.Now()
  198. // 将attendees所有数据标记为删除
  199. for index := range attendees {
  200. attendees[index].DeletedTime = now
  201. }
  202. // 更新数据,并且将未删除的参与者的删除标记去掉
  203. for _, dingSchedule := range returnData.Attendees {
  204. isNew := true
  205. for index, schedule := range attendees {
  206. if schedule.UserUnionId == *dingSchedule.Id {
  207. attendees[index].DeletedTime = nil
  208. service.SetUpdatedInfo(attendees[index], 0, "钉钉回调参数修改")
  209. saveAttendees = append(saveAttendees, attendees[index])
  210. isNew = false
  211. break
  212. }
  213. }
  214. if isNew {
  215. attendee := &model.PlatScheduleAttendee{
  216. SchId: schedule.Id,
  217. DingScheduleId: schedule.DingScheduleId,
  218. UserId: 0, // TODO 用户id需要关联到此处
  219. UserUnionId: *dingSchedule.Id,
  220. UserName: *dingSchedule.DisplayName,
  221. }
  222. service.SetCreatedInfo(attendee, 0, "钉钉回调参数创建")
  223. service.SetUpdatedInfo(attendee, 0, "钉钉回调参数修改")
  224. saveAttendees = append(saveAttendees, attendee)
  225. }
  226. }
  227. // 保存删除数据
  228. for index, att := range attendees {
  229. if att.DeletedTime != nil {
  230. saveAttendees = append(saveAttendees, attendees[index])
  231. }
  232. }
  233. // 保存数据
  234. _, err = s.Dao.Save(schedule)
  235. if err != nil {
  236. return err
  237. }
  238. // 保存参与人
  239. _, err = s.Dao.DB.Model("plat_schedule_attendee").Save(saveAttendees)
  240. return err
  241. }
  242. } else {
  243. return gerror.New("未知的修改类型:" + msg.ChangeType)
  244. }
  245. }
  246. }
  247. // 根据钉钉数据创建日程
  248. func (s *scheduleService) addScheduleByDing(rsp *calendar.GetEventResponse) error {
  249. var schedule model.PlatSchedule
  250. service.SetCreatedInfo(&schedule, 0, "钉钉回调参数创建")
  251. if rsp.Summary != nil {
  252. schedule.SchTitle = *rsp.Summary
  253. }
  254. if rsp.Description != nil {
  255. schedule.SchContent = *rsp.Description
  256. }
  257. if rsp.Start != nil && rsp.Start.DateTime != nil {
  258. schedule.SchDate = gtime.NewFromStr(*rsp.Start.DateTime)
  259. }
  260. if rsp.End != nil && rsp.End.DateTime != nil {
  261. schedule.SchDateEnd = gtime.NewFromStr(*rsp.End.DateTime)
  262. }
  263. schedule.UserId = 0 // TODO 获取系统的用户Id
  264. if rsp.Organizer != nil && rsp.Organizer.Id != nil {
  265. schedule.UserUnionId = *rsp.Organizer.Id
  266. }
  267. if rsp.Organizer != nil && rsp.Organizer.DisplayName != nil {
  268. schedule.UserName = *rsp.Organizer.DisplayName
  269. }
  270. if rsp.Id != nil {
  271. schedule.DingScheduleId = *rsp.Id
  272. }
  273. insertId, err := s.Dao.InsertAndGetId(schedule)
  274. if err != nil {
  275. return err
  276. }
  277. // 回填 日程参与人的信息 到系统中
  278. var attendees []*model.PlatScheduleAttendee
  279. for _, att := range rsp.Attendees {
  280. attendee := &model.PlatScheduleAttendee{
  281. SchId: int(insertId),
  282. DingScheduleId: schedule.DingScheduleId,
  283. UserId: 0, // TODO 用户id需要关联到此处
  284. UserUnionId: *att.Id,
  285. UserName: *att.DisplayName,
  286. }
  287. service.SetCreatedInfo(attendee, 0, "钉钉回调参数创建")
  288. attendees = append(attendees, attendee)
  289. }
  290. _, err = s.Dao.DB.Model("plat_schedule_attendee").Save(attendees)
  291. return err
  292. }
  293. // 根据钉钉数据,更新日程主表数据
  294. func updateScheduleByDing(rsp *calendar.GetEventResponse, schedule *model.PlatSchedule) {
  295. service.SetUpdatedInfo(schedule, 0, "钉钉回调参数修改")
  296. if rsp.Summary != nil {
  297. schedule.SchTitle = *rsp.Summary
  298. }
  299. if rsp.Description != nil {
  300. schedule.SchContent = *rsp.Description
  301. }
  302. if rsp.Start != nil && rsp.Start.DateTime != nil {
  303. schedule.SchDate = gtime.NewFromStr(*rsp.Start.DateTime)
  304. }
  305. if rsp.End != nil && rsp.End.DateTime != nil {
  306. schedule.SchDateEnd = gtime.NewFromStr(*rsp.End.DateTime)
  307. }
  308. schedule.UserId = 0 // TODO 获取系统的用户Id
  309. if rsp.Organizer != nil && rsp.Organizer.Id != nil {
  310. schedule.UserUnionId = *rsp.Organizer.Id
  311. }
  312. if rsp.Organizer != nil && rsp.Organizer.DisplayName != nil {
  313. schedule.UserName = *rsp.Organizer.DisplayName
  314. }
  315. }