From 548030097f2b95dff474c397c7393168c73ab8a2 Mon Sep 17 00:00:00 2001
From: liujiandao <274878379@qq.com>
Date: 星期三, 20 九月 2023 09:51:04 +0800
Subject: [PATCH] 产品与产品类型功能开发

---
 controllers/product_controller.go |  214 +++
 models/product_category.go        |   10 
 go.mod                            |    9 
 models/material.go                |  474 ++++++++
 docs/swagger.yaml                 |  461 ++++++--
 docs/docs.go                      |  667 +++++++++--
 docs/swagger.json                 |  665 +++++++++--
 router/router.go                  |   13 
 constvar/const.go                 |   18 
 go.sum                            |   17 
 utils/util.go                     |   11 
 models/db.go                      |    3 
 models/product.go                 |  583 +++++-----
 13 files changed, 2,416 insertions(+), 729 deletions(-)

diff --git a/constvar/const.go b/constvar/const.go
index 640baa6..009b7e9 100644
--- a/constvar/const.go
+++ b/constvar/const.go
@@ -51,6 +51,22 @@
 	StoredProduct                        // 鍙偍瀛樼殑浜у搧
 )
 
+type MaterialMode string
+
+const (
+	MaterialModeRaw      MaterialMode = "鍘熸潗鏂�"
+	MaterialModeSemi     MaterialMode = "鍗婃垚鍝�"
+	MaterialModeFinished MaterialMode = "鎴愬搧"
+)
+
+type MaterialStatus int
+
+const (
+	MaterialStatusCreate   MaterialStatus = iota // 鏂板缓
+	MaterialStatusActive                         // 鍚敤
+	MaterialStatusInactive = -1                  // 鍋滅敤
+)
+
 // InvoicingStrategy 寮�绁ㄧ瓥鐣�
 type InvoicingStrategy int
 
@@ -131,7 +147,7 @@
 const (
 	CostingMethodStandardPrice CostingMethod = iota + 1 //鏍囧噯浠锋牸
 	CostingMethodFIFO                                   //鍏堣繘鍏堝嚭
-	CostingMethodAverageCost                            //
+	CostingMethodAverageCost                            //骞冲潎鎴愭湰
 )
 
 func (t CostingMethod) Valid() bool {
diff --git a/controllers/product_controller.go b/controllers/product_controller.go
index 7c78abc..0f57587 100644
--- a/controllers/product_controller.go
+++ b/controllers/product_controller.go
@@ -2,10 +2,12 @@
 
 import (
 	"github.com/gin-gonic/gin"
+	"github.com/spf13/cast"
 	"wms/extend/code"
 	"wms/extend/util"
 	"wms/models"
 	"wms/request"
+	"wms/utils"
 )
 
 type ProductController struct {
@@ -15,11 +17,11 @@
 // @Tags      浜у搧
 // @Summary   娣诲姞浜у搧
 // @Produce   application/json
-// @Param     object  body  models.Product true  "浜у搧淇℃伅"
+// @Param     object  body  models.Material true  "浜у搧淇℃伅"
 // @Success   200 {object} util.Response "鎴愬姛"
 // @Router    /api-wms/v1/product/addProduct [post]
 func (slf ProductController) AddProduct(c *gin.Context) {
-	var params models.Product
+	var params models.Material
 	if err := c.BindJSON(&params); err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
 		return
@@ -32,7 +34,16 @@
 		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍞环涓嶈兘灏忎簬绛変簬闆�")
 		return
 	}
-	err := models.NewProductSearch().Create(&params)
+	if params.Model == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鐗╂枡绫诲瀷涓嶈兘涓虹┖")
+		return
+	}
+	if params.Unit == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鍗曚綅涓嶈兘涓虹┖")
+		return
+	}
+	params.ID = utils.GetUUID()
+	err := models.NewMaterialSearch().Create(&params)
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "浜у搧淇℃伅淇濆瓨澶辫触")
 		return
@@ -45,7 +56,7 @@
 // @Summary   鑾峰彇浜у搧鍒楄〃
 // @Produce   application/json
 // @Param     object  body  request.GetProductList true  "鏌ヨ鍙傛暟"
-// @Success   200 {object} util.ResponseList{data=[]models.Product}	"鎴愬姛"
+// @Success   200 {object} util.ResponseList{data=[]models.Material}	"鎴愬姛"
 // @Router    /api-wms/v1/product/getProductList [post]
 func (slf ProductController) GetProductList(c *gin.Context) {
 	var params request.GetProductList
@@ -53,7 +64,7 @@
 		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
 		return
 	}
-	search := models.NewProductSearch()
+	search := models.NewMaterialSearch()
 	if params.PageInfo.Check() {
 		search.SetPage(params.Page, params.PageSize)
 	}
@@ -70,9 +81,196 @@
 // @Tags      浜у搧
 // @Summary   鑾峰彇浜у搧璇︽儏
 // @Produce   application/json
-// @Param     object  body  request.GetProductList true  "鏌ヨ鍙傛暟"
-// @Success   200 {object} util.ResponseList{data=[]models.Product}	"鎴愬姛"
-// @Router    /api-wms/v1/product/getProductList [post]
+// @Param		id	path		string			true	"id"  "鏌ヨ鍙傛暟"
+// @Success   200 {object} util.Response{data=models.Material}	"鎴愬姛"
+// @Router    /api-wms/v1/product/getProductDetails/{id} [get]
 func (slf ProductController) GetProductDetails(c *gin.Context) {
+	id := c.Param("id")
+	if id == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥id")
+		return
+	}
+	material, err := models.NewMaterialSearch().SetID(id).First()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, material)
+}
 
+// UpdateProduct
+// @Tags      浜у搧
+// @Summary   淇敼浜у搧
+// @Produce   application/json
+// @Param     object  body  models.Material true  "浜у搧淇℃伅"
+// @Success   200 {object} util.Response "鎴愬姛"
+// @Router    /api-wms/v1/product/updateProduct [post]
+func (slf ProductController) UpdateProduct(c *gin.Context) {
+	var params models.Material
+	if err := c.BindJSON(&params); err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
+		return
+	}
+	if params.Name == "" {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍚嶇О涓嶈兘涓虹┖")
+		return
+	}
+	if params.SalePrice.IntPart() <= 0 {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍞环涓嶈兘灏忎簬绛変簬闆�")
+		return
+	}
+	if params.Model == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鐗╂枡绫诲瀷涓嶈兘涓虹┖")
+		return
+	}
+	if params.Unit == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鍗曚綅涓嶈兘涓虹┖")
+		return
+	}
+	err := models.NewMaterialSearch().SetID(params.ID).Save(&params)
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧淇℃伅鏇存柊澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, "鏇存柊鎴愬姛")
+}
+
+// DeleteProduct
+// @Tags      浜у搧
+// @Summary   鍒犻櫎浜у搧
+// @Produce   application/json
+// @Param		id	path		string			true	"id"  "鏌ヨ鍙傛暟"
+// @Success   200 {object} util.Response "鎴愬姛"
+// @Router    /api-wms/v1/product/deleteProduct/{id} [delete]
+func (slf ProductController) DeleteProduct(c *gin.Context) {
+	id := c.Param("id")
+	if id == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥id")
+		return
+	}
+	err := models.NewMaterialSearch().SetID(id).Delete()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍒犻櫎澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, "鍒犻櫎鎴愬姛")
+}
+
+// AddProductCategory
+// @Tags      浜у搧绫诲瀷
+// @Summary   娣诲姞浜у搧绫诲瀷
+// @Produce   application/json
+// @Param     object  body  models.ProductCategory true  "浜у搧绫诲瀷淇℃伅"
+// @Success   200 {object} util.Response "鎴愬姛"
+// @Router    /api-wms/v1/product/addProductCategory [post]
+func (slf ProductController) AddProductCategory(c *gin.Context) {
+	var params models.ProductCategory
+	if err := c.BindJSON(&params); err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
+		return
+	}
+	if params.Name == "" {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧绫诲瀷鍚嶇О涓嶈兘涓虹┖")
+		return
+	}
+	err := models.NewProductCategorySearch().Create(&params)
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧绫诲瀷淇℃伅淇濆瓨澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, "淇濆瓨鎴愬姛")
+}
+
+// GetProductCategoryList
+// @Tags      浜у搧绫诲瀷
+// @Summary   鑾峰彇浜у搧绫诲瀷鍒楄〃
+// @Produce   application/json
+// @Param     object  body  request.GetProductList true  "鏌ヨ鍙傛暟"
+// @Success   200 {object} util.ResponseList{data=[]models.ProductCategory}	"鎴愬姛"
+// @Router    /api-wms/v1/product/getProductCategoryList [post]
+func (slf ProductController) GetProductCategoryList(c *gin.Context) {
+	var params request.GetProductList
+	if err := c.BindJSON(&params); err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
+		return
+	}
+	search := models.NewProductCategorySearch()
+	if params.PageInfo.Check() {
+		search.SetPage(params.Page, params.PageSize)
+	}
+	list, total, err := search.SetKeyword(params.KeyWord).SetOrder("created_at desc").Find()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
+		return
+	}
+
+	util.ResponseFormatList(c, code.Success, list, int(total))
+}
+
+// GetProductCategoryDetails
+// @Tags      浜у搧绫诲瀷
+// @Summary   鑾峰彇浜у搧绫诲瀷璇︽儏
+// @Produce   application/json
+// @Param		id	path		string			true	"id"  "鏌ヨ鍙傛暟"
+// @Success   200 {object} util.Response{data=models.Material}	"鎴愬姛"
+// @Router    /api-wms/v1/product/getProductCategoryDetails/{id} [get]
+func (slf ProductController) GetProductCategoryDetails(c *gin.Context) {
+	id := c.Param("id")
+	if id == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥id")
+		return
+	}
+
+	first, err := models.NewProductCategorySearch().SetID(cast.ToUint(id)).First()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, first)
+}
+
+// UpdateProductCategory
+// @Tags      浜у搧绫诲瀷
+// @Summary   淇敼浜у搧绫诲瀷
+// @Produce   application/json
+// @Param     object  body  models.ProductCategory true  "浜у搧淇℃伅"
+// @Success   200 {object} util.Response "鎴愬姛"
+// @Router    /api-wms/v1/product/updateProductCategory [post]
+func (slf ProductController) UpdateProductCategory(c *gin.Context) {
+	var params models.ProductCategory
+	if err := c.BindJSON(&params); err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
+		return
+	}
+	if params.Name == "" {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧绫诲瀷鍚嶇О涓嶈兘涓虹┖")
+		return
+	}
+	err := models.NewProductCategorySearch().SetID(params.ID).Save(&params)
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧绫诲瀷淇℃伅鏇存柊澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, "鏇存柊鎴愬姛")
+}
+
+// DeleteProductCategory
+// @Tags      浜у搧绫诲瀷
+// @Summary   鍒犻櫎浜у搧绫诲瀷
+// @Produce   application/json
+// @Param		id	path		string			true	"id"  "鏌ヨ鍙傛暟"
+// @Success   200 {object} util.Response "鎴愬姛"
+// @Router    /api-wms/v1/product/deleteProductCategory/{id} [delete]
+func (slf ProductController) DeleteProductCategory(c *gin.Context) {
+	id := c.Param("id")
+	if id == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥id")
+		return
+	}
+	err := models.NewProductCategorySearch().SetID(cast.ToUint(id)).Delete()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍒犻櫎澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, "鍒犻櫎鎴愬姛")
 }
diff --git a/docs/docs.go b/docs/docs.go
index d8f9095..dd6d9d1 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -340,7 +340,7 @@
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/models.Product"
+                            "$ref": "#/definitions/models.Material"
                         }
                     }
                 ],
@@ -354,15 +354,141 @@
                 }
             }
         },
-        "/api-wms/v1/product/getProductList": {
+        "/api-wms/v1/product/addProductCategory": {
             "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "娣诲姞浜у搧绫诲瀷",
+                "parameters": [
+                    {
+                        "description": "浜у搧绫诲瀷淇℃伅",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.ProductCategory"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/deleteProduct/{id}": {
+            "delete": {
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
                     "浜у搧"
                 ],
-                "summary": "鑾峰彇浜у搧璇︽儏",
+                "summary": "鍒犻櫎浜у搧",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/deleteProductCategory/{id}": {
+            "delete": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "鍒犻櫎浜у搧绫诲瀷",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductCategoryDetails/{id}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "鑾峰彇浜у搧绫诲瀷璇︽儏",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/util.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/models.Material"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductCategoryList": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "鑾峰彇浜у搧绫诲瀷鍒楄〃",
                 "parameters": [
                     {
                         "description": "鏌ヨ鍙傛暟",
@@ -388,12 +514,157 @@
                                         "data": {
                                             "type": "array",
                                             "items": {
-                                                "$ref": "#/definitions/models.Product"
+                                                "$ref": "#/definitions/models.ProductCategory"
                                             }
                                         }
                                     }
                                 }
                             ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductDetails/{id}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧"
+                ],
+                "summary": "鑾峰彇浜у搧璇︽儏",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/util.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/models.Material"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductList": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧"
+                ],
+                "summary": "鑾峰彇浜у搧鍒楄〃",
+                "parameters": [
+                    {
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.GetProductList"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/util.ResponseList"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": "#/definitions/models.Material"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/updateProduct": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧"
+                ],
+                "summary": "淇敼浜у搧",
+                "parameters": [
+                    {
+                        "description": "浜у搧淇℃伅",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.Material"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/updateProductCategory": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "淇敼浜у搧绫诲瀷",
+                "parameters": [
+                    {
+                        "description": "浜у搧淇℃伅",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.ProductCategory"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
                         }
                     }
                 }
@@ -707,6 +978,52 @@
                 "BaseOperationTypeInternal"
             ]
         },
+        "constvar.CostingMethod": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-comments": {
+                "CostingMethodAverageCost": "骞冲潎鎴愭湰",
+                "CostingMethodFIFO": "鍏堣繘鍏堝嚭",
+                "CostingMethodStandardPrice": "鏍囧噯浠锋牸"
+            },
+            "x-enum-varnames": [
+                "CostingMethodStandardPrice",
+                "CostingMethodFIFO",
+                "CostingMethodAverageCost"
+            ]
+        },
+        "constvar.ForceRemovalStrategy": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-varnames": [
+                "ForceRemovalStrategyFIFO",
+                "ForceRemovalStrategyLIFO",
+                "ForceRemovalStrategyClosestLocation"
+            ]
+        },
+        "constvar.InventoryValuation": {
+            "type": "integer",
+            "enum": [
+                1,
+                2
+            ],
+            "x-enum-comments": {
+                "InventoryValuationAuto": "鑷姩",
+                "InventoryValuationManual": "鎵嬪姩"
+            },
+            "x-enum-varnames": [
+                "InventoryValuationManual",
+                "InventoryValuationAuto"
+            ]
+        },
         "constvar.InvoicingStrategy": {
             "type": "integer",
             "enum": [
@@ -761,6 +1078,19 @@
                 "LocationTypeTransit"
             ]
         },
