sendMail.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. package main
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/mail"
  5. "fmt"
  6. "log"
  7. "strings"
  8. )
  9. var (
  10. selfMail = `SELECT a.position_id, a.name, c.mail FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a LEFT JOIN jianyu.entniche_user c ON a.ent_user_id = c.id WHERE a.position_id = ?`
  11. infoSelf = `SELECT a.name, a.SZ_PID1, a.SZ_PID2, a.dept_name, b.role_id FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a INNER JOIN Jianyu_subjectdb_test.dwd_f_crm_personnel_management b ON b.position_id = a.position_id WHERE a.position_id = ? AND a.resign = 0`
  12. topMail = `SELECT a.name, a.ent_user_id, b.mail FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a LEFT JOIN jianyu.entniche_user b ON a.ent_user_id = b.id LEFT JOIN Jianyu_subjectdb_test.dwd_f_crm_personnel_management c ON a.position_id = c.position_id AND c.resign = 0
  13. WHERE a.SZ_PID3 IN (SELECT a.SZ_PID3 FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a WHERE a.position_id = ?) AND c.role_id = 3`
  14. topMail3 = `SELECT a.name, a.ent_user_id, b.mail FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a LEFT JOIN jianyu.entniche_user b ON a.ent_user_id = b.id LEFT JOIN Jianyu_subjectdb_test.dwd_f_crm_personnel_management c ON a.position_id = c.position_id
  15. WHERE a.dept_name = '销售三部' AND a.resign = 0 AND c.role_id = 3`
  16. dmInfo = `SELECT b.dept_name FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi b WHERE b.position_id IN (SELECT a.position_id FROM Jianyu_subjectdb_test.dwd_f_crm_personnel_management a
  17. WHERE assign_type = 1) GROUP BY b.dept_name`
  18. dmInfoCount = `SELECT COUNT(*) as num FROM Jianyu_subjectdb_test.dwd_f_crm_clue_info b WHERE b.position_id IN (SELECT a.position_id FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a WHERE dept_name = ? AND resign = 0) GROUP BY b.position_id HAVING num < ?`
  19. dmInfoMail = `SELECT a.name, a.position_id, (b.send_mail >> 2) & 1 AS flag_1, (b.send_mail >> 3) & 1 AS flag_2, c.mail FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a INNER JOIN Jianyu_subjectdb_test.dwd_f_crm_personnel_management b ON a.position_id = b.position_id LEFT JOIN jianyu.entniche_user c ON a.ent_user_id = c.id WHERE a.dept_name = ? AND a.resign = 0 AND b.role_id = 3`
  20. xgMail = `SELECT a.name, c.mail FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a INNER JOIN Jianyu_subjectdb_test.dwd_f_crm_personnel_management b ON a.position_id = b.position_id LEFT JOIN jianyu.entniche_user c ON a.ent_user_id = c.id WHERE b.role_id = 5 AND b.resign = 0`
  21. // 所有参与线索分配人员的邮箱
  22. allMail = `SELECT a.name, c.mail FROM Jianyu_subjectdb_test.dwd_f_crm_personnel_management a INNER JOIN Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi b ON a.position_id = b.position_id LEFT JOIN jianyu.entniche_user c ON b.ent_user_id = c.id WHERE a.assign_type = 1 AND a.resign = 0`
  23. // 超管
  24. cgMail = `SELECT a.name, c.mail FROM Jianyu_subjectdb_test.dwd_d_crm_department_level_succbi a INNER JOIN Jianyu_subjectdb_test.dwd_f_crm_personnel_management b ON a.position_id = b.position_id LEFT JOIN jianyu.entniche_user c ON a.ent_user_id = c.id WHERE b.role_id = 4 AND b.resign = 0`
  25. )
  26. // @Author jianghan
  27. // @Description 个人预警/上限
  28. // @Date 2024/4/11
  29. func WarningPerl() {
  30. sql := `SELECT count(*) FROM dwd_f_crm_clue_info where position_id = ? and trailstatus <> '08'`
  31. sql1 := `UPDATE dwd_f_crm_personnel_management SET send_mail = (%s) where position_id = ?`
  32. pp := TiDb.SelectBySql(`SELECT name, position_id, send_mail & 1 AS flag_1, (send_mail >> 1) & 1 AS flag_2 FROM dwd_f_crm_personnel_management WHERE resign = 0`)
  33. if pp != nil && len(*pp) > 0 {
  34. for _, m := range *pp {
  35. sendFlag1 := common.IntAll(m["flag_1"]) //预警邮件发送
  36. sendFlag2 := common.IntAll(m["flag_2"]) //上限邮件发送
  37. posid := common.Int64All(m["position_id"])
  38. count := TiDb.CountBySql(sql, posid)
  39. if count >= cfg.AllocationCap && sendFlag2 == 0 {
  40. ExceedLimitByPp(posid) // 发上限邮件
  41. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail | (1 << 1)"), posid)
  42. } else if count >= cfg.WarningValue && sendFlag1 == 0 && sendFlag2 == 0 {
  43. WillWarningByPp(posid) // 发预警邮件
  44. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail | (1 << 0)"), posid)
  45. } else if sendFlag1 == 1 && count < cfg.WarningValue { // 已发邮件
  46. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail & ~(1 << 0)"), posid)
  47. } else if sendFlag2 == 1 && count < cfg.AllocationCap { // 已发邮件
  48. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail & ~(1 << 1)"), posid)
  49. }
  50. }
  51. }
  52. }
  53. // @Author jianghan
  54. // @Description 部门预警/上限 所有人
  55. // @Date 2024/5/9
  56. func WarningDm() {
  57. sql1 := `UPDATE dwd_f_crm_personnel_management SET send_mail = (%s) where position_id = ?`
  58. dm := TiDb.SelectBySql(dmInfo)
  59. send := true // 所有人
  60. for _, m := range *dm {
  61. d1 := common.ObjToString(m["dept_name"])
  62. send1, send2 := true, true // 预警,上限 发送标记
  63. info := TiDb.SelectBySql(dmInfoCount, d1, cfg.WarningValue)
  64. if info != nil && len(*info) > 0 {
  65. send1 = false
  66. }
  67. info1 := TiDb.SelectBySql(dmInfoCount, d1, cfg.AllocationCap)
  68. if info1 != nil && len(*info1) > 0 {
  69. send2 = false
  70. }
  71. //for _, m1 := range *info {
  72. // count := common.IntAll(m1["num"])
  73. // if count < WarningSize {
  74. // send1 = false
  75. // }
  76. // if count < LimitSize {
  77. // send2 = false
  78. // }
  79. //}
  80. info2 := TiDb.SelectBySql(dmInfoMail, d1)
  81. if info2 == nil || len(*info2) == 0 {
  82. log.Println("未查询到部门领导邮箱", d1)
  83. continue
  84. }
  85. sendFlag1 := common.IntAll((*info2)[0]["flag_1"]) //预警邮件发送
  86. sendFlag2 := common.IntAll((*info2)[0]["flag_2"]) //上限邮件发送
  87. to := getMailAds(common.ObjToString((*info2)[0]["mail"]), common.ObjToString((*info2)[0]["name"]))
  88. posid := common.Int64All((*info2)[0]["position_id"])
  89. var toCc []string // 销管
  90. for _, m2 := range *TiDb.SelectBySql(xgMail) {
  91. if m3 := getMailAds(common.ObjToString(m2["mail"]), common.ObjToString(m2["name"])); m3 != "" {
  92. toCc = append(toCc, m3)
  93. }
  94. }
  95. if d1 != "销售三部" {
  96. toCc = append(toCc, getMailAds("shenbingyi@topnet.net.cn", "沈炳毅"))
  97. }
  98. if send2 && sendFlag2 == 0 { // 上限
  99. ExceedLimitByDm(d1, to, toCc)
  100. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail | (1 << 3)"), posid) // 倒数第四位修改成0
  101. sendFlag2 = 1
  102. } else {
  103. if !send2 && sendFlag2 == 1 {
  104. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail & ~(1 << 3)"), posid) // 倒数第四位修改成1
  105. }
  106. }
  107. if send1 && sendFlag1 == 0 && sendFlag2 == 0 { // 预警
  108. WillWarningByDm(d1, to, toCc)
  109. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail | (1 << 2)"), posid) // 倒数第三位修改成0
  110. } else {
  111. send = false // 所有人
  112. if !send1 && sendFlag1 == 1 {
  113. _, _ = TiDb.ExecBySql(fmt.Sprintf(sql1, "send_mail & ~(1 << 2)"), posid) // 倒数第三位修改成1
  114. }
  115. }
  116. }
  117. if send {
  118. WillWarningByAll()
  119. }
  120. }
  121. // @Author jianghan
  122. // @Description 个人私海线索即将达到预警提醒
  123. // @Date 2024/4/10
  124. func WillWarningByPp(posid int64) {
  125. title := "您的私海线索即将达到上限通知"
  126. content := "您的私海线索已超过%d条(不包含成交客户),即将达到私海线索上限%d条(不包含成交客户),请及时将无需跟进的线索退回公海,以避免无法接收新线索。"
  127. toMail := ""
  128. toCc := ""
  129. info := TiDb.SelectBySql(selfMail, posid)
  130. if info != nil && len(*info) > 0 {
  131. toMail = getMailAds(common.ObjToString((*info)[0]["mail"]), common.ObjToString((*info)[0]["name"]))
  132. }
  133. if toMail == "" {
  134. log.Println("未查询到邮箱地址, position id: ", posid)
  135. return
  136. }
  137. toCc = getCc(posid)
  138. content = fmt.Sprintf(content, cfg.WarningValue, cfg.AllocationCap)
  139. sendInfo(toMail, toCc, title, content)
  140. }
  141. // @Author jianghan
  142. // @Description 部门人员私海线索即将达到预警提醒
  143. // @Date 2024/4/10
  144. func WillWarningByDm(dname, to string, toCc []string) {
  145. title := "“%s”私海线索即将达到上限通知"
  146. content := "“%s”的所有参与线索分配的电销人员,私海线索都已达到%d条(不包含成交客户),即将达到私海线索上限%d条(不包含成交客户),请及时通知电销人员将无需跟进的线索退回公海,以避免无法接收新线索。"
  147. title = fmt.Sprintf(title, dname)
  148. content = fmt.Sprintf(content, dname, cfg.WarningValue, cfg.AllocationCap)
  149. sendInfo(to, strings.Join(toCc, ","), title, content)
  150. }
  151. // @Author jianghan
  152. // @Description 所有人私海线索即将达到预警提醒
  153. // @Date 2024/4/10
  154. func WillWarningByAll() {
  155. title := "所有电销人员私海线索即将达到上限通知"
  156. content := "所有参与线上线索自动分配的电销人员,私海线索都已达到%d条,请及时提醒销售部门将无需跟进的销售线索退回公海"
  157. var to []string // 销管
  158. for _, m2 := range *TiDb.SelectBySql(xgMail) {
  159. if m3 := getMailAds(common.ObjToString(m2["mail"]), common.ObjToString(m2["name"])); m3 != "" {
  160. to = append(to, m3)
  161. }
  162. }
  163. content = fmt.Sprintf(content, cfg.WarningValue)
  164. sendInfo(strings.Join(to, ","), "", title, content)
  165. }
  166. // @Author jianghan
  167. // @Description 个人私海线索达到上限提醒
  168. // @Date 2024/4/10
  169. func ExceedLimitByPp(posid int64) {
  170. title := "您的私海线索已达上限通知"
  171. content := "您的私海线索已达到私海线索上限%d条(不包含成交客户),当前无法接收新线索,请及时将无需跟进的线索退回公海"
  172. toMail := ""
  173. toCc := ""
  174. content = fmt.Sprintf(content, cfg.AllocationCap)
  175. info := TiDb.SelectBySql(selfMail, posid)
  176. if info != nil && len(*info) > 0 {
  177. toMail = getMailAds(common.ObjToString((*info)[0]["mail"]), common.ObjToString((*info)[0]["name"]))
  178. }
  179. if toMail == "" {
  180. log.Println("未查询到邮箱地址, position id: ", posid)
  181. return
  182. }
  183. toCc = getCc(posid)
  184. sendInfo(toMail, toCc, title, content)
  185. }
  186. // @Author jianghan
  187. // @Description 部门所有人私海线索达到上限提醒
  188. // @Date 2024/4/10
  189. func ExceedLimitByDm(dname, to string, toCc []string) {
  190. title := "“%s”私海线索已达到上限通知"
  191. content := "“%s”的所有参与线索分配的电销人员,私海线索都已达到私海线索上限%d条(不包含成交客户),当前无法接收新线索,请及时通知电销人员将无需跟进的线索退回公海"
  192. title = fmt.Sprintf(title, dname)
  193. content = fmt.Sprintf(content, dname, cfg.AllocationCap)
  194. sendInfo(to, strings.Join(toCc, ","), title, content)
  195. }
  196. // @Author jianghan
  197. // @Description 自动释放私海线索通知
  198. // @Date 2024/4/10
  199. func AutoReleaseNots() {
  200. title := "自动释放私海线索通知"
  201. content := "所有参与线上线索自动分配的电销人员,私海线索都已达到%d条,为避免线上产生的新线索无法分配,系统已自动将线索状态为“商机线索(已建联,包含已拨打未接通)”、“潜在客户”、“沉睡客户”的线索退回公海,如有异议请联系销管处理;"
  202. var to []string
  203. for _, m := range *TiDb.SelectBySql(allMail) {
  204. if m1 := getMailAds(common.ObjToString(m["mail"]), common.ObjToString(m["name"])); m1 != "" {
  205. to = append(to, m1)
  206. }
  207. }
  208. var toCc []string // 销管+高级电销经理+超管
  209. for _, m2 := range *TiDb.SelectBySql(xgMail) {
  210. if m3 := getMailAds(common.ObjToString(m2["mail"]), common.ObjToString(m2["name"])); m3 != "" {
  211. toCc = append(toCc, m3)
  212. }
  213. }
  214. for _, m2 := range *TiDb.SelectBySql(cgMail) {
  215. if m3 := getMailAds(common.ObjToString(m2["mail"]), common.ObjToString(m2["name"])); m3 != "" {
  216. toCc = append(toCc, m3)
  217. }
  218. }
  219. toCc = append(toCc, getMailAds("shenbingyi@topnet.net.cn", "沈炳毅"))
  220. sendInfo(strings.Join(to, ","), strings.Join(toCc, ","), title, fmt.Sprintf(content, cfg.AllocationCap))
  221. }
  222. // @Author jianghan
  223. // @Description 线上线索无法分配通知
  224. // @Date 2024/4/10
  225. func CantBeAssignedNots() {
  226. title := "【紧急】线上线索无法分配通知"
  227. content := "所有参与线上线索自动分配的电销人员,私海线索都已达到**条,且私海已无“潜在客户”、“沉睡客户”、“商机线索(已建联)”可释放,当前线上线索无法分配,请尽快处理,可前往【公海线索】查看“待分线索”条数"
  228. var to []string
  229. for _, m := range *TiDb.SelectBySql(allMail) {
  230. if m1 := getMailAds(common.ObjToString(m["mail"]), common.ObjToString(m["name"])); m1 != "" {
  231. to = append(to, m1)
  232. }
  233. }
  234. var toCc []string // 销管+高级电销经理+超管
  235. for _, m2 := range *TiDb.SelectBySql(xgMail) {
  236. if m3 := getMailAds(common.ObjToString(m2["mail"]), common.ObjToString(m2["name"])); m3 != "" {
  237. toCc = append(toCc, m3)
  238. }
  239. }
  240. for _, m2 := range *TiDb.SelectBySql(cgMail) {
  241. if m3 := getMailAds(common.ObjToString(m2["mail"]), common.ObjToString(m2["name"])); m3 != "" {
  242. toCc = append(toCc, m3)
  243. }
  244. }
  245. toCc = append(toCc, getMailAds("shenbingyi@topnet.net.cn", "沈炳毅"))
  246. sendInfo(strings.Join(to, ","), strings.Join(toCc, ","), title, fmt.Sprintf(content, cfg.AllocationCap))
  247. }
  248. // @Author jianghan
  249. // @Description 客成移交线索失败提醒
  250. // @Date 2024/4/10
  251. func HandOverFail(posid int64) {
  252. title := "客成线索移交失败通知"
  253. content := "您的私海线索已超过**条(不包含成交客户),已达到私海线索上限**条(不包含成交客户),导致“XXX线索名称(XXX手机号)”无法从客成到期自动移交至私海,请及时将无需跟进的线索退回公海,超过3个工作日(根据配置获取)不处理,该线索将自动退回至公海"
  254. toMail := ""
  255. toCc := ""
  256. info := TiDb.SelectBySql(selfMail, posid)
  257. if info != nil && len(*info) > 0 {
  258. toMail = getMailAds(common.ObjToString((*info)[0]["mail"]), common.ObjToString((*info)[0]["name"]))
  259. }
  260. if toMail == "" {
  261. log.Println("未查询到邮箱地址, position id: ", posid)
  262. return
  263. }
  264. toCc = getCc(posid)
  265. sendInfo(toMail, toCc, title, content)
  266. }
  267. // @Author jianghan
  268. // @Description 订单用户创建线索失败提醒
  269. // @Date 2024/4/10
  270. func OrderCreateFail(posid int64, bname string) {
  271. title := "订单用户创建线索失败通知"
  272. content := "您的私海线索已超过%d条(不包含成交客户),已达到私海线索上限%d条(不包含成交客户),导致订单系统的用户“%s”无法进入您的私海,请及时将无需跟进的线索退回公海,超过3个工作日不处理,该线索将自动进入至公海。"
  273. toMail := ""
  274. toCc := ""
  275. content = fmt.Sprintf(content, cfg.AllocationCap, cfg.AllocationCap, bname)
  276. info := TiDb.SelectBySql(selfMail, posid)
  277. if info != nil && len(*info) > 0 {
  278. toMail = getMailAds(common.ObjToString((*info)[0]["mail"]), common.ObjToString((*info)[0]["name"]))
  279. }
  280. if toMail == "" {
  281. log.Println("未查询到邮箱地址, position id: ", posid)
  282. return
  283. }
  284. toCc = getCc(posid)
  285. sendInfo(toMail, toCc, title, content)
  286. }
  287. // @Author jianghan
  288. // @Description 非集团公司线索分配失败
  289. // @Date 2024/5/11
  290. func AssFail(posid int64, ent, iname string) {
  291. title := "您跟进的非集团公司线上线索分配失败"
  292. content := "您的私海线索已达到私海线索上限**条(不包含成交客户),导致您正在跟进的非集团公司“%s”产生的新线索“%s”无法进入您的私海,请及时将无需跟进的线索退回公海,退回后联系您的电销经理将此线索再划转至您的私海。"
  293. toMail := ""
  294. toCc := ""
  295. content = fmt.Sprintf(content, cfg.AllocationCap, ent, iname)
  296. info := TiDb.SelectBySql(selfMail, posid)
  297. if info != nil && len(*info) > 0 {
  298. toMail = getMailAds(common.ObjToString((*info)[0]["mail"]), common.ObjToString((*info)[0]["name"]))
  299. }
  300. if toMail == "" {
  301. log.Println("未查询到邮箱地址, position id: ", posid)
  302. return
  303. }
  304. toCc = getCc(posid)
  305. sendInfo(toMail, toCc, title, content)
  306. }
  307. // @Author jianghan
  308. // @Description 发邮件
  309. // @Date 2024/5/8
  310. func sendInfo(to, cs, title, content string) {
  311. if to == "" {
  312. log.Println("send mail fail", title, to)
  313. return
  314. }
  315. log.Println("发送标题", title)
  316. log.Println("发送人:", to)
  317. log.Println("抄送:", cs)
  318. gmail := &mail.GmailAuth{
  319. SmtpHost: "smtp.exmail.qq.com",
  320. SmtpPort: 465,
  321. User: "public03@topnet.net.cn",
  322. Pwd: "ue9Rg9Sf4CVtdm5a",
  323. }
  324. status := mail.GSendMail_dx("剑鱼标讯", to, cs, "", title, content, "", "", gmail)
  325. if status {
  326. log.Println("send mail success", title, to)
  327. }
  328. }
  329. // @Author jianghan
  330. // @Description 获取抄送人员邮箱
  331. //
  332. // 销售三部 (SZ_PID1=5432)、销售一部(分组)
  333. //
  334. // @Date 2024/5/8
  335. func getCc(posid int64) (to string) {
  336. info := TiDb.SelectBySql(infoSelf, posid)
  337. if info == nil && len(*info) == 0 {
  338. log.Println("未查询到个人信息, positionId: ", posid)
  339. return
  340. }
  341. if common.ObjToString((*info)[0]["dept_name"]) == "销售三部" {
  342. if common.IntAll((*info)[0]["role_id"]) == 1 || common.IntAll((*info)[0]["role_id"]) == 2 {
  343. m := TiDb.SelectBySql(topMail3)
  344. if m != nil && len(*m) > 0 {
  345. to = getMailAds(common.ObjToString((*m)[0]["mail"]), common.ObjToString((*m)[0]["name"]))
  346. }
  347. }
  348. } else {
  349. if common.IntAll((*info)[0]["role_id"]) == 1 || common.IntAll((*info)[0]["role_id"]) == 2 {
  350. m := TiDb.SelectBySql(topMail, posid)
  351. if m != nil && len(*m) > 0 {
  352. to = getMailAds(common.ObjToString((*m)[0]["mail"]), common.ObjToString((*m)[0]["name"]))
  353. }
  354. //to = getMailAds("shenbingyi@topnet.net.cn", "沈炳毅")
  355. } else if common.IntAll((*info)[0]["role_id"]) == 3 {
  356. to = getMailAds("shenbingyi@topnet.net.cn", "沈炳毅")
  357. }
  358. }
  359. return
  360. }
  361. // @Author jianghan
  362. // @Description 获取配置文件邮箱地址
  363. // @Date 2024/5/13
  364. func getMailAds(mail, name string) string {
  365. log.Println("getMailAds", name, mail)
  366. if cfg.NameToMail != nil && len(cfg.NameToMail) > 0 {
  367. return cfg.NameToMail[name]
  368. } else {
  369. return mail
  370. }
  371. }