6
0

feedback.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. package feedback
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "lims_adapter/common"
  7. dao "lims_adapter/dao/feedback"
  8. "lims_adapter/model/feedback"
  9. "strconv"
  10. "dashoo.cn/common_definition/admin/permission_def"
  11. "dashoo.cn/micro_libary/micro_srv"
  12. "dashoo.cn/micro_libary/myerrors"
  13. "dashoo.cn/micro_libary/request"
  14. "github.com/gogf/gf/os/gtime"
  15. "github.com/gogf/gf/util/gvalid"
  16. "github.com/xuri/excelize/v2"
  17. )
  18. const PermissionFeedbackProcess = "feedback:process"
  19. type FeedbackService struct {
  20. Dao *dao.FeedbackDao
  21. DaoFlow *dao.FeedbackFlowDao
  22. DaoResult *dao.FeedbackResultDao
  23. Tenant string
  24. userInfo request.UserInfo
  25. }
  26. func NewFeedbackService(ctx context.Context) (*FeedbackService, error) {
  27. tenant, err := micro_srv.GetTenant(ctx)
  28. if err != nil {
  29. return nil, fmt.Errorf("获取组合码异常:%s", err.Error())
  30. }
  31. // 获取用户信息
  32. userInfo, err := micro_srv.GetUserInfo(ctx)
  33. if err != nil {
  34. return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
  35. }
  36. return &FeedbackService{
  37. Dao: dao.NewFeedbackDao(tenant),
  38. DaoFlow: dao.NewFeedbackFlowDao(tenant),
  39. DaoResult: dao.NewFeedbackResultDao(tenant),
  40. Tenant: tenant,
  41. userInfo: userInfo,
  42. }, nil
  43. }
  44. func (s FeedbackService) Get(ctx context.Context, req *feedback.FeedbackGetReq) (*feedback.FeedbackGetRsp, error) {
  45. f, err := s.Dao.Where("Id = ?", req.Id).One()
  46. if err != nil {
  47. return nil, err
  48. }
  49. if f == nil {
  50. return nil, myerrors.NewMsgError(nil, "反馈不存在")
  51. }
  52. flow, err := s.DaoFlow.Where("FeedbackId = ?", f.Id).All()
  53. if err != nil {
  54. return nil, err
  55. }
  56. result, err := s.DaoResult.Where("FeedbackId = ?", f.Id).All()
  57. if err != nil {
  58. return nil, err
  59. }
  60. return &feedback.FeedbackGetRsp{
  61. Feedback: *f,
  62. Flow: flow,
  63. Result: result,
  64. }, nil
  65. }
  66. func (s FeedbackService) List(ctx context.Context, req *feedback.FeedbackListReq) (int, []*feedback.Feedback, error) {
  67. dao := &s.Dao.FeedbackDao
  68. if req.Status != 0 {
  69. dao = dao.Where("Status = ?", req.Status)
  70. }
  71. if req.Type != "" {
  72. dao = dao.Where("Type = ?", req.Type)
  73. }
  74. if req.CreatedByName != "" {
  75. dao = dao.Where("CreatedByName LIKE ?", fmt.Sprintf("%%%s%%", req.CreatedByName))
  76. }
  77. if req.CreatedAtStart != nil {
  78. dao = dao.Where("CreatedAt > ?", req.CreatedAtStart)
  79. }
  80. if req.CreatedAtEnd != nil {
  81. dao = dao.Where("CreatedAt < ?", req.CreatedAtEnd)
  82. }
  83. if len(req.Id) != 0 {
  84. dao = dao.Where("Id in (?)", req.Id)
  85. }
  86. allow, err := Allow(s.Tenant, s.userInfo.Uuid, PermissionFeedbackProcess)
  87. if err != nil {
  88. return 0, nil, err
  89. }
  90. if !allow {
  91. dao = dao.Where("CreatedById = ?", s.userInfo.Id)
  92. }
  93. total, err := dao.Count()
  94. if err != nil {
  95. return 0, nil, err
  96. }
  97. if req.Page != nil {
  98. if req.Page.Current == 0 {
  99. req.Page.Current = 1
  100. }
  101. if req.Page.Size == 0 {
  102. req.Page.Size = 10
  103. }
  104. dao = dao.Page(req.Page.Current, req.Page.Size)
  105. }
  106. dao = dao.Order("CreatedAt", "desc")
  107. ent, err := dao.All()
  108. return total, ent, err
  109. }
  110. type organize struct {
  111. Id int
  112. FullName string
  113. }
  114. func (s FeedbackService) Add(ctx context.Context, req *feedback.FeedbackAddReq) (int, error) {
  115. validErr := gvalid.CheckStruct(ctx, req, nil)
  116. if validErr != nil {
  117. return 0, myerrors.NewMsgError(nil, validErr.Current().Error())
  118. }
  119. dept := &organize{}
  120. err := s.Dao.DB.Table("base_organize").Where("Id", s.userInfo.DeptId).Struct(dept)
  121. if err == sql.ErrNoRows {
  122. return 0, myerrors.NewMsgError(err, fmt.Sprintf("部门不存在 %s", s.userInfo.DeptId))
  123. }
  124. if err != nil {
  125. return 0, err
  126. }
  127. id, err := s.Dao.InsertAndGetId(feedback.Feedback{
  128. Type: req.Type,
  129. Status: 1,
  130. Content: req.Content,
  131. CurrentProcessorId: 0,
  132. CreatedById: int(s.userInfo.Id),
  133. CreatedByName: s.userInfo.RealName,
  134. CreatedByMobile: req.Mobile,
  135. CreatedByEmail: req.Email,
  136. CreatedByDeptId: dept.Id,
  137. CreatedByDeptName: dept.FullName,
  138. CreatedAt: gtime.New(),
  139. UpdatedAt: gtime.New(),
  140. })
  141. if err != nil {
  142. return 0, err
  143. }
  144. _, err = s.DaoFlow.Insert(feedback.FeedbackFlow{
  145. FeedbackId: int(id),
  146. Type: 1,
  147. Status: 1,
  148. ProcessById: int(s.userInfo.Id),
  149. ProcessByName: s.userInfo.RealName,
  150. Note: "",
  151. CreatedAt: gtime.New(),
  152. UpdatedAt: gtime.New(),
  153. })
  154. return int(id), err
  155. }
  156. type user struct {
  157. Id int
  158. Realname string
  159. }
  160. func (s FeedbackService) Trans(ctx context.Context, req *feedback.FeedbackTransReq) error {
  161. validErr := gvalid.CheckStruct(ctx, req, nil)
  162. if validErr != nil {
  163. return myerrors.NewMsgError(nil, validErr.Current().Error())
  164. }
  165. trnasTo := user{}
  166. err := s.Dao.DB.Table("base_user").Where("Id", req.UserId).Struct(&trnasTo)
  167. if err == sql.ErrNoRows {
  168. return myerrors.NewMsgError(nil, fmt.Sprintf("转交人不存在: %d", req.UserId))
  169. }
  170. if err != nil {
  171. return err
  172. }
  173. f, err := s.Dao.Where("Id = ?", req.Id).One()
  174. if err != nil {
  175. return err
  176. }
  177. if f == nil {
  178. return myerrors.NewMsgError(nil, fmt.Sprintf("反馈不存在: %d", req.Id))
  179. }
  180. _, err = s.Dao.Where("Id = ?", req.Id).Data(
  181. map[string]interface{}{
  182. "CurrentProcessorId": req.UserId,
  183. "CurrentProcessorName": trnasTo.Realname,
  184. }).Update()
  185. if err != nil {
  186. return err
  187. }
  188. _, err = s.DaoFlow.Insert(feedback.FeedbackFlow{
  189. FeedbackId: req.Id,
  190. Type: 2,
  191. Status: 1,
  192. ProcessById: int(s.userInfo.Id),
  193. ProcessByName: s.userInfo.RealName,
  194. Note: req.Note,
  195. CreatedAt: gtime.New(),
  196. UpdatedAt: gtime.New(),
  197. })
  198. return err
  199. }
  200. func (s FeedbackService) Process(ctx context.Context, req *feedback.FeedbackProcessReq) error {
  201. validErr := gvalid.CheckStruct(ctx, req, nil)
  202. if validErr != nil {
  203. return myerrors.NewMsgError(nil, validErr.Current().Error())
  204. }
  205. f, err := s.Dao.Where("Id = ?", req.Id).One()
  206. if err != nil {
  207. return err
  208. }
  209. if f == nil {
  210. return myerrors.NewMsgError(nil, fmt.Sprintf("反馈不存在: %d", req.Id))
  211. }
  212. _, err = s.Dao.Where("Id = ?", req.Id).Data(
  213. map[string]interface{}{
  214. "CurrentProcessorId": s.userInfo.Id,
  215. "CurrentProcessorName": s.userInfo.RealName,
  216. "ProcessedAt": gtime.Now(),
  217. "ProcessType": req.Type,
  218. "Status": 2,
  219. }).Update()
  220. if err != nil {
  221. return err
  222. }
  223. _, err = s.DaoFlow.Insert(feedback.FeedbackFlow{
  224. FeedbackId: req.Id,
  225. Type: 3,
  226. Status: 1,
  227. ProcessById: int(s.userInfo.Id),
  228. ProcessByName: s.userInfo.RealName,
  229. ProcessType: req.Type,
  230. Note: req.Note,
  231. CreatedAt: gtime.New(),
  232. UpdatedAt: gtime.New(),
  233. })
  234. if err != nil {
  235. return err
  236. }
  237. _, err = s.DaoResult.Insert(feedback.FeedbackResult{
  238. FeedbackId: req.Id,
  239. ProcessById: int(s.userInfo.Id),
  240. ProcessByName: s.userInfo.RealName,
  241. ProcessType: req.Type,
  242. ProcessNote: req.Note,
  243. CreatedAt: gtime.New(),
  244. UpdatedAt: gtime.New(),
  245. })
  246. return err
  247. }
  248. func (s FeedbackService) Reactivate(ctx context.Context, req *feedback.FeedbackReactivateReq) error {
  249. validErr := gvalid.CheckStruct(ctx, req, nil)
  250. if validErr != nil {
  251. return myerrors.NewMsgError(nil, validErr.Current().Error())
  252. }
  253. f, err := s.Dao.Where("Id = ?", req.Id).One()
  254. if err != nil {
  255. return err
  256. }
  257. if f == nil {
  258. return myerrors.NewMsgError(nil, fmt.Sprintf("反馈不存在: %d", req.Id))
  259. }
  260. _, err = s.Dao.Where("Id = ?", req.Id).Data(
  261. map[string]interface{}{
  262. "Status": 1,
  263. "CurrentProcessorId": 0,
  264. "CurrentProcessorName": nil,
  265. "ProcessedAt": nil,
  266. "ProcessType": nil,
  267. }).Update()
  268. if err != nil {
  269. return err
  270. }
  271. _, err = s.DaoFlow.Insert(feedback.FeedbackFlow{
  272. FeedbackId: req.Id,
  273. Type: 4,
  274. Status: 1,
  275. ProcessById: int(s.userInfo.Id),
  276. ProcessByName: s.userInfo.RealName,
  277. Note: req.Note,
  278. CreatedAt: gtime.New(),
  279. UpdatedAt: gtime.New(),
  280. })
  281. return err
  282. }
  283. type id struct {
  284. Id int
  285. }
  286. func (s FeedbackService) Processor(ctx context.Context) ([]feedback.FeedbackProcessorRsp, error) {
  287. rsp := []feedback.FeedbackProcessorRsp{}
  288. menu := &id{}
  289. err := s.Dao.DB.Table("base_menu").
  290. Where("Permission = ?", PermissionFeedbackProcess).
  291. Fields("Id").Struct(menu)
  292. if err == sql.ErrNoRows {
  293. return nil, myerrors.NewMsgError(err,
  294. fmt.Sprintf("未配置权限: %s", PermissionFeedbackProcess))
  295. }
  296. if err != nil {
  297. return nil, err
  298. }
  299. roles := []id{}
  300. err = s.Dao.DB.Table("base_role_menu").
  301. Where("find_in_set(?, `MenuIds`)", menu.Id).
  302. Fields("RoleId as Id").Structs(&roles)
  303. if err == sql.ErrNoRows {
  304. return rsp, nil
  305. }
  306. if err != nil {
  307. return nil, err
  308. }
  309. if len(roles) == 0 {
  310. return rsp, nil
  311. }
  312. dao := s.Dao.DB.Table("base_user a").LeftJoin("base_user_role b", "b.UserId=a.Id")
  313. orsql := ""
  314. for i, r := range roles {
  315. if i != 0 {
  316. orsql += " OR "
  317. }
  318. orsql += fmt.Sprintf("find_in_set(%d, `RoleIds`)", r.Id)
  319. }
  320. dao = dao.Where("a.Enabled = 1").Where(fmt.Sprintf("(%s)", orsql))
  321. err = dao.Fields("a.Id, a.Realname").Structs(&rsp)
  322. if err == sql.ErrNoRows {
  323. return rsp, nil
  324. }
  325. return rsp, err
  326. }
  327. func (s FeedbackService) Delete(ctx context.Context, id []int) error {
  328. _, err := s.Dao.Where("Id IN (?)", id).Delete()
  329. if err != nil {
  330. return err
  331. }
  332. _, err = s.DaoFlow.Where("FeedbackId IN (?)", id).Delete()
  333. if err != nil {
  334. return err
  335. }
  336. _, err = s.DaoResult.Where("FeedbackId IN (?)", id).Delete()
  337. return err
  338. }
  339. func (s FeedbackService) Export(ctx context.Context, req *feedback.FeedbackListReq) (*excelize.File, error) {
  340. _, data, err := s.List(ctx, req)
  341. if err != nil {
  342. return nil, err
  343. }
  344. typeMap, err := common.DictAsMap(s.Tenant, "OpinionsContent")
  345. if err != nil {
  346. return nil, myerrors.NewMsgError(nil, fmt.Sprintf("获取字典数据错误 OpinionsContent %s", err.Error()))
  347. }
  348. processTypeMap, err := common.DictAsMap(s.Tenant, "OPNHandleMethod")
  349. if err != nil {
  350. return nil, myerrors.NewMsgError(nil, fmt.Sprintf("获取字典数据错误 OPNHandleMethod %s", err.Error()))
  351. }
  352. statusMap := map[int]string{
  353. 1: "未处理",
  354. 2: "已处理",
  355. }
  356. f := excelize.NewFile()
  357. sheet := "Sheet1"
  358. header := []string{
  359. "反馈人姓名", "反馈时间", "反馈类型", "反馈内容", "处理状态", "处理人", "处理方式", "处理时间",
  360. }
  361. colWidth := []float64{
  362. 12, 20, 12, 40, 12, 12, 12, 20,
  363. }
  364. colStyle, err := f.NewStyle(&excelize.Style{
  365. Alignment: &excelize.Alignment{
  366. Horizontal: "center",
  367. Vertical: "center",
  368. WrapText: true,
  369. },
  370. Font: &excelize.Font{
  371. Size: 11,
  372. Family: "宋体",
  373. },
  374. })
  375. if err != nil {
  376. return nil, err
  377. }
  378. headerStyle, err := f.NewStyle(&excelize.Style{
  379. Alignment: &excelize.Alignment{
  380. Horizontal: "center",
  381. },
  382. Fill: excelize.Fill{
  383. Type: "pattern",
  384. Color: []string{"#a6a6a6"},
  385. Pattern: 1,
  386. },
  387. Border: []excelize.Border{
  388. {Type: "left", Color: "#000000", Style: 1},
  389. {Type: "top", Color: "#000000", Style: 1},
  390. {Type: "bottom", Color: "#000000", Style: 1},
  391. {Type: "right", Color: "#000000", Style: 1},
  392. },
  393. })
  394. if err != nil {
  395. return nil, err
  396. }
  397. lastcol, err := excelize.ColumnNumberToName(len(header))
  398. if err != nil {
  399. return nil, err
  400. }
  401. err = f.SetColStyle(sheet, "A:"+lastcol, colStyle)
  402. if err != nil {
  403. return nil, err
  404. }
  405. err = f.SetCellStyle(sheet, "A1", lastcol+"1", headerStyle)
  406. if err != nil {
  407. return nil, err
  408. }
  409. for i := range header {
  410. n, err := excelize.ColumnNumberToName(i + 1)
  411. if err != nil {
  412. return nil, err
  413. }
  414. f.SetCellValue(sheet, n+"1", header[i])
  415. }
  416. for i, w := range colWidth {
  417. n, err := excelize.ColumnNumberToName(i + 1)
  418. if err != nil {
  419. return nil, err
  420. }
  421. err = f.SetColWidth(sheet, n, n, w)
  422. if err != nil {
  423. return nil, err
  424. }
  425. }
  426. for row, item := range data {
  427. rowName := strconv.Itoa(row + 2)
  428. f.SetCellValue(sheet, "A"+rowName, item.CreatedByName)
  429. f.SetCellValue(sheet, "B"+rowName, item.CreatedAt)
  430. f.SetCellValue(sheet, "C"+rowName, typeMap[item.Type])
  431. f.SetCellValue(sheet, "D"+rowName, item.Content)
  432. f.SetCellValue(sheet, "E"+rowName, statusMap[item.Status])
  433. f.SetCellValue(sheet, "F"+rowName, item.CurrentProcessorName)
  434. f.SetCellValue(sheet, "G"+rowName, processTypeMap[item.ProcessType])
  435. f.SetCellValue(sheet, "H"+rowName, item.ProcessedAt)
  436. }
  437. index := f.NewSheet(sheet)
  438. f.SetActiveSheet(index)
  439. return f, nil
  440. }
  441. func Allow(tenant, uuid, permission string) (bool, error) {
  442. permissionSrv := micro_srv.InitMicroSrvClient("Permission", "micro_srv.admin")
  443. defer permissionSrv.Close()
  444. rsp := &permission_def.PermissionResp{}
  445. err := permissionSrv.Call(context.TODO(), "GetAllPermissionByUser", &permission_def.UuidReq{
  446. Tenant: tenant,
  447. Uuid: uuid,
  448. }, rsp)
  449. if err != nil {
  450. return false, fmt.Errorf("获取权限失败 %s", err.Error())
  451. }
  452. for _, p := range rsp.UserPermissions {
  453. if p == permission {
  454. return true, nil
  455. }
  456. }
  457. return false, nil
  458. }