From 39589bfe0f9ef9255e82780552abf70e91823982 Mon Sep 17 00:00:00 2001 From: chenlin Date: Mon, 12 Aug 2024 16:05:56 +0800 Subject: [PATCH] =?UTF-8?q?1.=E8=B4=A2=E5=8A=A1=E7=BB=9F=E8=AE=A1=E9=A1=B5?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0excel=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/apis/ordermanage/order.go | 21 ++-- app/admin/models/order.go | 160 ++++++++++++++++++++++++++-- docs/docs.go | 152 +++++++++++++++++++++++++- docs/swagger.json | 152 +++++++++++++++++++++++++- docs/swagger.yaml | 105 +++++++++++++++++- 5 files changed, 573 insertions(+), 17 deletions(-) diff --git a/app/admin/apis/ordermanage/order.go b/app/admin/apis/ordermanage/order.go index 1a31024..3298936 100644 --- a/app/admin/apis/ordermanage/order.go +++ b/app/admin/apis/ordermanage/order.go @@ -249,6 +249,14 @@ func ExpressNoList(c *gin.Context) { //app.OK(c, nil, "") } +// FundRecordList 查询财务统计列表 +// @Summary 查询财务统计列表 +// @Tags 财务管理 +// @Produce json +// @Accept json +// @Param request body models.FundRecordListReq true "查询财务统计列表模型" +// @Success 200 {object} models.FundRecordListResp +// @Router /api/v1/order/fund_record/list [post] func FundRecordList(c *gin.Context) { req := &models.FundRecordListReq{} if c.ShouldBindJSON(req) != nil { @@ -257,18 +265,19 @@ func FundRecordList(c *gin.Context) { return } - list, count, err := req.List() + list, count, exportUrl, err := req.List() if err != nil { logger.Errorf("err:", logger.Field("err", err)) app.Error(c, http.StatusInternalServerError, err, "查询失败") return } - ret := map[string]interface{}{ - "total": count, - "list": list, - "pageIndex": req.Page, - "pageSize": req.PageSize, + ret := models.FundRecordListResp{ + Total: count, + List: list, + PageIndex: req.Page, + PageSize: req.PageSize, + ExportUrl: exportUrl, } app.OK(c, ret, "") } diff --git a/app/admin/models/order.go b/app/admin/models/order.go index 0cfc637..a84cfac 100644 --- a/app/admin/models/order.go +++ b/app/admin/models/order.go @@ -18,6 +18,7 @@ import ( "go-admin/tools" "go-admin/tools/config" "golang.org/x/sync/errgroup" + "strconv" "time" ) @@ -1553,9 +1554,10 @@ func (m *ExpressNoInfo) SetStore() { } } +// FundRecordListReq 财务统计入参 type FundRecordListReq struct { Uid uint64 `json:"uid" ` - FundType string `json:"fund_type"` // -member_gold -member_platinum -member_black_gold + FundType string `json:"fund_type"` TransactionId string `json:"transaction_id"` // 支付单号 OutTradeNo string `json:"out_trade_no"` RefundId string `json:"refund_id"` @@ -1564,9 +1566,18 @@ type FundRecordListReq struct { EndTime time.Time `json:"end_time"` // 结束时间 Page int `json:"pageIndex"` PageSize int `json:"pageSize"` + IsExport uint32 `json:"is_export"` // 1-导出 } -func (m *FundRecordListReq) List() ([]FundRecord, int64, error) { +type FundRecordListResp struct { + List []FundRecord `json:"list"` + Total int64 `json:"total"` // 总条数 + PageIndex int `json:"pageIndex"` // 页码 + PageSize int `json:"pageSize"` // 每页展示条数 + ExportUrl string `json:"export_url"` +} + +func (m *FundRecordListReq) List() ([]FundRecord, int64, string, error) { var fundRecords []FundRecord qs := orm.Eloquent.Table("fund_record") @@ -1602,7 +1613,7 @@ func (m *FundRecordListReq) List() ([]FundRecord, int64, error) { err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) - return fundRecords, 0, err + return fundRecords, 0, "", err } if m.PageSize == 0 { m.PageSize = 10 @@ -1613,13 +1624,146 @@ func (m *FundRecordListReq) List() ([]FundRecord, int64, error) { if page < 0 { page = 0 } - err = qs.Order("created_at DESC").Offset(page * pageSize).Limit(pageSize).Find(&fundRecords).Error - if err != nil { - logger.Errorf("err:", logger.Field("err", err)) - return fundRecords, 0, err + + if m.IsExport == 1 { // 导出excel + err = qs.Order("created_at DESC").Find(&fundRecords).Error + if err != nil { + logger.Errorf("err:", logger.Field("err", err)) + return fundRecords, 0, "", err + } + + exportUrl, err := fundRecordListExport(fundRecords) + if err != nil { + logger.Errorf("err:", logger.Field("err", err)) + return fundRecords, 0, "", err + } + + return nil, 0, exportUrl, nil + } else { + err = qs.Order("created_at DESC").Offset(page * pageSize).Limit(pageSize).Find(&fundRecords).Error + if err != nil { + logger.Errorf("err:", logger.Field("err", err)) + return fundRecords, 0, "", err + } } - return fundRecords, count, nil + return fundRecords, count, "", nil +} + +// TranslateFundType 将fund_type转换为对应的字符 +func TranslateFundType(fundType string) string { + fundTypeMap := map[string]string{ + "member_fee": "会员费", + "buy_goods_refund": "商品退货", + "buy_goods": "商品购买", + "buy_goods_cancel": "商品取消", + "recycle_card": "回收卡带", + "postage_package_fee": "购买运费包", + "member_deposit": "押金", + "upgrade_member": "升级会员", + "member_expire_delay": "滞纳金", + "express_fee": "邮费", + "deposit_refund": "退押金", + "express_fee_refund": "退邮费", + "downgrade_renewal": "降级续费", + } + + if val, ok := fundTypeMap[fundType]; ok { + return val + } + return "未知类型" +} + +// ConvertAmount 将Amount转换为格式化字符串 +func ConvertAmount(amount int64) string { + // 转换为以分为单位的小数,保留两位小数 + convertedAmount := float64(amount) / 100.0 + sign := "+" + if convertedAmount < 0 { + sign = "-" + convertedAmount = -convertedAmount + } + return sign + strconv.FormatFloat(convertedAmount, 'f', 2, 64) +} + +// fundRecordListExport 导出财务统计数据 +func fundRecordListExport(list []FundRecord) (string, error) { + file := excelize.NewFile() + fSheet := "Sheet1" + + url := ExportUrl + fileName := time.Now().Format(TimeFormat) + "财务统计" + ".xlsx" + fmt.Println("url fileName:", url+fileName) + + title := []interface{}{"用户ID", "类型", "金额", "商户单号", "交易单号", "退款单号", "付款单号", "创建时间", "备注"} + + for i, _ := range title { + cell, _ := excelize.CoordinatesToCellName(1+i, 1) + err := file.SetCellValue(fSheet, cell, title[i]) + if err != nil { + logger.Errorf("file set value err:", err) + } + } + + var row []interface{} + nExcelStartRow := 0 + for rowId := 0; rowId < len(list); rowId++ { + formattedTime := list[rowId].CreatedAt.Format(QueryTimeFormat) + row = []interface{}{ + list[rowId].Uid, + TranslateFundType(list[rowId].FundType), + ConvertAmount(list[rowId].Amount), + list[rowId].OutTradeNo, + list[rowId].TransactionId, + list[rowId].RefundId, + list[rowId].PaymentNo, + formattedTime, + list[rowId].Remark, + } + + for j, _ := range row { + cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2) + err := file.SetCellValue(fSheet, cell, row[j]) + if err != nil { + logger.Error("file set value err:", logger.Field("err", err)) + } + } + nExcelStartRow++ + } + + // 设置所有单元格的样式: 居中、加边框 + style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, + "border":[{"type":"left","color":"000000","style":1}, + {"type":"top","color":"000000","style":1}, + {"type":"right","color":"000000","style":1}, + {"type":"bottom","color":"000000","style":1}]}`) + + //设置单元格高度 + file.SetRowHeight("Sheet1", 1, 20) + + // 设置单元格大小 + file.SetColWidth("Sheet1", "A", "A", 10) + file.SetColWidth("Sheet1", "B", "B", 13) + file.SetColWidth("Sheet1", "C", "C", 10) + file.SetColWidth("Sheet1", "D", "D", 16) + file.SetColWidth("Sheet1", "E", "E", 30) + file.SetColWidth("Sheet1", "F", "F", 30) + file.SetColWidth("Sheet1", "G", "G", 30) + file.SetColWidth("Sheet1", "H", "H", 25) + file.SetColWidth("Sheet1", "I", "I", 13) + + var endRow string + endRow = fmt.Sprintf("I"+"%d", nExcelStartRow+1) + + // 应用样式到整个表格 + _ = file.SetCellStyle("Sheet1", "A1", endRow, style) + + fmt.Println("save fileName:", config.ExportConfig.Path+fileName) + if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { + fmt.Println(err) + } + + return url + fileName, nil } type CooperativeOrderReq struct { diff --git a/docs/docs.go b/docs/docs.go index 4586538..a7664db 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -4589,6 +4589,39 @@ const docTemplate = `{ } } }, + "/api/v1/order/fund_record/list": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "财务管理" + ], + "summary": "查询财务统计列表", + "parameters": [ + { + "description": "查询财务统计列表模型", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.FundRecordListReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.FundRecordListResp" + } + } + } + } + }, "/api/v1/order/list": { "post": { "consumes": [ @@ -10751,7 +10784,7 @@ const docTemplate = `{ "description": "入/出库,开始时间", "type": "string" }, - "store_list": { + "store_id": { "description": "门店复选", "type": "array", "items": { @@ -11389,6 +11422,123 @@ const docTemplate = `{ } } }, + "models.FundRecord": { + "type": "object", + "properties": { + "amount": { + "type": "integer" + }, + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "fund_type": { + "description": "-member_gold -member_platinum -member_black_gold", + "type": "string" + }, + "id": { + "description": "数据库记录编号", + "type": "integer" + }, + "out_trade_no": { + "type": "string" + }, + "payment_no": { + "description": "付款单号", + "type": "string" + }, + "refund_id": { + "type": "string" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "1-待支付 2-已支付 3-已退款", + "type": "integer" + }, + "transaction_id": { + "description": "支付单号", + "type": "string" + }, + "uid": { + "type": "integer" + }, + "updatedAt": { + "description": "更新时间", + "type": "string" + } + } + }, + "models.FundRecordListReq": { + "type": "object", + "properties": { + "end_time": { + "description": "结束时间", + "type": "string" + }, + "fund_type": { + "type": "string" + }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, + "out_trade_no": { + "type": "string" + }, + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "payment_no": { + "type": "string" + }, + "refund_id": { + "type": "string" + }, + "start_time": { + "description": "开始时间", + "type": "string" + }, + "transaction_id": { + "description": "支付单号", + "type": "string" + }, + "uid": { + "type": "integer" + } + } + }, + "models.FundRecordListResp": { + "type": "object", + "properties": { + "export_url": { + "type": "string" + }, + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.FundRecord" + } + }, + "pageIndex": { + "description": "页码", + "type": "integer" + }, + "pageSize": { + "description": "每页展示条数", + "type": "integer" + }, + "total": { + "description": "总条数", + "type": "integer" + } + } + }, "models.GameCard": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 0884672..61aa213 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -4578,6 +4578,39 @@ } } }, + "/api/v1/order/fund_record/list": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "财务管理" + ], + "summary": "查询财务统计列表", + "parameters": [ + { + "description": "查询财务统计列表模型", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.FundRecordListReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.FundRecordListResp" + } + } + } + } + }, "/api/v1/order/list": { "post": { "consumes": [ @@ -10740,7 +10773,7 @@ "description": "入/出库,开始时间", "type": "string" }, - "store_list": { + "store_id": { "description": "门店复选", "type": "array", "items": { @@ -11378,6 +11411,123 @@ } } }, + "models.FundRecord": { + "type": "object", + "properties": { + "amount": { + "type": "integer" + }, + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "fund_type": { + "description": "-member_gold -member_platinum -member_black_gold", + "type": "string" + }, + "id": { + "description": "数据库记录编号", + "type": "integer" + }, + "out_trade_no": { + "type": "string" + }, + "payment_no": { + "description": "付款单号", + "type": "string" + }, + "refund_id": { + "type": "string" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "1-待支付 2-已支付 3-已退款", + "type": "integer" + }, + "transaction_id": { + "description": "支付单号", + "type": "string" + }, + "uid": { + "type": "integer" + }, + "updatedAt": { + "description": "更新时间", + "type": "string" + } + } + }, + "models.FundRecordListReq": { + "type": "object", + "properties": { + "end_time": { + "description": "结束时间", + "type": "string" + }, + "fund_type": { + "type": "string" + }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, + "out_trade_no": { + "type": "string" + }, + "pageIndex": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "payment_no": { + "type": "string" + }, + "refund_id": { + "type": "string" + }, + "start_time": { + "description": "开始时间", + "type": "string" + }, + "transaction_id": { + "description": "支付单号", + "type": "string" + }, + "uid": { + "type": "integer" + } + } + }, + "models.FundRecordListResp": { + "type": "object", + "properties": { + "export_url": { + "type": "string" + }, + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/models.FundRecord" + } + }, + "pageIndex": { + "description": "页码", + "type": "integer" + }, + "pageSize": { + "description": "每页展示条数", + "type": "integer" + }, + "total": { + "description": "总条数", + "type": "integer" + } + } + }, "models.GameCard": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index afd5a55..405dc3c 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -3357,7 +3357,7 @@ definitions: start_time: description: 入/出库,开始时间 type: string - store_list: + store_id: description: 门店复选 items: type: integer @@ -3822,6 +3822,88 @@ definitions: required: - erp_commodity_id type: object + models.FundRecord: + properties: + amount: + type: integer + createdAt: + description: 创建时间 + type: string + fund_type: + description: -member_gold -member_platinum -member_black_gold + type: string + id: + description: 数据库记录编号 + type: integer + out_trade_no: + type: string + payment_no: + description: 付款单号 + type: string + refund_id: + type: string + remark: + description: 备注 + type: string + status: + description: 1-待支付 2-已支付 3-已退款 + type: integer + transaction_id: + description: 支付单号 + type: string + uid: + type: integer + updatedAt: + description: 更新时间 + type: string + type: object + models.FundRecordListReq: + properties: + end_time: + description: 结束时间 + type: string + fund_type: + type: string + is_export: + description: 1-导出 + type: integer + out_trade_no: + type: string + pageIndex: + type: integer + pageSize: + type: integer + payment_no: + type: string + refund_id: + type: string + start_time: + description: 开始时间 + type: string + transaction_id: + description: 支付单号 + type: string + uid: + type: integer + type: object + models.FundRecordListResp: + properties: + export_url: + type: string + list: + items: + $ref: '#/definitions/models.FundRecord' + type: array + pageIndex: + description: 页码 + type: integer + pageSize: + description: 每页展示条数 + type: integer + total: + description: 总条数 + type: integer + type: object models.GameCard: properties: coverImg: @@ -10865,6 +10947,27 @@ paths: summary: 操作日志列表(update) tags: - system/日志 + /api/v1/order/fund_record/list: + post: + consumes: + - application/json + parameters: + - description: 查询财务统计列表模型 + in: body + name: request + required: true + schema: + $ref: '#/definitions/models.FundRecordListReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.FundRecordListResp' + summary: 查询财务统计列表 + tags: + - 财务管理 /api/v1/order/list: post: consumes: