vote.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright 2019 getensh.com. All rights reserved.
  2. // Use of this source code is governed by getensh.com.
  3. package vote
  4. import (
  5. "context"
  6. "encoding/json"
  7. "fmt"
  8. "gopkg.in/mgo.v2/bson"
  9. "gorm.io/gorm"
  10. "property-garden/errors"
  11. dbmodel "property-garden/model"
  12. "property-garden/parser"
  13. pb_v1 "property-garden/pb/v1"
  14. "property-garden/utils"
  15. "time"
  16. "git.getensh.com/common/gopkgs/database"
  17. "git.getensh.com/common/gopkgs/logger"
  18. "go.uber.org/zap"
  19. "google.golang.org/grpc/status"
  20. )
  21. const (
  22. TopicTypeCompletion = 1
  23. TopicTypeSingleChoice = 2
  24. TopicTypeMultiChoice = 3
  25. TopicTypeStar = 4
  26. )
  27. func checkVoteAddAnswerParam(req *pb_v1.VoteAddAnswerRequest) error {
  28. switch {
  29. case req.GardenId == 0:
  30. return status.Error(10003, "小区不能为空")
  31. case req.Id == 0:
  32. return status.Error(10003, "id不能为空")
  33. case req.Uid == 0:
  34. return status.Error(10003, "住户uid不能为空")
  35. }
  36. return nil
  37. }
  38. func getVoteOrigin(dbname string, id int64) (pb_v1.VoteItem, error) {
  39. p := dbmodel.NewVote(dbname)
  40. ret := pb_v1.VoteItem{}
  41. where := map[string]interface{}{
  42. "id": id,
  43. }
  44. err := p.Find(database.DB(), where)
  45. if err != nil && err != gorm.ErrRecordNotFound {
  46. return ret, errors.DataBaseError
  47. }
  48. if p.ID == 0 {
  49. return ret, errors.ErrRecordNotFound
  50. }
  51. ret = pb_v1.VoteItem{
  52. Title: p.Title,
  53. Start: p.Start,
  54. End: p.End,
  55. Id: p.ID,
  56. }
  57. topics := []*pb_v1.VoteTopic{}
  58. json.Unmarshal([]byte(p.Topics), &topics)
  59. ret.Topics = topics
  60. return ret, nil
  61. }
  62. func checkChoiceAnswer(origin []*pb_v1.VoteTopicChoiceItem, answer []string) bool {
  63. if len(answer) == 0 {
  64. return true
  65. }
  66. m := map[string]bool{}
  67. for _, v := range origin {
  68. m[v.Flag] = true
  69. }
  70. for _, v := range answer {
  71. if !m[v] {
  72. return false
  73. }
  74. }
  75. return true
  76. }
  77. func VoteAddAnswer(ctx context.Context, req *pb_v1.VoteAddAnswerRequest) (reply *pb_v1.VoteAddAnswerReply, err error) {
  78. reply = &pb_v1.VoteAddAnswerReply{}
  79. // 捕获各个task中的异常并返回给调用者
  80. defer func() {
  81. if r := recover(); r != nil {
  82. err = fmt.Errorf("%+v", r)
  83. e := &status.Status{}
  84. if er := json.Unmarshal([]byte(err.Error()), e); er != nil {
  85. logger.Error("err",
  86. zap.String("system_err", err.Error()),
  87. zap.Stack("stacktrace"))
  88. }
  89. }
  90. }()
  91. // 参数检查
  92. err = checkVoteAddAnswerParam(req)
  93. if err != nil {
  94. return nil, err
  95. }
  96. dbname := utils.GetGardenDbName(req.GardenId)
  97. vote, err := getVoteOrigin(dbname, req.Id)
  98. if err != nil {
  99. return nil, err
  100. }
  101. now := time.Now()
  102. if vote.Start > now.Unix() {
  103. return nil, status.Error(10003, "投票未开始")
  104. }
  105. if vote.End < now.Unix() {
  106. return nil, status.Error(10003, "投票已结束")
  107. }
  108. if len(vote.Topics) != len(req.Answers) {
  109. return nil, status.Error(10003, "题目数量不匹配")
  110. }
  111. voteM := map[int64]*pb_v1.VoteTopic{}
  112. for _, v := range vote.Topics {
  113. voteM[v.Number] = v
  114. }
  115. dst := dbmodel.VoteAnswer{
  116. Uid: req.Uid,
  117. CreatedAt: now.Unix(),
  118. UpdatedAt: now.Unix(),
  119. }
  120. dst.Answers = make([]dbmodel.AnswerItem, len(req.Answers))
  121. for i, v := range req.Answers {
  122. topic := voteM[v.Number]
  123. if topic == nil {
  124. return nil, status.Error(10003, "题目不存在")
  125. }
  126. dst.Answers[i] = dbmodel.AnswerItem{
  127. Number: v.Number,
  128. TopicType: v.TopicType,
  129. CompletionAnswer: []string{},
  130. ChoiceAnswer: []string{},
  131. StarAnswer: 0,
  132. }
  133. switch {
  134. case v.TopicType == TopicTypeCompletion:
  135. if len(v.CompletionAnswers) == 0 && topic.Must {
  136. return nil, status.Error(10003, fmt.Sprintf("第%d题为必选题,不能为空", v.Number))
  137. }
  138. dst.Answers[i].CompletionAnswer = v.CompletionAnswers
  139. case v.TopicType == TopicTypeSingleChoice:
  140. if len(v.ChoiceAnswers) == 0 && topic.Must {
  141. return nil, status.Error(10003, fmt.Sprintf("第%d题为必选题,不能为空", v.Number))
  142. }
  143. if !checkChoiceAnswer(topic.ChoiceItems, v.ChoiceAnswers) {
  144. return nil, status.Error(10003, fmt.Sprintf("第%d题选项标签错误", v.Number))
  145. }
  146. dst.Answers[i].ChoiceAnswer = v.ChoiceAnswers
  147. case v.TopicType == TopicTypeMultiChoice:
  148. if len(v.ChoiceAnswers) == 0 && topic.Must {
  149. return nil, status.Error(10003, fmt.Sprintf("第%d题为必选题,不能为空", v.Number))
  150. }
  151. if !checkChoiceAnswer(topic.ChoiceItems, v.ChoiceAnswers) {
  152. return nil, status.Error(10003, fmt.Sprintf("第%d题选项标签错误", v.Number))
  153. }
  154. dst.Answers[i].ChoiceAnswer = v.ChoiceAnswers
  155. case v.TopicType == TopicTypeStar:
  156. if v.StarAnswers == 0 && topic.Must {
  157. return nil, status.Error(10003, fmt.Sprintf("第%d题为必选题,不能为空", v.Number))
  158. }
  159. dst.Answers[i].StarAnswer = v.StarAnswers
  160. }
  161. }
  162. collection := parser.Session.DB(dbmodel.VoteMgoDb).C(dbmodel.VoteCollection(req.GardenId, req.Id))
  163. err = dst.Upsert(collection, bson.M{"uid": req.Uid})
  164. if err != nil {
  165. logger.Error("mgo",
  166. zap.String("error", err.Error()))
  167. return nil, errors.DataBaseError
  168. }
  169. StatisticDelCache(req.GardenId, req.Id)
  170. return reply, nil
  171. }