main.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. package main
  2. import (
  3. "database/sql"
  4. "flag"
  5. "fmt"
  6. _ "github.com/sijms/go-ora/v2"
  7. )
  8. //USE main -b test -start 20210101 -end 20220315
  9. var (
  10. odb *sql.DB
  11. brand string
  12. start int64 = 0
  13. end int64 = 0
  14. dbMapUrl = map[string]string{
  15. "ugg": "oracle://bosnds3:Longda2000@ugg.imix7.com:1521/orcl",
  16. "hdugg": "oracle://bosnds3:Longda2000@hdugg.imix7.com:1521/orcl",
  17. "ecco": "oracle://bosnds3:Longda2000@ecco.imix7.com:1521/orcl",
  18. "test": "oracle://bosnds3:Longda2000@qt.imix7.com:1521/test",
  19. }
  20. )
  21. type Number interface {
  22. int64 | int32 | int | string
  23. }
  24. type RetailInfo struct {
  25. Id int64
  26. DocNO string
  27. Vip int64
  28. BillDate int64
  29. Saler int64
  30. }
  31. type Vip struct {
  32. Id int64
  33. Name string
  34. CardNo string
  35. OnlyGuideId int64
  36. Phone string
  37. Openid string
  38. Wechat string
  39. }
  40. type HrEmpp struct {
  41. Id int64
  42. Name string
  43. No string
  44. Phone string // HANDSET
  45. }
  46. //todo 重新生成VIP
  47. func main() {
  48. flag.StringVar(&brand, "b", "", "brand like ugg ecco hdugg")
  49. flag.Int64Var(&start, "start", 0, "like 20210901")
  50. flag.Int64Var(&end, "end", 0, "like 20210901")
  51. flag.Parse()
  52. if brand == "" {
  53. fmt.Println("-b can not emp")
  54. return
  55. }
  56. if start == 0 {
  57. fmt.Println("-start can not emp")
  58. return
  59. }
  60. if end == 0 {
  61. fmt.Println("-end can not emp")
  62. return
  63. }
  64. initDatabase()
  65. rs, _ := GetAllRetail(start, end)
  66. for index, v := range rs {
  67. UpdateVipStatus(v.Vip, v.Saler, v.Id, v.BillDate)
  68. fmt.Println(index)
  69. }
  70. }
  71. func initDatabase() {
  72. dburl, ok := dbMapUrl[brand]
  73. if !ok {
  74. panic("brand error")
  75. }
  76. odb, _ = sql.Open("oracle", dburl)
  77. odb.SetMaxOpenConns(2)
  78. odb.SetMaxIdleConns(2)
  79. err := odb.Ping()
  80. if err != nil {
  81. panic(err)
  82. }
  83. }
  84. func GetVipOne(id int64) (Vip, error) {
  85. var v Vip
  86. sqlStr := `SELECT ID,VIPNAME,CARDNO,NVL(ONLY_GUIDE_ID,-1),MOBIL,NVL(OPENID,'N'),IS_WECHAT FROM C_CLIENT_VIP WHERE ID = :X1 `
  87. smt, err := odb.Prepare(sqlStr)
  88. if err != nil {
  89. return v, err
  90. }
  91. defer smt.Close()
  92. var vid, guide sql.NullInt64
  93. var name, card, phone, oid, ifwecaht sql.NullString
  94. err = smt.QueryRow(id).Scan(&vid, &name, &card, &guide, &phone, &oid, &ifwecaht)
  95. if err != nil {
  96. return v, err
  97. }
  98. v.Id = vid.Int64
  99. v.Name = name.String
  100. v.CardNo = card.String
  101. v.OnlyGuideId = guide.Int64
  102. v.Phone = phone.String
  103. v.Openid = oid.String
  104. v.Wechat = ifwecaht.String
  105. return v, nil
  106. }
  107. //获取所有包含VIP的零售单,零售信息
  108. func GetAllRetail(start, end int64) ([]RetailInfo, error) {
  109. sqlStr := `SELECT ID,DOCNO,C_VIP_ID,SALESREP_ID,BILLDATE FROM M_RETAIL WHERE BILLDATE BETWEEN :X1 AND :X2 AND C_VIP_ID IS NOT NULL AND M_TYPE = 1 ORDER BY ID`
  110. rows, err := odb.Query(sqlStr, start, end)
  111. if err != nil {
  112. return nil, err
  113. }
  114. defer rows.Close()
  115. var ms []RetailInfo
  116. for rows.Next() {
  117. var id, vid, billdate, saler sql.NullInt64
  118. var docno sql.NullString
  119. rows.Scan(&id, &docno, &vid, &saler, &billdate)
  120. var m RetailInfo
  121. m.Id = id.Int64
  122. m.Vip = vid.Int64
  123. m.BillDate = billdate.Int64
  124. m.Saler = saler.Int64
  125. m.DocNO = docno.String
  126. ms = append(ms, m)
  127. }
  128. return ms, nil
  129. }
  130. func GetHrEmpp(id int64) (HrEmpp, error) {
  131. sqlStr := `SELECT ID, NAME,NO,HANDSET FROM HR_EMPLOYEE WHERE ID = :X1`
  132. var name, no, phone sql.NullString
  133. var u HrEmpp
  134. smt, err := odb.Prepare(sqlStr)
  135. if err != nil {
  136. fmt.Println("GetHrEmpp", err)
  137. return u, err
  138. }
  139. defer smt.Close()
  140. err = smt.QueryRow(id).Scan(&u.Id, &name, &no, &phone)
  141. if err != nil {
  142. fmt.Println("GetHrEmpp", err)
  143. return u, err
  144. }
  145. u.Name = name.String
  146. u.No = no.String
  147. u.Phone = phone.String
  148. return u, nil
  149. }
  150. var 是否处理过VIP = make(map[int64]bool)
  151. var 是否已计算纳新 = make(map[int64]struct{})
  152. var 纳新前消费次数 = make(map[int64]int64)
  153. var 纳新后消费次数 = make(map[int64]int64)
  154. func UpdateVipOnlyGuideNull(vip int64) error {
  155. sqlStr := `UPDATE C_CLIENT_VIP SET ONLY_GUIDE_ID = NULL WHERE ID =:X1`
  156. smt, err := odb.Prepare(sqlStr)
  157. if err != nil {
  158. fmt.Println("UpdateVipOnlyGuideNull", err)
  159. return err
  160. }
  161. defer smt.Close()
  162. _, err = smt.Exec(vip)
  163. if err != nil {
  164. fmt.Println("UpdateVipOnlyGuideNull", vip, err)
  165. return err
  166. }
  167. return nil
  168. }
  169. func UpdateVipOnlyGuide(vip, sid int64) error {
  170. sqlStr := `UPDATE C_CLIENT_VIP SET ONLY_GUIDE_ID = :x1 WHERE ID =:X2`
  171. smt, err := odb.Prepare(sqlStr)
  172. if err != nil {
  173. fmt.Println("UpdateVipOnlyGuide", err)
  174. return err
  175. }
  176. defer smt.Close()
  177. _, err = smt.Exec(sid, vip)
  178. if err != nil {
  179. fmt.Println("UpdateVipOnlyGuide", vip, sid, err)
  180. return err
  181. }
  182. return nil
  183. }
  184. func UpdateVipStatus(vid, sid, mid, date int64) {
  185. first := 是否处理过VIP[vid] //第一次处理此VIP
  186. if !first { //没处理过
  187. UpdateVipOnlyGuideNull(vid) //将VIP的专属导购直接清空
  188. 是否处理过VIP[vid] = true //标记已经清空过专属导购
  189. }
  190. vip, err := GetVipOne(vid) //VIP信息
  191. if err != nil {
  192. fmt.Println(err)
  193. return
  194. }
  195. saler, err := GetHrEmpp(sid) //导购信息
  196. if err != nil {
  197. fmt.Println(err)
  198. return
  199. }
  200. if len(vip.Openid) > 15 && !first {
  201. frs := QueryFriendsNum(vip.Openid)
  202. if frs > 0 {
  203. UpdateQywxFriend(vid, "Y")
  204. } else {
  205. UpdateQywxFriend(vid, "N")
  206. }
  207. }
  208. //判断是否已经生成专属导购
  209. if vip.OnlyGuideId == -1 { //专属导购为空
  210. //判断是否满足专属导购
  211. fnum, _ := IfAddQywxFreind(vip.Openid, saler.Phone, date)
  212. if fnum > 0 { //开单今天有加好友
  213. ifDel, delTime, _ := IfDelQywxFreind(vip.Openid, saler.Phone, date)
  214. if !ifDel { //未删除
  215. UpdateVipOnlyGuide(vid, sid) //更新专属导购
  216. UpdateMRetailStatus(mid, "纳新初购")
  217. 纳新后消费次数[vid] = 1
  218. } else { //已删除
  219. if delTime == date { //当日删除
  220. UpdateVipOnlyGuideNull(vid)
  221. num := 纳新前消费次数[vid]
  222. if num > 0 {
  223. UpdateMRetailStatus(mid, "非纳新复购")
  224. } else {
  225. UpdateMRetailStatus(mid, "非纳新初购")
  226. }
  227. 纳新前消费次数[vid] = num + 1
  228. } else { //过后删除
  229. UpdateVipOnlyGuide(vid, 0) //更新专属导购
  230. UpdateMRetailStatus(mid, "纳新初购")
  231. 纳新后消费次数[vid] = 1
  232. }
  233. }
  234. } else {
  235. num := 纳新前消费次数[vid]
  236. if num > 0 {
  237. UpdateMRetailStatus(mid, "非纳新复购")
  238. } else {
  239. UpdateMRetailStatus(mid, "非纳新初购")
  240. }
  241. 纳新前消费次数[vid] = num + 1
  242. }
  243. } else {
  244. if vip.OnlyGuideId == 0 { //专属导购待分配
  245. num := 纳新前消费次数[vid]
  246. if num > 0 {
  247. UpdateMRetailStatus(mid, "非纳新复购")
  248. } else {
  249. UpdateMRetailStatus(mid, "非纳新初购")
  250. }
  251. 纳新前消费次数[vid] = num + 1
  252. } else { //已有专属导购
  253. num := 纳新后消费次数[vid]
  254. if num > 0 {
  255. UpdateMRetailStatus(mid, "纳新复购")
  256. } else {
  257. UpdateMRetailStatus(mid, "纳新初购")
  258. }
  259. 纳新后消费次数[vid] = num + 1
  260. }
  261. }
  262. }
  263. //是否删除,以及删除时间
  264. func IfDelQywxFreind(oid, phone string, date int64) (bool, int64, error) {
  265. sql1 := `select count(*) from qywx_friend where unionid=:x1 and phone =:x2 AND ISACTIVE='Y' AND OK ='N' `
  266. var num int64
  267. smt, err := odb.Prepare(sql1)
  268. if err != nil {
  269. return false, -1, err
  270. }
  271. err = smt.QueryRow(oid, phone).Scan(&num)
  272. if err != nil {
  273. fmt.Println("IfDelQywxFreind", err)
  274. return false, -1, err
  275. }
  276. smt.Close()
  277. if num > 0 {
  278. var num2 int64
  279. sql2 := `select TO_CHAR(MODIFIEDDATE,'YYYYMMDD') from qywx_friend where unionid=:x1 and phone =:x2 AND ISACTIVE='Y' AND OK ='N' `
  280. stm2, err := odb.Prepare(sql2)
  281. if err != nil {
  282. fmt.Println("IfDelQywxFreind", err)
  283. return false, -1, err
  284. }
  285. stm2.QueryRow(oid, phone).Scan(&num2)
  286. stm2.Close()
  287. return true, num2, nil
  288. } else {
  289. return false, date, nil
  290. }
  291. }
  292. //查询会员和导购当日是否添加好友关系
  293. func IfAddQywxFreind(oid, phone string, date int64) (int64, error) {
  294. //先判断是否当日加的
  295. //sql1 := `select count(*) from qywx_friend where unionid=:x1 and phone =:x2 AND ISACTIVE='Y' AND OK ='Y' AND TO_CHAR(MODIFIEDDATE,'YYYYMMDD') <= :x3`
  296. sql1 := `select count(*) from qywx_friend where unionid=:x1 and phone =:x2 AND ISACTIVE='Y' AND TO_CHAR(CREATIONDATE,'YYYYMMDD') <= :x3`
  297. var num int64
  298. smt, err := odb.Prepare(sql1)
  299. if err != nil {
  300. fmt.Println("IfAddQywxFreind", err)
  301. return -1, err
  302. }
  303. defer smt.Close()
  304. err = smt.QueryRow(oid, phone, date).Scan(&num)
  305. if err != nil {
  306. fmt.Println("IfAddQywxFreind", err)
  307. return -1, err
  308. }
  309. return num, nil
  310. }
  311. func UpdateMRetailStatus(mid int64, typ string) error {
  312. sqlStr := `UPDATE M_RETAIL SET VIP_STATUS = :x1 WHERE ID =:x2`
  313. smt, err := odb.Prepare(sqlStr)
  314. if err != nil {
  315. fmt.Println("UpdateMRetailStatus", err)
  316. return err
  317. }
  318. defer smt.Close()
  319. _, err = smt.Exec(typ, mid)
  320. if err != nil {
  321. fmt.Println("UpdateMRetailStatus", mid, typ, err)
  322. return err
  323. }
  324. return err
  325. }
  326. func QueryFriendsNum(UID string) int64 {
  327. sqlStr := `SELECT COUNT(*) FROM QYWX_FRIEND WHERE UNIONID =:X1 AND OK='Y'`
  328. smt, err := odb.Prepare(sqlStr)
  329. if err != nil {
  330. fmt.Println("QueryFriendsNum", err)
  331. return -1
  332. }
  333. defer smt.Close()
  334. var num sql.NullInt64
  335. row := smt.QueryRow(UID)
  336. row.Scan(&num)
  337. return num.Int64
  338. }
  339. func UpdateQywxFriend(vid int64, yesOrNo string) error {
  340. sqlStr := `UPDATE C_CLIENT_VIP SET IF_QYWX = :x1 where id =:x2`
  341. smt, err := odb.Prepare(sqlStr)
  342. if err != nil {
  343. fmt.Println("UpdateQywxFriend", err)
  344. return err
  345. }
  346. defer smt.Close()
  347. _, err = smt.Exec(yesOrNo, vid)
  348. if err != nil {
  349. fmt.Println("UpdateQywxFriend", vid, yesOrNo, err)
  350. return err
  351. }
  352. return nil
  353. }