+        "constvar.MaterialMode": {
+            "type": "string",
+            "enum": [
+                "鍘熸潗鏂�",
+                "鍗婃垚鍝�",
+                "鎴愬搧"
+            ],
+            "x-enum-varnames": [
+                "MaterialModeRaw",
+                "MaterialModeSemi",
+                "MaterialModeFinished"
+            ]
+        },
         "constvar.OperationStatus": {
             "type": "integer",
             "enum": [
@@ -801,24 +1131,6 @@
                 "Task",
                 "Object",
                 "TaskAndObject"
-            ]
-        },
-        "constvar.ProductType": {
-            "type": "integer",
-            "enum": [
-                1,
-                2,
-                3
-            ],
-            "x-enum-comments": {
-                "Consumables": "娑堣�楀搧",
-                "Server": "鏈嶅姟",
-                "StoredProduct": "鍙偍瀛樼殑浜у搧"
-            },
-            "x-enum-varnames": [
-                "Consumables",
-                "Server",
-                "StoredProduct"
             ]
         },
         "constvar.ReservationMethod": {
@@ -971,6 +1283,157 @@
                 }
             }
         },
+        "models.Material": {
+            "type": "object",
+            "properties": {
+                "HSCode": {
+                    "type": "string"
+                },
+                "amount": {
+                    "type": "number"
+                },
+                "barcode": {
+                    "description": "鏉$爜",
+                    "type": "string"
+                },
+                "buyExplain": {
+                    "type": "string"
+                },
+                "canBePurchased": {
+                    "description": "鏄惁鍙噰璐�",
+                    "type": "boolean"
+                },
+                "categoryId": {
+                    "description": "浜у搧绫诲埆id",
+                    "type": "integer"
+                },
+                "companyId": {
+                    "type": "integer"
+                },
+                "companyName": {
+                    "type": "string"
+                },
+                "controlStrategy": {
+                    "$ref": "#/definitions/constvar.InvoicingStrategy"
+                },
+                "cost": {
+                    "description": "鎴愭湰",
+                    "type": "number"
+                },
+                "currencyName": {
+                    "type": "string"
+                },
+                "customerTaxes": {
+                    "description": "瀹㈡埛绋庣櫨鍒嗘瘮",
+                    "type": "number"
+                },
+                "deliveryAdvanceTime": {
+                    "type": "integer"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "inStorageExplain": {
+                    "type": "string"
+                },
+                "internalNotes": {
+                    "description": "鍐呴儴璇存槑",
+                    "type": "string"
+                },
+                "internalReference": {
+                    "description": "鍐呴儴鍙傝��",
+                    "type": "string"
+                },
+                "internalTransferExplain": {
+                    "type": "string"
+                },
+                "invoicingStrategy": {
+                    "description": "wms娣诲姞瀛楁",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.InvoicingStrategy"
+                        }
+                    ]
+                },
+                "isSale": {
+                    "description": "PurchaseType      constvar.PurchaseType ` + "`" + `gorm:\"type:int(11);comment:閲囪喘绫诲瀷\" json:\"purchaseType\"` + "`" + `",
+                    "type": "boolean"
+                },
+                "maxInventory": {
+                    "type": "number"
+                },
+                "minInventory": {
+                    "description": "Explain           string                  ` + "`" + `gorm:\"type:varchar(512);comment:缂栧彿璇存槑\" json:\"explain\"` + "`" + `\nCodeStandardID    string                  ` + "`" + `gorm:\"type:varchar(191);comment:缂栫爜瑙勮寖ID\" json:\"codeStandardID\"` + "`" + `\nSpecs             string                  ` + "`" + `gorm:\"type:varchar(191);comment:鐗╂枡瑙勬牸\" json:\"specs\"` + "`" + `\nType              string                  ` + "`" + `gorm:\"type:varchar(191);comment:鐗╂枡鍨嬪彿\" json:\"type\"` + "`" + `",
+                    "type": "number"
+                },
+                "minPurchaseAmount": {
+                    "description": "PurchaseAheadDay  int                     ` + "`" + `gorm:\"type:int(11);comment:閲囪喘鎻愬墠鏈�(澶�)\" json:\"purchaseAheadDay\"` + "`" + `\nProduceAheadDay   int                     ` + "`" + `gorm:\"type:int(11);comment:鍒堕�犳彁鍓嶆湡(澶�)\" json:\"produceAheadDay\"` + "`" + `",
+                    "type": "number"
+                },
+                "model": {
+                    "description": "MaterialType constvar.ProductType  ` + "`" + `gorm:\"index;type:int(11);comment:鐗╂枡绫诲瀷(鏁板瓧)\" json:\"materialType\"` + "`" + `",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.MaterialMode"
+                        }
+                    ]
+                },
+                "name": {
+                    "type": "string"
+                },
+                "orderCreation": {
+                    "$ref": "#/definitions/constvar.OrderCreation"
+                },
+                "originCountryId": {
+                    "type": "integer"
+                },
+                "originCountryName": {
+                    "type": "string"
+                },
+                "outStorageExplain": {
+                    "type": "string"
+                },
+                "principal": {
+                    "description": "璐熻矗浜�",
+                    "type": "string"
+                },
+                "productTagId": {
+                    "description": "浜у搧鏍囩",
+                    "type": "integer"
+                },
+                "productTagName": {
+                    "type": "string"
+                },
+                "purchasePrice": {
+                    "type": "number"
+                },
+                "salePrice": {
+                    "type": "number"
+                },
+                "selectProduct": {
+                    "type": "integer"
+                },
+                "sellExplain": {
+                    "type": "string"
+                },
+                "supplier": {
+                    "description": "FSource           string                  ` + "`" + `gorm:\"type:varchar(191);comment:鐢熶骇杞﹂棿\" json:\"-\"` + "`" + `\nStatus            constvar.MaterialStatus ` + "`" + `gorm:\"type:int(11);comment:鐘舵�乗" json:\"status\"` + "`" + `",
+                    "type": "string"
+                },
+                "unit": {
+                    "description": "LockAmount        decimal.Decimal         ` + "`" + `gorm:\"type:decimal(35,18);default:0;comment:閿佸畾鏁伴噺\" json:\"lockAmount\"` + "`" + `",
+                    "type": "string"
+                },
+                "volume": {
+                    "description": "浣撶Н",
+                    "type": "number"
+                },
+                "weight": {
+                    "description": "閲嶉噺",
+                    "type": "number"
+                }
+            }
+        },
         "models.OperationType": {
             "type": "object",
             "properties": {
@@ -1085,150 +1548,50 @@
                 }
             }
         },
-        "models.Product": {
+        "models.ProductCategory": {
             "type": "object",
             "properties": {
-                "HSCode": {
-                    "type": "string"
+                "costingMethod": {
+                    "description": "鎴愭湰鏂规硶",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.CostingMethod"
+                        }
+                    ]
                 },
-                "barcode": {
-                    "description": "鏉$爜",
-                    "type": "string"
-                },
-                "buyExplain": {
-                    "type": "string"
-                },
-                "canBePurchased": {
-                    "description": "鏄惁鍙噰璐�",
-                    "type": "boolean"
-                },
-                "canBeSell": {
-                    "description": "鏄惁閿�鍞�",
-                    "type": "boolean"
-                },
-                "categoryId": {
-                    "description": "浜у搧鍒嗙被id",
-                    "type": "integer"
-                },
-                "companyId": {
-                    "type": "integer"
-                },
-                "companyName": {
-                    "type": "string"
-                },
-                "controlStrategy": {
-                    "$ref": "#/definitions/constvar.InvoicingStrategy"
-                },
-                "cost": {
-                    "description": "鎴愭湰",
-                    "type": "number"
-                },
-                "createTime": {
-                    "type": "string"
-                },
-                "currencyId": {
-                    "type": "integer"
-                },
-                "currencyName": {
-                    "type": "string"
-                },
-                "customerAdvanceTime": {
-                    "type": "number"
-                },
-                "customerTaxes": {
-                    "description": "瀹㈡埛绋庣櫨鍒嗘瘮",
-                    "type": "number"
-                },
-                "deliveryAdvanceTime": {
-                    "type": "number"
+                "forceRemovalStrategy": {
+                    "description": "寮哄埗涓嬫灦绛栫暐",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ForceRemovalStrategy"
+                        }
+                    ]
                 },
                 "id": {
                     "type": "integer"
                 },
-                "inStorageExplain": {
-                    "type": "string"
-                },
-                "internalNotes": {
-                    "description": "鍐呴儴璇存槑",
-                    "type": "string"
-                },
-                "internalReference": {
-                    "description": "鍐呴儴鍙傝��",
-                    "type": "string"
-                },
-                "internalTransferExplain": {
-                    "type": "string"
-                },
-                "invoicingStrategy": {
-                    "$ref": "#/definitions/constvar.InvoicingStrategy"
-                },
-                "name": {
-                    "description": "浜у搧鍚嶇О",
-                    "type": "string"
-                },
-                "objectTemplateId": {
-                    "type": "string"
-                },
-                "orderCreation": {
-                    "$ref": "#/definitions/constvar.OrderCreation"
-                },
-                "originCountryId": {
-                    "type": "integer"
-                },
-                "originCountryName": {
-                    "type": "string"
-                },
-                "outStorageExplain": {
-                    "type": "string"
-                },
-                "price": {
-                    "type": "number"
-                },
-                "principal": {
-                    "description": "璐熻矗浜�",
-                    "type": "string"
-                },
-                "productTagId": {
-                    "description": "浜у搧鏍囩",
-                    "type": "integer"
-                },
-                "productTagName": {
-                    "type": "string"
-                },
-                "salePrice": {
-                    "description": "閿�鍞环鏍�",
-                    "type": "number"
-                },
-                "selectProduct": {
-                    "type": "integer"
-                },
-                "sellExplain": {
-                    "type": "string"
-                },
-                "supplierId": {
-                    "type": "integer"
-                },
-                "supplierName": {
-                    "type": "string"
-                },
-                "type": {
-                    "description": "浜у搧绫诲瀷",
+                "inventoryValuation": {
+                    "description": "搴撳瓨璁′环",
                     "allOf": [
                         {
-                            "$ref": "#/definitions/constvar.ProductType"
+                            "$ref": "#/definitions/constvar.InventoryValuation"
                         }
                     ]
                 },
-                "updateTime": {
+                "name": {
+                    "description": "浣嶇疆鍚嶇О",
                     "type": "string"
                 },
-                "volume": {
-                    "description": "浣撶Н",
-                    "type": "number"
+                "parentId": {
+                    "description": "涓婄骇id",
+                    "type": "integer"
                 },
-                "weight": {
-                    "description": "閲嶉噺",
-                    "type": "number"
+                "routeId": {
+                    "type": "integer"
+                },
+                "routeName": {
+                    "description": "鍏徃",
+                    "type": "string"
                 }
             }
         },
@@ -1706,6 +2069,8 @@
 	Description:      "",
 	InfoInstanceName: "swagger",
 	SwaggerTemplate:  docTemplate,
+	LeftDelim:        "{{",
+	RightDelim:       "}}",
 }
 
 func init() {
diff --git a/docs/swagger.json b/docs/swagger.json
index 85fbd31..1435b82 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -328,7 +328,7 @@
                         "in": "body",
                         "required": true,
                         "schema": {
-                            "$ref": "#/definitions/models.Product"
+                            "$ref": "#/definitions/models.Material"
                         }
                     }
                 ],
@@ -342,15 +342,141 @@
                 }
             }
         },
