publish_sop_task_logic.go 14 KB

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