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(&params); 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