publish_sop_task_logic.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. package sop_task
  2. import (
  3. "context"
  4. "errors"
  5. "github.com/suyuan32/simple-admin-common/msg/errormsg"
  6. "regexp"
  7. "strings"
  8. "wechat-api/ent"
  9. "wechat-api/ent/contact"
  10. "wechat-api/ent/custom_types"
  11. "wechat-api/ent/labelrelationship"
  12. "wechat-api/ent/messagerecords"
  13. "wechat-api/ent/predicate"
  14. "wechat-api/ent/sopstage"
  15. "wechat-api/ent/soptask"
  16. "wechat-api/internal/utils/dberrorhandler"
  17. "wechat-api/internal/svc"
  18. "wechat-api/internal/types"
  19. "github.com/zeromicro/go-zero/core/logx"
  20. )
  21. type PublishSopTaskLogic struct {
  22. logx.Logger
  23. ctx context.Context
  24. svcCtx *svc.ServiceContext
  25. }
  26. func NewPublishSopTaskLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PublishSopTaskLogic {
  27. return &PublishSopTaskLogic{
  28. Logger: logx.WithContext(ctx),
  29. ctx: ctx,
  30. svcCtx: svcCtx}
  31. }
  32. func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
  33. organizationId := l.ctx.Value("organizationId").(uint64)
  34. // 开始事务
  35. //tx, err := l.svcCtx.DB.Tx(context.Background())
  36. //if err != nil {
  37. // return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  38. //}
  39. // 根据 id 查询 sop_task
  40. sopTask, err := l.svcCtx.DB.SopTask.Query().
  41. Where(
  42. soptask.ID(req.Id),
  43. soptask.Status(1),
  44. soptask.OrganizationIDEQ(organizationId),
  45. ).
  46. WithTaskStages().
  47. Only(l.ctx)
  48. if err != nil {
  49. //_ = tx.Rollback()
  50. return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  51. }
  52. // 判断 sop_task 是否存在
  53. if sopTask != nil {
  54. if sopTask.BotWxidList == nil {
  55. return nil, errors.New(errormsg.ValidationError)
  56. }
  57. // 查询任务的所有 sop_stages
  58. err = l.svcCtx.DB.SopTask.UpdateOneID(req.Id).
  59. SetStatus(3).
  60. Exec(l.ctx)
  61. if err != nil {
  62. //_ = tx.Rollback()
  63. return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  64. }
  65. sopStages, err := l.svcCtx.DB.SopStage.Query().
  66. Where(sopstage.HasSopTaskWith(soptask.OrganizationIDEQ(organizationId), soptask.StatusEQ(3), soptask.DeletedAtIsNil()), sopstage.DeletedAtIsNil()).
  67. All(l.ctx)
  68. if err != nil {
  69. //_ = tx.Rollback()
  70. return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  71. }
  72. stageMap := make(map[uint64]*ent.SopStage)
  73. for _, stage := range sopStages {
  74. stageMap[stage.ID] = stage
  75. }
  76. // 遍历 stage
  77. for _, stage := range sopTask.Edges.TaskStages {
  78. if stage.ConditionType == 1 {
  79. // 构造查询条件
  80. var predicates []predicate.Contact
  81. for _, condition := range stage.ConditionList {
  82. subPredicate := contact.HasContactRelationshipsWith(
  83. labelrelationship.LabelIDIn(condition.LabelIdList...))
  84. labelrelationship.OrganizationIDEQ(organizationId)
  85. if condition.Equal == 2 {
  86. subPredicate = contact.Not(subPredicate)
  87. }
  88. predicates = append(predicates, subPredicate)
  89. }
  90. // 查询满足条件的联系人
  91. var contacts []*ent.Contact
  92. var err error
  93. sourceType := 3
  94. if stage.ConditionOperator == 1 {
  95. contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.And(predicates...)).All(l.ctx)
  96. } else {
  97. contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.Or(predicates...)).All(l.ctx)
  98. }
  99. if err != nil {
  100. //_ = tx.Rollback()
  101. return nil, err
  102. }
  103. // 遍历 contacts
  104. for _, c := range contacts {
  105. // 判断联系人所属微信是否包含在任务当中
  106. if sopTask.BotWxidList == nil || (sopTask.BotWxidList != nil && valueInArray(c.WxWxid, sopTask.BotWxidList)) {
  107. if stage.ActionMessage != nil {
  108. for i, message := range stage.ActionMessage {
  109. meta := custom_types.Meta{}
  110. if message.Meta != nil {
  111. meta.Filename = message.Meta.Filename
  112. }
  113. _, _ = l.svcCtx.DB.MessageRecords.Create().
  114. SetNotNilBotWxid(&c.WxWxid).
  115. SetNotNilContactID(&c.ID).
  116. SetNotNilContactType(&c.Type).
  117. SetNotNilContactWxid(&c.Wxid).
  118. SetNotNilContentType(&message.Type).
  119. SetNotNilContent(&message.Content).
  120. SetMeta(meta).
  121. SetNotNilSourceType(&sourceType).
  122. SetNotNilSourceID(&stage.ID).
  123. SetSubSourceID(uint64(i)).
  124. SetOrganizationID(organizationId).
  125. Save(l.ctx)
  126. //if err != nil {
  127. // return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  128. //}
  129. }
  130. }
  131. if stage.ActionForward != nil {
  132. if stage.ActionForward.Wxid != "" {
  133. forwardWxids := splitString(stage.ActionForward.Wxid)
  134. for _, forwardWxid := range forwardWxids {
  135. for i, message := range stage.ActionForward.Action {
  136. meta := custom_types.Meta{}
  137. if message.Meta != nil {
  138. meta.Filename = message.Meta.Filename
  139. }
  140. content := varReplace(message.Content, c)
  141. _, err = l.svcCtx.DB.MessageRecords.Create().
  142. SetBotWxid(c.WxWxid).
  143. SetContactID(0).
  144. SetContactType(0).
  145. SetContactWxid(forwardWxid).
  146. SetContentType(message.Type).
  147. SetContent(content).
  148. SetMeta(meta).
  149. SetSourceType(sourceType).
  150. SetSourceID(stage.ID).
  151. SetSubSourceID(c.ID + uint64(i)).
  152. SetOrganizationID(organizationId).
  153. Save(l.ctx)
  154. }
  155. }
  156. }
  157. }
  158. // 查询当前联系人的标签关系
  159. currentLabelRelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.ContactID(c.ID)).All(l.ctx)
  160. if err != nil {
  161. //_ = tx.Rollback()
  162. return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  163. }
  164. // 提取当前标签ID
  165. var currentLabelIds []uint64
  166. for _, relationship := range currentLabelRelationships {
  167. currentLabelIds = append(currentLabelIds, relationship.LabelID)
  168. }
  169. if stage.ActionLabelAdd != nil || stage.ActionLabelDel != nil {
  170. // 递归调用 AddLabelRelationships
  171. err = l.AddLabelRelationships(stageMap, *c, currentLabelIds, stage.ActionLabelAdd, stage.ActionLabelDel, organizationId)
  172. if err != nil {
  173. //_ = tx.Rollback()
  174. return nil, err
  175. }
  176. }
  177. }
  178. }
  179. }
  180. }
  181. // 所有操作成功,提交事务
  182. //err = tx.Commit()
  183. //if err != nil {
  184. // return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  185. //}
  186. return &types.BaseMsgResp{Msg: errormsg.Success}, nil
  187. } else {
  188. // 所有操作成功,提交事务
  189. //err = tx.Commit()
  190. //if err != nil {
  191. // return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
  192. //}
  193. //// 返回错误信息:任务不存在
  194. return nil, errors.New(errormsg.TargetNotFound)
  195. }
  196. }
  197. func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages map[uint64]*ent.SopStage, contact ent.Contact, currentLabelIds []uint64, addLabelIds []uint64, delLabelIds []uint64, organizationId uint64) (err error) {
  198. //// 开始事务
  199. //tx, err := l.svcCtx.DB.Tx(context.Background())
  200. //if err != nil {
  201. // return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  202. //}
  203. // 获取 addLabelIds 中不在 currentLabelIds 中的标签ID
  204. var newLabelIds []uint64
  205. var remLabelIds []uint64
  206. var finalLabelIds []uint64
  207. // 创建一个映射,用于快速查找 currentLabelIds 中的元素
  208. currentLabelIdSet := make(map[uint64]struct{})
  209. for _, id := range currentLabelIds {
  210. currentLabelIdSet[id] = struct{}{}
  211. }
  212. delLabelIdSet := make(map[uint64]struct{})
  213. for _, id := range delLabelIds {
  214. delLabelIdSet[id] = struct{}{}
  215. }
  216. if addLabelIds != nil && len(addLabelIds) > 0 {
  217. // 遍历 addLabelIds,找出不在 currentLabelIds 中的元素
  218. for _, id := range addLabelIds {
  219. if _, ce := currentLabelIdSet[id]; !ce {
  220. if _, re := delLabelIdSet[id]; !re {
  221. newLabelIds = append(newLabelIds, id)
  222. }
  223. }
  224. }
  225. if len(newLabelIds) > 0 {
  226. // 创建需要新增的标签关系
  227. for _, id := range newLabelIds {
  228. currentLabelIdSet[id] = struct{}{}
  229. _, err = l.svcCtx.DB.LabelRelationship.Create().
  230. SetLabelID(id).
  231. SetContactID(contact.ID).
  232. SetOrganizationID(organizationId).
  233. Save(l.ctx)
  234. if err != nil {
  235. //_ = tx.Rollback()
  236. return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  237. }
  238. }
  239. // 合并 currentLabelIds 和 newLabelIds
  240. currentLabelIds = append(currentLabelIds, newLabelIds...)
  241. }
  242. }
  243. if delLabelIds != nil && len(delLabelIds) > 0 {
  244. // 遍历 delLabelIds,找出在 currentLabelIds 中的元素
  245. for _, id := range delLabelIds {
  246. if _, exists := currentLabelIdSet[id]; exists {
  247. remLabelIds = append(remLabelIds, id)
  248. delete(currentLabelIdSet, id)
  249. }
  250. }
  251. if len(remLabelIds) > 0 {
  252. _, err = l.svcCtx.DB.LabelRelationship.Delete().Where(labelrelationship.LabelIDIn(remLabelIds...), labelrelationship.ContactIDEQ(contact.ID), labelrelationship.OrganizationIDEQ(organizationId)).Exec(l.ctx)
  253. if err != nil {
  254. //_ = tx.Rollback()
  255. return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  256. }
  257. }
  258. }
  259. if len(newLabelIds) == 0 && len(remLabelIds) == 0 {
  260. return nil
  261. }
  262. for id := range currentLabelIdSet {
  263. finalLabelIds = append(finalLabelIds, id)
  264. }
  265. // 遍历 sop_stages,找出满足条件的 stage
  266. for key, stage := range sopStages {
  267. if stage != nil && stage.ConditionType == 1 && isLabelIdListMatchFilter(finalLabelIds, stage.ConditionOperator, stage.ConditionList) {
  268. // 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
  269. _, err := l.svcCtx.DB.MessageRecords.Query().
  270. Where(
  271. messagerecords.ContactWxid(contact.Wxid),
  272. messagerecords.SourceType(3),
  273. messagerecords.SourceID(stage.ID),
  274. messagerecords.SubSourceID(0),
  275. ).
  276. Only(l.ctx)
  277. if !ent.IsNotFound(err) {
  278. continue
  279. }
  280. // 判断ActionMessage是否为空
  281. sourceType := 3
  282. if stage.ActionMessage != nil {
  283. for i, message := range stage.ActionMessage {
  284. meta := custom_types.Meta{}
  285. if message.Meta != nil {
  286. meta.Filename = message.Meta.Filename
  287. }
  288. _, _ = l.svcCtx.DB.MessageRecords.Create().
  289. SetNotNilBotWxid(&contact.WxWxid).
  290. SetNotNilContactID(&contact.ID).
  291. SetNotNilContactType(&contact.Type).
  292. SetNotNilContactWxid(&contact.Wxid).
  293. SetNotNilContentType(&message.Type).
  294. SetNotNilContent(&message.Content).
  295. SetMeta(meta).
  296. SetNotNilSourceType(&sourceType).
  297. SetNotNilSourceID(&stage.ID).
  298. SetSubSourceID(uint64(i)).
  299. SetOrganizationID(organizationId).
  300. Save(l.ctx)
  301. //if err != nil {
  302. // return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  303. //}
  304. }
  305. }
  306. if stage.ActionForward != nil {
  307. if stage.ActionForward.Wxid != "" {
  308. forwardWxids := splitString(stage.ActionForward.Wxid)
  309. for _, forwardWxid := range forwardWxids {
  310. for i, message := range stage.ActionForward.Action {
  311. meta := custom_types.Meta{}
  312. if message.Meta != nil {
  313. meta.Filename = message.Meta.Filename
  314. }
  315. _, err = l.svcCtx.DB.MessageRecords.Create().
  316. SetBotWxid(contact.WxWxid).
  317. SetContactID(0).
  318. SetContactType(0).
  319. SetContactWxid(forwardWxid).
  320. SetContentType(message.Type).
  321. SetContent(message.Content).
  322. SetMeta(meta).
  323. SetSourceType(sourceType).
  324. SetSourceID(stage.ID).
  325. SetSubSourceID(contact.ID + uint64(i)).
  326. SetOrganizationID(organizationId).
  327. Save(l.ctx)
  328. }
  329. }
  330. }
  331. }
  332. if stage.ActionLabelAdd != nil || stage.ActionLabelDel != nil {
  333. // 递归调用 AddLabelRelationships
  334. sopStages[key] = nil
  335. err = l.AddLabelRelationships(sopStages, contact, finalLabelIds, stage.ActionLabelAdd, stage.ActionLabelDel, organizationId)
  336. if err != nil {
  337. //_ = tx.Rollback()
  338. return err
  339. }
  340. }
  341. }
  342. }
  343. // 所有操作成功,提交事务
  344. //err = tx.Commit()
  345. //if err != nil {
  346. // return dberrorhandler.DefaultEntError(l.Logger, err, nil)
  347. //}
  348. return nil
  349. }
  350. func valueInArray(val string, array []string) bool {
  351. for _, item := range array {
  352. if item == val {
  353. return true
  354. }
  355. }
  356. return false
  357. }
  358. func isLabelIdListMatchFilter(labelIdList []uint64, conditionOperator int, conditionList []custom_types.Condition) bool {
  359. labelIdSet := make(map[uint64]struct{})
  360. for _, id := range labelIdList {
  361. labelIdSet[id] = struct{}{}
  362. }
  363. for _, condition := range conditionList {
  364. match := false
  365. for _, id := range condition.LabelIdList {
  366. if _, ok := labelIdSet[id]; ok {
  367. match = true
  368. break
  369. }
  370. }
  371. if condition.Equal == 2 {
  372. match = !match
  373. }
  374. if conditionOperator == 1 && !match {
  375. return false
  376. } else if conditionOperator == 2 && match {
  377. return true
  378. }
  379. }
  380. return conditionOperator == 1
  381. }
  382. func splitString(input string) []string {
  383. // Define the regular expression pattern to match Chinese comma, English comma, and Chinese enumeration comma
  384. pattern := `[,,、]`
  385. re := regexp.MustCompile(pattern)
  386. // Split the input string based on the pattern
  387. return re.Split(input, -1)
  388. }
  389. func varReplace(s string, contactInfo *ent.Contact) string {
  390. nickname := ""
  391. if contactInfo != nil {
  392. nickname = contactInfo.Nickname
  393. }
  394. s = strings.Replace(s, "${nickname}", nickname, -1)
  395. return s
  396. }