-        "/api-wms/v1/product/getProductList": {
+        "/api-wms/v1/product/addProductCategory": {
             "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "娣诲姞浜у搧绫诲瀷",
+                "parameters": [
+                    {
+                        "description": "浜у搧绫诲瀷淇℃伅",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.ProductCategory"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/deleteProduct/{id}": {
+            "delete": {
                 "produces": [
                     "application/json"
                 ],
                 "tags": [
                     "浜у搧"
                 ],
-                "summary": "鑾峰彇浜у搧璇︽儏",
+                "summary": "鍒犻櫎浜у搧",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/deleteProductCategory/{id}": {
+            "delete": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "鍒犻櫎浜у搧绫诲瀷",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductCategoryDetails/{id}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "鑾峰彇浜у搧绫诲瀷璇︽儏",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/util.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/models.Material"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductCategoryList": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "鑾峰彇浜у搧绫诲瀷鍒楄〃",
                 "parameters": [
                     {
                         "description": "鏌ヨ鍙傛暟",
@@ -376,12 +502,157 @@
                                         "data": {
                                             "type": "array",
                                             "items": {
-                                                "$ref": "#/definitions/models.Product"
+                                                "$ref": "#/definitions/models.ProductCategory"
                                             }
                                         }
                                     }
                                 }
                             ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductDetails/{id}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧"
+                ],
+                "summary": "鑾峰彇浜у搧璇︽儏",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/util.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/models.Material"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/getProductList": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧"
+                ],
+                "summary": "鑾峰彇浜у搧鍒楄〃",
+                "parameters": [
+                    {
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.GetProductList"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/util.ResponseList"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": "#/definitions/models.Material"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/updateProduct": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧"
+                ],
+                "summary": "淇敼浜у搧",
+                "parameters": [
+                    {
+                        "description": "浜у搧淇℃伅",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.Material"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api-wms/v1/product/updateProductCategory": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "浜у搧绫诲瀷"
+                ],
+                "summary": "淇敼浜у搧绫诲瀷",
+                "parameters": [
+                    {
+                        "description": "浜у搧淇℃伅",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.ProductCategory"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/util.Response"
                         }
                     }
                 }
@@ -695,6 +966,52 @@
                 "BaseOperationTypeInternal"
             ]
         },
+        "constvar.CostingMethod": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-comments": {
+                "CostingMethodAverageCost": "骞冲潎鎴愭湰",
+                "CostingMethodFIFO": "鍏堣繘鍏堝嚭",
+                "CostingMethodStandardPrice": "鏍囧噯浠锋牸"
+            },
+            "x-enum-varnames": [
+                "CostingMethodStandardPrice",
+                "CostingMethodFIFO",
+                "CostingMethodAverageCost"
+            ]
+        },
+        "constvar.ForceRemovalStrategy": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-varnames": [
+                "ForceRemovalStrategyFIFO",
+                "ForceRemovalStrategyLIFO",
+                "ForceRemovalStrategyClosestLocation"
+            ]
+        },
+        "constvar.InventoryValuation": {
+            "type": "integer",
+            "enum": [
+                1,
+                2
+            ],
+            "x-enum-comments": {
+                "InventoryValuationAuto": "鑷姩",
+                "InventoryValuationManual": "鎵嬪姩"
+            },
+            "x-enum-varnames": [
+                "InventoryValuationManual",
+                "InventoryValuationAuto"
+            ]
+        },
         "constvar.InvoicingStrategy": {
             "type": "integer",
             "enum": [
@@ -749,6 +1066,19 @@
                 "LocationTypeTransit"
             ]
         },
+        "constvar.MaterialMode": {
+            "type": "string",
+            "enum": [
+                "鍘熸潗鏂�",
+                "鍗婃垚鍝�",
+                "鎴愬搧"
+            ],
+            "x-enum-varnames": [
+                "MaterialModeRaw",
+                "MaterialModeSemi",
+                "MaterialModeFinished"
+            ]
+        },
         "constvar.OperationStatus": {
             "type": "integer",
             "enum": [
@@ -789,24 +1119,6 @@
                 "Task",
                 "Object",
                 "TaskAndObject"
-            ]
-        },
-        "constvar.ProductType": {
-            "type": "integer",
-            "enum": [
-                1,
-                2,
-                3
-            ],
-            "x-enum-comments": {
-                "Consumables": "娑堣�楀搧",
-                "Server": "鏈嶅姟",
-                "StoredProduct": "鍙偍瀛樼殑浜у搧"
-            },
-            "x-enum-varnames": [
-                "Consumables",
-                "Server",
-                "StoredProduct"
             ]
         },
         "constvar.ReservationMethod": {
@@ -959,6 +1271,157 @@
                 }
             }
         },
+        "models.Material": {
+            "type": "object",
+            "properties": {
+                "HSCode": {
+                    "type": "string"
+                },
+                "amount": {
+                    "type": "number"
+                },
+                "barcode": {
+                    "description": "鏉$爜",
+                    "type": "string"
+                },
+                "buyExplain": {
+                    "type": "string"
+                },
+                "canBePurchased": {
+                    "description": "鏄惁鍙噰璐�",
+                    "type": "boolean"
+                },
+                "categoryId": {
+                    "description": "浜у搧绫诲埆id",
+                    "type": "integer"
+                },
+                "companyId": {
+                    "type": "integer"
+                },
+                "companyName": {
+                    "type": "string"
+                },
+                "controlStrategy": {
+                    "$ref": "#/definitions/constvar.InvoicingStrategy"
+                },
+                "cost": {
+                    "description": "鎴愭湰",
+                    "type": "number"
+                },
+                "currencyName": {
+                    "type": "string"
+                },
+                "customerTaxes": {
+                    "description": "瀹㈡埛绋庣櫨鍒嗘瘮",
+                    "type": "number"
+                },
+                "deliveryAdvanceTime": {
+                    "type": "integer"
+                },
+                "id": {
+                    "type": "string"
+                },
+                "inStorageExplain": {
+                    "type": "string"
+                },
+                "internalNotes": {
+                    "description": "鍐呴儴璇存槑",
+                    "type": "string"
+                },
+                "internalReference": {
+                    "description": "鍐呴儴鍙傝��",
+                    "type": "string"
+                },
+                "internalTransferExplain": {
+                    "type": "string"
+                },
+                "invoicingStrategy": {
+                    "description": "wms娣诲姞瀛楁",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.InvoicingStrategy"
+                        }
+                    ]
+                },
+                "isSale": {
+                    "description": "PurchaseType      constvar.PurchaseType `gorm:\"type:int(11);comment:閲囪喘绫诲瀷\" json:\"purchaseType\"`",
+                    "type": "boolean"
+                },
+                "maxInventory": {
+                    "type": "number"
+                },
+                "minInventory": {
+                    "description": "Explain           string                  `gorm:\"type:varchar(512);comment:缂栧彿璇存槑\" json:\"explain\"`\nCodeStandardID    string                  `gorm:\"type:varchar(191);comment:缂栫爜瑙勮寖ID\" json:\"codeStandardID\"`\nSpecs             string                  `gorm:\"type:varchar(191);comment:鐗╂枡瑙勬牸\" json:\"specs\"`\nType              string                  `gorm:\"type:varchar(191);comment:鐗╂枡鍨嬪彿\" json:\"type\"`",
+                    "type": "number"
+                },
+                "minPurchaseAmount": {
+                    "description": "PurchaseAheadDay  int                     `gorm:\"type:int(11);comment:閲囪喘鎻愬墠鏈�(澶�)\" json:\"purchaseAheadDay\"`\nProduceAheadDay   int                     `gorm:\"type:int(11);comment:鍒堕�犳彁鍓嶆湡(澶�)\" json:\"produceAheadDay\"`",
+                    "type": "number"
+                },
+                "model": {
+                    "description": "MaterialType constvar.ProductType  `gorm:\"index;type:int(11);comment:鐗╂枡绫诲瀷(鏁板瓧)\" json:\"materialType\"`",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.MaterialMode"
+                        }
+                    ]
+                },
+                "name": {
+                    "type": "string"
+                },
+                "orderCreation": {
+                    "$ref": "#/definitions/constvar.OrderCreation"
+                },
+                "originCountryId": {
+                    "type": "integer"
+                },
+                "originCountryName": {
+                    "type": "string"
+                },
+                "outStorageExplain": {
+                    "type": "string"
+                },
+                "principal": {
+                    "description": "璐熻矗浜�",
+                    "type": "string"
+                },
+                "productTagId": {
+                    "description": "浜у搧鏍囩",
+                    "type": "integer"
+                },
+                "productTagName": {
+                    "type": "string"
+                },
+                "purchasePrice": {
+                    "type": "number"
+                },
+                "salePrice": {
+                    "type": "number"
+                },
+                "selectProduct": {
+                    "type": "integer"
+                },
+                "sellExplain": {
+                    "type": "string"
+                },
+                "supplier": {
+                    "description": "FSource           string                  `gorm:\"type:varchar(191);comment:鐢熶骇杞﹂棿\" json:\"-\"`\nStatus            constvar.MaterialStatus `gorm:\"type:int(11);comment:鐘舵�乗" json:\"status\"`",
+                    "type": "string"
+                },
+                "unit": {
+                    "description": "LockAmount        decimal.Decimal         `gorm:\"type:decimal(35,18);default:0;comment:閿佸畾鏁伴噺\" json:\"lockAmount\"`",
+                    "type": "string"
+                },
+                "volume": {
+                    "description": "浣撶Н",
+                    "type": "number"
+                },
+                "weight": {
+                    "description": "閲嶉噺",
+                    "type": "number"
+                }
+            }
+        },
         "models.OperationType": {
             "type": "object",
             "properties": {
@@ -1073,150 +1536,50 @@
                 }
             }
         },
