From 9d296a1c658c19c6faa51dfef31d025e59a480cb Mon Sep 17 00:00:00 2001 From: zhangqian <zhangqian@123.com> Date: 星期二, 02 七月 2024 12:02:45 +0800 Subject: [PATCH] 按仓库统计月度报表下载接口 --- constvar/const.go | 5 controllers/operation.go | 4 controllers/report_forms_controller.go | 43 +++++++ models/warehouse_month_stats.go | 8 + models/operation.go | 6 + service/dict.go | 19 +++ docs/swagger.yaml | 35 +++++ docs/docs.go | 60 ++++++++++ models/operation_details.go | 17 ++ docs/swagger.json | 60 ++++++++++ router/router.go | 5 service/warehouse_month_forms.go | 98 ++++++++++++++++ 12 files changed, 355 insertions(+), 5 deletions(-) diff --git a/constvar/const.go b/constvar/const.go index 82d7c47..7ddf618 100644 --- a/constvar/const.go +++ b/constvar/const.go @@ -333,6 +333,11 @@ TakeStock // 鐩樼偣绫诲瀷 ) +const ( + InputTotalHeader string = "鍏ュ簱鍚堣" + OutPutTotalHeader string = "鍑哄簱鍚堣" +) + func (t MiniDictType) Valid() bool { if t <= 0 { return false diff --git a/controllers/operation.go b/controllers/operation.go index d948560..c522015 100644 --- a/controllers/operation.go +++ b/controllers/operation.go @@ -100,6 +100,10 @@ params.Status = constvar.OperationStatus_Ready //params.Number = strconv.FormatInt(time.Now().Unix(), 10) + for _, detail := range params.Details { + detail.BaseOperationType = params.BaseOperationType + } + var numberNum int64 if err := mysqlx.GetDB().Model(&models.Operation{}).Where("number=?", params.Number).Count(&numberNum).Error; err != nil { util.ResponseFormat(c, code.RequestParamError, err.Error()) diff --git a/controllers/report_forms_controller.go b/controllers/report_forms_controller.go index 230525c..afe8111 100644 --- a/controllers/report_forms_controller.go +++ b/controllers/report_forms_controller.go @@ -466,6 +466,8 @@ return } + params.Preload = true + result, err := monthFormsService.Query(params) if err != nil { logx.Errorf("MonthStats query err:%v", err) @@ -528,3 +530,44 @@ task.WarehouseMonthStats() util.ResponseFormat(c, code.Success, nil) } + +// DownloadWarehouseMonthStats +// @Tags 鎶ヨ〃 +// @Summary 涓嬭浇鎸変粨搴撶粺璁℃湀搴︾粺璁″簱瀛樻姤琛� +// @Produce application/json +// @Param object body request.GetMonthStats true "鏌ヨ鍙傛暟" +// @Param Authorization header string true "token" +// @Success 200 {object} util.ResponseList{data=[]models.MonthStats} "鎴愬姛" +// @Router /api-wms/v1/forms/downloadWarehouseMonthStats [post] +func (slf ReportFormsController) DownloadWarehouseMonthStats(c *gin.Context) { + var params request.GetMonthStats + if err := c.BindJSON(¶ms); err != nil { + util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�") + return + } + + if params.WarehouseID == 0 { + util.ResponseFormat(c, code.RequestParamError, "浠撳簱ID鍙傛暟缂哄け") + return + } + + monthFormsService := service.NewWarehouseMonthFormsService() + list, err := monthFormsService.FetchAll(params) + if err != nil { + logx.Errorf("DownloadMonthStats FetchAll err:%v", err) + util.ResponseFormat(c, code.InternalError, "鏌ヨ澶辫触") + return + } + filename, err := monthFormsService.Export(list) + if err != nil { + logx.Errorf("DownloadMonthStats Export err:%v", err) + util.ResponseFormat(c, code.InternalError, "瀵煎嚭鏁版嵁鍒版枃浠跺け璐�") + return + } + + fileContentDisposition := "attachment;filename=\"" + url.QueryEscape(filename) + "\"" + c.Header("Content-Type", "application/xlsx") + c.Header("Content-Disposition", fileContentDisposition) + c.File(filename) + defer os.Remove(filename) +} diff --git a/docs/docs.go b/docs/docs.go index 07fee6b..7310db0 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1033,6 +1033,58 @@ } } }, + "/api-wms/v1/forms/downloadWarehouseMonthStats": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "鎶ヨ〃" + ], + "summary": "涓嬭浇鎸変粨搴撶粺璁℃湀搴︾粺璁″簱瀛樻姤琛�", + "parameters": [ + { + "description": "鏌ヨ鍙傛暟", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GetMonthStats" + } + }, + { + "type": "string", + "description": "token", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "鎴愬姛", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/util.ResponseList" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.MonthStats" + } + } + } + } + ] + } + } + } + } + }, "/api-wms/v1/forms/getHistory": { "post": { "produces": [ @@ -5260,6 +5312,14 @@ "auxiliaryUnit": { "type": "string" }, + "baseOperationType": { + "description": "鍩虹浣滀笟绫诲瀷", + "allOf": [ + { + "$ref": "#/definitions/constvar.BaseOperationType" + } + ] + }, "cost": { "description": "鎴愭湰鍗曚环", "type": "number" diff --git a/docs/swagger.json b/docs/swagger.json index 1aff6fb..eb8f26a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1022,6 +1022,58 @@ } } }, + "/api-wms/v1/forms/downloadWarehouseMonthStats": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "鎶ヨ〃" + ], + "summary": "涓嬭浇鎸変粨搴撶粺璁℃湀搴︾粺璁″簱瀛樻姤琛�", + "parameters": [ + { + "description": "鏌ヨ鍙傛暟", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GetMonthStats" + } + }, + { + "type": "string", + "description": "token", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "鎴愬姛", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/util.ResponseList" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/models.MonthStats" + } + } + } + } + ] + } + } + } + } + }, "/api-wms/v1/forms/getHistory": { "post": { "produces": [ @@ -5249,6 +5301,14 @@ "auxiliaryUnit": { "type": "string" }, + "baseOperationType": { + "description": "鍩虹浣滀笟绫诲瀷", + "allOf": [ + { + "$ref": "#/definitions/constvar.BaseOperationType" + } + ] + }, "cost": { "description": "鎴愭湰鍗曚环", "type": "number" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 08e97ae..253cd0b 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1041,6 +1041,10 @@ type: number auxiliaryUnit: type: string + baseOperationType: + allOf: + - $ref: '#/definitions/constvar.BaseOperationType' + description: 鍩虹浣滀笟绫诲瀷 cost: description: 鎴愭湰鍗曚环 type: number @@ -2965,6 +2969,37 @@ summary: 涓嬭浇鏈堝害缁熻搴撳瓨鎶ヨ〃 tags: - 鎶ヨ〃 + /api-wms/v1/forms/downloadWarehouseMonthStats: + post: + parameters: + - description: 鏌ヨ鍙傛暟 + in: body + name: object + required: true + schema: + $ref: '#/definitions/request.GetMonthStats' + - description: token + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: 鎴愬姛 + schema: + allOf: + - $ref: '#/definitions/util.ResponseList' + - properties: + data: + items: + $ref: '#/definitions/models.MonthStats' + type: array + type: object + summary: 涓嬭浇鎸変粨搴撶粺璁℃湀搴︾粺璁″簱瀛樻姤琛� + tags: + - 鎶ヨ〃 /api-wms/v1/forms/getHistory: post: parameters: diff --git a/models/operation.go b/models/operation.go index 826208d..9e2846c 100644 --- a/models/operation.go +++ b/models/operation.go @@ -95,6 +95,12 @@ return &OperationSearch{Orm: mysqlx.GetDB()} } +func (slf *OperationSearch) BeforeCreate(tx *gorm.DB) { + for k := range slf.Details { + slf.Details[k].BaseOperationType = slf.BaseOperationType + } +} + func (slf *OperationSearch) SetOrm(tx *gorm.DB) *OperationSearch { slf.Orm = tx return slf diff --git a/models/operation_details.go b/models/operation_details.go index 8269f76..c596a44 100644 --- a/models/operation_details.go +++ b/models/operation_details.go @@ -4,6 +4,7 @@ "fmt" "github.com/shopspring/decimal" "gorm.io/gorm" + "wms/constvar" "wms/pkg/mysqlx" ) @@ -11,9 +12,10 @@ // OperationDetails 鎿嶄綔鏄庣粏琛� OperationDetails struct { WmsModel - Id int `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"` - OperationID int `json:"operationId" gorm:"index;type:int;not null;comment:鎿嶄綔璁板綍id"` //鎿嶄綔id - ProductId string `json:"productId" gorm:"type:varchar(191);not null;comment:浜у搧id"` //浜у搧id + Id int `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"` + OperationID int `json:"operationId" gorm:"index;type:int;not null;comment:鎿嶄綔璁板綍id"` //鎿嶄綔id + BaseOperationType constvar.BaseOperationType `json:"baseOperationType" gorm:"type:tinyint;not null;comment:鍩虹浣滀笟绫诲瀷"` //鍩虹浣滀笟绫诲瀷 + ProductId string `json:"productId" gorm:"type:varchar(191);not null;comment:浜у搧id"` //浜у搧id //ProductName string `json:"productName" gorm:"type:varchar(255);not null;comment:浜у搧鍚嶇О"` //浜у搧鍚嶇О Amount decimal.Decimal `json:"amount" gorm:"type:decimal(20,2);not null;comment:鏁伴噺"` //鏁伴噺 //Unit string `json:"unit" gorm:"type:varchar(31);comment:鍗曚綅"` //鍗曚綅 @@ -106,6 +108,11 @@ return slf } +func (slf *OperationDetailsSearch) SetBaseOperationType(baseOperationType constvar.BaseOperationType) *OperationDetailsSearch { + slf.BaseOperationType = baseOperationType + return slf +} + func (slf *OperationDetailsSearch) build() *gorm.DB { var db = slf.Orm.Model(&OperationDetails{}) @@ -139,6 +146,10 @@ db = db.Select(slf.Fields) } + if slf.BaseOperationType != 0 { + db = db.Where("base_operation_type = ?", slf.BaseOperationType) + } + return db } diff --git a/models/warehouse_month_stats.go b/models/warehouse_month_stats.go index 658fab5..ae73de2 100644 --- a/models/warehouse_month_stats.go +++ b/models/warehouse_month_stats.go @@ -306,6 +306,14 @@ return m } +func WarehouseStatsItemMap(records []*WarehouseStatsItems) (m map[string]*WarehouseStatsItems) { + m = make(map[string]*WarehouseStatsItems, len(records)) + for _, record := range records { + m[record.Name] = record + } + return m +} + func (slf *WarehouseMonthStatsSearch) Count() (int64, error) { var ( total int64 diff --git a/router/router.go b/router/router.go index f9868b5..a540f4f 100644 --- a/router/router.go +++ b/router/router.go @@ -179,8 +179,9 @@ reportFormsAPI.POST("downloadMonthStats", reportFormsController.DownloadMonthStats) //涓嬭浇鏈堝害缁熻鎶ヨ〃 reportFormsAPI.POST("doMonthStats", reportFormsController.DoMonthStats) //鎵嬪姩璺戞湀搴︾粺璁″簱瀛樻姤琛� - reportFormsAPI.POST("warehouseMonthStats", reportFormsController.WarehouseMonthStats) //鎸変粨搴撹幏鍙栨湀搴︾粺璁℃姤琛� - reportFormsAPI.POST("doWarehouseMonthStats", reportFormsController.DoWareHouseMonthStats) //鎵嬪姩璺戞寜浠撳簱鑾峰彇鏈堝害缁熻鎶ヨ〃 + reportFormsAPI.POST("warehouseMonthStats", reportFormsController.WarehouseMonthStats) //鎸変粨搴撹幏鍙栨湀搴︾粺璁℃姤琛� + reportFormsAPI.POST("doWarehouseMonthStats", reportFormsController.DoWareHouseMonthStats) //鎵嬪姩璺戞寜浠撳簱鑾峰彇鏈堝害缁熻鎶ヨ〃 + reportFormsAPI.POST("downloadWarehouseMonthStats", reportFormsController.DownloadWarehouseMonthStats) //涓嬭浇鎸変粨搴撹幏鍙栨湀搴︾粺璁℃姤琛� } //閲嶈璐ц鍒� diff --git a/service/dict.go b/service/dict.go new file mode 100644 index 0000000..50cbb5a --- /dev/null +++ b/service/dict.go @@ -0,0 +1,19 @@ +package service + +import ( + "wms/constvar" + "wms/models" +) + +func GetDictNameListByType(dictType constvar.MiniDictType) (names []string) { + dictList, err := models.NewMiniDictSearch().SetType(dictType).SetOrder("id asc").FindNotTotal() + if err != nil { + return nil + } + + for _, dict := range dictList { + names = append(names, dict.Name) + } + + return names +} diff --git a/service/warehouse_month_forms.go b/service/warehouse_month_forms.go index c245dbd..9edf8c4 100644 --- a/service/warehouse_month_forms.go +++ b/service/warehouse_month_forms.go @@ -1,7 +1,10 @@ package service import ( + "fmt" "github.com/shopspring/decimal" + "github.com/xuri/excelize/v2" + "strconv" "time" "wms/constvar" "wms/models" @@ -58,6 +61,101 @@ return } +func (slf *WarehouseMonthFormsService) Export(dataList []*models.WarehouseMonthStats) (filename string, err error) { + // 鍒涘缓涓�涓柊鐨� Excel 鏂囦欢 + f := excelize.NewFile() + + if err != nil { + logx.Errorf("NewSheet err:%v", err) + return "", err + } + + headers, headerLen, inputTypes, outputTypes := slf.GetHeaders() + err = SetExcelHeader(headers, f) + if err != nil { + logx.Errorf("SetExcelHeader err:%v", err) + return "", err + } + + //琛ㄥご鏍峰紡 + style, err := SetHeaderStyle(f) + if err != nil { + return "", err + } + + f.SetCellStyle("Sheet1", "A1", getColumnAlphabet(headerLen)+"2", style) + // 璁剧疆鍒楀 + f.SetColWidth("Sheet1", "A", "F", 30) + f.SetColWidth("Sheet1", "G", getColumnAlphabet(headerLen), 15) + + inputStart := 7 + outputStart := 7 + len(inputTypes) + for i, v := range dataList { + column := strconv.Itoa(i + 3) + f.SetCellValue("Sheet1", "A"+column, v.ProductId) + f.SetCellValue("Sheet1", "B"+column, v.ProductName) + f.SetCellValue("Sheet1", "C"+column, v.EndAmount) + f.SetCellValue("Sheet1", "D"+column, v.BeginAmount) + f.SetCellValue("Sheet1", "E"+column, v.Unit) + f.SetCellValue("Sheet1", "F"+column, v.SalePrice) + + slf.FillDealerTypeToExcel(v.InputItems, inputStart, i+3, inputTypes, f) + slf.FillDealerTypeToExcel(v.OutputItems, outputStart, i+3, outputTypes, f) + } + + fileName := fmt.Sprintf("%s鏈堝害缁熻鎶ヨ〃%s.xlsx", "浠撳簱", time.Now().Format("2006-01-02-1504")) + if err := f.SaveAs(fileName); err != nil { + return fileName, err + } + + return fileName, nil +} + +func (slf *WarehouseMonthFormsService) GetHeaders() (headers []interface{}, headerLen int, inputTypes, outputTypes []string) { + // 鑷畾涔夎〃澶� + + //鏌ヨ鍏ュ簱绫诲瀷 + inputTypes = GetDictNameListByType(constvar.StorageType) + inputTypes = append(inputTypes, constvar.InputTotalHeader) + + headerLen += len(inputTypes) + + //鏌ヨ鍏ュ簱绫诲瀷 + outputTypes = GetDictNameListByType(constvar.StockoutType) + outputTypes = append(outputTypes, constvar.OutPutTotalHeader) + + headerLen += len(inputTypes) + + headerLen += 6 + + headers = []interface{}{"鐗╂枡缂栧彿", "鐗╂枡缂栫爜", "鏈堟湯缁撳瓨", "鏈堝垵缁撳瓨", "鍗曚綅", "鍗曚环", map[string][]string{"鏈湀鍏ュ簱": inputTypes}, map[string][]string{"鏈湀鍑哄簱": outputTypes}} + return headers, headerLen, inputTypes, outputTypes +} + +func (slf *WarehouseMonthFormsService) SumItems(items []*models.WarehouseStatsItems) (sum decimal.Decimal) { + for _, v := range items { + sum = sum.Add(v.Amount) + } + return sum +} + +func (slf *WarehouseMonthFormsService) FillDealerTypeToExcel(items []*models.WarehouseStatsItems, startIndex int, column int, dealerTypes []string, f *excelize.File) { + columnStr := strconv.Itoa(column) + sum := slf.SumItems(items) + detailMap := models.WarehouseStatsItemMap(items) + + for i := 0; i < len(dealerTypes); i++ { + var amount decimal.Decimal + if detailMap[dealerTypes[i]] != nil { + amount = detailMap[dealerTypes[i]].Amount + } else if dealerTypes[i] == constvar.InputTotalHeader { + amount = sum + } + f.SetCellValue("Sheet1", getColumnAlphabet(startIndex+i)+columnStr, amount) + } + return +} + func GetCurrentWarehouseStats(date string, warehouseId int, productIds []string) (statRecords []*models.WarehouseMonthStats, err error) { //鏈湀鏈熷垵鏁伴噺/涓婃湀缁撲綑鏁伴噺 groupSumList, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).GroupSum("product_id", "amount") -- Gitblit v1.8.0