一物一码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

hdl_qrcode.go 8.8 KiB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package hdl
  2. import (
  3. "applet/app/db"
  4. "applet/app/db/model"
  5. "applet/app/e"
  6. "applet/app/enum"
  7. "applet/app/lib/validate"
  8. "applet/app/md"
  9. "applet/app/svc"
  10. "applet/app/utils"
  11. "github.com/360EntSecGroup-Skylar/excelize"
  12. "github.com/gin-gonic/gin"
  13. "github.com/shopspring/decimal"
  14. "strconv"
  15. "time"
  16. )
  17. func QrcodeBatchList(c *gin.Context) {
  18. var req md.QrcodeBatchListReq
  19. err := c.ShouldBindJSON(&req)
  20. if err != nil {
  21. err = validate.HandleValidateErr(err)
  22. err1 := err.(e.E)
  23. e.OutErr(c, err1.Code, err1.Error())
  24. return
  25. }
  26. qrcodeBatchDb := db.QrcodeBatchDb{}
  27. qrcodeBatchDb.Set()
  28. list, total, err := qrcodeBatchDb.List(req.Page, req.Limit)
  29. if err != nil {
  30. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  31. return
  32. }
  33. qrcodeTotalNums, waitUseQrcodeNums, alreadyUseQrcodeNums, allowCreateQrcodeNums, err := svc.StatisticsQrcodeData()
  34. if err != nil {
  35. e.OutErr(c, e.ERR, err.Error())
  36. return
  37. }
  38. e.OutSuc(c, map[string]interface{}{
  39. "list": list,
  40. "total": total,
  41. "batch_state_list": []map[string]interface{}{
  42. {
  43. "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForUseIng).String(),
  44. "value": enum.QrcodeBatchStateForUseIng,
  45. },
  46. {
  47. "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForUseAlready).String(),
  48. "value": enum.QrcodeBatchStateForUseAlready,
  49. },
  50. {
  51. "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForExpire).String(),
  52. "value": enum.QrcodeBatchStateForExpire,
  53. },
  54. {
  55. "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForCancel).String(),
  56. "value": enum.QrcodeBatchStateForCancel,
  57. },
  58. },
  59. "statistics_qrcode_data": map[string]interface{}{
  60. "qrcode_total_nums": qrcodeTotalNums,
  61. "wait_use_qrcode_nums": waitUseQrcodeNums,
  62. "already_use_qrcode_nums": alreadyUseQrcodeNums,
  63. "allow_create_qrcode_nums": allowCreateQrcodeNums,
  64. },
  65. }, nil)
  66. return
  67. }
  68. func QrcodeBatchAdd(c *gin.Context) {
  69. var req md.QrcodeBatchAddReq
  70. err := c.ShouldBindJSON(&req)
  71. if err != nil {
  72. err = validate.HandleValidateErr(err)
  73. err1 := err.(e.E)
  74. e.OutErr(c, err1.Code, err1.Error())
  75. return
  76. }
  77. var totalNum int
  78. var totalAmount decimal.Decimal
  79. for _, v := range req.List {
  80. //TODO::判断amount 是否在 1 ~ 200 之间
  81. if utils.StrToFloat64(v.Amount) < 1 || utils.StrToFloat64(v.Amount) > 200 {
  82. e.OutErr(c, e.ERR, "根据微信相关规定, 二维码金额须在 1 ~ 200 元之间")
  83. return
  84. }
  85. totalNum += v.Num
  86. amount, _ := decimal.NewFromString(v.Amount)
  87. num := decimal.NewFromInt(int64(v.Num))
  88. totalAmount = totalAmount.Add(amount.Mul(num))
  89. }
  90. session := db.Db.NewSession()
  91. defer session.Close()
  92. session.Begin()
  93. now := time.Now()
  94. //1、新增批次数据 `qrcode_batch`
  95. var qrcodeBatch = model.QrcodeBatch{
  96. Name: req.Name,
  97. TotalNum: totalNum,
  98. TotalAmount: totalAmount.String(),
  99. State: enum.QrcodeBatchStateForUseIng,
  100. ExpireDate: req.ExpireDate,
  101. Memo: req.Memo,
  102. CreateAt: now.Format("2006-01-02 15:04:05"),
  103. UpdateAt: now.Format("2006-01-02 15:04:05"),
  104. }
  105. qrcodeBatchDb := db.QrcodeBatchDb{}
  106. err = qrcodeBatchDb.AddBySession(session, &qrcodeBatch)
  107. if err != nil {
  108. _ = session.Rollback()
  109. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  110. return
  111. }
  112. //2、获取 qrcode 表中是否有可用二维码
  113. qrcodeDb := db.QrcodeDb{}
  114. qrcodeDb.Set()
  115. _, allowUseQrcodeTotal, err := qrcodeDb.FindQrcodeForAllowUse()
  116. if err != nil {
  117. _ = session.Rollback()
  118. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  119. return
  120. }
  121. diffQrcodeNum := totalNum - int(allowUseQrcodeTotal)
  122. if diffQrcodeNum > 0 {
  123. //TODO::为避免频繁请求微信二维码接口
  124. if diffQrcodeNum > 1000 {
  125. e.OutErr(c, e.ERR, "为保证二维码数据准确性,每批次新增二维码不宜操过1000张")
  126. return
  127. }
  128. //3、不够用,新增二维码
  129. err := svc.CreateQrcode(diffQrcodeNum)
  130. if err != nil {
  131. _ = session.Rollback()
  132. e.OutErr(c, e.ERR, err.Error())
  133. return
  134. }
  135. }
  136. //4、生成 "二维码-批次" 记录
  137. err = svc.OperateQrcode(qrcodeBatch.Id, totalNum, req, session)
  138. if err != nil {
  139. _ = session.Rollback()
  140. e.OutErr(c, e.ERR, err.Error())
  141. return
  142. }
  143. err = session.Commit()
  144. if err != nil {
  145. _ = session.Rollback()
  146. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  147. return
  148. }
  149. e.OutSuc(c, "success", nil)
  150. return
  151. }
  152. func GetBatchAddName(c *gin.Context) {
  153. var name = "第【1】批"
  154. qrcodeBatchDb := db.QrcodeBatchDb{}
  155. qrcodeBatchDb.Set()
  156. qrcodeBatch, err := qrcodeBatchDb.GeLastId()
  157. if err != nil {
  158. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  159. return
  160. }
  161. if qrcodeBatch != nil {
  162. name = "第【" + utils.IntToStr(qrcodeBatch.Id+1) + "】批"
  163. }
  164. e.OutSuc(c, map[string]string{
  165. "name": name,
  166. }, nil)
  167. return
  168. }
  169. func QrcodeBatchDetail(c *gin.Context) {
  170. batchId := c.DefaultQuery("id", "")
  171. qrcodeBatchDb := db.QrcodeBatchDb{}
  172. qrcodeBatchDb.Set()
  173. qrcodeBatch, err := qrcodeBatchDb.GetQrcodeBatchById(utils.StrToInt(batchId))
  174. if err != nil {
  175. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  176. return
  177. }
  178. if qrcodeBatch == nil {
  179. e.OutErr(c, e.ERR_NO_DATA, "未查询到对应的批次记录")
  180. return
  181. }
  182. qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{}
  183. qrcodeWithBatchRecordsDb.Set()
  184. data, _, err := qrcodeWithBatchRecordsDb.FindQrcodeWithBatchRecordsById(utils.StrToInt(batchId))
  185. if err != nil {
  186. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  187. return
  188. }
  189. var list = map[string]*md.QrcodeBatchAddReqListDetail{}
  190. for _, v := range data {
  191. if list[v.Amount] == nil {
  192. list[v.Amount] = &md.QrcodeBatchAddReqListDetail{}
  193. }
  194. list[v.Amount].Num++
  195. list[v.Amount].Amount = v.Amount
  196. switch v.State {
  197. case enum.QrcodeWithBatchRecordsStateForWait:
  198. list[v.Amount].WaitUseNum++
  199. break
  200. case enum.QrcodeWithBatchRecordsStateForAlready:
  201. list[v.Amount].UsedNum++
  202. break
  203. case enum.QrcodeWithBatchRecordsStateForExpire:
  204. list[v.Amount].ExpiredNum++
  205. break
  206. case enum.QrcodeWithBatchRecordsStateForCancel:
  207. list[v.Amount].CancelNum++
  208. break
  209. }
  210. }
  211. var resultList []*md.QrcodeBatchAddReqListDetail
  212. for _, v := range list {
  213. resultList = append(resultList, v)
  214. }
  215. e.OutSuc(c, map[string]interface{}{
  216. "info": qrcodeBatch,
  217. "list": resultList,
  218. }, nil)
  219. return
  220. }
  221. func QrcodeBatchDelete(c *gin.Context) {
  222. batchId := c.Param("id")
  223. session := db.Db.NewSession()
  224. defer session.Close()
  225. session.Begin()
  226. //1、删除 `qrcode_batch` 记录
  227. qrcodeBatchDb := db.QrcodeBatchDb{}
  228. qrcodeBatchDb.Set()
  229. _, err := qrcodeBatchDb.DeleteQrcodeBatchBySession(session, utils.StrToInt(batchId))
  230. if err != nil {
  231. _ = session.Rollback()
  232. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  233. return
  234. }
  235. //2、将所关联的 `qrcode` 状态改为 "可用"
  236. qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{}
  237. qrcodeWithBatchRecordsDb.Set()
  238. data, _, err := qrcodeWithBatchRecordsDb.FindQrcodeWithBatchRecordsById(utils.StrToInt(batchId))
  239. if err != nil {
  240. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  241. return
  242. }
  243. var updateQrcodeIds []int
  244. for _, v := range data {
  245. updateQrcodeIds = append(updateQrcodeIds, v.QrcodeId)
  246. }
  247. qrcodeDb := db.QrcodeDb{}
  248. qrcodeDb.Set()
  249. _, err = qrcodeDb.BatchUpdateQrcodeBySession(session, updateQrcodeIds, enum.QrcodeSateAllowUse)
  250. if err != nil {
  251. _ = session.Rollback()
  252. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  253. return
  254. }
  255. //3、删除 `qrcode_with_batch_records` 记录
  256. _, err = qrcodeWithBatchRecordsDb.DeleteQrcodeWithBatchRecordsBySession(session, utils.StrToInt(batchId))
  257. if err != nil {
  258. _ = session.Rollback()
  259. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  260. return
  261. }
  262. err = session.Commit()
  263. if err != nil {
  264. _ = session.Rollback()
  265. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  266. return
  267. }
  268. e.OutSuc(c, "success", nil)
  269. return
  270. }
  271. func QrcodeBatchDownload(c *gin.Context) {
  272. batchId := c.DefaultQuery("id", "")
  273. qrcodeBatchDb := db.QrcodeBatchDb{}
  274. qrcodeBatchDb.Set()
  275. qrcodeBatch, err := qrcodeBatchDb.GetQrcodeBatchById(utils.StrToInt(batchId))
  276. if err != nil {
  277. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  278. return
  279. }
  280. if qrcodeBatch == nil {
  281. e.OutErr(c, e.ERR_NO_DATA, "未查询到对应的批次记录")
  282. return
  283. }
  284. qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{}
  285. qrcodeWithBatchRecordsDb.Set()
  286. data, _, err := qrcodeWithBatchRecordsDb.FindQrcodeWithBatchRecordsLeftJoinQrcode(utils.StrToInt(batchId))
  287. if err != nil {
  288. e.OutErr(c, e.ERR_DB_ORM, err.Error())
  289. return
  290. }
  291. titleList := []string{"批次", "有效期", "金额", "二维码地址"}
  292. xlsx := excelize.NewFile()
  293. xlsx.SetSheetRow("Sheet1", "A1", &titleList)
  294. //表头被第一行用了,只能从第二行开始
  295. j := 2
  296. for _, vv := range data {
  297. xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{qrcodeBatch.Name, qrcodeBatch.ExpireDate, vv.Amount, vv.Url})
  298. j++
  299. }
  300. //if err := xlsx.SaveAs(qrcodeBatch.Name + ".xlsx"); err != nil {
  301. // e.OutErr(c, e.ERR, err.Error())
  302. // return
  303. //}
  304. c.Header("Content-Type", "application/octet-stream")
  305. c.Header("Content-Disposition", "attachment; filename="+qrcodeBatch.Name+".xlsx")
  306. c.Header("Content-Transfer-Encoding", "binary")
  307. //回写到web 流媒体 形成下载
  308. _ = xlsx.Write(c.Writer)
  309. return
  310. }