-        "models.Product": {
+        "models.ProductCategory": {
             "type": "object",
             "properties": {
-                "HSCode": {
-                    "type": "string"
+                "costingMethod": {
+                    "description": "鎴愭湰鏂规硶",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.CostingMethod"
+                        }
+                    ]
                 },
-                "barcode": {
-                    "description": "鏉$爜",
-                    "type": "string"
-                },
-                "buyExplain": {
-                    "type": "string"
-                },
-                "canBePurchased": {
-                    "description": "鏄惁鍙噰璐�",
-                    "type": "boolean"
-                },
-                "canBeSell": {
-                    "description": "鏄惁閿�鍞�",
-                    "type": "boolean"
-                },
-                "categoryId": {
-                    "description": "浜у搧鍒嗙被id",
-                    "type": "integer"
-                },
-                "companyId": {
-                    "type": "integer"
-                },
-                "companyName": {
-                    "type": "string"
-                },
-                "controlStrategy": {
-                    "$ref": "#/definitions/constvar.InvoicingStrategy"
-                },
-                "cost": {
-                    "description": "鎴愭湰",
-                    "type": "number"
-                },
-                "createTime": {
-                    "type": "string"
-                },
-                "currencyId": {
-                    "type": "integer"
-                },
-                "currencyName": {
-                    "type": "string"
-                },
-                "customerAdvanceTime": {
-                    "type": "number"
-                },
-                "customerTaxes": {
-                    "description": "瀹㈡埛绋庣櫨鍒嗘瘮",
-                    "type": "number"
-                },
-                "deliveryAdvanceTime": {
-                    "type": "number"
+                "forceRemovalStrategy": {
+                    "description": "寮哄埗涓嬫灦绛栫暐",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ForceRemovalStrategy"
+                        }
+                    ]
                 },
                 "id": {
                     "type": "integer"
                 },
-                "inStorageExplain": {
-                    "type": "string"
-                },
-                "internalNotes": {
-                    "description": "鍐呴儴璇存槑",
-                    "type": "string"
-                },
-                "internalReference": {
-                    "description": "鍐呴儴鍙傝��",
-                    "type": "string"
-                },
-                "internalTransferExplain": {
-                    "type": "string"
-                },
-                "invoicingStrategy": {
-                    "$ref": "#/definitions/constvar.InvoicingStrategy"
-                },
-                "name": {
-                    "description": "浜у搧鍚嶇О",
-                    "type": "string"
-                },
-                "objectTemplateId": {
-                    "type": "string"
-                },
-                "orderCreation": {
-                    "$ref": "#/definitions/constvar.OrderCreation"
-                },
-                "originCountryId": {
-                    "type": "integer"
-                },
-                "originCountryName": {
-                    "type": "string"
-                },
-                "outStorageExplain": {
-                    "type": "string"
-                },
-                "price": {
-                    "type": "number"
-                },
-                "principal": {
-                    "description": "璐熻矗浜�",
-                    "type": "string"
-                },
-                "productTagId": {
-                    "description": "浜у搧鏍囩",
-                    "type": "integer"
-                },
-                "productTagName": {
-                    "type": "string"
-                },
-                "salePrice": {
-                    "description": "閿�鍞环鏍�",
-                    "type": "number"
-                },
-                "selectProduct": {
-                    "type": "integer"
-                },
-                "sellExplain": {
-                    "type": "string"
-                },
-                "supplierId": {
-                    "type": "integer"
-                },
-                "supplierName": {
-                    "type": "string"
-                },
-                "type": {
-                    "description": "浜у搧绫诲瀷",
+                "inventoryValuation": {
+                    "description": "搴撳瓨璁′环",
                     "allOf": [
                         {
-                            "$ref": "#/definitions/constvar.ProductType"
+                            "$ref": "#/definitions/constvar.InventoryValuation"
                         }
                     ]
                 },
-                "updateTime": {
+                "name": {
+                    "description": "浣嶇疆鍚嶇О",
                     "type": "string"
                 },
-                "volume": {
-                    "description": "浣撶Н",
-                    "type": "number"
+                "parentId": {
+                    "description": "涓婄骇id",
+                    "type": "integer"
                 },
-                "weight": {
-                    "description": "閲嶉噺",
-                    "type": "number"
+                "routeId": {
+                    "type": "integer"
+                },
+                "routeName": {
+                    "description": "鍏徃",
+                    "type": "string"
                 }
             }
         },
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 76b7b0e..2d89dc0 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -13,6 +13,41 @@
     - BaseOperationTypeIncoming
     - BaseOperationTypeOutgoing
     - BaseOperationTypeInternal
+  constvar.CostingMethod:
+    enum:
+    - 1
+    - 2
+    - 3
+    type: integer
+    x-enum-comments:
+      CostingMethodAverageCost: 骞冲潎鎴愭湰
+      CostingMethodFIFO: 鍏堣繘鍏堝嚭
+      CostingMethodStandardPrice: 鏍囧噯浠锋牸
+    x-enum-varnames:
+    - CostingMethodStandardPrice
+    - CostingMethodFIFO
+    - CostingMethodAverageCost
+  constvar.ForceRemovalStrategy:
+    enum:
+    - 1
+    - 2
+    - 3
+    type: integer
+    x-enum-varnames:
+    - ForceRemovalStrategyFIFO
+    - ForceRemovalStrategyLIFO
+    - ForceRemovalStrategyClosestLocation
+  constvar.InventoryValuation:
+    enum:
+    - 1
+    - 2
+    type: integer
+    x-enum-comments:
+      InventoryValuationAuto: 鑷姩
+      InventoryValuationManual: 鎵嬪姩
+    x-enum-varnames:
+    - InventoryValuationManual
+    - InventoryValuationAuto
   constvar.InvoicingStrategy:
     enum:
     - 1
@@ -59,6 +94,16 @@
     - LocationTypeInventoryLoss
     - LocationTypeProduction
     - LocationTypeTransit
+  constvar.MaterialMode:
+    enum:
+    - 鍘熸潗鏂�
+    - 鍗婃垚鍝�
+    - 鎴愬搧
+    type: string
+    x-enum-varnames:
+    - MaterialModeRaw
+    - MaterialModeSemi
+    - MaterialModeFinished
   constvar.OperationStatus:
     enum:
     - 1
@@ -93,20 +138,6 @@
     - Task
     - Object
     - TaskAndObject
-  constvar.ProductType:
-    enum:
-    - 1
-    - 2
-    - 3
-    type: integer
-    x-enum-comments:
-      Consumables: 娑堣�楀搧
-      Server: 鏈嶅姟
-      StoredProduct: 鍙偍瀛樼殑浜у搧
-    x-enum-varnames:
-    - Consumables
-    - Server
-    - StoredProduct
   constvar.ReservationMethod:
     enum:
     - 1
@@ -212,6 +243,120 @@
       updateTime:
         type: string
     type: object
+  models.Material:
+    properties:
+      HSCode:
+        type: string
+      amount:
+        type: number
+      barcode:
+        description: 鏉$爜
+        type: string
+      buyExplain:
+        type: string
+      canBePurchased:
+        description: 鏄惁鍙噰璐�
+        type: boolean
+      categoryId:
+        description: 浜у搧绫诲埆id
+        type: integer
+      companyId:
+        type: integer
+      companyName:
+        type: string
+      controlStrategy:
+        $ref: '#/definitions/constvar.InvoicingStrategy'
+      cost:
+        description: 鎴愭湰
+        type: number
+      currencyName:
+        type: string
+      customerTaxes:
+        description: 瀹㈡埛绋庣櫨鍒嗘瘮
+        type: number
+      deliveryAdvanceTime:
+        type: integer
+      id:
+        type: string
+      inStorageExplain:
+        type: string
+      internalNotes:
+        description: 鍐呴儴璇存槑
+        type: string
+      internalReference:
+        description: 鍐呴儴鍙傝��
+        type: string
+      internalTransferExplain:
+        type: string
+      invoicingStrategy:
+        allOf:
+        - $ref: '#/definitions/constvar.InvoicingStrategy'
+        description: wms娣诲姞瀛楁
+      isSale:
+        description: PurchaseType      constvar.PurchaseType `gorm:"type:int(11);comment:閲囪喘绫诲瀷"
+          json:"purchaseType"`
+        type: boolean
+      maxInventory:
+        type: number
+      minInventory:
+        description: |-
+          Explain           string                  `gorm:"type:varchar(512);comment:缂栧彿璇存槑" json:"explain"`
+          CodeStandardID    string                  `gorm:"type:varchar(191);comment:缂栫爜瑙勮寖ID" json:"codeStandardID"`
+          Specs             string                  `gorm:"type:varchar(191);comment:鐗╂枡瑙勬牸" json:"specs"`
+          Type              string                  `gorm:"type:varchar(191);comment:鐗╂枡鍨嬪彿" json:"type"`
+        type: number
+      minPurchaseAmount:
+        description: |-
+          PurchaseAheadDay  int                     `gorm:"type:int(11);comment:閲囪喘鎻愬墠鏈�(澶�)" json:"purchaseAheadDay"`
+          ProduceAheadDay   int                     `gorm:"type:int(11);comment:鍒堕�犳彁鍓嶆湡(澶�)" json:"produceAheadDay"`
+        type: number
+      model:
+        allOf:
+        - $ref: '#/definitions/constvar.MaterialMode'
+        description: MaterialType constvar.ProductType  `gorm:"index;type:int(11);comment:鐗╂枡绫诲瀷(鏁板瓧)"
+          json:"materialType"`
+      name:
+        type: string
+      orderCreation:
+        $ref: '#/definitions/constvar.OrderCreation'
+      originCountryId:
+        type: integer
+      originCountryName:
+        type: string
+      outStorageExplain:
+        type: string
+      principal:
+        description: 璐熻矗浜�
+        type: string
+      productTagId:
+        description: 浜у搧鏍囩
+        type: integer
+      productTagName:
+        type: string
+      purchasePrice:
+        type: number
+      salePrice:
+        type: number
+      selectProduct:
+        type: integer
+      sellExplain:
+        type: string
+      supplier:
+        description: |-
+          FSource           string                  `gorm:"type:varchar(191);comment:鐢熶骇杞﹂棿" json:"-"`
+          Status            constvar.MaterialStatus `gorm:"type:int(11);comment:鐘舵��" json:"status"`
+        type: string
+      unit:
+        description: LockAmount        decimal.Decimal         `gorm:"type:decimal(35,18);default:0;comment:閿佸畾鏁伴噺"
+          json:"lockAmount"`
+        type: string
+      volume:
+        description: 浣撶Н
+        type: number
+      weight:
+        description: 閲嶉噺
+        type: number
+    type: object
   models.OperationType:
     properties:
       ReservationDaysBeforePriority:
@@ -282,106 +427,33 @@
         description: 浠撳簱id
         type: integer
     type: object
-  models.Product:
+  models.ProductCategory:
     properties:
-      HSCode:
-        type: string
-      barcode:
-        description: 鏉$爜
-        type: string
-      buyExplain:
-        type: string
-      canBePurchased:
-        description: 鏄惁鍙噰璐�
-        type: boolean
-      canBeSell:
-        description: 鏄惁閿�鍞�
-        type: boolean
-      categoryId:
-        description: 浜у搧鍒嗙被id
-        type: integer
-      companyId:
-        type: integer
-      companyName:
-        type: string
-      controlStrategy:
-        $ref: '#/definitions/constvar.InvoicingStrategy'
-      cost:
-        description: 鎴愭湰
-        type: number
-      createTime:
-        type: string
-      currencyId:
-        type: integer
-      currencyName:
-        type: string
-      customerAdvanceTime:
-        type: number
-      customerTaxes:
-        description: 瀹㈡埛绋庣櫨鍒嗘瘮
-        type: number
-      deliveryAdvanceTime:
-        type: number
+      costingMethod:
+        allOf:
+        - $ref: '#/definitions/constvar.CostingMethod'
+        description: 鎴愭湰鏂规硶
+      forceRemovalStrategy:
+        allOf:
+        - $ref: '#/definitions/constvar.ForceRemovalStrategy'
+        description: 寮哄埗涓嬫灦绛栫暐
       id:
         type: integer
-      inStorageExplain:
-        type: string
-      internalNotes:
-        description: 鍐呴儴璇存槑
-        type: string
-      internalReference:
-        description: 鍐呴儴鍙傝��
-        type: string
-      internalTransferExplain:
-        type: string
-      invoicingStrategy:
-        $ref: '#/definitions/constvar.InvoicingStrategy'
-      name:
-        description: 浜у搧鍚嶇О
-        type: string
-      objectTemplateId:
-        type: string
-      orderCreation:
-        $ref: '#/definitions/constvar.OrderCreation'
-      originCountryId:
-        type: integer
-      originCountryName:
-        type: string
-      outStorageExplain:
-        type: string
-      price:
-        type: number
-      principal:
-        description: 璐熻矗浜�
-        type: string
-      productTagId:
-        description: 浜у搧鏍囩
-        type: integer
-      productTagName:
-        type: string
-      salePrice:
-        description: 閿�鍞环鏍�
-        type: number
-      selectProduct:
-        type: integer
-      sellExplain:
-        type: string
-      supplierId:
-        type: integer
-      supplierName:
-        type: string
-      type:
+      inventoryValuation:
         allOf:
-        - $ref: '#/definitions/constvar.ProductType'
-        description: 浜у搧绫诲瀷
-      updateTime:
+        - $ref: '#/definitions/constvar.InventoryValuation'
+        description: 搴撳瓨璁′环
+      name:
+        description: 浣嶇疆鍚嶇О
         type: string
-      volume:
-        description: 浣撶Н
-        type: number
-      weight:
-        description: 閲嶉噺
-        type: number
+      parentId:
+        description: 涓婄骇id
+        type: integer
+      routeId:
+        type: integer
+      routeName:
+        description: 鍏徃
+        type: string
     type: object
   models.Warehouse:
     properties:
@@ -902,7 +974,7 @@
         name: object
         required: true
         schema:
-          $ref: '#/definitions/models.Product'
+          $ref: '#/definitions/models.Material'
       produces:
       - application/json
       responses:
@@ -911,6 +983,133 @@
           schema:
             $ref: '#/definitions/util.Response'
       summary: 娣诲姞浜у搧
+      tags:
+      - 浜у搧
+  /api-wms/v1/product/addProductCategory:
+    post:
+      parameters:
+      - description: 浜у搧绫诲瀷淇℃伅
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/models.ProductCategory'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            $ref: '#/definitions/util.Response'
+      summary: 娣诲姞浜у搧绫诲瀷
+      tags:
+      - 浜у搧绫诲瀷
+  /api-wms/v1/product/deleteProduct/{id}:
+    delete:
+      parameters:
+      - description: id
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            $ref: '#/definitions/util.Response'
+      summary: 鍒犻櫎浜у搧
+      tags:
+      - 浜у搧
+  /api-wms/v1/product/deleteProductCategory/{id}:
+    delete:
+      parameters:
+      - description: id
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            $ref: '#/definitions/util.Response'
+      summary: 鍒犻櫎浜у搧绫诲瀷
+      tags:
+      - 浜у搧绫诲瀷
+  /api-wms/v1/product/getProductCategoryDetails/{id}:
+    get:
+      parameters:
+      - description: id
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            allOf:
+            - $ref: '#/definitions/util.Response'
+            - properties:
+                data:
+                  $ref: '#/definitions/models.Material'
+              type: object
+      summary: 鑾峰彇浜у搧绫诲瀷璇︽儏
+      tags:
+      - 浜у搧绫诲瀷
+  /api-wms/v1/product/getProductCategoryList:
+    post:
+      parameters:
+      - description: 鏌ヨ鍙傛暟
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/request.GetProductList'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            allOf:
+            - $ref: '#/definitions/util.ResponseList'
+            - properties:
+                data:
+                  items:
+                    $ref: '#/definitions/models.ProductCategory'
+                  type: array
+              type: object
+      summary: 鑾峰彇浜у搧绫诲瀷鍒楄〃
+      tags:
+      - 浜у搧绫诲瀷
+  /api-wms/v1/product/getProductDetails/{id}:
+    get:
+      parameters:
+      - description: id
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            allOf:
+            - $ref: '#/definitions/util.Response'
+            - properties:
+                data:
+                  $ref: '#/definitions/models.Material'
+              type: object
+      summary: 鑾峰彇浜у搧璇︽儏
       tags:
       - 浜у搧
   /api-wms/v1/product/getProductList:
@@ -933,12 +1132,50 @@
             - properties:
                 data:
                   items:
-                    $ref: '#/definitions/models.Product'
+                    $ref: '#/definitions/models.Material'
                   type: array
               type: object
-      summary: 鑾峰彇浜у搧璇︽儏
+      summary: 鑾峰彇浜у搧鍒楄〃
       tags:
       - 浜у搧
+  /api-wms/v1/product/updateProduct:
+    post:
+      parameters:
+      - description: 浜у搧淇℃伅
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/models.Material'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            $ref: '#/definitions/util.Response'
+      summary: 淇敼浜у搧
+      tags:
+      - 浜у搧
+  /api-wms/v1/product/updateProductCategory:
+    post:
+      parameters:
+      - description: 浜у搧淇℃伅
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/models.ProductCategory'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            $ref: '#/definitions/util.Response'
+      summary: 淇敼浜у搧绫诲瀷
+      tags:
+      - 浜у搧绫诲瀷
   /api-wms/v1/warehouse/operationType:
     get:
       parameters:
diff --git a/go.mod b/go.mod
index 84ea6f9..4a55e73 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@
 	basic.com/aps/nsqclient.git v0.0.0-20230517072415-37491f4a5d25
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/gin-gonic/gin v1.9.0
+	github.com/google/uuid v1.1.2
 	github.com/nsqio/go-nsq v1.1.0
 	github.com/shopspring/decimal v1.3.1
 	github.com/spf13/cast v1.5.0
@@ -14,7 +15,7 @@
 	github.com/swaggo/gin-swagger v1.6.0
 	github.com/swaggo/swag v1.16.1
 	go.uber.org/zap v1.24.0
-	golang.org/x/crypto v0.11.0
+	golang.org/x/crypto v0.12.0
 	google.golang.org/genproto v0.0.0-20230323212658-478b75c54725
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1
 	gorm.io/driver/mysql v1.5.0
@@ -62,9 +63,9 @@
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.8.0 // indirect
 	golang.org/x/arch v0.4.0 // indirect
-	golang.org/x/net v0.12.0 // indirect
-	golang.org/x/sys v0.10.0 // indirect
-	golang.org/x/text v0.11.0 // indirect
+	golang.org/x/net v0.14.0 // indirect
+	golang.org/x/sys v0.11.0 // indirect
+	golang.org/x/text v0.12.0 // indirect
 	golang.org/x/tools v0.11.0 // indirect
 	google.golang.org/protobuf v1.31.0 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
diff --git a/go.sum b/go.sum
index 4aa9e74..3191386 100644
--- a/go.sum
+++ b/go.sum
@@ -165,6 +165,7 @@
 github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
@@ -304,8 +305,8 @@
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
-golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
+golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
+golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -376,8 +377,8 @@
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
-golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
+golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
+golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -440,8 +441,8 @@
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
-golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -453,8 +454,8 @@
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
-golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
diff --git a/models/db.go b/models/db.go
index e32a28e..ed1c78b 100644
--- a/models/db.go
+++ b/models/db.go
@@ -82,8 +82,9 @@
 		OperationDetails{},
 		Scrap{},
 		MoveHistory{},
-		Product{},
+		//Product{},
 		ProductCategory{},
+		Material{},
 	)
 	return err
 }
diff --git a/models/material.go b/models/material.go
new file mode 100644
index 0000000..26bd05e
--- /dev/null
+++ b/models/material.go
@@ -0,0 +1,474 @@
+package models
+
+import (
+	"fmt"
+	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
+	"wms/constvar"
+	"wms/pkg/mysqlx"
+)
+
+type (
+	// Material 鐗╂枡
+	Material struct {
+		BaseModelString
+		Name string `gorm:"unique;type:varchar(191);not null;comment:鐗╂枡鍚嶇О" json:"name"`
+		//MaterialType constvar.ProductType  `gorm:"index;type:int(11);comment:鐗╂枡绫诲瀷(鏁板瓧)" json:"materialType"`
+		Model constvar.MaterialMode `gorm:"type:varchar(191);not null;comment:鐗╂枡绫诲瀷(瀛楃涓�)" json:"model"`
+		//Explain           string                  `gorm:"type:varchar(512);comment:缂栧彿璇存槑" json:"explain"`
+		//CodeStandardID    string                  `gorm:"type:varchar(191);comment:缂栫爜瑙勮寖ID" json:"codeStandardID"`
+		//Specs             string                  `gorm:"type:varchar(191);comment:鐗╂枡瑙勬牸" json:"specs"`
+		//Type              string                  `gorm:"type:varchar(191);comment:鐗╂枡鍨嬪彿" json:"type"`
+		MinInventory decimal.Decimal `gorm:"type:decimal(35,18);comment:鏈�灏忓簱瀛�" json:"minInventory"`
+		MaxInventory decimal.Decimal `gorm:"type:decimal(35,18);comment:鏈�澶у簱瀛�" json:"maxInventory"`
+		Amount       decimal.Decimal `gorm:"type:decimal(35,18);comment:鏁伴噺" json:"amount"`
+		//LockAmount        decimal.Decimal         `gorm:"type:decimal(35,18);default:0;comment:閿佸畾鏁伴噺" json:"lockAmount"`
+		Unit string `gorm:"type:varchar(100);comment:鍗曚綅" json:"unit"`
+		//Note              string                  `gorm:"type:varchar(1024);comment:澶囨敞" json:"note"`
+		TemplateID string `gorm:"type:varchar(191);comment:妯℃澘ID" json:"-"`
+		//FSource           string                  `gorm:"type:varchar(191);comment:鐢熶骇杞﹂棿" json:"-"`
+		//Status            constvar.MaterialStatus `gorm:"type:int(11);comment:鐘舵��" json:"status"`
+		Supplier      string          `gorm:"type:varchar(191);comment:渚涘簲鍟�" json:"supplier"`
+		PurchasePrice decimal.Decimal `gorm:"type:decimal(35,18);comment:閲囪喘浠锋牸" json:"purchasePrice"`
+		//PurchaseAheadDay  int                     `gorm:"type:int(11);comment:閲囪喘鎻愬墠鏈�(澶�)" json:"purchaseAheadDay"`
+		//ProduceAheadDay   int                     `gorm:"type:int(11);comment:鍒堕�犳彁鍓嶆湡(澶�)" json:"produceAheadDay"`
+		MinPurchaseAmount decimal.Decimal `gorm:"type:decimal(35,18);comment:鏈�灏忛噰璐噺" json:"minPurchaseAmount"`
+		//PurchaseType      constvar.PurchaseType `gorm:"type:int(11);comment:閲囪喘绫诲瀷" json:"purchaseType"`
+		IsSale    bool            `gorm:"type:tinyint(1);comment:鏄惁閿�鍞�" json:"isSale"`
+		SalePrice decimal.Decimal `gorm:"type:decimal(35,18);comment:閿�鍞崟浠�" json:"salePrice"`
+		AutoIncr  uint            `gorm:"type:int(11);comment:鑷ID;default:0;" json:"-"`
+		//wms娣诲姞瀛楁
+		InvoicingStrategy       constvar.InvoicingStrategy `gorm:"type:int(11);comment:寮�绁ㄧ瓥鐣�" json:"invoicingStrategy"`
+		OrderCreation           constvar.OrderCreation     `gorm:"type:int(11);comment:璁㈠崟鍒涘缓" json:"orderCreation"`
+		CustomerTaxes           decimal.Decimal            `gorm:"type:decimal(20,2);comment:瀹㈡埛绋�" json:"customerTaxes"`     //瀹㈡埛绋庣櫨鍒嗘瘮
+		Cost                    decimal.Decimal            `gorm:"type:decimal(20,2);comment:鎴愭湰" json:"cost"`               //鎴愭湰
+		CategoryId              int                        `gorm:"type:int(11);comment:浜у搧绫诲埆id" json:"categoryId"`           //浜у搧绫诲埆id
+		InternalReference       string                     `gorm:"type:varchar(255);comment:鍐呴儴鍙傝��" json:"internalReference"` //鍐呴儴鍙傝��
+		Barcode                 string                     `gorm:"type:varchar(255);comment:鏉$爜" json:"barcode"`             //鏉$爜
+		ProductTagId            int                        `gorm:"type:int(11);comment:浜у搧鏍囩id" json:"productTagId"`         //浜у搧鏍囩
+		ProductTagName          string                     `gorm:"type:varchar(255);comment:浜у搧鏍囩鍚嶇О" json:"productTagName"`
+		CompanyId               int                        `gorm:"type:int(11);comment:鍏徃id" json:"companyId"`
+		CompanyName             string                     `gorm:"type:varchar(255);comment:鍏徃鍚嶇О" json:"companyName"`
+		InternalNotes           string                     `gorm:"type:varchar(512);comment:鍐呴儴璇存槑" json:"internalNotes"` //鍐呴儴璇存槑
+		SelectProduct           int                        `gorm:"type:int(11);comment:鍙�変骇鍝乮d" json:"selectProduct"`
+		SellExplain             string                     `gorm:"type:varchar(512);comment:閿�鍞鏄�" json:"sellExplain"`
+		CanBePurchased          bool                       `gorm:"type:int(11);comment:鏄惁鍙噰璐�" json:"canBePurchased"` //鏄惁鍙噰璐�
+		CurrencyName            string                     `gorm:"type:varchar(255);comment:甯佺鍚嶇О" json:"currencyName"`
+		DeliveryAdvanceTime     int                        `gorm:"type:int(11);comment:浜よ揣鎻愬墠鏃堕棿(澶�)" json:"deliveryAdvanceTime"`
+		ControlStrategy         constvar.InvoicingStrategy `gorm:"type:int(11);comment:鎺у埗绛栫暐" json:"controlStrategy"`
+		BuyExplain              string                     `gorm:"type:varchar(512);comment:閲囪喘璇存槑" json:"buyExplain"`
+		Principal               string                     `gorm:"type:varchar(255);comment:璐熻矗浜�" json:"principal"` //璐熻矗浜�
+		Weight                  decimal.Decimal            `gorm:"type:decimal(20,2);comment:閲嶉噺" json:"weight"`    //閲嶉噺
+		Volume                  decimal.Decimal            `gorm:"type:decimal(20,2);comment:浣撶Н" json:"volume"`    //浣撶Н
+		HSCode                  string                     `gorm:"type:varchar(255);comment:HS缂栫爜" json:"HSCode"`
+		OriginCountryId         int                        `gorm:"type:int(11);comment:鍘熶骇鍦癷d" json:"originCountryId"`
+		OriginCountryName       string                     `gorm:"type:varchar(255);comment:鍘熶骇鍦板悕绉�" json:"originCountryName"`
+		InStorageExplain        string                     `gorm:"type:varchar(512);comment:鍏ュ簱璇存槑" json:"inStorageExplain"`
+		OutStorageExplain       string                     `gorm:"type:varchar(512);comment:鍑哄簱璇存槑" json:"outStorageExplain"`
+		InternalTransferExplain string                     `gorm:"type:varchar(512);comment:鍐呴儴璋冩嫧璇存槑" json:"internalTransferExplain"`
+		//CompanyArr              []IdAndName                `gorm:"-" json:"companyArr"`
+	}
+
+	MaterialSearch struct {
+		Material
+		//MaterialTypes   []constvar.MaterialType
+		Keyword string
+		//SetTemplateType constvar.SetTemplateType
+		Order    string
+		PageNum  int
+		PageSize int
+		Ids      []string
+		Orm      *gorm.DB
+	}
+
+	IdAndName struct {
+		Id   string `json:"id"`
+		Name string `json:"name"`
+	}
+)
+
+func (slf Material) TableName() string {
+	return "material"
+}
+
+func NewMaterialSearch() *MaterialSearch {
+	return &MaterialSearch{Orm: mysqlx.GetDB()}
+}
+
+func (slf *MaterialSearch) SetOrm(tx *gorm.DB) *MaterialSearch {
+	slf.Orm = tx
+	return slf
+}
+
+func (slf *MaterialSearch) SetPage(page, size int) *MaterialSearch {
+	slf.PageNum, slf.PageSize = page, size
+	return slf
+}
+
+func (slf *MaterialSearch) SetOrder(order string) *MaterialSearch {
+	slf.Order = order
+	return slf
+}
+
+func (slf *MaterialSearch) SetID(id string) *MaterialSearch {
+	slf.ID = id
+	return slf
+}
+
+func (slf *MaterialSearch) SetIsSale(isSale bool) *MaterialSearch {
+	slf.IsSale = isSale
+	return slf
+}
+
+func (slf *MaterialSearch) SetIDs(ids []string) *MaterialSearch {
+	slf.Ids = ids
+	return slf
+}
+
+func (slf *MaterialSearch) SetName(name string) *MaterialSearch {
+	slf.Name = name
+	return slf
+}
+
+//func (slf *MaterialSearch) SetMaterialType(materialType constvar.MaterialType) *MaterialSearch {
+//	slf.MaterialType = materialType
+//	return slf
+//}
+//
+//func (slf *MaterialSearch) SetMaterialTypes(materialTypes []constvar.MaterialType) *MaterialSearch {
+//	slf.MaterialTypes = materialTypes
+//	return slf
+//}
+
+func (slf *MaterialSearch) SetKeyword(keyword string) *MaterialSearch {
+	slf.Keyword = keyword
+	return slf
+}
+
+func (slf *MaterialSearch) SetTemplateID(id string) *MaterialSearch {
+	slf.TemplateID = id
+	return slf
+}
+
+//
+//func (slf *MaterialSearch) SetSetTemplateType(setType constvar.SetTemplateType) *MaterialSearch {
+//	slf.SetTemplateType = setType
+//	return slf
+//}
+
+//func (slf *MaterialSearch) SetStatus(status constvar.MaterialStatus) *MaterialSearch {
+//	slf.Status = status
+//	return slf
+//}
+
+func (slf *MaterialSearch) build() *gorm.DB {
+	var db = slf.Orm.Table(slf.TableName())
+
+	if slf.ID != "" {
+		db = db.Where("id = ?", slf.ID)
+	}
+
+	if slf.Name != "" {
+		db = db.Where("name = ?", slf.Name)
+	}
+
+	if slf.TemplateID != "" {
+		db = db.Where("template_id = ?", slf.TemplateID)
+	}
+
+	//if slf.SetTemplateType > 0 {
+	//	if slf.SetTemplateType == constvar.SetTemplateTypeWithTemplate { // 妯℃澘ID闈炵┖
+	//		db = db.Where("template_id <> ?", "")
+	//	} else if slf.SetTemplateType == constvar.SetTemplateTypeWithNoTemplate {
+	//		db = db.Where("template_id = ?", "")
+	//	}
+	//}
+
+	//if slf.MaterialType > 0 {
+	//	db = db.Where("material_type = ?", slf.MaterialType)
+	//}
+
+	//if len(slf.MaterialTypes) > 0 {
+	//	var query string
+	//	for i, materialType := range slf.MaterialTypes {
+	//		if i == 0 {
+	//			query += fmt.Sprintf("(material_type = %d", materialType)
+	//		} else {
+	//			query += fmt.Sprintf(" or material_type = %d", materialType)
+	//		}
+	//		if i == len(slf.MaterialTypes)-1 {
+	//			query += ")"
+	//		}
+	//	}
+	//	db = db.Where(query)
+	//}
+
+	if slf.Keyword != "" {
+		db = db.Where("name LIKE ? or id LIKE ? ", "%"+slf.Keyword+"%", "%"+slf.Keyword+"%")
+	}
+
+	if slf.Order != "" {
+		db = db.Order(slf.Order)
+	}
+
+	//if slf.Status != 0 {
+	//	db = db.Where("status = ?", slf.Status)
+	//}
+	if len(slf.Ids) > 0 {
+		db = db.Where("id in ?", slf.Ids)
+	}
+	if slf.IsSale {
+		db = db.Where("is_sale = ?", 1)
+	}
+
+	return db
+}
+
+// Create 鍗曟潯鎻掑叆
+func (slf *MaterialSearch) Create(record *Material) error {
+	var db = slf.build()
+
+	if err := db.Create(record).Error; err != nil {
+		return fmt.Errorf("create err: %v, record: %+v", err, record)
+	}
+
+	return nil
+}
+
+// CreateBatch 鎵归噺鎻掑叆
+func (slf *MaterialSearch) CreateBatch(records []*Material) error {
+	var db = slf.build()
+
+	if err := db.Create(&records).Error; err != nil {
+		return fmt.Errorf("create batch err: %v, records: %+v", err, records)
+	}
+
+	return nil
+}
+
+func (slf *MaterialSearch) Save(record *Material) error {
+	var db = slf.build()
+
+	if err := db.Omit("CreatedAt").Save(record).Error; err != nil {
+		return fmt.Errorf("save err: %v, record: %+v", err, record)
+	}
+
+	return nil
+}
+
+func (slf *MaterialSearch) UpdateByMap(upMap map[string]interface{}) error {
+	var (
+		db = slf.build()
+	)
+
+	if err := db.Updates(upMap).Error; err != nil {
+		return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
+	}
+
+	return nil
+}
+
+func (slf *MaterialSearch) UpdateByQuery(query string, args []interface{}, upMap map[string]interface{}) error {
+	var (
+		db = slf.Orm.Table(slf.TableName()).Where(query, args...)
+	)
+
+	if err := db.Updates(upMap).Error; err != nil {
+		return fmt.Errorf("update by query err: %v, query: %s, args: %+v, upMap: %+v", err, query, args, upMap)
+	}
+
+	return nil
+}
+
+func (slf *MaterialSearch) Delete() error {
+	var db = slf.build()
+
+	if err := db.Unscoped().Delete(&Material{}).Error; err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (slf *MaterialSearch) First() (*Material, error) {
+	var (
+		record = new(Material)
+		db     = slf.build()
+	)
+
+	if err := db.First(record).Error; err != nil {
+		return record, err
+	}
+
+	return record, nil
+}
+
+func (slf *MaterialSearch) Find() ([]*Material, int64, error) {
+	var (
+		records = make([]*Material, 0)
+		total   int64
+		db      = slf.build()
+	)
+
+	if err := db.Count(&total).Error; err != nil {
+		return records, total, fmt.Errorf("find count err: %v", err)
+	}
+	if slf.PageNum*slf.PageSize > 0 {
+		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+	}
+	if err := db.Find(&records).Error; err != nil {
+		return records, total, fmt.Errorf("find records err: %v", err)
+	}
+
+	return records, total, nil
+}
+
+func (slf *MaterialSearch) FindNotTotal() ([]*Material, error) {
+	var (
+		records = make([]*Material, 0)
+		db      = slf.build()
+	)
+
+	if slf.PageNum*slf.PageSize > 0 {
+		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+	}
+	if err := db.Find(&records).Error; err != nil {
+		return records, fmt.Errorf("find records err: %v", err)
+	}
+
+	return records, nil
+}
+
+// FindByQuery 鎸囧畾鏉′欢鏌ヨ.
+func (slf *MaterialSearch) FindByQuery(query string, args []interface{}) ([]*Material, int64, error) {
+	var (
+		records = make([]*Material, 0)
+		total   int64
+		db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
+	)
+
+	if err := db.Count(&total).Error; err != nil {
+		return records, total, fmt.Errorf("find by query count err: %v", err)
+	}
+	if slf.PageNum*slf.PageSize > 0 {
+		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+	}
+	if err := db.Find(&records).Error; err != nil {
+		return records, total, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
+	}
+
+	return records, total, nil
+}
+
+// FindByQueryNotTotal 鎸囧畾鏉′欢鏌ヨ&涓嶆煡璇㈡�绘潯鏁�.
+func (slf *MaterialSearch) FindByQueryNotTotal(query string, args []interface{}) ([]*Material, error) {
+	var (
+		records = make([]*Material, 0)
+		db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
+	)
+
+	if slf.PageNum*slf.PageSize > 0 {
+		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+	}
+	if err := db.Find(&records).Error; err != nil {
+		return records, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
+	}
+
+	return records, nil
+}
+
+//func (slf *MaterialSearch) Upsert(materialList []*Material) error {
+//	var buffer bytes.Buffer
+//	sql := fmt.Sprintf("insert into `%s` (`id`,`created_at`,`updated_at`,`name`,`model`,`material_type`,`explain`,`code_standard_id`,`specs`,"+
+//		"`type`,`min_inventory`,`max_inventory`,`amount`,`unit`,`note`,`f_source`, `purchase_type`) values", slf.TableName())
+//	if _, err := buffer.WriteString(sql); err != nil {
+//		return err
+//	}
+//
+//	for i, e := range materialList {
+//		buffer.WriteString(fmt.Sprintf("('%v','%v','%v','%v','%v','%v','%v','%v','%v','%v','%v','%v','%v','%v','%v','%v', '%d')", e.ID, e.CreatedAt.String(), e.UpdatedAt.String(), e.Name,
+//			e.Model, e.MaterialType, e.Explain, e.CodeStandardID, e.Specs, e.Type, e.MinInventory, e.MaxInventory, e.Amount, e.Unit, e.Note, e.FSource, int(e.PurchaseType)))
+//		if i == len(materialList)-1 {
+//			buffer.WriteString("")
+//		} else {
+//			buffer.WriteString(",")
+//		}
+//	}
+//	buffer.WriteString(fmt.Sprintf("on duplicate key update `updated_at`=values(`updated_at`), `name`=values(`name`), `specs`=values(`specs`), `type`=values(`type`), " +
+//		"`min_inventory`=values(`min_inventory`), `max_inventory`=values(`max_inventory`), `amount`=values(`amount`), `unit`=values(`unit`), `note`=values(`note`), `f_source`=values(`f_source`), `purchase_type`=values(`purchase_type`);"))
+//	err := slf.Orm.Exec(buffer.String()).Error
+//	if err != nil {
+//		logx.Errorf("Upsert sql:%v, err:%v", buffer.String(), err)
+//	}
+//	return err
+//}
+
+func (slf *MaterialSearch) GetMaterialListByIds(ids []string) ([]*Material, error) {
+	var (
+		records = make([]*Material, 0)
+		db      = slf.Orm.Table(slf.TableName()).Where("id in (?)", ids)
+	)
+
+	if err := db.Find(&records).Error; err != nil {
+		return records, fmt.Errorf("find records err: %v", err)
+	}
+
+	return records, nil
+}
+
+//func ExportMaterial(materials []*Material) (string, error) {
+//	var fileName string
+//	f := excelize.NewFile()
+//
+//	f.SetCellValue("Sheet1", "A1", "鐗╂枡缂栫爜")
+//	f.SetCellValue("Sheet1", "B1", "缂栫爜璇存槑")
+//	f.SetCellValue("Sheet1", "C1", "鐗╂枡鍚嶇О")
+//	f.SetCellValue("Sheet1", "D1", "鐗╂枡瑙勬牸")
+//	f.SetCellValue("Sheet1", "E1", "鐗╂枡鍨嬪彿")
+//	f.SetCellValue("Sheet1", "F1", "渚涘簲鍟�")
+//	f.SetCellValue("Sheet1", "G1", "閲囪喘浠锋牸")
+//	f.SetCellValue("Sheet1", "H1", "瀹夊叏搴撳瓨")
+//	f.SetCellValue("Sheet1", "I1", "鍓╀綑搴撳瓨")
+//	f.SetCellValue("Sheet1", "J1", "鐗╂枡绫诲瀷")
+//	f.SetCellValue("Sheet1", "K1", "鍗曚綅")
+//	f.SetCellValue("Sheet1", "L1", "澶囨敞")
+//
+//	for i, m := range materials {
+//		f.SetCellValue("Sheet1", "A"+strconv.Itoa(i+2), m.ID)
+//		f.SetCellValue("Sheet1", "B"+strconv.Itoa(i+2), m.Explain)
+//		f.SetCellValue("Sheet1", "C"+strconv.Itoa(i+2), m.Name)
+//		f.SetCellValue("Sheet1", "D"+strconv.Itoa(i+2), m.Specs)
+//		f.SetCellValue("Sheet1", "E"+strconv.Itoa(i+2), m.Type)
+//		f.SetCellValue("Sheet1", "F"+strconv.Itoa(i+2), m.Supplier)
+//		f.SetCellValue("Sheet1", "G"+strconv.Itoa(i+2), m.PurchasePrice.String())
+//		f.SetCellValue("Sheet1", "H"+strconv.Itoa(i+2), m.MinInventory.String()+"-"+m.MaxInventory.String())
+//		f.SetCellValue("Sheet1", "I"+strconv.Itoa(i+2), m.Amount.String())
+//		f.SetCellValue("Sheet1", "J"+strconv.Itoa(i+2), m.Model)
+//		f.SetCellValue("Sheet1", "K"+strconv.Itoa(i+2), m.Unit)
+//		f.SetCellValue("Sheet1", "L"+strconv.Itoa(i+2), m.Note)
+//	}
+//
+//	fileName = "material.xlsx"
+//	if err := f.SaveAs(fileName); err != nil {
+//		return fileName, err
+//	}
+//
+//	return fileName, nil
+//}
+
+func (slf *MaterialSearch) MaxAutoIncr() (int64, error) {
+	type Result struct {
+		Max int64
+	}
+
+	var (
+		result Result
+		db     = slf.build()
+	)
+
+	err := db.Select("MAX(auto_incr) as max").Scan(&result).Error
+	if err != nil {
+		return result.Max, fmt.Errorf("max err: %v", err)
+	}
+	return result.Max, nil
+}
diff --git a/models/product.go b/models/product.go
index 66c371d..373ee26 100644
--- a/models/product.go
+++ b/models/product.go
@@ -1,293 +1,294 @@
 package models
 
-import (
-	"fmt"
-	"github.com/shopspring/decimal"
-	"gorm.io/gorm"
-	"wms/constvar"
-	"wms/pkg/mysqlx"
-)
-
-type (
-	// Product 浜у搧
-	Product struct {
-		WmsModel
-		Id                      int                        `gorm:"column:id;primary_key;AUTO_INCREMENT" json:"id"`
-		Name                    string                     `gorm:"index;type:varchar(255);not null;comment:浜у搧鍚嶇О" json:"name"` //浜у搧鍚嶇О
-		Type                    constvar.ProductType       `gorm:"type:int(11);comment:浜у搧绫诲瀷" json:"type"`                     //浜у搧绫诲瀷
-		InvoicingStrategy       constvar.InvoicingStrategy `gorm:"type:int(11);comment:寮�绁ㄧ瓥鐣�" json:"invoicingStrategy"`
-		OrderCreation           constvar.OrderCreation     `gorm:"type:int(11);comment:璁㈠崟鍒涘缓" json:"orderCreation"`
-		ObjectTemplateId        string                     `gorm:"type:varchar(191);comment:椤圭洰妯$増id" json:"objectTemplateId"`
-		SalePrice               decimal.Decimal            `gorm:"type:decimal(35,18);comment:閿�鍞崟浠�" json:"salePrice"`       //閿�鍞环鏍�
-		CustomerTaxes           decimal.Decimal            `gorm:"type:decimal(20,2);comment:瀹㈡埛绋�" json:"customerTaxes"`     //瀹㈡埛绋庣櫨鍒嗘瘮
-		Cost                    decimal.Decimal            `gorm:"type:decimal(20,2);comment:鎴愭湰" json:"cost"`               //鎴愭湰
-		CategoryId              int                        `gorm:"type:int(11);comment:浜у搧绫诲瀷id" json:"categoryId"`           //浜у搧鍒嗙被id
-		InternalReference       string                     `gorm:"type:varchar(255);comment:鍐呴儴鍙傝��" json:"internalReference"` //鍐呴儴鍙傝��
-		Barcode                 string                     `gorm:"type:varchar(255);comment:鏉$爜" json:"barcode"`             //鏉$爜
-		ProductTagId            int                        `gorm:"type:int(11);comment:浜у搧鏍囩id" json:"productTagId"`         //浜у搧鏍囩
-		ProductTagName          string                     `gorm:"type:varchar(255);comment:浜у搧鏍囩鍚嶇О" json:"productTagName"`
-		CompanyId               int                        `gorm:"type:int(11);comment:鍏徃id" json:"companyId"`
-		CompanyName             string                     `gorm:"type:varchar(255);comment:鍏徃鍚嶇О" json:"companyName"`
-		InternalNotes           string                     `gorm:"type:varchar(512);comment:鍐呴儴璇存槑" json:"internalNotes"` //鍐呴儴璇存槑
-		CanBeSell               bool                       `gorm:"type:tinyint(1);comment:鏄惁鍙攢鍞�" json:"canBeSell"`      //鏄惁閿�鍞�
-		SelectProduct           int                        `gorm:"type:int(11);comment:鍙�変骇鍝乮d" json:"selectProduct"`
-		SellExplain             string                     `gorm:"type:varchar(512);comment:閿�鍞鏄�" json:"sellExplain"`
-		CanBePurchased          bool                       `gorm:"type:int(11);comment:鏄惁鍙噰璐�" json:"canBePurchased"` //鏄惁鍙噰璐�
-		SupplierId              int                        `gorm:"type:int(11);comment:渚涘簲鍟唅d" json:"supplierId"`
-		SupplierName            string                     `gorm:"type:varchar(255);comment:渚涘簲鍟嗗悕绉�" json:"supplierName"`
-		Price                   decimal.Decimal            `gorm:"type:decimal(20,2);comment:浠锋牸" json:"price"`
-		CurrencyId              int                        `gorm:"type:int(11);comment:甯佺id" json:"currencyId"`
-		CurrencyName            string                     `gorm:"type:varchar(255);comment:甯佺鍚嶇О" json:"currencyName"`
-		DeliveryAdvanceTime     decimal.Decimal            `gorm:"type:decimal(20,5);comment:鎻愬墠浜よ揣鏃堕棿" json:"deliveryAdvanceTime"`
-		ControlStrategy         constvar.InvoicingStrategy `gorm:"type:int(11);comment:鎺у埗绛栫暐" json:"controlStrategy"`
-		BuyExplain              string                     `gorm:"type:varchar(512);comment:閲囪喘璇存槑" json:"buyExplain"`
-		Principal               string                     `gorm:"type:varchar(255);comment:璐熻矗浜�" json:"principal"` //璐熻矗浜�
-		Weight                  decimal.Decimal            `gorm:"type:decimal(20,2);comment:閲嶉噺" json:"weight"`    //閲嶉噺
-		Volume                  decimal.Decimal            `gorm:"type:decimal(20,2);comment:浣撶Н" json:"volume"`    //浣撶Н
-		CustomerAdvanceTime     decimal.Decimal            `gorm:"type:decimal(20,5);comment:瀹㈡埛鍓嶇疆鏃堕棿" json:"customerAdvanceTime"`
-		HSCode                  string                     `gorm:"type:varchar(255);comment:HS缂栫爜" json:"HSCode"`
-		OriginCountryId         int                        `gorm:"type:int(11);comment:鍘熶骇鍦癷d" json:"originCountryId"`
-		OriginCountryName       string                     `gorm:"type:varchar(255);comment:鍘熶骇鍦板悕绉�" json:"originCountryName"`
-		InStorageExplain        string                     `gorm:"type:varchar(512);comment:鍏ュ簱璇存槑" json:"inStorageExplain"`
-		OutStorageExplain       string                     `gorm:"type:varchar(512);comment:鍑哄簱璇存槑" json:"outStorageExplain"`
-		InternalTransferExplain string                     `gorm:"type:varchar(512);comment:鍐呴儴璋冩嫧璇存槑" json:"internalTransferExplain"`
-	}
-
-	ProductSearch struct {
-		Product
-		Order    string
-		PageNum  int
-		PageSize int
-		Keyword  string
-		Orm      *gorm.DB
-		Preload  bool
-	}
-
-	PurchaseInfo struct {
-		PurchasePrice     decimal.Decimal `gorm:"type:decimal(35,18);comment:閲囪喘浠锋牸" json:"purchasePrice"`
-		PurchaseAheadDay  int             `gorm:"type:int(11);comment:閲囪喘鎻愬墠鏈�(澶�)" json:"purchaseAheadDay"`
-		ProduceAheadDay   int             `gorm:"type:int(11);comment:鍒堕�犳彁鍓嶆湡(澶�)" json:"produceAheadDay"`
-		MinPurchaseAmount decimal.Decimal `gorm:"type:decimal(35,18);comment:鏈�灏忛噰璐噺" json:"minPurchaseAmount"`
-	}
-)
-
-func (slf *Product) TableName() string {
-	return "wms_product"
-}
-
-func (slf *Product) BeforeCreate(db *gorm.DB) error {
-	return nil
-}
-
-func (slf *Product) AfterFind(db *gorm.DB) error {
-	return nil
-}
-
-func NewProductSearch() *ProductSearch {
-	return &ProductSearch{Orm: mysqlx.GetDB()}
-}
-
-func (slf *ProductSearch) SetOrm(tx *gorm.DB) *ProductSearch {
-	slf.Orm = tx
-	return slf
-}
-
-func (slf *ProductSearch) SetPage(page, size int) *ProductSearch {
-	slf.PageNum, slf.PageSize = page, size
-	return slf
-}
-
-func (slf *ProductSearch) SetOrder(order string) *ProductSearch {
-	slf.Order = order
-	return slf
-}
-
-func (slf *ProductSearch) SetID(id uint) *ProductSearch {
-	slf.ID = id
-	return slf
-}
-
-func (slf *ProductSearch) SetName(name string) *ProductSearch {
-	slf.Name = name
-	return slf
-}
-
-func (slf *ProductSearch) SetKeyword(keyword string) *ProductSearch {
-	slf.Keyword = keyword
-	return slf
-}
-
-func (slf *ProductSearch) SetPreload(preload bool) *ProductSearch {
-	slf.Preload = preload
-	return slf
-}
-
-func (slf *ProductSearch) build() *gorm.DB {
-	var db = slf.Orm.Model(&Product{})
-
-	if slf.ID != 0 {
-		db = db.Where("id = ?", slf.ID)
-	}
-
-	if slf.Order != "" {
-		db = db.Order(slf.Order)
-	}
-
-	if slf.Keyword != "" {
-		db = db.Where("name like ?", fmt.Sprintf("%%%v%%", slf.Keyword))
-	}
-
-	if slf.Name != "" {
-		db = db.Where("name = ?", slf.Name)
-	}
-
-	return db
-}
-
-// Create 鍗曟潯鎻掑叆
-func (slf *ProductSearch) Create(record *Product) error {
-	var db = slf.build()
-
-	if err := db.Create(record).Error; err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// CreateBatch 鎵归噺鎻掑叆
-func (slf *ProductSearch) CreateBatch(records []*Product) error {
-	var db = slf.build()
-
-	if err := db.Create(&records).Error; err != nil {
-		return fmt.Errorf("create batch err: %v, records: %+v", err, records)
-	}
-
-	return nil
-}
-
-func (slf *ProductSearch) Update(record *Product) error {
-	var db = slf.build()
-
-	if err := db.Omit("CreatedAt").Updates(record).Error; err != nil {
-		return fmt.Errorf("save err: %v, record: %+v", err, record)
-	}
-
-	return nil
-}
-
-func (slf *ProductSearch) UpdateByMap(upMap map[string]interface{}) error {
-	var (
-		db = slf.build()
-	)
-
-	if err := db.Updates(upMap).Error; err != nil {
-		return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
-	}
-
-	return nil
-}
-
-func (slf *ProductSearch) UpdateByQuery(query string, args []interface{}, upMap map[string]interface{}) error {
-	var (
-		db = slf.Orm.Table(slf.TableName()).Where(query, args...)
-	)
-
-	if err := db.Updates(upMap).Error; err != nil {
-		return fmt.Errorf("update by query err: %v, query: %s, args: %+v, upMap: %+v", err, query, args, upMap)
-	}
-
-	return nil
-}
-
-func (slf *ProductSearch) Delete() error {
-	var db = slf.build()
-	return db.Delete(&Product{}).Error
-}
-
-func (slf *ProductSearch) First() (*Product, error) {
-	var (
-		record = new(Product)
-		db     = slf.build()
-	)
-
-	if err := db.First(record).Error; err != nil {
-		return record, err
-	}
-
-	return record, nil
-}
-
-func (slf *ProductSearch) Find() ([]*Product, int64, error) {
-	var (
-		records = make([]*Product, 0)
-		total   int64
-		db      = slf.build()
-	)
-
-	if err := db.Count(&total).Error; err != nil {
-		return records, total, fmt.Errorf("find count err: %v", err)
-	}
-	if slf.PageNum*slf.PageSize > 0 {
-		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
-	}
-	if err := db.Find(&records).Error; err != nil {
-		return records, total, fmt.Errorf("find records err: %v", err)
-	}
-
-	return records, total, nil
-}
-
-func (slf *ProductSearch) FindNotTotal() ([]*Product, error) {
-	var (
-		records = make([]*Product, 0)
-		db      = slf.build()
-	)
-
-	if slf.PageNum*slf.PageSize > 0 {
-		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
-	}
-	if err := db.Find(&records).Error; err != nil {
-		return records, fmt.Errorf("find records err: %v", err)
-	}
-
-	return records, nil
-}
-
-// FindByQuery 鎸囧畾鏉′欢鏌ヨ.
-func (slf *ProductSearch) FindByQuery(query string, args []interface{}) ([]*Product, int64, error) {
-	var (
-		records = make([]*Product, 0)
-		total   int64
-		db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
-	)
-
-	if err := db.Count(&total).Error; err != nil {
-		return records, total, fmt.Errorf("find by query count err: %v", err)
-	}
-	if slf.PageNum*slf.PageSize > 0 {
-		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
-	}
-	if err := db.Find(&records).Error; err != nil {
-		return records, total, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
-	}
-
-	return records, total, nil
-}
-
-// FindByQueryNotTotal 鎸囧畾鏉′欢鏌ヨ&涓嶆煡璇㈡�绘潯鏁�.
-func (slf *ProductSearch) FindByQueryNotTotal(query string, args []interface{}) ([]*Product, error) {
-	var (
-		records = make([]*Product, 0)
-		db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
-	)
-
-	if slf.PageNum*slf.PageSize > 0 {
-		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
-	}
-	if err := db.Find(&records).Error; err != nil {
-		return records, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
-	}
-
-	return records, nil
-}
+//
+//import (
+//	"fmt"
+//	"github.com/shopspring/decimal"
+//	"gorm.io/gorm"
+//	"wms/constvar"
+//	"wms/pkg/mysqlx"
+//)
+//
+//type (
+//	// Product 浜у搧
+//	Product struct {
+//		WmsModel
+//		Id                      int                        `gorm:"column:id;primary_key;AUTO_INCREMENT" json:"id"`
+//		Name                    string                     `gorm:"index;type:varchar(255);not null;comment:浜у搧鍚嶇О" json:"name"` //浜у搧鍚嶇О
+//		Type                    constvar.ProductType       `gorm:"type:int(11);comment:浜у搧绫诲瀷" json:"type"`                     //浜у搧绫诲瀷
+//		InvoicingStrategy       constvar.InvoicingStrategy `gorm:"type:int(11);comment:寮�绁ㄧ瓥鐣�" json:"invoicingStrategy"`
+//		OrderCreation           constvar.OrderCreation     `gorm:"type:int(11);comment:璁㈠崟鍒涘缓" json:"orderCreation"`
+//		ObjectTemplateId        string                     `gorm:"type:varchar(191);comment:椤圭洰妯$増id" json:"objectTemplateId"`
+//		SalePrice               decimal.Decimal            `gorm:"type:decimal(35,18);comment:閿�鍞崟浠�" json:"salePrice"`       //閿�鍞环鏍�
+//		CustomerTaxes           decimal.Decimal            `gorm:"type:decimal(20,2);comment:瀹㈡埛绋�" json:"customerTaxes"`     //瀹㈡埛绋庣櫨鍒嗘瘮
+//		Cost                    decimal.Decimal            `gorm:"type:decimal(20,2);comment:鎴愭湰" json:"cost"`               //鎴愭湰
+//		CategoryId              int                        `gorm:"type:int(11);comment:浜у搧绫诲瀷id" json:"categoryId"`           //浜у搧鍒嗙被id
+//		InternalReference       string                     `gorm:"type:varchar(255);comment:鍐呴儴鍙傝��" json:"internalReference"` //鍐呴儴鍙傝��
+//		Barcode                 string                     `gorm:"type:varchar(255);comment:鏉$爜" json:"barcode"`             //鏉$爜
+//		ProductTagId            int                        `gorm:"type:int(11);comment:浜у搧鏍囩id" json:"productTagId"`         //浜у搧鏍囩
+//		ProductTagName          string                     `gorm:"type:varchar(255);comment:浜у搧鏍囩鍚嶇О" json:"productTagName"`
+//		CompanyId               int                        `gorm:"type:int(11);comment:鍏徃id" json:"companyId"`
+//		CompanyName             string                     `gorm:"type:varchar(255);comment:鍏徃鍚嶇О" json:"companyName"`
+//		InternalNotes           string                     `gorm:"type:varchar(512);comment:鍐呴儴璇存槑" json:"internalNotes"` //鍐呴儴璇存槑
+//		CanBeSell               bool                       `gorm:"type:tinyint(1);comment:鏄惁鍙攢鍞�" json:"canBeSell"`      //鏄惁閿�鍞�
+//		SelectProduct           int                        `gorm:"type:int(11);comment:鍙�変骇鍝乮d" json:"selectProduct"`
+//		SellExplain             string                     `gorm:"type:varchar(512);comment:閿�鍞鏄�" json:"sellExplain"`
+//		CanBePurchased          bool                       `gorm:"type:int(11);comment:鏄惁鍙噰璐�" json:"canBePurchased"` //鏄惁鍙噰璐�
+//		SupplierId              int                        `gorm:"type:int(11);comment:渚涘簲鍟唅d" json:"supplierId"`
+//		SupplierName            string                     `gorm:"type:varchar(255);comment:渚涘簲鍟嗗悕绉�" json:"supplierName"`
+//		Price                   decimal.Decimal            `gorm:"type:decimal(20,2);comment:浠锋牸" json:"price"`
+//		CurrencyId              int                        `gorm:"type:int(11);comment:甯佺id" json:"currencyId"`
+//		CurrencyName            string                     `gorm:"type:varchar(255);comment:甯佺鍚嶇О" json:"currencyName"`
+//		DeliveryAdvanceTime     decimal.Decimal            `gorm:"type:decimal(20,5);comment:鎻愬墠浜よ揣鏃堕棿" json:"deliveryAdvanceTime"`
+//		ControlStrategy         constvar.InvoicingStrategy `gorm:"type:int(11);comment:鎺у埗绛栫暐" json:"controlStrategy"`
+//		BuyExplain              string                     `gorm:"type:varchar(512);comment:閲囪喘璇存槑" json:"buyExplain"`
+//		Principal               string                     `gorm:"type:varchar(255);comment:璐熻矗浜�" json:"principal"` //璐熻矗浜�
+//		Weight                  decimal.Decimal            `gorm:"type:decimal(20,2);comment:閲嶉噺" json:"weight"`    //閲嶉噺
+//		Volume                  decimal.Decimal            `gorm:"type:decimal(20,2);comment:浣撶Н" json:"volume"`    //浣撶Н
+//		CustomerAdvanceTime     decimal.Decimal            `gorm:"type:decimal(20,5);comment:瀹㈡埛鍓嶇疆鏃堕棿" json:"customerAdvanceTime"`
+//		HSCode                  string                     `gorm:"type:varchar(255);comment:HS缂栫爜" json:"HSCode"`
+//		OriginCountryId         int                        `gorm:"type:int(11);comment:鍘熶骇鍦癷d" json:"originCountryId"`
+//		OriginCountryName       string                     `gorm:"type:varchar(255);comment:鍘熶骇鍦板悕绉�" json:"originCountryName"`
+//		InStorageExplain        string                     `gorm:"type:varchar(512);comment:鍏ュ簱璇存槑" json:"inStorageExplain"`
+//		OutStorageExplain       string                     `gorm:"type:varchar(512);comment:鍑哄簱璇存槑" json:"outStorageExplain"`
+//		InternalTransferExplain string                     `gorm:"type:varchar(512);comment:鍐呴儴璋冩嫧璇存槑" json:"internalTransferExplain"`
+//	}
+//
+//	ProductSearch struct {
+//		Product
+//		Order    string
+//		PageNum  int
+//		PageSize int
+//		Keyword  string
+//		Orm      *gorm.DB
+//		Preload  bool
+//	}
+//
+//	PurchaseInfo struct {
+//		PurchasePrice     decimal.Decimal `gorm:"type:decimal(35,18);comment:閲囪喘浠锋牸" json:"purchasePrice"`
+//		PurchaseAheadDay  int             `gorm:"type:int(11);comment:閲囪喘鎻愬墠鏈�(澶�)" json:"purchaseAheadDay"`
+//		ProduceAheadDay   int             `gorm:"type:int(11);comment:鍒堕�犳彁鍓嶆湡(澶�)" json:"produceAheadDay"`
+//		MinPurchaseAmount decimal.Decimal `gorm:"type:decimal(35,18);comment:鏈�灏忛噰璐噺" json:"minPurchaseAmount"`
+//	}
+//)
+//
+//func (slf *Product) TableName() string {
+//	return "wms_product"
+//}
+//
+//func (slf *Product) BeforeCreate(db *gorm.DB) error {
+//	return nil
+//}
+//
+//func (slf *Product) AfterFind(db *gorm.DB) error {
+//	return nil
+//}
+//
+//func NewProductSearch() *ProductSearch {
+//	return &ProductSearch{Orm: mysqlx.GetDB()}
+//}
+//
+//func (slf *ProductSearch) SetOrm(tx *gorm.DB) *ProductSearch {
+//	slf.Orm = tx
+//	return slf
+//}
+//
+//func (slf *ProductSearch) SetPage(page, size int) *ProductSearch {
+//	slf.PageNum, slf.PageSize = page, size
+//	return slf
+//}
+//
+//func (slf *ProductSearch) SetOrder(order string) *ProductSearch {
+//	slf.Order = order
+//	return slf
+//}
+//
+//func (slf *ProductSearch) SetID(id uint) *ProductSearch {
+//	slf.ID = id
+//	return slf
+//}
+//
+//func (slf *ProductSearch) SetName(name string) *ProductSearch {
+//	slf.Name = name
+//	return slf
+//}
+//
+//func (slf *ProductSearch) SetKeyword(keyword string) *ProductSearch {
+//	slf.Keyword = keyword
+//	return slf
+//}
+//
+//func (slf *ProductSearch) SetPreload(preload bool) *ProductSearch {
+//	slf.Preload = preload
+//	return slf
+//}
+//
+//func (slf *ProductSearch) build() *gorm.DB {
+//	var db = slf.Orm.Model(&Product{})
+//
+//	if slf.ID != 0 {
+//		db = db.Where("id = ?", slf.ID)
+//	}
+//
+//	if slf.Order != "" {
+//		db = db.Order(slf.Order)
+//	}
+//
+//	if slf.Keyword != "" {
+//		db = db.Where("name like ?", fmt.Sprintf("%%%v%%", slf.Keyword))
+//	}
+//
+//	if slf.Name != "" {
+//		db = db.Where("name = ?", slf.Name)
+//	}
+//
+//	return db
+//}
+//
+//// Create 鍗曟潯鎻掑叆
+//func (slf *ProductSearch) Create(record *Product) error {
+//	var db = slf.build()
+//
+//	if err := db.Create(record).Error; err != nil {
+//		return err
+//	}
+//
+//	return nil
+//}
+//
+//// CreateBatch 鎵归噺鎻掑叆
+//func (slf *ProductSearch) CreateBatch(records []*Product) error {
+//	var db = slf.build()
+//
+//	if err := db.Create(&records).Error; err != nil {
+//		return fmt.Errorf("create batch err: %v, records: %+v", err, records)
+//	}
+//
+//	return nil
+//}
+//
+//func (slf *ProductSearch) Update(record *Product) error {
+//	var db = slf.build()
+//
+//	if err := db.Omit("CreatedAt").Updates(record).Error; err != nil {
+//		return fmt.Errorf("save err: %v, record: %+v", err, record)
+//	}
+//
+//	return nil
+//}
+//
+//func (slf *ProductSearch) UpdateByMap(upMap map[string]interface{}) error {
+//	var (
+//		db = slf.build()
+//	)
+//
+//	if err := db.Updates(upMap).Error; err != nil {
+//		return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
+//	}
+//
+//	return nil
+//}
+//
+//func (slf *ProductSearch) UpdateByQuery(query string, args []interface{}, upMap map[string]interface{}) error {
+//	var (
+//		db = slf.Orm.Table(slf.TableName()).Where(query, args...)
+//	)
+//
+//	if err := db.Updates(upMap).Error; err != nil {
+//		return fmt.Errorf("update by query err: %v, query: %s, args: %+v, upMap: %+v", err, query, args, upMap)
+//	}
+//
+//	return nil
+//}
+//
+//func (slf *ProductSearch) Delete() error {
+//	var db = slf.build()
+//	return db.Delete(&Product{}).Error
+//}
+//
+//func (slf *ProductSearch) First() (*Product, error) {
+//	var (
+//		record = new(Product)
+//		db     = slf.build()
+//	)
+//
+//	if err := db.First(record).Error; err != nil {
+//		return record, err
+//	}
+//
+//	return record, nil
+//}
+//
+//func (slf *ProductSearch) Find() ([]*Product, int64, error) {
+//	var (
+//		records = make([]*Product, 0)
+//		total   int64
+//		db      = slf.build()
+//	)
+//
+//	if err := db.Count(&total).Error; err != nil {
+//		return records, total, fmt.Errorf("find count err: %v", err)
+//	}
+//	if slf.PageNum*slf.PageSize > 0 {
+//		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+//	}
+//	if err := db.Find(&records).Error; err != nil {
+//		return records, total, fmt.Errorf("find records err: %v", err)
+//	}
+//
+//	return records, total, nil
+//}
+//
+//func (slf *ProductSearch) FindNotTotal() ([]*Product, error) {
+//	var (
+//		records = make([]*Product, 0)
+//		db      = slf.build()
+//	)
+//
+//	if slf.PageNum*slf.PageSize > 0 {
+//		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+//	}
+//	if err := db.Find(&records).Error; err != nil {
+//		return records, fmt.Errorf("find records err: %v", err)
+//	}
+//
+//	return records, nil
+//}
+//
+//// FindByQuery 鎸囧畾鏉′欢鏌ヨ.
+//func (slf *ProductSearch) FindByQuery(query string, args []interface{}) ([]*Product, int64, error) {
+//	var (
+//		records = make([]*Product, 0)
+//		total   int64
+//		db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
+//	)
+//
+//	if err := db.Count(&total).Error; err != nil {
+//		return records, total, fmt.Errorf("find by query count err: %v", err)
+//	}
+//	if slf.PageNum*slf.PageSize > 0 {
+//		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+//	}
+//	if err := db.Find(&records).Error; err != nil {
+//		return records, total, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
+//	}
+//
+//	return records, total, nil
+//}
+//
+//// FindByQueryNotTotal 鎸囧畾鏉′欢鏌ヨ&涓嶆煡璇㈡�绘潯鏁�.
+//func (slf *ProductSearch) FindByQueryNotTotal(query string, args []interface{}) ([]*Product, error) {
+//	var (
+//		records = make([]*Product, 0)
+//		db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
+//	)
+//
+//	if slf.PageNum*slf.PageSize > 0 {
+//		db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+//	}
+//	if err := db.Find(&records).Error; err != nil {
+//		return records, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
+//	}
+//
+//	return records, nil
+//}
diff --git a/models/product_category.go b/models/product_category.go
index 1658605..b1985d3 100644
--- a/models/product_category.go
+++ b/models/product_category.go
@@ -243,3 +243,13 @@
 
 	return records, nil
 }
+
+func (slf *ProductCategorySearch) Save(record *ProductCategory) error {
+	var db = slf.build()
+
+	if err := db.Omit("CreatedAt").Save(record).Error; err != nil {
+		return fmt.Errorf("save err: %v, record: %+v", err, record)
+	}
+
+	return nil
+}
diff --git a/router/router.go b/router/router.go
index 0df3ac9..926c4af 100644
--- a/router/router.go
+++ b/router/router.go
@@ -73,8 +73,17 @@
 	productController := new(controllers.ProductController)
 	productAPI := r.Group(urlPrefix + "/product")
 	{
-		productAPI.POST("addProduct", productController.AddProduct)         // 鏂板浜у搧
-		productAPI.POST("getProductList", productController.GetProductList) // 鑾峰彇浜у搧鍒楄〃
+		productAPI.POST("addProduct", productController.AddProduct)                  // 鏂板浜у搧
+		productAPI.POST("getProductList", productController.GetProductList)          // 鑾峰彇浜у搧鍒楄〃
+		productAPI.GET("getProductDetails/:id", productController.GetProductDetails) // 鑾峰彇浜у搧璇︽儏
+		productAPI.POST("updateProduct", productController.UpdateProduct)            // 淇敼浜у搧璇︽儏
+		productAPI.DELETE("deleteProduct/:id", productController.DeleteProduct)      // 鍒犻櫎浜у搧
+
+		productAPI.POST("addProductCategory", productController.AddProductCategory)                  //娣诲姞浜у搧绫诲瀷
+		productAPI.POST("getProductCategoryList", productController.GetProductCategoryList)          //鑾峰彇浜у搧绫诲瀷鍒楄〃
+		productAPI.GET("getProductCategoryDetails/:id", productController.GetProductCategoryDetails) //鑾峰彇浜у搧绫诲瀷璇︽儏
+		productAPI.POST("updateProductCategory", productController.UpdateProductCategory)            //淇敼浜у搧绫诲瀷
+		productAPI.DELETE("deleteProductCategory/:id", productController.DeleteProductCategory)      //鍒犻櫎浜у搧绫诲瀷
 	}
 
 	return r
diff --git a/utils/util.go b/utils/util.go
new file mode 100644
index 0000000..61c9c1c
--- /dev/null
+++ b/utils/util.go
@@ -0,0 +1,11 @@
+package utils
+
+import (
+	"github.com/google/uuid"
+	"strings"
+)
+
+func GetUUID() string {
+	s := uuid.New().String()
+	return strings.ReplaceAll(s, "-", "")
+}

--
Gitblit v1.8.0