publish_sop_task_logic.go 12 KB

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