publish_sop_task_logic.go 14 KB

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