mysql.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. package pendant
  2. import (
  3. "bytes"
  4. "context"
  5. "database/sql"
  6. "fmt"
  7. "time"
  8. "go-common/app/service/main/usersuit/model"
  9. xsql "go-common/library/database/sql"
  10. "go-common/library/log"
  11. "go-common/library/xstr"
  12. "github.com/pkg/errors"
  13. )
  14. const (
  15. _getGroupOnlineSQL = "SELECT id,name,rank,status,image,image_model,frequency_limit,time_limit FROM pendant_group WHERE status = 1 or id in (30,31) ORDER BY rank"
  16. _getGroupByIDSQL = "SELECT id,name,rank,status,image,image_model,frequency_limit,time_limit FROM pendant_group where id = ?"
  17. _selGIDRefPIDSQL = "SELECT gid,pid FROM pendant_group_ref"
  18. _getPendantInfoSQL = "SELECT id,name,image,image_model,status FROM pendant_info"
  19. _getPendantInfoByIDSQL = "SELECT id,name,image,image_model,status FROM pendant_info where id = ? limit 1"
  20. _getPendantInfosSQL = "SELECT id,name,image,image_model,status,rank FROM pendant_info ORDER BY rank"
  21. _getPendantPriceSQL = "SELECT pid,type,price FROM pendant_price where pid = ? "
  22. _getOrderHistorySQL = "SELECT mid,order_id,pay_id,appid,status,pid,time_length,cost,buy_time,is_callback,callback_time,pay_type FROM user_pendant_order WHERE %s"
  23. _getUserPackageSQL = "SELECT mid,pid,expires,type,status,is_vip FROM user_pendant_pkg WHERE mid = ? AND pid = ? "
  24. _getUserPackageByMidSQL = "SELECT mid,pid,expires,type,status,is_vip FROM user_pendant_pkg WHERE mid = ? AND expires >= ? AND status > 0 ORDER BY mtime DESC"
  25. _countOrderHistorySQL = "SELECT count(1) FROM user_pendant_order WHERE %s"
  26. _getPendantEquipByMidSQL = "SELECT mid,pid,expires FROM user_pendant_equip WHERE mid = ? and expires >= ?"
  27. _getPendantEquipByMidsSQL = "SELECT mid,pid,expires FROM user_pendant_equip WHERE mid IN (%s) and expires >= ?"
  28. _insertPendantPackageSQL = "INSERT INTO user_pendant_pkg(mid,pid,expires,type,status,is_vip) VALUES (?,?,?,?,?,?)"
  29. _insertOrderHistory = "INSERT INTO user_pendant_order(mid,order_id,pay_id,appid,status,pid,time_length,cost,buy_time,is_callback,callback_time,pay_type) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"
  30. _insertOperationSQL = "INSERT INTO pendant_grant_history(mid,pid,source_type,operator_name,operator_action) VALUES (?,?,?,?,?)"
  31. _insertEquipSQL = "INSERT INTO user_pendant_equip(mid,pid,expires) VALUES (?,?,?) ON DUPLICATE KEY UPDATE pid=VALUES(pid),expires=VALUES(expires)"
  32. _updatePackageSQL = "UPDATE user_pendant_pkg %s WHERE mid=? AND pid=?"
  33. _updatePackageExpireSQL = "UPDATE user_pendant_pkg SET status=0 WHERE mid=? AND expires<?"
  34. _updateOrderInfoSQL = "UPDATE user_pendant_order SET status=?,pay_id=?,is_callback=?,callback_time=? WHERE order_id=?"
  35. _updateEquipMIDSQL = "UPDATE user_pendant_equip SET pid=0,expires=0 WHERE mid=?"
  36. )
  37. //PendantGroupInfo return all group info
  38. func (d *Dao) PendantGroupInfo(c context.Context) (res []*model.PendantGroupInfo, err error) {
  39. var row *xsql.Rows
  40. res = make([]*model.PendantGroupInfo, 0)
  41. if row, err = d.db.Query(c, _getGroupOnlineSQL); err != nil {
  42. log.Error("PendantGroupInfo query error %v", err)
  43. return
  44. }
  45. defer row.Close()
  46. for row.Next() {
  47. info := new(model.PendantGroupInfo)
  48. if err = row.Scan(&info.ID, &info.Name, &info.Rank, &info.Status, &info.Image, &info.ImageModel, &info.FrequencyLimit, &info.TimeLimit); err != nil {
  49. log.Error("PendantGroupInfo scan error %v", err)
  50. return
  51. }
  52. res = append(res, info)
  53. }
  54. return
  55. }
  56. // GroupByID return group info by id
  57. func (d *Dao) GroupByID(c context.Context, gid int64) (res *model.PendantGroupInfo, err error) {
  58. var row *xsql.Row
  59. res = new(model.PendantGroupInfo)
  60. row = d.db.QueryRow(c, _getGroupByIDSQL, gid)
  61. if err = row.Scan(&res.ID, &res.Name, &res.Rank, &res.Status, &res.Image, &res.ImageModel, &res.FrequencyLimit, &res.TimeLimit); err != nil {
  62. if err == xsql.ErrNoRows {
  63. res = nil
  64. err = nil
  65. return
  66. }
  67. log.Error("PendantGroupInfo scan error %v", err)
  68. return
  69. }
  70. return
  71. }
  72. // GIDRefPID gid relation of pid .
  73. func (d *Dao) GIDRefPID(c context.Context) (gidMap map[int64][]int64, pidMap map[int64]int64, err error) {
  74. var rows *xsql.Rows
  75. if rows, err = d.db.Query(c, _selGIDRefPIDSQL); err != nil {
  76. err = errors.WithStack(err)
  77. return
  78. }
  79. defer rows.Close()
  80. gidMap = make(map[int64][]int64)
  81. pidMap = make(map[int64]int64)
  82. for rows.Next() {
  83. var gid, pid int64
  84. if err = rows.Scan(&gid, &pid); err != nil {
  85. if err == xsql.ErrNoRows {
  86. gidMap = nil
  87. pidMap = nil
  88. err = nil
  89. return
  90. }
  91. err = errors.WithStack(err)
  92. return
  93. }
  94. pidMap[pid] = gid
  95. gidMap[gid] = append(gidMap[gid], pid)
  96. }
  97. return
  98. }
  99. // PendantList return pendant info
  100. func (d *Dao) PendantList(c context.Context) (res []*model.Pendant, err error) {
  101. var (
  102. row *xsql.Rows
  103. )
  104. res = make([]*model.Pendant, 0)
  105. if row, err = d.db.Query(c, _getPendantInfosSQL); err != nil {
  106. log.Error("PendantInfo query error %v", err)
  107. return
  108. }
  109. defer row.Close()
  110. for row.Next() {
  111. info := new(model.Pendant)
  112. if err = row.Scan(&info.ID, &info.Name, &info.Image, &info.ImageModel, &info.Status, &info.Rank); err != nil {
  113. log.Error("PendantInfo scan error %v", err)
  114. return
  115. }
  116. res = append(res, info)
  117. }
  118. return
  119. }
  120. // Pendants return pendant info by ids
  121. func (d *Dao) Pendants(c context.Context, pids []int64) (res []*model.Pendant, err error) {
  122. var (
  123. row *xsql.Rows
  124. bf bytes.Buffer
  125. )
  126. res = make([]*model.Pendant, 0)
  127. bf.WriteString(_getPendantInfoSQL)
  128. bf.WriteString(" where id in(")
  129. bf.WriteString(xstr.JoinInts(pids))
  130. bf.WriteString(") and status = 1 ORDER BY rank")
  131. if row, err = d.db.Query(c, bf.String()); err != nil {
  132. log.Error("Pendants query error %v", err)
  133. return
  134. }
  135. defer row.Close()
  136. for row.Next() {
  137. info := new(model.Pendant)
  138. if err = row.Scan(&info.ID, &info.Name, &info.Image, &info.ImageModel, &info.Status); err != nil {
  139. log.Error("Pendants scan error %v", err)
  140. return
  141. }
  142. res = append(res, info)
  143. }
  144. return
  145. }
  146. // PendantInfo return pendant info by id
  147. func (d *Dao) PendantInfo(c context.Context, pid int64) (res *model.Pendant, err error) {
  148. var (
  149. row *xsql.Row
  150. )
  151. res = new(model.Pendant)
  152. row = d.db.QueryRow(c, _getPendantInfoByIDSQL, pid)
  153. if err = row.Scan(&res.ID, &res.Name, &res.Image, &res.ImageModel, &res.Status); err != nil {
  154. if err == xsql.ErrNoRows {
  155. res = nil
  156. err = nil
  157. return
  158. }
  159. log.Error("Pendant scan error %v", err)
  160. return
  161. }
  162. return
  163. }
  164. // PendantPrice return pendant price
  165. func (d *Dao) PendantPrice(c context.Context, pid int64) (res map[int64]*model.PendantPrice, err error) {
  166. var row *xsql.Rows
  167. res = make(map[int64]*model.PendantPrice)
  168. if row, err = d.db.Query(c, _getPendantPriceSQL, pid); err != nil {
  169. log.Error("PendantPrice query error %v", err)
  170. return
  171. }
  172. defer row.Close()
  173. for row.Next() {
  174. info := new(model.PendantPrice)
  175. if err = row.Scan(&info.Pid, &info.Type, &info.Price); err != nil {
  176. log.Error("PendantPrice scan error %v", err)
  177. return
  178. }
  179. res[info.Type] = info
  180. }
  181. return
  182. }
  183. // getOrderInfoSQL return a sql string
  184. func (d *Dao) getOrderInfoSQL(c context.Context, arg *model.ArgOrderHistory, tp string) (sql string, values []interface{}) {
  185. values = make([]interface{}, 0, 5)
  186. var cond bytes.Buffer
  187. cond.WriteString("mid = ?")
  188. values = append(values, arg.Mid)
  189. if arg.OrderID != "" {
  190. cond.WriteString(" AND order_id = ?")
  191. values = append(values, arg.OrderID)
  192. }
  193. if arg.Pid != 0 {
  194. cond.WriteString(" AND pid = ?")
  195. values = append(values, arg.Pid)
  196. }
  197. if arg.Status != 0 {
  198. cond.WriteString(" AND status = ?")
  199. values = append(values, arg.Status)
  200. }
  201. if arg.PayType != 0 {
  202. cond.WriteString(" AND pay_type = ?")
  203. values = append(values, arg.PayType)
  204. }
  205. if arg.PayID != "" {
  206. cond.WriteString(" AND pay_id = ?")
  207. values = append(values, arg.PayID)
  208. }
  209. if arg.StartTime != 0 {
  210. cond.WriteString(" AND buy_time >= ?")
  211. values = append(values, arg.StartTime)
  212. }
  213. if arg.EndTime != 0 {
  214. cond.WriteString(" AND buy_time <= ?")
  215. values = append(values, arg.EndTime)
  216. }
  217. if tp == "info" {
  218. cond.WriteString(" order by buy_time DESC LIMIT ?,20")
  219. values = append(values, (arg.Page-1)*20)
  220. sql = fmt.Sprintf(_getOrderHistorySQL, cond.String())
  221. } else if tp == "count" {
  222. sql = fmt.Sprintf(_countOrderHistorySQL, cond.String())
  223. }
  224. return
  225. }
  226. // OrderInfo return order info
  227. func (d *Dao) OrderInfo(c context.Context, arg *model.ArgOrderHistory) (res []*model.PendantOrderInfo, count int64, err error) {
  228. sqlstr, values := d.getOrderInfoSQL(c, arg, "info")
  229. var (
  230. row *xsql.Rows
  231. r *xsql.Row
  232. )
  233. res = make([]*model.PendantOrderInfo, 0)
  234. if row, err = d.db.Query(c, sqlstr, values...); err != nil {
  235. log.Error("PendantOrderInfo query error %v", err)
  236. return
  237. }
  238. defer row.Close()
  239. cstr, values2 := d.getOrderInfoSQL(c, arg, "count")
  240. r = d.db.QueryRow(c, cstr, values2...)
  241. for row.Next() {
  242. info := new(model.PendantOrderInfo)
  243. if err = row.Scan(&info.Mid, &info.OrderID, &info.PayID, &info.AppID, &info.Stauts, &info.Pid, &info.TimeLength, &info.Cost, &info.BuyTime, &info.IsCallback, &info.CallbackTime, &info.PayType); err != nil {
  244. log.Error("PendantOrderInfo scan error %v", err)
  245. return
  246. }
  247. if info.PayType == 3 {
  248. info.PayPrice = info.PayPrice / 100
  249. }
  250. res = append(res, info)
  251. }
  252. err = r.Scan(&count)
  253. if err == xsql.ErrNoRows {
  254. res = nil
  255. err = nil
  256. return
  257. }
  258. return
  259. }
  260. // OrderInfoByID return order info by order id
  261. func (d *Dao) OrderInfoByID(c context.Context, orderID string) (res *model.PendantOrderInfo, err error) {
  262. row := d.db.QueryRow(c, fmt.Sprintf(_getOrderHistorySQL, "order_id=?"), orderID)
  263. res = new(model.PendantOrderInfo)
  264. if err = row.Scan(&res.Mid, &res.OrderID, &res.PayID, &res.AppID, &res.Stauts, &res.Pid, &res.TimeLength, &res.Cost, &res.BuyTime, &res.IsCallback, &res.CallbackTime, &res.PayType); err != nil {
  265. if err == xsql.ErrNoRows {
  266. res = nil
  267. err = nil
  268. return
  269. }
  270. log.Error("OrderInfoByID scan error %v", err)
  271. return
  272. }
  273. return
  274. }
  275. // AddOrderInfo add order log
  276. func (d *Dao) AddOrderInfo(c context.Context, arg *model.PendantOrderInfo) (id int64, err error) {
  277. var res sql.Result
  278. if res, err = d.db.Exec(c, _insertOrderHistory, arg.Mid, arg.OrderID, arg.PayID, arg.AppID, arg.Stauts, arg.Pid, arg.TimeLength, arg.Cost, arg.BuyTime, arg.IsCallback, arg.CallbackTime, arg.PayType); err != nil {
  279. log.Error("AddOrderInfo insert error %v", err)
  280. return
  281. }
  282. return res.LastInsertId()
  283. }
  284. // TxAddOrderInfo add order log
  285. func (d *Dao) TxAddOrderInfo(c context.Context, arg *model.PendantOrderInfo, tx *xsql.Tx) (id int64, err error) {
  286. var res sql.Result
  287. if res, err = tx.Exec(_insertOrderHistory, arg.Mid, arg.OrderID, arg.PayID, arg.AppID, arg.Stauts, arg.Pid, arg.TimeLength, arg.Cost, arg.BuyTime, arg.IsCallback, arg.CallbackTime, arg.PayType); err != nil {
  288. log.Error("TxAddOrderInfo insert error %v", err)
  289. return
  290. }
  291. return res.LastInsertId()
  292. }
  293. // UpdateOrderInfo update order info
  294. func (d *Dao) UpdateOrderInfo(c context.Context, arg *model.PendantOrderInfo) (id int64, err error) {
  295. var res sql.Result
  296. if res, err = d.db.Exec(c, _updateOrderInfoSQL, arg.Stauts, arg.PayID, arg.IsCallback, arg.CallbackTime, arg.OrderID); err != nil {
  297. log.Error("UpdateOrderInfo update error %v", err)
  298. return
  299. }
  300. return res.LastInsertId()
  301. }
  302. // TxUpdateOrderInfo update order info
  303. func (d *Dao) TxUpdateOrderInfo(c context.Context, arg *model.PendantOrderInfo, tx *xsql.Tx) (id int64, err error) {
  304. var res sql.Result
  305. if res, err = tx.Exec(_updateOrderInfoSQL, arg.Stauts, arg.PayID, arg.IsCallback, arg.CallbackTime, arg.OrderID); err != nil {
  306. log.Error("UpdateOrderInfo update error %v", err)
  307. return
  308. }
  309. return res.LastInsertId()
  310. }
  311. // PackageByMid get pendant in user's package
  312. func (d *Dao) PackageByMid(c context.Context, mid int64) (res []*model.PendantPackage, err error) {
  313. var (
  314. row *xsql.Rows
  315. t = time.Now().Unix()
  316. )
  317. res = make([]*model.PendantPackage, 0)
  318. if row, err = d.db.Query(c, _getUserPackageByMidSQL, mid, t); err != nil {
  319. log.Error("Package query error %v", err)
  320. return
  321. }
  322. defer row.Close()
  323. for row.Next() {
  324. info := new(model.PendantPackage)
  325. if err = row.Scan(&info.Mid, &info.Pid, &info.Expires, &info.Type, &info.Status, &info.IsVIP); err != nil {
  326. log.Error("Package scan error %v", err)
  327. return
  328. }
  329. res = append(res, info)
  330. }
  331. return
  332. }
  333. // PackageByID get pendant in user's package
  334. func (d *Dao) PackageByID(c context.Context, mid, pid int64) (res *model.PendantPackage, err error) {
  335. var row *xsql.Row
  336. res = new(model.PendantPackage)
  337. row = d.db.QueryRow(c, _getUserPackageSQL, mid, pid)
  338. if err = row.Scan(&res.Mid, &res.Pid, &res.Expires, &res.Type, &res.Status, &res.IsVIP); err != nil {
  339. if err == xsql.ErrNoRows {
  340. res = nil
  341. err = nil
  342. return
  343. }
  344. log.Error("Package scan error %v", err)
  345. return
  346. }
  347. return
  348. }
  349. // EquipByMid obtain pendant equiped
  350. func (d *Dao) EquipByMid(c context.Context, mid, t int64) (res *model.PendantEquip, noRow bool, err error) {
  351. var row *xsql.Row
  352. res = new(model.PendantEquip)
  353. row = d.db.QueryRow(c, _getPendantEquipByMidSQL, mid, t)
  354. if err = row.Scan(&res.Mid, &res.Pid, &res.Expires); err != nil {
  355. if err == xsql.ErrNoRows {
  356. noRow = true
  357. res = nil
  358. err = nil
  359. return
  360. }
  361. err = errors.WithStack(err)
  362. }
  363. return
  364. }
  365. // EquipByMids obtain equipss by mids .
  366. func (d *Dao) EquipByMids(c context.Context, mids []int64, t int64) (res map[int64]*model.PendantEquip, err error) {
  367. res = make(map[int64]*model.PendantEquip)
  368. rows, err := d.db.Query(c, fmt.Sprintf(_getPendantEquipByMidsSQL, xstr.JoinInts(mids)), t)
  369. if err != nil {
  370. err = errors.WithStack(err)
  371. return
  372. }
  373. defer rows.Close()
  374. for rows.Next() {
  375. pe := &model.PendantEquip{}
  376. if err = rows.Scan(&pe.Mid, &pe.Pid, &pe.Expires); err != nil {
  377. if err == xsql.ErrNoRows {
  378. err = nil
  379. return
  380. }
  381. err = errors.WithStack(err)
  382. }
  383. if _, ok := res[pe.Mid]; !ok {
  384. res[pe.Mid] = pe
  385. }
  386. }
  387. err = rows.Err()
  388. return
  389. }
  390. // AddEquip add equip
  391. func (d *Dao) AddEquip(c context.Context, arg *model.PendantEquip) (n int64, err error) {
  392. var res sql.Result
  393. if res, err = d.db.Exec(c, _insertEquipSQL, arg.Mid, arg.Pid, arg.Expires); err != nil {
  394. return 0, err
  395. }
  396. return res.RowsAffected()
  397. }
  398. // UpEquipMID uninstall user pid by mid.
  399. func (d *Dao) UpEquipMID(c context.Context, mid int64) (n int64, err error) {
  400. var res sql.Result
  401. if res, err = d.db.Exec(c, _updateEquipMIDSQL, mid); err != nil {
  402. return 0, err
  403. }
  404. return res.RowsAffected()
  405. }
  406. // TxUpdatePackageInfo update package info
  407. func (d *Dao) TxUpdatePackageInfo(c context.Context, arg *model.PendantPackage, tx *xsql.Tx) (n int64, err error) {
  408. var (
  409. bf bytes.Buffer
  410. values = make([]interface{}, 0, 4)
  411. res sql.Result
  412. )
  413. if arg.Status != 0 && arg.Expires != 0 {
  414. bf.WriteString("SET status=?,expires=?,type=?")
  415. values = append(values, arg.Status)
  416. values = append(values, arg.Expires)
  417. values = append(values, arg.Type)
  418. } else if arg.Status != 0 {
  419. bf.WriteString("SET status=?,type=?")
  420. values = append(values, arg.Status)
  421. values = append(values, arg.Type)
  422. } else if arg.Expires != 0 {
  423. bf.WriteString("SET expires=?,type=?")
  424. values = append(values, arg.Expires)
  425. values = append(values, arg.Type)
  426. }
  427. values = append(values, arg.Mid)
  428. values = append(values, arg.Pid)
  429. if res, err = tx.Exec(fmt.Sprintf(_updatePackageSQL, bf.String()), values...); err != nil {
  430. log.Error("TxUpdatePackageInfo update error %v", err)
  431. return
  432. }
  433. return res.RowsAffected()
  434. }
  435. // CheckPackageExpire check expire items and update
  436. func (d *Dao) CheckPackageExpire(c context.Context, mid, expires int64) (rows int64, err error) {
  437. var res sql.Result
  438. if res, err = d.db.Exec(c, _updatePackageExpireSQL, mid, expires); err != nil {
  439. log.Error("CheckPackageExpire error %v", err)
  440. return
  441. }
  442. return res.RowsAffected()
  443. }
  444. // BeginTran begin a tx.
  445. func (d *Dao) BeginTran(c context.Context) (res *xsql.Tx, err error) {
  446. if res, err = d.db.Begin(c); err != nil || res == nil {
  447. log.Error("BeginTran error %v", err)
  448. return
  449. }
  450. return
  451. }
  452. // TxAddPackage add a pendant in package
  453. func (d *Dao) TxAddPackage(c context.Context, arg *model.PendantPackage, tx *xsql.Tx) (id int64, err error) {
  454. var res sql.Result
  455. if res, err = tx.Exec(_insertPendantPackageSQL, arg.Mid, arg.Pid, arg.Expires, arg.Type, arg.Status, arg.IsVIP); err != nil {
  456. log.Error("TxAddPackage insert error %v", err)
  457. return
  458. }
  459. return res.LastInsertId()
  460. }
  461. // TxAddHistory add a history of operation
  462. func (d *Dao) TxAddHistory(c context.Context, arg *model.PendantHistory, tx *xsql.Tx) (id int64, err error) {
  463. var res sql.Result
  464. if res, err = tx.Exec(_insertOperationSQL, arg.Mid, arg.Pid, arg.SourceType, arg.OperatorName, arg.OperatorAction); err != nil {
  465. log.Error("TxAddHistory insert error %v", err)
  466. return
  467. }
  468. return res.LastInsertId()
  469. }