package hdl import ( "applet/app/db" "applet/app/db/model" "applet/app/e" "applet/app/enum" "applet/app/lib/validate" "applet/app/md" "applet/app/svc" "applet/app/utils" "github.com/360EntSecGroup-Skylar/excelize" "github.com/gin-gonic/gin" "github.com/shopspring/decimal" "strconv" "time" ) func QrcodeBatchList(c *gin.Context) { var req md.QrcodeBatchListReq err := c.ShouldBindJSON(&req) if err != nil { err = validate.HandleValidateErr(err) err1 := err.(e.E) e.OutErr(c, err1.Code, err1.Error()) return } qrcodeBatchDb := db.QrcodeBatchDb{} qrcodeBatchDb.Set() list, total, err := qrcodeBatchDb.List(req.Page, req.Limit) if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } qrcodeTotalNums, waitUseQrcodeNums, alreadyUseQrcodeNums, allowCreateQrcodeNums, err := svc.StatisticsQrcodeData() if err != nil { e.OutErr(c, e.ERR, err.Error()) return } e.OutSuc(c, map[string]interface{}{ "list": list, "total": total, "batch_state_list": []map[string]interface{}{ { "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForUseIng).String(), "value": enum.QrcodeBatchStateForUseIng, }, { "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForUseAlready).String(), "value": enum.QrcodeBatchStateForUseAlready, }, { "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForExpire).String(), "value": enum.QrcodeBatchStateForExpire, }, { "name": enum.QrcodeBatchState(enum.QrcodeBatchStateForCancel).String(), "value": enum.QrcodeBatchStateForCancel, }, }, "statistics_qrcode_data": map[string]interface{}{ "qrcode_total_nums": qrcodeTotalNums, "wait_use_qrcode_nums": waitUseQrcodeNums, "already_use_qrcode_nums": alreadyUseQrcodeNums, "allow_create_qrcode_nums": allowCreateQrcodeNums, }, }, nil) return } func QrcodeBatchAdd(c *gin.Context) { var req md.QrcodeBatchAddReq err := c.ShouldBindJSON(&req) if err != nil { err = validate.HandleValidateErr(err) err1 := err.(e.E) e.OutErr(c, err1.Code, err1.Error()) return } var totalNum int var totalAmount decimal.Decimal for _, v := range req.List { //TODO::判断amount 是否在 1 ~ 200 之间 if utils.StrToFloat64(v.Amount) < 1 || utils.StrToFloat64(v.Amount) > 200 { e.OutErr(c, e.ERR, "根据微信相关规定, 二维码金额须在 1 ~ 200 元之间") return } totalNum += v.Num amount, _ := decimal.NewFromString(v.Amount) num := decimal.NewFromInt(int64(v.Num)) totalAmount = totalAmount.Add(amount.Mul(num)) } session := db.Db.NewSession() defer session.Close() session.Begin() now := time.Now() //1、新增批次数据 `qrcode_batch` var qrcodeBatch = model.QrcodeBatch{ Name: req.Name, TotalNum: totalNum, TotalAmount: totalAmount.String(), State: enum.QrcodeBatchStateForUseIng, ExpireDate: req.ExpireDate, Memo: req.Memo, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), } qrcodeBatchDb := db.QrcodeBatchDb{} err = qrcodeBatchDb.AddBySession(session, &qrcodeBatch) if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } //2、获取 qrcode 表中是否有可用二维码 qrcodeDb := db.QrcodeDb{} qrcodeDb.Set() _, allowUseQrcodeTotal, err := qrcodeDb.FindQrcodeForAllowUse() if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } diffQrcodeNum := totalNum - int(allowUseQrcodeTotal) if diffQrcodeNum > 0 { //TODO::为避免频繁请求微信二维码接口 if diffQrcodeNum > 1000 { e.OutErr(c, e.ERR, "为保证二维码数据准确性,每批次新增二维码不宜操过1000张") return } //3、不够用,新增二维码 err := svc.CreateQrcode(diffQrcodeNum) if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR, err.Error()) return } } //4、生成 "二维码-批次" 记录 err = svc.OperateQrcode(qrcodeBatch.Id, totalNum, req, session) if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR, err.Error()) return } err = session.Commit() if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } e.OutSuc(c, "success", nil) return } func GetBatchAddName(c *gin.Context) { var name = "第【1】批" qrcodeBatchDb := db.QrcodeBatchDb{} qrcodeBatchDb.Set() qrcodeBatch, err := qrcodeBatchDb.GeLastId() if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } if qrcodeBatch != nil { name = "第【" + utils.IntToStr(qrcodeBatch.Id+1) + "】批" } e.OutSuc(c, map[string]string{ "name": name, }, nil) return } func QrcodeBatchDetail(c *gin.Context) { batchId := c.DefaultQuery("id", "") qrcodeBatchDb := db.QrcodeBatchDb{} qrcodeBatchDb.Set() qrcodeBatch, err := qrcodeBatchDb.GetQrcodeBatchById(utils.StrToInt(batchId)) if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } if qrcodeBatch == nil { e.OutErr(c, e.ERR_NO_DATA, "未查询到对应的批次记录") return } qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{} qrcodeWithBatchRecordsDb.Set() data, _, err := qrcodeWithBatchRecordsDb.FindQrcodeWithBatchRecordsById(utils.StrToInt(batchId)) if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } var list = map[string]*md.QrcodeBatchAddReqListDetail{} for _, v := range data { if list[v.Amount] == nil { list[v.Amount] = &md.QrcodeBatchAddReqListDetail{} } list[v.Amount].Num++ list[v.Amount].Amount = v.Amount switch v.State { case enum.QrcodeWithBatchRecordsStateForWait: list[v.Amount].WaitUseNum++ break case enum.QrcodeWithBatchRecordsStateForAlready: list[v.Amount].UsedNum++ break case enum.QrcodeWithBatchRecordsStateForExpire: list[v.Amount].ExpiredNum++ break case enum.QrcodeWithBatchRecordsStateForCancel: list[v.Amount].CancelNum++ break } } var resultList []*md.QrcodeBatchAddReqListDetail for _, v := range list { resultList = append(resultList, v) } e.OutSuc(c, map[string]interface{}{ "info": qrcodeBatch, "list": resultList, }, nil) return } func QrcodeBatchDelete(c *gin.Context) { batchId := c.Param("id") session := db.Db.NewSession() defer session.Close() session.Begin() //1、删除 `qrcode_batch` 记录 qrcodeBatchDb := db.QrcodeBatchDb{} qrcodeBatchDb.Set() _, err := qrcodeBatchDb.DeleteQrcodeBatchBySession(session, utils.StrToInt(batchId)) if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } //2、将所关联的 `qrcode` 状态改为 "可用" qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{} qrcodeWithBatchRecordsDb.Set() data, _, err := qrcodeWithBatchRecordsDb.FindQrcodeWithBatchRecordsById(utils.StrToInt(batchId)) if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } var updateQrcodeIds []int for _, v := range data { updateQrcodeIds = append(updateQrcodeIds, v.QrcodeId) } qrcodeDb := db.QrcodeDb{} qrcodeDb.Set() _, err = qrcodeDb.BatchUpdateQrcodeBySession(session, updateQrcodeIds, enum.QrcodeSateAllowUse) if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } //3、删除 `qrcode_with_batch_records` 记录 _, err = qrcodeWithBatchRecordsDb.DeleteQrcodeWithBatchRecordsBySession(session, utils.StrToInt(batchId)) if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } err = session.Commit() if err != nil { _ = session.Rollback() e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } e.OutSuc(c, "success", nil) return } func QrcodeBatchDownload(c *gin.Context) { batchId := c.DefaultQuery("id", "") qrcodeBatchDb := db.QrcodeBatchDb{} qrcodeBatchDb.Set() qrcodeBatch, err := qrcodeBatchDb.GetQrcodeBatchById(utils.StrToInt(batchId)) if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } if qrcodeBatch == nil { e.OutErr(c, e.ERR_NO_DATA, "未查询到对应的批次记录") return } qrcodeWithBatchRecordsDb := db.QrcodeWithBatchRecordsDb{} qrcodeWithBatchRecordsDb.Set() data, _, err := qrcodeWithBatchRecordsDb.FindQrcodeWithBatchRecordsLeftJoinQrcode(utils.StrToInt(batchId)) if err != nil { e.OutErr(c, e.ERR_DB_ORM, err.Error()) return } titleList := []string{"批次", "有效期", "金额", "二维码地址"} xlsx := excelize.NewFile() xlsx.SetSheetRow("Sheet1", "A1", &titleList) //表头被第一行用了,只能从第二行开始 j := 2 for _, vv := range data { xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{qrcodeBatch.Name, qrcodeBatch.ExpireDate, vv.Amount, vv.Url}) j++ } //if err := xlsx.SaveAs(qrcodeBatch.Name + ".xlsx"); err != nil { // e.OutErr(c, e.ERR, err.Error()) // return //} c.Header("Content-Type", "application/octet-stream") c.Header("Content-Disposition", "attachment; filename="+qrcodeBatch.Name+".xlsx") c.Header("Content-Transfer-Encoding", "binary") //回写到web 流媒体 形成下载 _ = xlsx.Write(c.Writer) return }