mysql.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. package dao
  2. import (
  3. "bytes"
  4. "context"
  5. xsql "database/sql"
  6. "fmt"
  7. "strconv"
  8. "time"
  9. "go-common/app/job/main/coupon/model"
  10. "go-common/library/database/sql"
  11. "go-common/library/xstr"
  12. "github.com/pkg/errors"
  13. )
  14. const (
  15. _updateStateSQL = "UPDATE `coupon_info_%02d` SET `state` = ?,`use_ver` = ?,`ver` = ? WHERE `coupon_token` = ? AND `ver` = ?;"
  16. _couponByTokenSQL = "SELECT `id`,`coupon_token`,`mid`,`state`,`start_time`,`expire_time`,`origin`,`coupon_type`,`order_no`,`oid`,`remark`,`use_ver`,`ver`,`ctime`,`mtime` FROM `coupon_info_%02d` WHERE `coupon_token` = ?;"
  17. _couponsSQL = "SELECT `id`,`coupon_token`,`mid`,`state`,`start_time`,`expire_time`,`origin`,`coupon_type`,`order_no`,`oid`,`remark`,`use_ver`,`ver`,`ctime`,`mtime` FROM `coupon_info_%02d` WHERE `state` = ? AND `mtime` > ?;"
  18. _addCouponChangeLogSQL = "INSERT INTO `coupon_change_log_%02d` (`coupon_token`,`mid`,`state`,`ctime`) VALUES(?,?,?,?);"
  19. // balance coupon
  20. _byOrderNoSQL = "SELECT `id`,`order_no`,`mid`,`count`,`state`,`coupon_type`,`third_trade_no`,`remark`,`tips`,`use_ver`,`ver`,`ctime`,`mtime` FROM `coupon_order` WHERE `order_no` = ?;"
  21. _updateOrderSQL = "UPDATE `coupon_order` SET `state` = ?,`use_ver` =?,`ver` = ? WHERE `order_no` = ? AND `ver` = ?;"
  22. _addOrderLogSQL = "INSERT INTO `coupon_order_log`(`order_no`,`mid`,`state`,`ctime`)VALUES(?,?,?,?);"
  23. _consumeCouponLogSQL = "SELECT `id`,`order_no`,`mid`,`batch_token`,`balance`,`change_balance`,`change_type`,`ctime`,`mtime` FROM `coupon_balance_change_log_%02d` WHERE `order_no` = ? AND `change_type` = ?;"
  24. _byMidAndBatchTokenSQL = "SELECT `id`,`batch_token`,`mid`,`balance`,`start_time`,`expire_time`,`origin`,`coupon_type`,`ver`,`ctime`,`mtime` FROM `coupon_balance_info_%02d` WHERE `mid` = ? AND `batch_token` = ? ;"
  25. _inPayOrderSQL = "SELECT `id`,`order_no`,`mid`,`count`,`state`,`coupon_type`,`third_trade_no`,`remark`,`tips`,`use_ver`,`ver`,`ctime`,`mtime` FROM `coupon_order` WHERE `state` = ? AND `mtime` > ?;"
  26. _batchUpdateBalance = "UPDATE `coupon_balance_info_%02d` SET `ver` =`ver` + 1, `balance` = CASE id"
  27. _addBalanceLogSQL = "INSERT INTO `coupon_balance_change_log_%02d`(`order_no`,`mid`,`batch_token`,`balance`,`change_balance`,`change_type`,`ctime`)VALUES "
  28. _couponBlancesSQL = "SELECT `id`,`batch_token`,`mid`,`balance`,`start_time`,`expire_time`,`origin`,`coupon_type`,`ver`,`ctime`,`mtime` FROM `coupon_balance_info_%02d` WHERE `mid` = ? AND `coupon_type` = ?;"
  29. _updateBlanceSQL = "UPDATE `coupon_balance_info_%02d` SET `balance` = ?,`ver` = `ver` + 1 WHERE `id` = ? AND `ver` = ?;"
  30. _updateUserCardSQL = "UPDATE coupon_user_card SET state=? WHERE mid=? AND coupon_token=? AND batch_token=?"
  31. )
  32. func hitInfo(mid int64) int64 {
  33. return mid % 100
  34. }
  35. func hitChangeLog(mid int64) int64 {
  36. return mid % 100
  37. }
  38. func hitUser(mid int64) int64 {
  39. return mid % 10
  40. }
  41. func hitUserLog(mid int64) int64 {
  42. return mid % 10
  43. }
  44. // UpdateCoupon update coupon in use.
  45. func (d *Dao) UpdateCoupon(c context.Context, tx *sql.Tx, mid int64, state int8, useVer int64, ver int64, couponToken string) (a int64, err error) {
  46. var res xsql.Result
  47. if res, err = tx.Exec(fmt.Sprintf(_updateStateSQL, hitInfo(mid)), state, useVer, ver+1, couponToken, ver); err != nil {
  48. err = errors.WithStack(err)
  49. return
  50. }
  51. if a, err = res.RowsAffected(); err != nil {
  52. err = errors.WithStack(err)
  53. return
  54. }
  55. return
  56. }
  57. // CouponInfo coupon info.
  58. func (d *Dao) CouponInfo(c context.Context, mid int64, token string) (r *model.CouponInfo, err error) {
  59. var row *sql.Row
  60. r = &model.CouponInfo{}
  61. row = d.db.QueryRow(c, fmt.Sprintf(_couponByTokenSQL, hitInfo(mid)), token)
  62. if err = row.Scan(&r.ID, &r.CouponToken, &r.Mid, &r.State, &r.StartTime, &r.ExpireTime, &r.Origin, &r.CouponType, &r.OrderNO, &r.Oid, &r.Remark,
  63. &r.UseVer, &r.Ver, &r.CTime, &r.MTime); err != nil {
  64. if err == xsql.ErrNoRows {
  65. err = nil
  66. r = nil
  67. return
  68. }
  69. err = errors.WithStack(err)
  70. return
  71. }
  72. return
  73. }
  74. // CouponList query .
  75. func (d *Dao) CouponList(c context.Context, index int64, state int8, t time.Time) (res []*model.CouponInfo, err error) {
  76. var rows *sql.Rows
  77. if rows, err = d.db.Query(c, fmt.Sprintf(_couponsSQL, hitInfo(index)), state, t); err != nil {
  78. err = errors.WithStack(err)
  79. return
  80. }
  81. defer rows.Close()
  82. for rows.Next() {
  83. r := &model.CouponInfo{}
  84. if err = rows.Scan(&r.ID, &r.CouponToken, &r.Mid, &r.State, &r.StartTime, &r.ExpireTime, &r.Origin, &r.CouponType, &r.OrderNO, &r.Oid, &r.Remark,
  85. &r.UseVer, &r.Ver, &r.CTime, &r.MTime); err != nil {
  86. err = errors.WithStack(err)
  87. res = nil
  88. return
  89. }
  90. res = append(res, r)
  91. }
  92. err = rows.Err()
  93. return
  94. }
  95. //InsertPointHistory .
  96. func (d *Dao) InsertPointHistory(c context.Context, tx *sql.Tx, l *model.CouponChangeLog) (a int64, err error) {
  97. var res xsql.Result
  98. if res, err = tx.Exec(fmt.Sprintf(_addCouponChangeLogSQL, hitChangeLog(l.Mid)), l.CouponToken, l.Mid, l.State, l.Ctime); err != nil {
  99. err = errors.WithStack(err)
  100. return
  101. }
  102. if a, err = res.RowsAffected(); err != nil {
  103. err = errors.WithStack(err)
  104. }
  105. return
  106. }
  107. // BeginTran begin transaction.
  108. func (d *Dao) BeginTran(c context.Context) (*sql.Tx, error) {
  109. return d.db.Begin(c)
  110. }
  111. // ByOrderNo query order by order no.
  112. func (d *Dao) ByOrderNo(c context.Context, orderNo string) (r *model.CouponOrder, err error) {
  113. var row *sql.Row
  114. r = &model.CouponOrder{}
  115. row = d.db.QueryRow(c, _byOrderNoSQL, orderNo)
  116. if err = row.Scan(&r.ID, &r.OrderNo, &r.Mid, &r.Count, &r.State, &r.CouponType, &r.ThirdTradeNo, &r.Remark, &r.Tips, &r.UseVer, &r.Ver, &r.Ctime, &r.Mtime); err != nil {
  117. if err == sql.ErrNoRows {
  118. err = nil
  119. r = nil
  120. return
  121. }
  122. err = errors.WithStack(err)
  123. return
  124. }
  125. return
  126. }
  127. // UpdateOrderState update order state.
  128. func (d *Dao) UpdateOrderState(c context.Context, tx *sql.Tx, mid int64, state int8, useVer int64, ver int64, orderNo string) (a int64, err error) {
  129. var res xsql.Result
  130. if res, err = tx.Exec(_updateOrderSQL, state, useVer, ver+1, orderNo, ver); err != nil {
  131. err = errors.WithStack(err)
  132. return
  133. }
  134. if a, err = res.RowsAffected(); err != nil {
  135. err = errors.WithStack(err)
  136. return
  137. }
  138. return
  139. }
  140. // AddOrderLog add order log.
  141. func (d *Dao) AddOrderLog(c context.Context, tx *sql.Tx, o *model.CouponOrderLog) (a int64, err error) {
  142. var res xsql.Result
  143. if res, err = tx.Exec(_addOrderLogSQL, o.OrderNo, o.Mid, o.State, o.Ctime); err != nil {
  144. err = errors.WithStack(err)
  145. return
  146. }
  147. if a, err = res.RowsAffected(); err != nil {
  148. err = errors.WithStack(err)
  149. }
  150. return
  151. }
  152. // ConsumeCouponLog consume coupon log.
  153. func (d *Dao) ConsumeCouponLog(c context.Context, mid int64, orderNo string, ct int8) (rs []*model.CouponBalanceChangeLog, err error) {
  154. var rows *sql.Rows
  155. if rows, err = d.db.Query(c, fmt.Sprintf(_consumeCouponLogSQL, hitUserLog(mid)), orderNo, ct); err != nil {
  156. err = errors.WithStack(err)
  157. return
  158. }
  159. defer rows.Close()
  160. for rows.Next() {
  161. r := &model.CouponBalanceChangeLog{}
  162. if err = rows.Scan(&r.ID, &r.OrderNo, &r.Mid, &r.BatchToken, &r.Balance, &r.ChangeBalance, &r.ChangeType, &r.Ctime, &r.Mtime); err != nil {
  163. err = errors.WithStack(err)
  164. rs = nil
  165. return
  166. }
  167. rs = append(rs, r)
  168. }
  169. err = rows.Err()
  170. return
  171. }
  172. // ByMidAndBatchToken query coupon by batch token and mid.
  173. func (d *Dao) ByMidAndBatchToken(c context.Context, mid int64, batchToken string) (r *model.CouponBalanceInfo, err error) {
  174. var row *sql.Row
  175. r = &model.CouponBalanceInfo{}
  176. row = d.db.QueryRow(c, fmt.Sprintf(_byMidAndBatchTokenSQL, hitUser(mid)), mid, batchToken)
  177. if err = row.Scan(&r.ID, &r.BatchToken, &r.Mid, &r.Balance, &r.StartTime, &r.ExpireTime, &r.Origin, &r.CouponType, &r.Ver, &r.CTime, &r.MTime); err != nil {
  178. if err == sql.ErrNoRows {
  179. err = nil
  180. r = nil
  181. return
  182. }
  183. err = errors.WithStack(err)
  184. return
  185. }
  186. return
  187. }
  188. // UpdateBlance update blance.
  189. func (d *Dao) UpdateBlance(c context.Context, tx *sql.Tx, id int64, mid int64, ver int64, balance int64) (a int64, err error) {
  190. var res xsql.Result
  191. if res, err = tx.Exec(fmt.Sprintf(_updateBlanceSQL, hitUser(mid)), balance, id, ver); err != nil {
  192. err = errors.WithStack(err)
  193. return
  194. }
  195. if a, err = res.RowsAffected(); err != nil {
  196. err = errors.WithStack(err)
  197. return
  198. }
  199. return
  200. }
  201. // OrderInPay order in pay.
  202. func (d *Dao) OrderInPay(c context.Context, state int8, t time.Time) (res []*model.CouponOrder, err error) {
  203. var rows *sql.Rows
  204. if rows, err = d.db.Query(c, _inPayOrderSQL, state, t); err != nil {
  205. err = errors.WithStack(err)
  206. return
  207. }
  208. defer rows.Close()
  209. for rows.Next() {
  210. r := &model.CouponOrder{}
  211. if err = rows.Scan(&r.ID, &r.OrderNo, &r.Mid, &r.Count, &r.State, &r.CouponType, &r.ThirdTradeNo, &r.Remark, &r.Tips, &r.UseVer,
  212. &r.Ver, &r.Ctime, &r.Mtime); err != nil {
  213. if err == sql.ErrNoRows {
  214. err = nil
  215. res = nil
  216. return
  217. }
  218. err = errors.WithStack(err)
  219. return
  220. }
  221. res = append(res, r)
  222. }
  223. err = rows.Err()
  224. return
  225. }
  226. // BatchUpdateBlance batch update blance.
  227. func (d *Dao) BatchUpdateBlance(c context.Context, tx *sql.Tx, mid int64, blances []*model.CouponBalanceInfo) (a int64, err error) {
  228. var (
  229. res xsql.Result
  230. buf bytes.Buffer
  231. ids []int64
  232. )
  233. buf.WriteString(fmt.Sprintf(_batchUpdateBalance, hitUser(mid)))
  234. for _, v := range blances {
  235. buf.WriteString(" WHEN ")
  236. buf.WriteString(strconv.FormatInt(v.ID, 10))
  237. buf.WriteString(" THEN ")
  238. buf.WriteString(strconv.FormatInt(v.Balance, 10))
  239. ids = append(ids, v.ID)
  240. }
  241. buf.WriteString(" END WHERE `id` in (")
  242. buf.WriteString(xstr.JoinInts(ids))
  243. buf.WriteString(") AND `ver` = CASE id ")
  244. for _, v := range blances {
  245. buf.WriteString(" WHEN ")
  246. buf.WriteString(strconv.FormatInt(v.ID, 10))
  247. buf.WriteString(" THEN ")
  248. buf.WriteString(strconv.FormatInt(v.Ver, 10))
  249. }
  250. buf.WriteString(" END;")
  251. if res, err = tx.Exec(buf.String()); err != nil {
  252. err = errors.WithStack(err)
  253. return
  254. }
  255. if a, err = res.RowsAffected(); err != nil {
  256. err = errors.WithStack(err)
  257. return
  258. }
  259. return
  260. }
  261. // BatchInsertBlanceLog Batch Insert Balance log
  262. func (d *Dao) BatchInsertBlanceLog(c context.Context, tx *sql.Tx, mid int64, ls []*model.CouponBalanceChangeLog) (a int64, err error) {
  263. var (
  264. buf bytes.Buffer
  265. res xsql.Result
  266. sql string
  267. )
  268. buf.WriteString(fmt.Sprintf(_addBalanceLogSQL, hitUserLog(mid)))
  269. for _, v := range ls {
  270. buf.WriteString("('")
  271. buf.WriteString(v.OrderNo)
  272. buf.WriteString("',")
  273. buf.WriteString(strconv.FormatInt(v.Mid, 10))
  274. buf.WriteString(",'")
  275. buf.WriteString(v.BatchToken)
  276. buf.WriteString("',")
  277. buf.WriteString(strconv.FormatInt(v.Balance, 10))
  278. buf.WriteString(",")
  279. buf.WriteString(strconv.FormatInt(v.ChangeBalance, 10))
  280. buf.WriteString(",")
  281. buf.WriteString(strconv.Itoa(int(v.ChangeType)))
  282. buf.WriteString(",'")
  283. buf.WriteString(fmt.Sprintf("%v", v.Ctime.Time().Format("2006-01-02 15:04:05")))
  284. buf.WriteString("'),")
  285. }
  286. sql = buf.String()
  287. if res, err = tx.Exec(sql[0 : len(sql)-1]); err != nil {
  288. err = errors.WithStack(err)
  289. return
  290. }
  291. if a, err = res.RowsAffected(); err != nil {
  292. err = errors.WithStack(err)
  293. }
  294. return
  295. }
  296. // BlanceList user balance by mid.
  297. func (d *Dao) BlanceList(c context.Context, mid int64, ct int8) (res []*model.CouponBalanceInfo, err error) {
  298. var rows *sql.Rows
  299. if rows, err = d.db.Query(c, fmt.Sprintf(_couponBlancesSQL, hitUser(mid)), mid, ct); err != nil {
  300. err = errors.WithStack(err)
  301. return
  302. }
  303. defer rows.Close()
  304. for rows.Next() {
  305. r := &model.CouponBalanceInfo{}
  306. if err = rows.Scan(&r.ID, &r.BatchToken, &r.Mid, &r.Balance, &r.StartTime, &r.ExpireTime, &r.Origin, &r.CouponType, &r.Ver, &r.CTime, &r.MTime); err != nil {
  307. err = errors.WithStack(err)
  308. res = nil
  309. return
  310. }
  311. res = append(res, r)
  312. }
  313. err = rows.Err()
  314. return
  315. }
  316. // UpdateUserCard .
  317. func (d *Dao) UpdateUserCard(c context.Context, mid int64, state int8, couponToken, batchToken string) (a int64, err error) {
  318. var res xsql.Result
  319. if res, err = d.db.Exec(c, _updateUserCardSQL, state, mid, couponToken, batchToken); err != nil {
  320. err = errors.WithStack(err)
  321. return
  322. }
  323. if a, err = res.RowsAffected(); err != nil {
  324. err = errors.WithStack(err)
  325. return
  326. }
  327. return
  328. }