plat_schedule.go 10 KB

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