delivery_project_event.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. package opsdev
  2. import (
  3. "context"
  4. "strings"
  5. "dashoo.cn/opms_libary/myerrors"
  6. eventdao "dashoo.cn/opms_parent/app/dao/opsdev"
  7. eventmodel "dashoo.cn/opms_parent/app/model/opsdev"
  8. "dashoo.cn/opms_parent/app/service"
  9. "github.com/gogf/gf/database/gdb"
  10. "github.com/gogf/gf/frame/g"
  11. "github.com/gogf/gf/os/gtime"
  12. "github.com/gogf/gf/util/gconv"
  13. )
  14. // DeliveryProjectEventService 交付项目事件业务逻辑实现类
  15. type DeliveryProjectEventService struct {
  16. *service.ContextService
  17. EventDao *eventdao.OpsDeliveryProjectEventDao
  18. RecordDao *eventdao.OpsDeliveryProjectEventRecordDao
  19. AttachmentDao *eventdao.OpsDeliveryProjectEventAttachmentDao
  20. ProjectDao *eventdao.OpsDeliveryProjectDao
  21. TaskDao *eventdao.OpsEventTaskDao
  22. TaskRecordDao *eventdao.OpsEventTaskRecordDao
  23. }
  24. // NewDeliveryProjectEventService 初始化service
  25. func NewDeliveryProjectEventService(ctx context.Context) (svc *DeliveryProjectEventService, err error) {
  26. svc = new(DeliveryProjectEventService)
  27. if svc.ContextService, err = svc.Init(ctx); err != nil {
  28. return nil, err
  29. }
  30. svc.EventDao = eventdao.NewOpsDeliveryProjectEventDao(svc.Tenant)
  31. svc.RecordDao = eventdao.NewOpsDeliveryProjectEventRecordDao(svc.Tenant)
  32. svc.AttachmentDao = eventdao.NewOpsDeliveryProjectEventAttachmentDao(svc.Tenant)
  33. svc.ProjectDao = eventdao.NewOpsDeliveryProjectDao(svc.Tenant)
  34. svc.TaskDao = eventdao.NewOpsEventTaskDao(svc.Tenant)
  35. svc.TaskRecordDao = eventdao.NewOpsEventTaskRecordDao(svc.Tenant)
  36. return svc, nil
  37. }
  38. // GetList 分页查询事件列表
  39. func (s *DeliveryProjectEventService) GetList(req *eventmodel.OpsDeliveryProjectEventSearchReq) (total int, list []*eventmodel.OpsDeliveryProjectEventRsp, err error) {
  40. db := s.EventDao.FieldsEx(s.EventDao.Columns.DeletedTime)
  41. // 项目ID筛选
  42. if req.ProjectId > 0 {
  43. db = db.Where(s.EventDao.Columns.ProjectId, req.ProjectId)
  44. }
  45. // 事件标题模糊查询
  46. if req.DeliveryEventTitle != "" {
  47. db = db.Where(s.EventDao.Columns.DeliveryEventTitle+" like ?", "%"+req.DeliveryEventTitle+"%")
  48. }
  49. // 事件描述模糊查询
  50. if req.DeliveryEventDesc != "" {
  51. db = db.Where(s.EventDao.Columns.DeliveryEventDesc+" like ?", "%"+req.DeliveryEventDesc+"%")
  52. }
  53. // 事件类型筛选(多选)
  54. if len(req.DeliveryEventType) > 0 {
  55. db = db.Where(s.EventDao.Columns.DeliveryEventType+" in (?)", req.DeliveryEventType)
  56. }
  57. // 事件状态筛选(多选)
  58. if len(req.DeliveryEventStatus) > 0 {
  59. db = db.Where(s.EventDao.Columns.DeliveryEventStatus+" in (?)", req.DeliveryEventStatus)
  60. }
  61. // 事件结果筛选(多选)
  62. if len(req.DeliveryEventResult) > 0 {
  63. db = db.Where(s.EventDao.Columns.DeliveryEventResult+" in (?)", req.DeliveryEventResult)
  64. }
  65. // 反馈来源筛选
  66. if req.FeedbackSource != "" {
  67. db = db.Where(s.EventDao.Columns.FeedbackSource, req.FeedbackSource)
  68. }
  69. // 反馈人模糊查询
  70. if req.FeedbackReporter != "" {
  71. db = db.Where(s.EventDao.Columns.FeedbackReporter+" like ?", "%"+req.FeedbackReporter+"%")
  72. }
  73. // 负责人筛选(多选精确匹配)
  74. if len(req.OpsUserName) > 0 {
  75. db = db.Where(s.EventDao.Columns.OpsUserName+" in (?)", req.OpsUserName)
  76. }
  77. // 反馈时间范围
  78. if req.FeedbackDateStart != "" {
  79. db = db.Where(s.EventDao.Columns.FeedbackDate+">= ?", req.FeedbackDateStart)
  80. }
  81. if req.FeedbackDateEnd != "" {
  82. db = db.Where(s.EventDao.Columns.FeedbackDate+"<= ?", req.FeedbackDateEnd)
  83. }
  84. // 处理时间范围
  85. if req.CompleteTimeStart != "" {
  86. db = db.Where(s.EventDao.Columns.CompleteTime+">= ?", req.CompleteTimeStart)
  87. }
  88. if req.CompleteTimeEnd != "" {
  89. db = db.Where(s.EventDao.Columns.CompleteTime+"<= ?", req.CompleteTimeEnd)
  90. }
  91. // 统计总数
  92. total, err = db.Count()
  93. if err != nil {
  94. g.Log().Error(err)
  95. return 0, nil, myerrors.DbError("获取事件总数失败")
  96. }
  97. // 分页查询
  98. pageNum, pageSize := req.GetPage()
  99. var entityList []*eventmodel.OpsDeliveryProjectEvent
  100. // 处理排序
  101. if len(req.SortFields) > 0 {
  102. orderClauses := []string{}
  103. for _, sort := range req.SortFields {
  104. // 将前端字段名转换为数据库列名
  105. colName := s.getSortColumnName(sort.Field)
  106. if colName != "" {
  107. orderClauses = append(orderClauses, colName+" "+strings.ToUpper(sort.Order))
  108. }
  109. }
  110. if len(orderClauses) > 0 {
  111. db = db.Order(strings.Join(orderClauses, ", "))
  112. } else {
  113. db = db.Order(s.EventDao.Columns.CreatedTime + " desc")
  114. }
  115. } else {
  116. db = db.Order(s.EventDao.Columns.CreatedTime + " desc")
  117. }
  118. err = db.Page(pageNum, pageSize).Scan(&entityList)
  119. if err != nil {
  120. g.Log().Error(err)
  121. return 0, nil, myerrors.DbError("查询事件列表失败")
  122. }
  123. // 转换为响应结构体
  124. if err = gconv.Structs(entityList, &list); err != nil {
  125. g.Log().Error(err)
  126. return 0, nil, myerrors.DbError("数据转换失败")
  127. }
  128. return
  129. }
  130. // getSortColumnName 将前端排序字段名转换为数据库列名
  131. func (s *DeliveryProjectEventService) getSortColumnName(field string) string {
  132. // 前端字段名到数据库列名的映射
  133. fieldMap := map[string]string{
  134. "deliveryEventType": s.EventDao.Columns.DeliveryEventType,
  135. "deliveryEventStatus": s.EventDao.Columns.DeliveryEventStatus,
  136. "deliveryEventResult": s.EventDao.Columns.DeliveryEventResult,
  137. "opsUserName": s.EventDao.Columns.OpsUserName,
  138. "feedbackReporter": s.EventDao.Columns.FeedbackReporter,
  139. "feedbackDate": s.EventDao.Columns.FeedbackDate,
  140. "completeTime": s.EventDao.Columns.CompleteTime,
  141. }
  142. if colName, ok := fieldMap[field]; ok {
  143. return colName
  144. }
  145. return ""
  146. }
  147. // Create 新增事件,包含事务控制和过程记录、附件存储
  148. func (s *DeliveryProjectEventService) Create(req *eventmodel.OpsDeliveryProjectEventAddReq) error {
  149. // 生成事件编码
  150. eventNo := s.generateEventNo()
  151. // 构造数据
  152. data := g.Map{
  153. s.EventDao.Columns.ProjectId: req.ProjectId,
  154. s.EventDao.Columns.DeliveryEventNo: eventNo,
  155. s.EventDao.Columns.DeliveryEventTitle: req.DeliveryEventTitle,
  156. s.EventDao.Columns.DeliveryEventDesc: req.DeliveryEventDesc,
  157. s.EventDao.Columns.DeliveryEventType: req.DeliveryEventType,
  158. s.EventDao.Columns.DeliveryEventStatus: "10", // 待处理
  159. s.EventDao.Columns.FeedbackSource: req.FeedbackSource,
  160. s.EventDao.Columns.FeedbackReporter: req.FeedbackReporter,
  161. s.EventDao.Columns.FeedbackDate: gtime.Now(),
  162. s.EventDao.Columns.OnSite: req.OnSite,
  163. }
  164. // 补齐审计字段
  165. service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
  166. // 使用事务控制
  167. return s.EventDao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  168. // 1. 创建事件记录
  169. result, err := s.EventDao.TX(tx).Data(data).Insert()
  170. if err != nil {
  171. g.Log().Error(err)
  172. return myerrors.DbError("新增事件失败")
  173. }
  174. // 获取新创建的事件ID
  175. eventId, err := result.LastInsertId()
  176. if err != nil {
  177. g.Log().Error(err)
  178. return myerrors.DbError("获取事件ID失败")
  179. }
  180. // 2. 创建事件过程记录
  181. recordData := g.Map{
  182. s.RecordDao.Columns.DeliveryEventId: eventId,
  183. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  184. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  185. s.RecordDao.Columns.HandleContent: "创建事件<br/>事件标题: " + req.DeliveryEventTitle,
  186. }
  187. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  188. _, err = s.RecordDao.TX(tx).Data(recordData).Insert()
  189. if err != nil {
  190. g.Log().Error(err)
  191. return myerrors.DbError("新增事件过程记录失败")
  192. }
  193. // 3. 保存附件信息
  194. if len(req.Attachments) > 0 {
  195. for _, att := range req.Attachments {
  196. attData := g.Map{
  197. s.AttachmentDao.Columns.DeliveryEventId: eventId,
  198. s.AttachmentDao.Columns.EventId: eventId,
  199. s.AttachmentDao.Columns.FileName: att.FileName,
  200. s.AttachmentDao.Columns.FileUrl: att.FileUrl,
  201. s.AttachmentDao.Columns.FileType: att.FileType,
  202. }
  203. service.SetCreatedInfo(attData, s.GetCxtUserId(), s.GetCxtUserName())
  204. _, err = s.AttachmentDao.TX(tx).Data(attData).Insert()
  205. if err != nil {
  206. g.Log().Error(err)
  207. return myerrors.DbError("保存附件信息失败")
  208. }
  209. }
  210. }
  211. return nil
  212. })
  213. }
  214. // UpdateById 根据ID更新事件
  215. func (s *DeliveryProjectEventService) UpdateById(req *eventmodel.OpsDeliveryProjectEventUpdateReq) error {
  216. // 校验数据是否存在
  217. var entity eventmodel.OpsDeliveryProjectEvent
  218. err := s.EventDao.FieldsEx(s.EventDao.Columns.DeletedTime).WherePri(s.EventDao.Columns.Id, req.Id).Scan(&entity)
  219. if err != nil {
  220. g.Log().Error(err)
  221. return myerrors.DbError("查询事件数据失败")
  222. }
  223. if entity.Id <= 0 {
  224. return myerrors.TipsError("事件数据不存在")
  225. }
  226. // 构造更新数据 - 从请求中动态构建,支持前端传来的任何有效字段
  227. data := g.Map{}
  228. // 基础字段(编辑时可能更新)
  229. data[s.EventDao.Columns.DeliveryEventTitle] = req.DeliveryEventTitle
  230. data[s.EventDao.Columns.DeliveryEventDesc] = req.DeliveryEventDesc
  231. data[s.EventDao.Columns.DeliveryEventType] = req.DeliveryEventType
  232. data[s.EventDao.Columns.FeedbackSource] = req.FeedbackSource
  233. data[s.EventDao.Columns.FeedbackReporter] = req.FeedbackReporter
  234. data[s.EventDao.Columns.OnSite] = req.OnSite
  235. // 处理状态和结果字段(关闭事件时传入)
  236. if req.DeliveryEventStatus != "" {
  237. data[s.EventDao.Columns.DeliveryEventStatus] = req.DeliveryEventStatus
  238. }
  239. if req.DeliveryEventResult != "" {
  240. data[s.EventDao.Columns.DeliveryEventResult] = req.DeliveryEventResult
  241. }
  242. // 处理完成相关字段(处理/关闭事件时传入)
  243. if req.CompleteDesc != "" {
  244. data[s.EventDao.Columns.CompleteDesc] = req.CompleteDesc
  245. }
  246. if req.CompleteTime != "" {
  247. data[s.EventDao.Columns.CompleteTime] = req.CompleteTime
  248. }
  249. if req.ActualWorkHour > 0 {
  250. data[s.EventDao.Columns.ActualWorkHour] = req.ActualWorkHour
  251. }
  252. // 处理负责人相关字段(分配时传入)
  253. if req.OpsUserId > 0 {
  254. data[s.EventDao.Columns.OpsUserId] = req.OpsUserId
  255. data[s.EventDao.Columns.OpsUserName] = req.OpsUserName
  256. }
  257. // 补齐审计字段
  258. service.SetUpdatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
  259. // 更新操作,排除不可改字段
  260. _, err = s.EventDao.FieldsEx(service.UpdateFieldEx...).Data(data).WherePri(s.EventDao.Columns.Id, req.Id).Update()
  261. if err != nil {
  262. g.Log().Error(err)
  263. return myerrors.DbError("更新事件失败")
  264. }
  265. return nil
  266. }
  267. // DeleteByIds 根据ID批量删除
  268. func (s *DeliveryProjectEventService) DeleteByIds(ids []int64) error {
  269. if len(ids) == 0 {
  270. return myerrors.TipsError("请选择需要删除的事件")
  271. }
  272. return s.EventDao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  273. // 1. 删除事件
  274. _, err := s.EventDao.TX(tx).WhereIn(s.EventDao.Columns.Id, ids).Delete()
  275. if err != nil {
  276. g.Log().Error(err)
  277. return myerrors.DbError("删除事件失败")
  278. }
  279. // 2. 删除关联的过程记录
  280. _, err = s.RecordDao.TX(tx).WhereIn(s.RecordDao.Columns.DeliveryEventId, ids).Delete()
  281. if err != nil {
  282. g.Log().Error(err)
  283. return myerrors.DbError("删除事件过程记录失败")
  284. }
  285. // 3. 删除关联的附件
  286. _, err = s.AttachmentDao.TX(tx).WhereIn(s.AttachmentDao.Columns.DeliveryEventId, ids).Delete()
  287. if err != nil {
  288. g.Log().Error(err)
  289. return myerrors.DbError("删除事件附件失败")
  290. }
  291. return nil
  292. })
  293. }
  294. // Cancel 作废事件
  295. func (s *DeliveryProjectEventService) Cancel(req *eventmodel.OpsDeliveryProjectEventCancelReq) error {
  296. // 校验数据是否存在
  297. var entity eventmodel.OpsDeliveryProjectEvent
  298. err := s.EventDao.FieldsEx(s.EventDao.Columns.DeletedTime).WherePri(s.EventDao.Columns.Id, req.Id).Scan(&entity)
  299. if err != nil {
  300. g.Log().Error(err)
  301. return myerrors.DbError("查询事件数据失败")
  302. }
  303. if entity.Id <= 0 {
  304. return myerrors.TipsError("事件数据不存在")
  305. }
  306. // 已关闭的事件不能作废
  307. if entity.DeliveryEventStatus == eventmodel.DeliveryEventStatusClosed {
  308. return myerrors.TipsError("已关闭的事件不能作废")
  309. }
  310. // 已作废的事件不能再次作废
  311. if entity.DeliveryEventStatus == eventmodel.DeliveryEventStatusCancelled {
  312. return myerrors.TipsError("该事件已作废")
  313. }
  314. return s.EventDao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  315. // 1. 更新事件状态为已作废
  316. data := g.Map{
  317. s.EventDao.Columns.DeliveryEventStatus: eventmodel.DeliveryEventStatusCancelled,
  318. s.EventDao.Columns.Remark: req.CancelReason,
  319. }
  320. service.SetUpdatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
  321. _, err := s.EventDao.TX(tx).FieldsEx(service.UpdateFieldEx...).Data(data).WherePri(s.EventDao.Columns.Id, req.Id).Update()
  322. if err != nil {
  323. g.Log().Error(err)
  324. return myerrors.DbError("作废事件失败")
  325. }
  326. // 2. 添加作废过程记录
  327. recordContent := "作废事件<br/>作废原因: " + req.CancelReason
  328. recordData := g.Map{
  329. s.RecordDao.Columns.DeliveryEventId: req.Id,
  330. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  331. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  332. s.RecordDao.Columns.HandleContent: recordContent,
  333. }
  334. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  335. recordResult, err := s.RecordDao.TX(tx).Data(recordData).Insert()
  336. if err != nil {
  337. g.Log().Error(err)
  338. return myerrors.DbError("新增过程记录失败")
  339. }
  340. recordId, _ := recordResult.LastInsertId()
  341. // 3. 保存附件
  342. if len(req.Attachments) > 0 {
  343. for _, att := range req.Attachments {
  344. attData := g.Map{
  345. s.AttachmentDao.Columns.DeliveryEventId: req.Id,
  346. s.AttachmentDao.Columns.EventRecordId: recordId,
  347. s.AttachmentDao.Columns.FileName: att.FileName,
  348. s.AttachmentDao.Columns.FileUrl: att.FileUrl,
  349. s.AttachmentDao.Columns.FileType: att.FileType,
  350. }
  351. service.SetCreatedInfo(attData, s.GetCxtUserId(), s.GetCxtUserName())
  352. _, err = s.AttachmentDao.TX(tx).Data(attData).Insert()
  353. if err != nil {
  354. g.Log().Error(err)
  355. return myerrors.DbError("保存附件信息失败")
  356. }
  357. }
  358. }
  359. _ = recordId // 避免未使用变量警告
  360. // 4. 查询关联的任务并作废
  361. var tasks []*eventmodel.OpsEventTask
  362. err = s.TaskDao.TX(tx).Where(s.TaskDao.Columns.EventId, req.Id).
  363. Where(s.TaskDao.Columns.EventType, eventmodel.EventTypeDelivery).
  364. Scan(&tasks)
  365. if err != nil {
  366. g.Log().Error(err)
  367. return myerrors.DbError("查询关联任务失败")
  368. }
  369. // 5. 作废关联的任务
  370. for _, task := range tasks {
  371. // 已完成的任务不能作废
  372. if task.TaskStatus == "30" {
  373. continue
  374. }
  375. // 已作废的任务不需要再次作废
  376. if task.TaskStatus == "90" {
  377. continue
  378. }
  379. // 更新任务状态为作废
  380. taskData := g.Map{
  381. s.TaskDao.Columns.TaskStatus: "90",
  382. }
  383. service.SetUpdatedInfo(taskData, s.GetCxtUserId(), s.GetCxtUserName())
  384. _, err := s.TaskDao.TX(tx).FieldsEx(service.UpdateFieldEx...).Data(taskData).
  385. WherePri(s.TaskDao.Columns.Id, task.Id).Update()
  386. if err != nil {
  387. g.Log().Error(err)
  388. return myerrors.DbError("作废关联任务失败")
  389. }
  390. // 添加任务作废过程记录
  391. taskRecordData := g.Map{
  392. s.TaskRecordDao.Columns.TaskId: task.Id,
  393. s.TaskRecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  394. s.TaskRecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  395. s.TaskRecordDao.Columns.HandleContent: "作废任务<br/>作废原因: 关联事件被作废 - " + req.CancelReason,
  396. }
  397. service.SetCreatedInfo(taskRecordData, s.GetCxtUserId(), s.GetCxtUserName())
  398. _, err = s.TaskRecordDao.TX(tx).Data(taskRecordData).Insert()
  399. if err != nil {
  400. g.Log().Error(err)
  401. return myerrors.DbError("新增任务过程记录失败")
  402. }
  403. }
  404. return nil
  405. })
  406. }
  407. // GetById 根据ID查询单条(关联项目信息)
  408. func (s *DeliveryProjectEventService) GetById(id int) (*eventmodel.OpsDeliveryProjectEventRsp, error) {
  409. var entity eventmodel.OpsDeliveryProjectEvent
  410. err := s.EventDao.FieldsEx(s.EventDao.Columns.DeletedTime).WherePri(s.EventDao.Columns.Id, id).Scan(&entity)
  411. if err != nil {
  412. g.Log().Error(err)
  413. return nil, myerrors.DbError("查询事件数据失败")
  414. }
  415. if entity.Id <= 0 {
  416. return nil, myerrors.TipsError("事件数据不存在")
  417. }
  418. var rsp eventmodel.OpsDeliveryProjectEventRsp
  419. if err := gconv.Struct(entity, &rsp); err != nil {
  420. g.Log().Error(err)
  421. return nil, myerrors.DbError("数据转换失败")
  422. }
  423. // 查询关联的项目信息
  424. if entity.ProjectId > 0 {
  425. var project eventmodel.OpsDeliveryProject
  426. err := s.ProjectDao.FieldsEx(s.ProjectDao.Columns.DeletedTime).
  427. WherePri(s.ProjectDao.Columns.Id, entity.ProjectId).
  428. Scan(&project)
  429. if err != nil {
  430. g.Log().Error(err)
  431. } else if project.Id > 0 {
  432. // 填充项目信息
  433. rsp.ProjectName = project.ProjectName
  434. rsp.ContractNo = project.ContractNo
  435. rsp.CustName = project.CustName
  436. rsp.ProductLine = project.ProductLine
  437. rsp.SalesUserName = project.SalesUserName
  438. // 填充关键节点时间
  439. if project.InternalKickoffTime != nil {
  440. rsp.InternalKickoffTime = project.InternalKickoffTime.Format("Y-m-d H:i:s")
  441. }
  442. if project.ExternalKickoffTime != nil {
  443. rsp.ExternalKickoffTime = project.ExternalKickoffTime.Format("Y-m-d H:i:s")
  444. }
  445. if project.DeliveryPlanSubmitTime != nil {
  446. rsp.DeliveryPlanSubmitTime = project.DeliveryPlanSubmitTime.Format("Y-m-d H:i:s")
  447. }
  448. if project.DeploymentTime != nil {
  449. rsp.DeploymentTime = project.DeploymentTime.Format("Y-m-d H:i:s")
  450. }
  451. if project.TrialRunTime != nil {
  452. rsp.TrialRunTime = project.TrialRunTime.Format("Y-m-d H:i:s")
  453. }
  454. if project.GoLiveTime != nil {
  455. rsp.GoLiveTime = project.GoLiveTime.Format("Y-m-d H:i:s")
  456. }
  457. }
  458. }
  459. return &rsp, nil
  460. }
  461. // GetAttachments 获取事件附件列表
  462. func (s *DeliveryProjectEventService) GetAttachments(eventId int) ([]*eventmodel.OpsDeliveryProjectEventAttachment, error) {
  463. var list []*eventmodel.OpsDeliveryProjectEventAttachment
  464. err := s.AttachmentDao.Where(s.AttachmentDao.Columns.DeliveryEventId, eventId).Scan(&list)
  465. if err != nil {
  466. g.Log().Error(err)
  467. return nil, myerrors.DbError("查询附件列表失败")
  468. }
  469. return list, nil
  470. }
  471. // GetRecords 获取事件过程记录列表(包含附件)
  472. func (s *DeliveryProjectEventService) GetRecords(req *eventmodel.OpsDeliveryProjectEventRecordSearchReq) ([]*eventmodel.OpsDeliveryProjectEventRecordWithAttachments, error) {
  473. var records []*eventmodel.OpsDeliveryProjectEventRecord
  474. err := s.RecordDao.Where(s.RecordDao.Columns.DeliveryEventId, req.DeliveryEventId).
  475. Order(s.RecordDao.Columns.CreatedTime + " desc").
  476. Scan(&records)
  477. if err != nil {
  478. g.Log().Error(err)
  479. return nil, myerrors.DbError("查询过程记录失败")
  480. }
  481. result := make([]*eventmodel.OpsDeliveryProjectEventRecordWithAttachments, 0, len(records))
  482. for _, record := range records {
  483. recordRsp := &eventmodel.OpsDeliveryProjectEventRecordWithAttachments{
  484. OpsDeliveryProjectEventRecord: *record,
  485. Attachments: []*eventmodel.OpsDeliveryProjectEventAttachment{},
  486. }
  487. // 查询该记录关联的附件
  488. if record.Id > 0 {
  489. var attachments []*eventmodel.OpsDeliveryProjectEventAttachment
  490. err := s.AttachmentDao.Where(s.AttachmentDao.Columns.EventRecordId, record.Id).
  491. Scan(&attachments)
  492. if err != nil {
  493. g.Log().Error(err)
  494. } else {
  495. recordRsp.Attachments = attachments
  496. }
  497. }
  498. result = append(result, recordRsp)
  499. }
  500. return result, nil
  501. }
  502. // AddRecord 添加事件过程记录(带附件)
  503. func (s *DeliveryProjectEventService) AddRecord(req *eventmodel.OpsDeliveryProjectEventRecordAddReqWithAttachments) error {
  504. return s.EventDao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  505. // 1. 创建过程记录
  506. recordData := g.Map{
  507. s.RecordDao.Columns.DeliveryEventId: req.DeliveryEventId,
  508. s.RecordDao.Columns.HandleUserId: s.GetCxtUserId(),
  509. s.RecordDao.Columns.HandleUserName: s.GetCxtUserName(),
  510. s.RecordDao.Columns.HandleContent: req.HandleContent,
  511. }
  512. service.SetCreatedInfo(recordData, s.GetCxtUserId(), s.GetCxtUserName())
  513. result, err := s.RecordDao.TX(tx).Data(recordData).Insert()
  514. if err != nil {
  515. g.Log().Error(err)
  516. return myerrors.DbError("新增过程记录失败")
  517. }
  518. // 获取记录ID
  519. recordId, err := result.LastInsertId()
  520. if err != nil {
  521. g.Log().Error(err)
  522. return myerrors.DbError("获取记录ID失败")
  523. }
  524. // 2. 保存附件
  525. if len(req.Attachments) > 0 {
  526. for _, att := range req.Attachments {
  527. attData := g.Map{
  528. s.AttachmentDao.Columns.DeliveryEventId: req.DeliveryEventId,
  529. s.AttachmentDao.Columns.EventRecordId: recordId,
  530. s.AttachmentDao.Columns.FileName: att.FileName,
  531. s.AttachmentDao.Columns.FileUrl: att.FileUrl,
  532. s.AttachmentDao.Columns.FileType: att.FileType,
  533. }
  534. service.SetCreatedInfo(attData, s.GetCxtUserId(), s.GetCxtUserName())
  535. _, err = s.AttachmentDao.TX(tx).Data(attData).Insert()
  536. if err != nil {
  537. g.Log().Error(err)
  538. return myerrors.DbError("保存附件信息失败")
  539. }
  540. }
  541. }
  542. return nil
  543. })
  544. }
  545. // generateEventNo 生成事件编码
  546. func (s *DeliveryProjectEventService) generateEventNo() string {
  547. // 格式: EVT + 年月日 + 4位序号
  548. now := gtime.Now()
  549. prefix := "EVT" + now.Format("Ymd")
  550. // 查询当天最大序号
  551. var maxNo string
  552. err := s.EventDao.Where(s.EventDao.Columns.DeliveryEventNo+" like ?", prefix+"%").Order(s.EventDao.Columns.DeliveryEventNo + " desc").Fields(s.EventDao.Columns.DeliveryEventNo).Scan(&maxNo)
  553. if err != nil {
  554. return prefix + "0001"
  555. }
  556. if maxNo == "" {
  557. return prefix + "0001"
  558. }
  559. // 提取序号并+1
  560. if len(maxNo) >= len(prefix)+4 {
  561. seq := maxNo[len(prefix):]
  562. var seqNum int
  563. gconv.Struct(seq, &seqNum)
  564. seqNum++
  565. return prefix + gconv.String(seqNum)
  566. }
  567. return prefix + "0001"
  568. }