allowance.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. package service
  2. import (
  3. "context"
  4. "encoding/csv"
  5. "fmt"
  6. "mime/multipart"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "go-common/app/admin/main/coupon/model"
  11. "go-common/library/database/sql"
  12. "go-common/library/ecode"
  13. "go-common/library/log"
  14. xtime "go-common/library/time"
  15. "github.com/pkg/errors"
  16. )
  17. // AddAllowanceBatchInfo add allowance batch info.
  18. func (s *Service) AddAllowanceBatchInfo(c context.Context, b *model.CouponBatchInfo) (token string, err error) {
  19. if b.ExpireDay < 0 && (b.StartTime <= 0 && b.ExpireTime <= 0) {
  20. err = ecode.CouponExpireErr
  21. return
  22. }
  23. if b.ExpireDay < 0 && b.StartTime >= b.ExpireTime {
  24. err = ecode.CouPonBatchTimeErr
  25. return
  26. }
  27. if b.Amount >= b.FullAmount {
  28. err = ecode.CouponAmountErr
  29. return
  30. }
  31. b.BatchToken = s.token()
  32. b.Ctime = xtime.Time(time.Now().Unix())
  33. if _, err = s.dao.AddAllowanceBatchInfo(c, b); err != nil {
  34. err = errors.WithStack(err)
  35. }
  36. token = b.BatchToken
  37. return
  38. }
  39. //UpdateAllowanceBatchInfo update allowance batch info.
  40. func (s *Service) UpdateAllowanceBatchInfo(c context.Context, b *model.CouponBatchInfo) (err error) {
  41. if _, err = s.dao.UpdateAllowanceBatchInfo(c, b); err != nil {
  42. err = errors.WithStack(err)
  43. }
  44. return
  45. }
  46. //UpdateCodeBatchInfo update code batch info.
  47. func (s *Service) UpdateCodeBatchInfo(c context.Context, b *model.CouponBatchInfo) (err error) {
  48. var data *model.CouponBatchInfo
  49. if data, err = s.BatchInfoByID(c, b.ID); err != nil {
  50. return
  51. }
  52. if data == nil || batchState(data) != model.CodeBatchUsable {
  53. return ecode.RequestErr
  54. }
  55. if _, err = s.dao.UpdateCodeBatchInfo(c, b); err != nil {
  56. err = errors.WithStack(err)
  57. }
  58. return
  59. }
  60. //UpdateBatchStatus update batch status.
  61. func (s *Service) UpdateBatchStatus(c context.Context, status int8, operator string, id int64) (err error) {
  62. var data *model.CouponBatchInfo
  63. if data, err = s.BatchInfoByID(c, id); err != nil {
  64. return
  65. }
  66. if data == nil ||
  67. (status == model.CodeBatchBlock && batchState(data) != model.CodeBatchUsable) ||
  68. (status == model.CodeBatchUsable && batchState(data) != model.CodeBatchBlock) {
  69. return ecode.RequestErr
  70. }
  71. if _, err = s.dao.UpdateBatchStatus(c, status, operator, id); err != nil {
  72. err = errors.WithStack(err)
  73. }
  74. return
  75. }
  76. //BatchInfo allowance batch info.
  77. func (s *Service) BatchInfo(c context.Context, token string) (res *model.CouponBatchInfo, err error) {
  78. if res, err = s.dao.BatchInfo(c, token); err != nil {
  79. err = errors.WithStack(err)
  80. }
  81. return
  82. }
  83. //BatchInfoByID allowance batch info.
  84. func (s *Service) BatchInfoByID(c context.Context, id int64) (*model.CouponBatchInfo, error) {
  85. return s.dao.BatchInfoByID(c, id)
  86. }
  87. // AllowanceSalary allowance salary.
  88. func (s *Service) AllowanceSalary(c context.Context, f multipart.File, h *multipart.FileHeader, mids []int64, token, msgType string) (count int, err error) {
  89. var bi *model.CouponBatchInfo
  90. if len(mids) == 0 {
  91. if mids, err = s.ReadCsv(f, h); err != nil {
  92. err = errors.WithStack(err)
  93. return
  94. }
  95. }
  96. if len(mids) == 0 {
  97. err = ecode.CouponBatchSalaryCountZeroErr
  98. return
  99. }
  100. if len(mids) > _maxSalaryCount {
  101. err = ecode.CouponBatchSalaryLimitErr
  102. return
  103. }
  104. if bi, err = s.dao.BatchInfo(c, token); err != nil {
  105. err = errors.WithStack(err)
  106. return
  107. }
  108. if bi == nil {
  109. err = ecode.CouPonTokenNotFoundErr
  110. return
  111. }
  112. if bi.State != model.BatchStateNormal {
  113. err = ecode.CouPonHadBlockErr
  114. return
  115. }
  116. if bi.ExpireDay < 0 && bi.ExpireTime < time.Now().Unix() {
  117. err = ecode.CouponBatchExpireTimeErr
  118. return
  119. }
  120. if bi.MaxCount != _notLimitSalary && len(mids) > int(bi.MaxCount-bi.CurrentCount) {
  121. err = ecode.CouponBatchSalaryLimitErr
  122. return
  123. }
  124. s.RunSalaryCoupon(c, mids, token, bi.AppID, model.CouponAllowance, model.AdminSalaryOrigin, msgType)
  125. count = len(mids)
  126. return
  127. }
  128. // ReadCsv read csv file
  129. func (s *Service) ReadCsv(f multipart.File, h *multipart.FileHeader) (mids []int64, err error) {
  130. var (
  131. mid int64
  132. records [][]string
  133. )
  134. mids = []int64{}
  135. defer f.Close()
  136. if h != nil && !strings.HasSuffix(h.Filename, ".csv") {
  137. err = ecode.CouponUpdateFileErr
  138. return
  139. }
  140. r := csv.NewReader(f)
  141. records, err = r.ReadAll()
  142. if err != nil {
  143. err = errors.WithStack(err)
  144. return
  145. }
  146. for _, v := range records {
  147. if len(v) <= 0 {
  148. continue
  149. }
  150. if mid, err = strconv.ParseInt(v[0], 10, 64); err != nil {
  151. err = errors.WithStack(err)
  152. break
  153. }
  154. mids = append(mids, mid)
  155. }
  156. return
  157. }
  158. // //AllowancePage allowance page.
  159. // func (s *Service) AllowancePage(c context.Context, arg *model.ArgAllowanceSearch) (res *model.PageCouponInfo, err error) {
  160. // var page *model.SearchData
  161. // res = &model.PageCouponInfo{}
  162. // if page, err = s.dao.AllowancePage(c, arg); err != nil {
  163. // err = errors.WithStack(err)
  164. // return
  165. // }
  166. // if page != nil && page.Data != nil && page.Data.Page != nil {
  167. // res.Count = page.Data.Page.Total
  168. // res.Item = page.Data.Result
  169. // }
  170. // return
  171. // }
  172. //AllowanceList allowance list.
  173. func (s *Service) AllowanceList(c context.Context, arg *model.ArgAllowanceSearch) (res []*model.CouponAllowanceInfo, err error) {
  174. if res, err = s.dao.AllowanceList(c, arg); err != nil {
  175. err = errors.WithStack(err)
  176. }
  177. for _, v := range res {
  178. if v.State == model.NotUsed && v.ExpireTime < time.Now().Unix() {
  179. v.State = model.Expire
  180. }
  181. }
  182. return
  183. }
  184. //UpdateAllowanceState update allowance state.
  185. func (s *Service) UpdateAllowanceState(c context.Context, mid int64, state int8, token string) (err error) {
  186. var (
  187. cp *model.CouponAllowanceInfo
  188. changeType int8
  189. )
  190. if cp, err = s.dao.AllowanceByToken(c, mid, token); err != nil {
  191. err = errors.WithStack(err)
  192. return
  193. }
  194. if cp == nil {
  195. err = ecode.CouPonTokenNotFoundErr
  196. return
  197. }
  198. if state == model.Block {
  199. changeType = model.AllowanceBlock
  200. } else {
  201. changeType = model.AllowanceUnBlock
  202. }
  203. if err = s.UpdateAllowanceCoupon(c, mid, state, token, cp.Ver, changeType, cp); err != nil {
  204. err = errors.WithStack(err)
  205. }
  206. return
  207. }
  208. // UpdateAllowanceCoupon update coupon info.
  209. func (s *Service) UpdateAllowanceCoupon(c context.Context, mid int64, state int8, token string, ver int64, changeType int8, cp *model.CouponAllowanceInfo) (err error) {
  210. var (
  211. tx *sql.Tx
  212. aff int64
  213. )
  214. if tx, err = s.dao.BeginTran(c); err != nil {
  215. log.Error("%+v", err)
  216. return
  217. }
  218. defer func() {
  219. if err != nil {
  220. if err1 := tx.Rollback(); err1 != nil {
  221. log.Error("tx.Rollback %+v", err1)
  222. }
  223. return
  224. }
  225. if err = tx.Commit(); err != nil {
  226. log.Error("tx.Commit %+v", err)
  227. }
  228. }()
  229. if aff, err = s.dao.UpdateAllowanceStatus(c, tx, state, mid, token, ver); err != nil {
  230. err = errors.WithStack(err)
  231. }
  232. if aff != 1 {
  233. err = fmt.Errorf("coupon update faild")
  234. return
  235. }
  236. l := &model.CouponAllowanceChangeLog{
  237. CouponToken: cp.CouponToken,
  238. Mid: cp.Mid,
  239. State: state,
  240. Ctime: xtime.Time(time.Now().Unix()),
  241. OrderNO: cp.OrderNO,
  242. ChangeType: changeType,
  243. }
  244. if aff, err = s.dao.InsertCouponAllowanceHistory(c, tx, l); err != nil {
  245. err = errors.WithStack(err)
  246. return
  247. }
  248. if aff != 1 {
  249. err = fmt.Errorf("add change log faild")
  250. return
  251. }
  252. s.dao.DelCouponAllowancesKey(c, cp.Mid, model.NotUsed)
  253. s.dao.DelCouponAllowancesKey(c, cp.Mid, model.InUse)
  254. return
  255. }