From 3545b1af80395204e96f748cb6c52cf1dc572606 Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期三, 30 八月 2023 14:34:35 +0800
Subject: [PATCH] merge

---
 proto/quality_inspect.proto                |   15 
 model/purchase/purchase.go                 |  103 +++
 model/purchase/request/purchase.go         |   30 
 model/purchase/purchase_products.go        |   10 
 api/v1/purchase/quality_inspection.go      |  137 +++++
 config.yaml                                |    2 
 service/purchase/quality_inspect.go        |   61 ++
 proto/qualityinspect/quality_inspect.pb.go |  233 +++++---
 docs/swagger.yaml                          |  165 ++++++
 docs/docs.go                               |  248 +++++++++
 docs/swagger.json                          |  248 +++++++++
 api/v1/purchase/purchase.go                |   53 +
 router/purchase/purchase.go                |    8 
 utils/structx.go                           |   16 
 model/purchase/response/purchase.go        |   48 +
 service/purchase/purchase.go               |  105 +++-
 16 files changed, 1,308 insertions(+), 174 deletions(-)

diff --git a/api/v1/purchase/purchase.go b/api/v1/purchase/purchase.go
index c82be66..0a5c918 100644
--- a/api/v1/purchase/purchase.go
+++ b/api/v1/purchase/purchase.go
@@ -1,8 +1,8 @@
 package purchase
 
 import (
+	"fmt"
 	"github.com/gin-gonic/gin"
-	"github.com/mitchellh/mapstructure"
 	"go.uber.org/zap"
 	"gorm.io/gorm"
 	"srm/global"
@@ -12,6 +12,7 @@
 	purchaserequest "srm/model/purchase/request"
 	"strconv"
 	"strings"
+	"time"
 
 	//"srm/model/purchase"
 
@@ -29,19 +30,21 @@
 // @Security  ApiKeyAuth
 // @accept    application/json
 // @Produce   application/json
-// @Param     data  body     purchaserequest.AddPurchase   true  "閲囪喘鍗曠敤鎴峰悕, 閲囪喘鍗曟墜鏈哄彿鐮�"
+// @Param     data  body     purchaserequest.AddPurchase   true  "閲囪喘鍗�,閲囪喘鍗曚骇鍝�"
 // @Success   200   {object}  response.Response{msg=string}  "鍒涘缓閲囪喘鍗�"
 // @Router    /purchase/purchase [post]
 func (e *PurchaseApi) CreatePurchase(c *gin.Context) {
 	var params purchaserequest.AddPurchase
 	err := c.ShouldBindJSON(&params)
 	if err != nil {
+		global.GVA_LOG.Error("Add Purchase failed", zap.Error(err))
 		response.FailWithMessage(err.Error(), c)
 		return
 	}
 
 	var purchaseRecord purchase.Purchase
-	if err := mapstructure.Decode(params.Purchase, &purchaseRecord); err != nil {
+	if err := utils.AssignTo(params.Purchase, &purchaseRecord); err != nil {
+		global.GVA_LOG.Error("Add Purchase failed", zap.Error(err))
 		response.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -50,6 +53,19 @@
 	purchaseRecord.Status = purchase.OrderStatusConfirmed
 	purchaseRecord.HandledBy = "admin"
 	purchaseRecord.Creator = "admin"
+	purchaseRecord.Number = fmt.Sprintf("CG%v", time.Now().Unix())
+	purchaseRecord.Principal = "admin"
+
+	if !purchaseRecord.WholeDiscountType.IsValid(purchaseRecord.TotalPrice, purchaseRecord.WholeDiscount) {
+		response.FailWithMessage("鏁村崟鎶樻墸鏁板�间笉姝g‘", c)
+		return
+	}
+
+	if !purchaseRecord.PriceAdjustmentType.IsValid(purchaseRecord.TotalPrice, purchaseRecord.PriceAdjustment) {
+		response.FailWithMessage("浠锋牸璋冩暣鏁板�间笉姝g‘", c)
+		return
+	}
+
 	err = service.NewPurchaseService().CreatePurchase(&purchaseRecord, params.ProductList)
 
 	if err != nil {
@@ -58,7 +74,7 @@
 			return
 		}
 		global.GVA_LOG.Error("鍒涘缓澶辫触!", zap.Error(err))
-		response.FailWithMessage("鍒涘缓澶辫触", c)
+		response.FailWithMessage(err.Error(), c)
 		return
 	}
 	response.OkWithMessage("鍒涘缓鎴愬姛", c)
@@ -106,7 +122,7 @@
 	}
 
 	var purchaseRecord purchase.Purchase
-	if err := mapstructure.Decode(params.Purchase, &purchaseRecord); err != nil {
+	if err := utils.AssignTo(params.Purchase, &purchaseRecord); err != nil {
 		response.FailWithMessage(err.Error(), c)
 		return
 	}
@@ -149,7 +165,26 @@
 		response.FailWithMessage("鑾峰彇澶辫触", c)
 		return
 	}
-	response.OkWithDetailed(purchaseRes.PurchaseResponse{Purchase: data, ProductList: productList}, "鑾峰彇鎴愬姛", c)
+	respProductList := make([]*purchaseRes.PurchaseProducts, len(productList))
+	err = utils.AssignTo(productList, &respProductList)
+	if err != nil {
+		global.GVA_LOG.Error("鑾峰彇澶辫触!", zap.Error(err))
+		response.FailWithMessage("鑾峰彇澶辫触", c)
+		return
+	}
+	for k, item := range productList {
+		respProductList[k].Amount = item.Amount
+		respProductList[k].Price = item.Price
+		respProductList[k].Total = item.Total
+		err = utils.AssignTo(item.Product, &respProductList[k])
+		if err != nil {
+			global.GVA_LOG.Error("鑾峰彇澶辫触!", zap.Error(err))
+			response.FailWithMessage("鑾峰彇澶辫触", c)
+			return
+		}
+	}
+
+	response.OkWithDetailed(purchaseRes.PurchaseResponse{Purchase: data, ProductList: respProductList}, "鑾峰彇鎴愬姛", c)
 }
 
 // GetPurchaseList
@@ -173,14 +208,14 @@
 		response.FailWithMessage(err.Error(), c)
 		return
 	}
-	PurchaseList, total, err := service.NewPurchaseService().GetPurchaseList(pageInfo)
+	purchaseList, total, err := service.NewPurchaseService().GetPurchaseList(pageInfo)
 	if err != nil {
 		global.GVA_LOG.Error("鑾峰彇澶辫触!", zap.Error(err))
 		response.FailWithMessage("鑾峰彇澶辫触"+err.Error(), c)
 		return
 	}
 	response.OkWithDetailed(response.PageResult{
-		List:     PurchaseList,
+		List:     purchaseList,
 		Total:    total,
 		Page:     pageInfo.Page,
 		PageSize: pageInfo.PageSize,
@@ -229,7 +264,7 @@
 	}
 
 	purchaseTypeList := make([]*purchase.PurchaseType, 0, len(params))
-	if err := mapstructure.Decode(params, &purchaseTypeList); err != nil {
+	if err := utils.AssignTo(params, &purchaseTypeList); err != nil {
 		response.FailWithMessage(err.Error(), c)
 		return
 	}
diff --git a/api/v1/purchase/quality_inspection.go b/api/v1/purchase/quality_inspection.go
new file mode 100644
index 0000000..803f593
--- /dev/null
+++ b/api/v1/purchase/quality_inspection.go
@@ -0,0 +1,137 @@
+package purchase
+
+import (
+	"context"
+	"github.com/gin-gonic/gin"
+	"go.uber.org/zap"
+	"srm/global"
+	"srm/model/common/request"
+	"srm/model/common/response"
+	"srm/model/purchase"
+	purchaseRes "srm/model/purchase/response"
+	"srm/proto/qualityinspect"
+	service "srm/service/purchase"
+	"srm/utils"
+)
+
+type QualityInspectApi struct{}
+
+// GetQualityInspectList
+// @Tags      QualityInspect
+// @Summary   鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�
+// @Security  ApiKeyAuth
+// @accept    application/json
+// @Produce   application/json
+// @Param     data  query     request.PageInfo                                        true  "椤电爜, 姣忛〉澶у皬"
+// @Success   200   {object}  response.Response{data=response.PageResult,msg=string}  "鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�,杩斿洖鍖呮嫭鍒楄〃,鎬绘暟,椤电爜,姣忛〉鏁伴噺"
+// @Router    /purchase/qualityInspectList [get]
+func (e *QualityInspectApi) GetQualityInspectList(c *gin.Context) {
+	var pageInfo request.PageInfo
+	err := c.ShouldBindQuery(&pageInfo)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	err = utils.Verify(pageInfo, utils.PageInfoVerify)
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	list, total, err := service.NewPurchaseService().GetPurchaseList(pageInfo)
+	purchaseList := list.([]*purchase.Purchase)
+	purchaseNumbers := make([]string, 0, len(purchaseList))
+	for _, item := range purchaseList {
+		purchaseNumbers = append(purchaseNumbers, item.Number)
+	}
+	resultList := make([]*purchaseRes.QualityInspectList, 0, len(purchaseList))
+	if len(purchaseList) == 0 {
+		err = utils.AssignTo(purchaseList, &resultList)
+		if err != nil {
+			global.GVA_LOG.Error("mapStructure decode", zap.Error(err))
+			response.FailWithMessage("鍐呴儴閿欒", c)
+			return
+		}
+
+		client := qualityinspect.NewQualityInspectServiceClient(qualityinspect.Conn)
+		inspectList, err := client.GetInspectList(context.Background(), &qualityinspect.GetInspectListRequest{
+			PurchaseOrderId: purchaseNumbers,
+		})
+		if err != nil {
+			global.GVA_LOG.Error("GetInspectList", zap.Error(err))
+			response.FailWithMessage("鍐呴儴閿欒", c)
+			return
+		}
+
+		inspectUnFinishedMap := make(map[string]bool, len(purchaseNumbers)) //榛樿瀹屾垚
+		for _, inspectItem := range inspectList.List {
+			if inspectItem.Status != qualityinspect.InspectStatus_InspectStatusInspectFinish {
+				inspectUnFinishedMap[inspectItem.PurchaseOrderId] = true
+			}
+		}
+
+		for _, result := range resultList {
+			if inspectUnFinishedMap[result.Number] {
+				result.InspectStatus = "寰呰川妫�"
+			} else {
+				result.InspectStatus = "宸插畬鎴�"
+			}
+		}
+	}
+
+	response.OkWithDetailed(response.PageResult{
+		List:     resultList,
+		Total:    total,
+		Page:     pageInfo.Page,
+		PageSize: pageInfo.PageSize,
+	}, "鑾峰彇鎴愬姛", c)
+}
+
+//
+//// GetQualityInspect
+//// @Tags      QualityInspect
+//// @Summary   鑾峰彇鍗曚竴璐ㄦ鍗曚俊鎭�
+//// @Security  ApiKeyAuth
+//// @accept    application/json
+//// @Produce   application/json
+//// @Param		id	path		int	true	"璐ㄦ鍗旾D"                                           true  "璐ㄦ鍗旾D"
+//// @Success   200   {object}  response.Response{data=QualityInspectRes.QualityInspectResponse,msg=string}  "鑾峰彇鍗曚竴璐ㄦ鍗曚俊鎭�,杩斿洖鍖呮嫭璐ㄦ鍗曡鎯�"
+//// @Router    /purchase/qualityInspect/{id} [get]
+//func (e *QualityInspectApi) GetQualityInspect(c *gin.Context) {
+//	id, _ := strconv.Atoi(c.Param("id"))
+//	if id == 0 {
+//		response.FailWithMessage("鍙傛暟缂哄け", c)
+//		return
+//	}
+//	data, err := service.NewPurchaseService().GetPurchase(uint(id))
+//	if err != nil {
+//		global.GVA_LOG.Error("鑾峰彇澶辫触!", zap.Error(err))
+//		response.FailWithMessage("鑾峰彇澶辫触", c)
+//		return
+//	}
+//	productList, err := service.NewPurchaseService().GetPurchaseProductList(uint(id))
+//	if err != nil {
+//		global.GVA_LOG.Error("鑾峰彇澶辫触!", zap.Error(err))
+//		response.FailWithMessage("鑾峰彇澶辫触", c)
+//		return
+//	}
+//	respProductList := make([]*purchaseRes.PurchaseProducts, len(productList))
+//	err = mapstructure.Decode(productList, &respProductList)
+//	if err != nil {
+//		global.GVA_LOG.Error("鑾峰彇澶辫触!", zap.Error(err))
+//		response.FailWithMessage("鑾峰彇澶辫触", c)
+//		return
+//	}
+//	for k, item := range productList {
+//		respProductList[k].Amount = item.Amount
+//		respProductList[k].Price = item.Price
+//		respProductList[k].Total = item.Total
+//		err = mapstructure.Decode(item.Product, &respProductList[k])
+//		if err != nil {
+//			global.GVA_LOG.Error("鑾峰彇澶辫触!", zap.Error(err))
+//			response.FailWithMessage("鑾峰彇澶辫触", c)
+//			return
+//		}
+//	}
+//
+//	response.OkWithDetailed(purchaseRes.PurchaseResponse{Purchase: data, ProductList: respProductList}, "鑾峰彇鎴愬姛", c)
+//}
diff --git a/config.yaml b/config.yaml
index a172756..0cfd477 100644
--- a/config.yaml
+++ b/config.yaml
@@ -182,7 +182,7 @@
   iplimit-time: 3600
   use-multipoint: false
   use-redis: false
-  grpc-url: 192.168.20.118:9091
+  grpc-url: 192.168.20.119:9091
   grpc-admin-url: 192.168.20.119:50051
 tencent-cos:
   bucket: xxxxx-10005608
diff --git a/docs/docs.go b/docs/docs.go
index 90295a0..9156122 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -4629,7 +4629,7 @@
                 "summary": "鍒涘缓閲囪喘鍗�",
                 "parameters": [
                     {
-                        "description": "閲囪喘鍗曠敤鎴峰悕, 閲囪喘鍗曟墜鏈哄彿鐮�",
+                        "description": "閲囪喘鍗�,閲囪喘鍗曚骇鍝�",
                         "name": "data",
                         "in": "body",
                         "required": true,
@@ -4905,6 +4905,68 @@
                                             "items": {
                                                 "$ref": "#/definitions/purchase.PurchaseType"
                                             }
+                                        },
+                                        "msg": {
+                                            "type": "string"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/purchase/qualityInspectList": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "QualityInspect"
+                ],
+                "summary": "鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "鍏抽敭瀛�",
+                        "name": "keyword",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "椤电爜",
+                        "name": "page",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "姣忛〉澶у皬",
+                        "name": "pageSize",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�,杩斿洖鍖呮嫭鍒楄〃,鎬绘暟,椤电爜,姣忛〉鏁伴噺",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/response.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/response.PageResult"
                                         },
                                         "msg": {
                                             "type": "string"
@@ -8414,6 +8476,21 @@
                 "OrderStatusCompleted"
             ]
         },
+        "purchase.PriceAdjustmentType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2
+            ],
+            "x-enum-comments": {
+                "PriceAdjustmentTypeAdd": "澧炲姞",
+                "PriceAdjustmentTypeSub": "鍑忓皯"
+            },
+            "x-enum-varnames": [
+                "PriceAdjustmentTypeAdd",
+                "PriceAdjustmentTypeSub"
+            ]
+        },
         "purchase.Purchase": {
             "type": "object",
             "properties": {
@@ -8441,6 +8518,10 @@
                     "description": "涓婚敭ID",
                     "type": "integer"
                 },
+                "invoiceAmount": {
+                    "description": "宸叉敹绁ㄩ噾棰�",
+                    "type": "number"
+                },
                 "name": {
                     "description": "閲囪喘鍚嶇О",
                     "type": "string"
@@ -8449,8 +8530,36 @@
                     "description": "閲囪喘缂栧彿",
                     "type": "string"
                 },
+                "orderSource": {
+                    "description": "鍗曟嵁鏉ユ簮",
+                    "type": "string"
+                },
+                "orderType": {
+                    "description": "鍗曟嵁绫诲瀷",
+                    "type": "string"
+                },
+                "paidAmount": {
+                    "description": "宸蹭粯閲戦",
+                    "type": "number"
+                },
                 "phone": {
                     "description": "鑱旂郴浜虹數璇�",
+                    "type": "string"
+                },
+                "priceAdjustment": {
+                    "description": "浠锋牸璋冩暣鍊�",
+                    "type": "number"
+                },
+                "priceAdjustmentType": {
+                    "description": "浠锋牸璋冩暣绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.PriceAdjustmentType"
+                        }
+                    ]
+                },
+                "principal": {
+                    "description": "閲囪喘璐熻矗浜�",
                     "type": "string"
                 },
                 "purchaseType": {
@@ -8464,9 +8573,17 @@
                     "description": "閲囪喘鏁伴噺",
                     "type": "number"
                 },
+                "realTotalPrice": {
+                    "description": "鏈�缁堜环鏍�",
+                    "type": "number"
+                },
                 "remark": {
                     "description": "澶囨敞",
                     "type": "string"
+                },
+                "shouldPayAmount": {
+                    "description": "搴斾粯閲戦",
+                    "type": "number"
                 },
                 "signingDate": {
                     "description": "绛剧害鏃ユ湡",
@@ -8486,6 +8603,30 @@
                 "supplierId": {
                     "description": "渚涘簲鍟唅d",
                     "type": "integer"
+                },
+                "totalPrice": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
+                "unInvoiceAmount": {
+                    "description": "鏈敹绁ㄩ噾棰�",
+                    "type": "number"
+                },
+                "warehouse": {
+                    "description": "鏀惰揣浠撳簱",
+                    "type": "string"
+                },
+                "wholeDiscount": {
+                    "description": "鏁村崟鎶樻墸鍊�",
+                    "type": "number"
+                },
+                "wholeDiscountType": {
+                    "description": "鏁村崟鎶樻墸绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.WholeDiscountType"
+                        }
+                    ]
                 }
             }
         },
@@ -8551,6 +8692,21 @@
                 }
             }
         },
+        "purchase.WholeDiscountType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2
+            ],
+            "x-enum-comments": {
+                "WholeDiscountTypeDiscount": "鐩存帴闄嶄环",
+                "WholeDiscountTypePercent": "鐧惧垎姣旈檷浠�"
+            },
+            "x-enum-varnames": [
+                "WholeDiscountTypePercent",
+                "WholeDiscountTypeDiscount"
+            ]
+        },
         "purchaserequest.AddPurchase": {
             "type": "object",
             "properties": {
@@ -8592,9 +8748,29 @@
                     "description": "鑱旂郴浜虹數璇�",
                     "type": "string"
                 },
+                "priceAdjustment": {
+                    "description": "浠锋牸璋冩暣鍊�",
+                    "type": "number"
+                },
+                "priceAdjustmentType": {
+                    "description": "浠锋牸璋冩暣绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.PriceAdjustmentType"
+                        }
+                    ]
+                },
                 "purchaseTypeId": {
                     "description": "閲囪喘绫诲瀷id",
                     "type": "integer"
+                },
+                "quantity": {
+                    "description": "閲囪喘鏁伴噺",
+                    "type": "number"
+                },
+                "realTotalPrice": {
+                    "description": "鏈�缁堜环鏍�",
+                    "type": "number"
                 },
                 "remark": {
                     "description": "澶囨敞",
@@ -8615,6 +8791,22 @@
                 "supplierId": {
                     "description": "渚涘簲鍟唅d",
                     "type": "integer"
+                },
+                "totalPrice": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
+                "wholeDiscount": {
+                    "description": "鏁村崟鎶樻墸鍊�",
+                    "type": "number"
+                },
+                "wholeDiscountType": {
+                    "description": "鏁村崟鎶樻墸绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.WholeDiscountType"
+                        }
+                    ]
                 }
             }
         },
@@ -9109,13 +9301,65 @@
                 }
             }
         },
+        "response.PurchaseProducts": {
+            "type": "object",
+            "properties": {
+                "amount": {
+                    "description": "閲囪喘鏁伴噺",
+                    "type": "number"
+                },
+                "deliveryTime": {
+                    "type": "integer"
+                },
+                "modelNumber": {
+                    "type": "string"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "number": {
+                    "type": "string"
+                },
+                "price": {
+                    "description": "閲囪喘鍗曚环",
+                    "type": "number"
+                },
+                "productId": {
+                    "description": "浜у搧id",
+                    "type": "integer"
+                },
+                "productType": {
+                    "type": "string"
+                },
+                "purchaseId": {
+                    "description": "閲囪喘id",
+                    "type": "integer"
+                },
+                "purchasePrice": {
+                    "type": "number"
+                },
+                "shippingDuration": {
+                    "type": "integer"
+                },
+                "specifications": {
+                    "type": "string"
+                },
+                "total": {
+                    "description": "閲囪喘鎬讳环",
+                    "type": "number"
+                },
+                "unit": {
+                    "type": "string"
+                }
+            }
+        },
         "response.PurchaseResponse": {
             "type": "object",
             "properties": {
                 "productList": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/purchase.PurchaseProducts"
+                        "$ref": "#/definitions/response.PurchaseProducts"
                     }
                 },
                 "purchase": {
diff --git a/docs/swagger.json b/docs/swagger.json
index f6761ea..c0e042f 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -4620,7 +4620,7 @@
                 "summary": "鍒涘缓閲囪喘鍗�",
                 "parameters": [
                     {
-                        "description": "閲囪喘鍗曠敤鎴峰悕, 閲囪喘鍗曟墜鏈哄彿鐮�",
+                        "description": "閲囪喘鍗�,閲囪喘鍗曚骇鍝�",
                         "name": "data",
                         "in": "body",
                         "required": true,
@@ -4896,6 +4896,68 @@
                                             "items": {
                                                 "$ref": "#/definitions/purchase.PurchaseType"
                                             }
+                                        },
+                                        "msg": {
+                                            "type": "string"
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/purchase/qualityInspectList": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "QualityInspect"
+                ],
+                "summary": "鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "鍏抽敭瀛�",
+                        "name": "keyword",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "椤电爜",
+                        "name": "page",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "姣忛〉澶у皬",
+                        "name": "pageSize",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�,杩斿洖鍖呮嫭鍒楄〃,鎬绘暟,椤电爜,姣忛〉鏁伴噺",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/response.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "$ref": "#/definitions/response.PageResult"
                                         },
                                         "msg": {
                                             "type": "string"
@@ -8405,6 +8467,21 @@
                 "OrderStatusCompleted"
             ]
         },
+        "purchase.PriceAdjustmentType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2
+            ],
+            "x-enum-comments": {
+                "PriceAdjustmentTypeAdd": "澧炲姞",
+                "PriceAdjustmentTypeSub": "鍑忓皯"
+            },
+            "x-enum-varnames": [
+                "PriceAdjustmentTypeAdd",
+                "PriceAdjustmentTypeSub"
+            ]
+        },
         "purchase.Purchase": {
             "type": "object",
             "properties": {
@@ -8432,6 +8509,10 @@
                     "description": "涓婚敭ID",
                     "type": "integer"
                 },
+                "invoiceAmount": {
+                    "description": "宸叉敹绁ㄩ噾棰�",
+                    "type": "number"
+                },
                 "name": {
                     "description": "閲囪喘鍚嶇О",
                     "type": "string"
@@ -8440,8 +8521,36 @@
                     "description": "閲囪喘缂栧彿",
                     "type": "string"
                 },
+                "orderSource": {
+                    "description": "鍗曟嵁鏉ユ簮",
+                    "type": "string"
+                },
+                "orderType": {
+                    "description": "鍗曟嵁绫诲瀷",
+                    "type": "string"
+                },
+                "paidAmount": {
+                    "description": "宸蹭粯閲戦",
+                    "type": "number"
+                },
                 "phone": {
                     "description": "鑱旂郴浜虹數璇�",
+                    "type": "string"
+                },
+                "priceAdjustment": {
+                    "description": "浠锋牸璋冩暣鍊�",
+                    "type": "number"
+                },
+                "priceAdjustmentType": {
+                    "description": "浠锋牸璋冩暣绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.PriceAdjustmentType"
+                        }
+                    ]
+                },
+                "principal": {
+                    "description": "閲囪喘璐熻矗浜�",
                     "type": "string"
                 },
                 "purchaseType": {
@@ -8455,9 +8564,17 @@
                     "description": "閲囪喘鏁伴噺",
                     "type": "number"
                 },
+                "realTotalPrice": {
+                    "description": "鏈�缁堜环鏍�",
+                    "type": "number"
+                },
                 "remark": {
                     "description": "澶囨敞",
                     "type": "string"
+                },
+                "shouldPayAmount": {
+                    "description": "搴斾粯閲戦",
+                    "type": "number"
                 },
                 "signingDate": {
                     "description": "绛剧害鏃ユ湡",
@@ -8477,6 +8594,30 @@
                 "supplierId": {
                     "description": "渚涘簲鍟唅d",
                     "type": "integer"
+                },
+                "totalPrice": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
+                "unInvoiceAmount": {
+                    "description": "鏈敹绁ㄩ噾棰�",
+                    "type": "number"
+                },
+                "warehouse": {
+                    "description": "鏀惰揣浠撳簱",
+                    "type": "string"
+                },
+                "wholeDiscount": {
+                    "description": "鏁村崟鎶樻墸鍊�",
+                    "type": "number"
+                },
+                "wholeDiscountType": {
+                    "description": "鏁村崟鎶樻墸绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.WholeDiscountType"
+                        }
+                    ]
                 }
             }
         },
@@ -8542,6 +8683,21 @@
                 }
             }
         },
+        "purchase.WholeDiscountType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2
+            ],
+            "x-enum-comments": {
+                "WholeDiscountTypeDiscount": "鐩存帴闄嶄环",
+                "WholeDiscountTypePercent": "鐧惧垎姣旈檷浠�"
+            },
+            "x-enum-varnames": [
+                "WholeDiscountTypePercent",
+                "WholeDiscountTypeDiscount"
+            ]
+        },
         "purchaserequest.AddPurchase": {
             "type": "object",
             "properties": {
@@ -8583,9 +8739,29 @@
                     "description": "鑱旂郴浜虹數璇�",
                     "type": "string"
                 },
+                "priceAdjustment": {
+                    "description": "浠锋牸璋冩暣鍊�",
+                    "type": "number"
+                },
+                "priceAdjustmentType": {
+                    "description": "浠锋牸璋冩暣绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.PriceAdjustmentType"
+                        }
+                    ]
+                },
                 "purchaseTypeId": {
                     "description": "閲囪喘绫诲瀷id",
                     "type": "integer"
+                },
+                "quantity": {
+                    "description": "閲囪喘鏁伴噺",
+                    "type": "number"
+                },
+                "realTotalPrice": {
+                    "description": "鏈�缁堜环鏍�",
+                    "type": "number"
                 },
                 "remark": {
                     "description": "澶囨敞",
@@ -8606,6 +8782,22 @@
                 "supplierId": {
                     "description": "渚涘簲鍟唅d",
                     "type": "integer"
+                },
+                "totalPrice": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
+                "wholeDiscount": {
+                    "description": "鏁村崟鎶樻墸鍊�",
+                    "type": "number"
+                },
+                "wholeDiscountType": {
+                    "description": "鏁村崟鎶樻墸绫诲瀷",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/purchase.WholeDiscountType"
+                        }
+                    ]
                 }
             }
         },
@@ -9100,13 +9292,65 @@
                 }
             }
         },
+        "response.PurchaseProducts": {
+            "type": "object",
+            "properties": {
+                "amount": {
+                    "description": "閲囪喘鏁伴噺",
+                    "type": "number"
+                },
+                "deliveryTime": {
+                    "type": "integer"
+                },
+                "modelNumber": {
+                    "type": "string"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "number": {
+                    "type": "string"
+                },
+                "price": {
+                    "description": "閲囪喘鍗曚环",
+                    "type": "number"
+                },
+                "productId": {
+                    "description": "浜у搧id",
+                    "type": "integer"
+                },
+                "productType": {
+                    "type": "string"
+                },
+                "purchaseId": {
+                    "description": "閲囪喘id",
+                    "type": "integer"
+                },
+                "purchasePrice": {
+                    "type": "number"
+                },
+                "shippingDuration": {
+                    "type": "integer"
+                },
+                "specifications": {
+                    "type": "string"
+                },
+                "total": {
+                    "description": "閲囪喘鎬讳环",
+                    "type": "number"
+                },
+                "unit": {
+                    "type": "string"
+                }
+            }
+        },
         "response.PurchaseResponse": {
             "type": "object",
             "properties": {
                 "productList": {
                     "type": "array",
                     "items": {
-                        "$ref": "#/definitions/purchase.PurchaseProducts"
+                        "$ref": "#/definitions/response.PurchaseProducts"
                     }
                 },
                 "purchase": {
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 93c77e5..2df7b38 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -694,6 +694,17 @@
     - OrderStatusReceived
     - OrderStatusStored
     - OrderStatusCompleted
+  purchase.PriceAdjustmentType:
+    enum:
+    - 1
+    - 2
+    type: integer
+    x-enum-comments:
+      PriceAdjustmentTypeAdd: 澧炲姞
+      PriceAdjustmentTypeSub: 鍑忓皯
+    x-enum-varnames:
+    - PriceAdjustmentTypeAdd
+    - PriceAdjustmentTypeSub
   purchase.Purchase:
     properties:
       contact:
@@ -714,14 +725,36 @@
       id:
         description: 涓婚敭ID
         type: integer
+      invoiceAmount:
+        description: 宸叉敹绁ㄩ噾棰�
+        type: number
       name:
         description: 閲囪喘鍚嶇О
         type: string
       number:
         description: 閲囪喘缂栧彿
         type: string
+      orderSource:
+        description: 鍗曟嵁鏉ユ簮
+        type: string
+      orderType:
+        description: 鍗曟嵁绫诲瀷
+        type: string
+      paidAmount:
+        description: 宸蹭粯閲戦
+        type: number
       phone:
         description: 鑱旂郴浜虹數璇�
+        type: string
+      priceAdjustment:
+        description: 浠锋牸璋冩暣鍊�
+        type: number
+      priceAdjustmentType:
+        allOf:
+        - $ref: '#/definitions/purchase.PriceAdjustmentType'
+        description: 浠锋牸璋冩暣绫诲瀷
+      principal:
+        description: 閲囪喘璐熻矗浜�
         type: string
       purchaseType:
         $ref: '#/definitions/purchase.PurchaseType'
@@ -731,9 +764,15 @@
       quantity:
         description: 閲囪喘鏁伴噺
         type: number
+      realTotalPrice:
+        description: 鏈�缁堜环鏍�
+        type: number
       remark:
         description: 澶囨敞
         type: string
+      shouldPayAmount:
+        description: 搴斾粯閲戦
+        type: number
       signingDate:
         description: 绛剧害鏃ユ湡
         type: string
@@ -746,6 +785,22 @@
       supplierId:
         description: 渚涘簲鍟唅d
         type: integer
+      totalPrice:
+        description: 浠风◣鍚堣
+        type: number
+      unInvoiceAmount:
+        description: 鏈敹绁ㄩ噾棰�
+        type: number
+      warehouse:
+        description: 鏀惰揣浠撳簱
+        type: string
+      wholeDiscount:
+        description: 鏁村崟鎶樻墸鍊�
+        type: number
+      wholeDiscountType:
+        allOf:
+        - $ref: '#/definitions/purchase.WholeDiscountType'
+        description: 鏁村崟鎶樻墸绫诲瀷
     type: object
   purchase.PurchaseProducts:
     properties:
@@ -792,6 +847,17 @@
         description: 鎺掑簭
         type: integer
     type: object
+  purchase.WholeDiscountType:
+    enum:
+    - 1
+    - 2
+    type: integer
+    x-enum-comments:
+      WholeDiscountTypeDiscount: 鐩存帴闄嶄环
+      WholeDiscountTypePercent: 鐧惧垎姣旈檷浠�
+    x-enum-varnames:
+    - WholeDiscountTypePercent
+    - WholeDiscountTypeDiscount
   purchaserequest.AddPurchase:
     properties:
       productList:
@@ -821,9 +887,22 @@
       phone:
         description: 鑱旂郴浜虹數璇�
         type: string
+      priceAdjustment:
+        description: 浠锋牸璋冩暣鍊�
+        type: number
+      priceAdjustmentType:
+        allOf:
+        - $ref: '#/definitions/purchase.PriceAdjustmentType'
+        description: 浠锋牸璋冩暣绫诲瀷
       purchaseTypeId:
         description: 閲囪喘绫诲瀷id
         type: integer
+      quantity:
+        description: 閲囪喘鏁伴噺
+        type: number
+      realTotalPrice:
+        description: 鏈�缁堜环鏍�
+        type: number
       remark:
         description: 澶囨敞
         type: string
@@ -837,6 +916,16 @@
       supplierId:
         description: 渚涘簲鍟唅d
         type: integer
+      totalPrice:
+        description: 浠风◣鍚堣
+        type: number
+      wholeDiscount:
+        description: 鏁村崟鎶樻墸鍊�
+        type: number
+      wholeDiscountType:
+        allOf:
+        - $ref: '#/definitions/purchase.WholeDiscountType'
+        description: 鏁村崟鎶樻墸绫诲瀷
     type: object
   purchaserequest.PurchaseType:
     properties:
@@ -1174,11 +1263,47 @@
           $ref: '#/definitions/request.CasbinInfo'
         type: array
     type: object
+  response.PurchaseProducts:
+    properties:
+      amount:
+        description: 閲囪喘鏁伴噺
+        type: number
+      deliveryTime:
+        type: integer
+      modelNumber:
+        type: string
+      name:
+        type: string
+      number:
+        type: string
+      price:
+        description: 閲囪喘鍗曚环
+        type: number
+      productId:
+        description: 浜у搧id
+        type: integer
+      productType:
+        type: string
+      purchaseId:
+        description: 閲囪喘id
+        type: integer
+      purchasePrice:
+        type: number
+      shippingDuration:
+        type: integer
+      specifications:
+        type: string
+      total:
+        description: 閲囪喘鎬讳环
+        type: number
+      unit:
+        type: string
+    type: object
   response.PurchaseResponse:
     properties:
       productList:
         items:
-          $ref: '#/definitions/purchase.PurchaseProducts'
+          $ref: '#/definitions/response.PurchaseProducts'
         type: array
       purchase:
         $ref: '#/definitions/purchase.Purchase'
@@ -4520,7 +4645,7 @@
       consumes:
       - application/json
       parameters:
-      - description: 閲囪喘鍗曠敤鎴峰悕, 閲囪喘鍗曟墜鏈哄彿鐮�
+      - description: 閲囪喘鍗�,閲囪喘鍗曚骇鍝�
         in: body
         name: data
         required: true
@@ -4716,6 +4841,42 @@
       summary: 鑾峰彇閲囪喘绫诲瀷鍒楄〃
       tags:
       - Purchase
+  /purchase/qualityInspectList:
+    get:
+      consumes:
+      - application/json
+      parameters:
+      - description: 鍏抽敭瀛�
+        in: query
+        name: keyword
+        type: string
+      - description: 椤电爜
+        in: query
+        name: page
+        type: integer
+      - description: 姣忛〉澶у皬
+        in: query
+        name: pageSize
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�,杩斿洖鍖呮嫭鍒楄〃,鎬绘暟,椤电爜,姣忛〉鏁伴噺
+          schema:
+            allOf:
+            - $ref: '#/definitions/response.Response'
+            - properties:
+                data:
+                  $ref: '#/definitions/response.PageResult'
+                msg:
+                  type: string
+              type: object
+      security:
+      - ApiKeyAuth: []
+      summary: 鍒嗛〉鑾峰彇璐ㄦ鍗曞垪琛�
+      tags:
+      - QualityInspect
   /purchase/submit/{id}:
     post:
       consumes:
diff --git a/model/purchase/purchase.go b/model/purchase/purchase.go
index 4627f87..0e9fbdb 100644
--- a/model/purchase/purchase.go
+++ b/model/purchase/purchase.go
@@ -8,21 +8,35 @@
 
 type Purchase struct {
 	global.GVA_MODEL
-	PurchaseTypeId int             `json:"purchaseTypeId" form:"purchaseType" gorm:"type:int(11);not null;default 0;comment:閲囪喘绫诲瀷id"` // 閲囪喘绫诲瀷id
-	PurchaseType   PurchaseType    `json:"purchaseType" gorm:"foreignKey:PurchaseTypeId"`
-	SupplierId     int             `json:"supplierId" form:"supplierId" gorm:"type:int(11);not null;default 0;comment:渚涘簲鍟唅d"` // 渚涘簲鍟唅d
-	Supplier       test.Supplier   `json:"supplier" gorm:"foreignKey:SupplierId"`
-	Number         string          `json:"number" form:"number" gorm:"unique;type:varchar(255);not null;default '';comment:閲囪喘缂栧彿"`      // 閲囪喘缂栧彿
-	Name           string          `json:"name" form:"name" gorm:"type:varchar(255);not null;default '';comment:閲囪喘鍚嶇О"`                 // 閲囪喘鍚嶇О
-	Quantity       decimal.Decimal `json:"quantity" form:"quantity" gorm:"type:decimal(12,4);not null;comment:閲囪喘鏁伴噺"`                   // 閲囪喘鏁伴噺
-	Contact        string          `json:"contact" form:"contact" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜�"`            // 鑱旂郴浜�
-	Phone          string          `json:"phone" form:"phone" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜虹數璇�"`              // 鑱旂郴浜虹數璇�
-	SigningDate    string          `json:"signingDate" form:"signingDate" gorm:"type:varchar(255);not null;default '';comment:绛剧害鏃ユ湡"`   // 绛剧害鏃ユ湡
-	DeliveryDate   string          `json:"deliveryDate" form:"deliveryDate" gorm:"type:varchar(255);not null;default '';comment:浜や粯鏃ユ湡"` //浜や粯鏃ユ湡
-	Remark         string          `json:"remark" form:"remark" gorm:"type:varchar(1000);not null;default '';comment:澶囨敞"`              //澶囨敞
-	Status         OrderStatus     `json:"status" form:"status" gorm:"type:tinyint(1);not null;default 0;comment:鐘舵��"`                  //鐘舵��
-	HandledBy      string          `json:"handledBy" form:"handledBy" gorm:"type:varchar(255);not null;default '';comment:缁忓姙浜�"`        //缁忓姙浜�
-	Creator        string          `json:"creator" form:"creator" gorm:"type:varchar(255);not null;default '';comment:鍒跺崟浜�"`            //鍒跺崟浜�
+	PurchaseTypeId      int                 `json:"purchaseTypeId" form:"purchaseType" gorm:"type:int(11);not null;default 0;comment:閲囪喘绫诲瀷id"` // 閲囪喘绫诲瀷id
+	PurchaseType        PurchaseType        `json:"purchaseType" gorm:"foreignKey:PurchaseTypeId"`
+	OrderSource         string              `json:"orderSource" gorm:"type:varchar(255);not null;default '';comment:鍗曟嵁鏉ユ簮"`             // 鍗曟嵁鏉ユ簮
+	SupplierId          int                 `json:"supplierId" form:"supplierId" gorm:"type:int(11);not null;default 0;comment:渚涘簲鍟唅d"` // 渚涘簲鍟唅d
+	Supplier            test.Supplier       `json:"supplier" gorm:"foreignKey:SupplierId"`
+	Number              string              `json:"number" form:"number" gorm:"unique;type:varchar(255);not null;default '';comment:閲囪喘缂栧彿"`                  // 閲囪喘缂栧彿
+	Name                string              `json:"name" form:"name" gorm:"type:varchar(255);not null;default '';comment:閲囪喘鍚嶇О"`                             // 閲囪喘鍚嶇О
+	Contact             string              `json:"contact" form:"contact" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜�"`                        // 鑱旂郴浜�
+	Phone               string              `json:"phone" form:"phone" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜虹數璇�"`                          // 鑱旂郴浜虹數璇�
+	SigningDate         string              `json:"signingDate" form:"signingDate" gorm:"type:varchar(255);not null;default '';comment:绛剧害鏃ユ湡"`               // 绛剧害鏃ユ湡
+	DeliveryDate        string              `json:"deliveryDate" form:"deliveryDate" gorm:"type:varchar(255);not null;default '';comment:浜や粯鏃ユ湡"`             //浜や粯鏃ユ湡
+	Remark              string              `json:"remark" form:"remark" gorm:"type:varchar(1000);not null;default '';comment:澶囨敞"`                          //澶囨敞
+	Status              OrderStatus         `json:"status" form:"status" gorm:"type:tinyint(1);not null;default 0;comment:鐘舵��"`                              //鐘舵��
+	HandledBy           string              `json:"handledBy" form:"handledBy" gorm:"type:varchar(255);not null;default '';comment:缁忓姙浜�"`                    //缁忓姙浜�
+	Creator             string              `json:"creator" form:"creator" gorm:"type:varchar(255);not null;default '';comment:鍒跺崟浜�"`                        //鍒跺崟浜�
+	Principal           string              `json:"principal" form:"principal" gorm:"type:varchar(255);not null;default '';comment:閲囪喘璐熻矗浜�"`                  //閲囪喘璐熻矗浜�
+	OrderType           string              `json:"orderType" form:"orderType" gorm:"type:varchar(255);not null;default '';comment:鍗曟嵁绫诲瀷"`                   //鍗曟嵁绫诲瀷
+	Warehouse           string              `json:"warehouse" form:"warehouse" gorm:"type:varchar(255);not null;default '';comment:鏀惰揣浠撳簱"`                   //鏀惰揣浠撳簱
+	Quantity            decimal.Decimal     `json:"quantity" form:"quantity" gorm:"type:decimal(12,4);not null;comment:閲囪喘鏁伴噺"`                               // 閲囪喘鏁伴噺
+	TotalPrice          decimal.Decimal     `json:"totalPrice" form:"totalPrice" gorm:"type:decimal(12,2);not null;default '';comment:浠风◣鍚堣"`                //浠风◣鍚堣
+	WholeDiscountType   WholeDiscountType   `json:"wholeDiscountType" form:"wholeDiscountType" gorm:"type:tinyint(1);not null;default '';comment:鏁村崟鎶樻墸"`     //鏁村崟鎶樻墸绫诲瀷
+	WholeDiscount       decimal.Decimal     `json:"wholeDiscount" form:"wholeDiscount" gorm:"type:decimal(12,2);not null;default '';comment:鏁村崟鎶樻墸"`          //鏁村崟鎶樻墸鍊�
+	PriceAdjustmentType PriceAdjustmentType `json:"priceAdjustmentType" form:"priceAdjustmentType" gorm:"type:tinyint(1);not null;default '';comment:浠锋牸璋冩暣"` //浠锋牸璋冩暣绫诲瀷
+	PriceAdjustment     decimal.Decimal     `json:"priceAdjustment" form:"priceAdjustment" gorm:"type:decimal(12,2);not null;default '';comment:浠锋牸璋冩暣"`      //浠锋牸璋冩暣鍊�
+	RealTotalPrice      decimal.Decimal     `json:"realTotalPrice" form:"realTotalPrice" gorm:"type:decimal(12,2);not null;default '';comment:鏈�缁堜环鏍�"`        //鏈�缁堜环鏍�
+	InvoiceAmount       decimal.Decimal     `json:"invoiceAmount" form:"invoiceAmount" gorm:"type:decimal(12,2);not null;default '';comment:宸叉敹绁ㄩ噾棰�"`         //宸叉敹绁ㄩ噾棰�
+	UnInvoiceAmount     decimal.Decimal     `json:"unInvoiceAmount" form:"unInvoiceAmount" gorm:"type:decimal(12,2);not null;default '';comment:鏈敹绁ㄩ噾棰�"`     //鏈敹绁ㄩ噾棰�
+	ShouldPayAmount     decimal.Decimal     `json:"shouldPayAmount" form:"shouldPayAmount" gorm:"type:decimal(12,2);not null;default '';comment:搴斾粯閲戦"`      //搴斾粯閲戦
+	PaidAmount          decimal.Decimal     `json:"paidAmount" form:"paidAmount" gorm:"type:decimal(12,2);not null;default '';comment:宸蹭粯閲戦"`                //宸蹭粯閲戦
 }
 
 type OrderStatus int
@@ -33,3 +47,62 @@
 	OrderStatusStored    OrderStatus = 3 //宸插叆搴�
 	OrderStatusCompleted OrderStatus = 4 //宸插畬鎴�
 )
+
+type WholeDiscountType int
+
+const (
+	WholeDiscountTypePercent  WholeDiscountType = 1 //鐧惧垎姣旈檷浠�
+	WholeDiscountTypeDiscount WholeDiscountType = 2 //鐩存帴闄嶄环
+)
+
+func (wdt WholeDiscountType) IsValid(totalPrice, value decimal.Decimal) bool {
+	if wdt == 0 {
+		return true
+	}
+	if wdt != WholeDiscountTypePercent && wdt != WholeDiscountTypeDiscount {
+		return false
+	}
+	if wdt == WholeDiscountTypeDiscount && value.GreaterThan(totalPrice) {
+		return false
+	}
+	if wdt == WholeDiscountTypePercent && totalPrice.Mul(value).Div(decimal.NewFromInt(100)).GreaterThan(totalPrice) {
+		return false
+	}
+	return true
+}
+
+type PriceAdjustmentType int
+
+const (
+	PriceAdjustmentTypeAdd PriceAdjustmentType = 1 //澧炲姞
+	PriceAdjustmentTypeSub PriceAdjustmentType = 2 //鍑忓皯
+)
+
+func (pat PriceAdjustmentType) IsValid(totalPrice, value decimal.Decimal) bool {
+	if pat == 0 {
+		return true
+	}
+	if pat != PriceAdjustmentTypeAdd && pat != PriceAdjustmentTypeSub {
+		return false
+	}
+	if pat == PriceAdjustmentTypeSub && value.GreaterThan(totalPrice) {
+		return false
+	}
+	return true
+}
+
+func (slf Purchase) CalcRealTotalPrice() decimal.Decimal {
+	totalPrice := slf.TotalPrice
+	if slf.WholeDiscountType == WholeDiscountTypePercent {
+		totalPrice = totalPrice.Mul(decimal.NewFromInt(1).Sub(slf.WholeDiscount.Div(decimal.NewFromInt(100))))
+	} else if slf.WholeDiscountType == WholeDiscountTypeDiscount {
+		totalPrice = totalPrice.Sub(slf.WholeDiscount)
+	}
+
+	if slf.PriceAdjustmentType == PriceAdjustmentTypeAdd {
+		totalPrice = totalPrice.Add(slf.PriceAdjustment)
+	} else if slf.PriceAdjustmentType == PriceAdjustmentTypeSub {
+		totalPrice = totalPrice.Sub(slf.PriceAdjustment)
+	}
+	return totalPrice.RoundCeil(2)
+}
diff --git a/model/purchase/purchase_products.go b/model/purchase/purchase_products.go
index 53aa43d..c04ff6b 100644
--- a/model/purchase/purchase_products.go
+++ b/model/purchase/purchase_products.go
@@ -3,14 +3,16 @@
 import (
 	"github.com/shopspring/decimal"
 	"srm/global"
+	"srm/model/test"
 )
 
 type PurchaseProducts struct {
 	global.GVA_MODEL
 	PurchaseId int             `json:"purchaseId" form:"purchaseType" gorm:"type:int(11);not null;default 0;comment:閲囪喘绫诲瀷id"` // 閲囪喘id
 	ProductId  int             `json:"productId" form:"supplierId" gorm:"type:int(11);not null;default 0;comment:渚涘簲鍟唅d"`     // 浜у搧id
-	Amount     decimal.Decimal `json:"amount" form:"amount" gorm:"type:decimal(12,2);not null;default 0;comment:閲囪喘鏁伴噺"`       // 閲囪喘鏁伴噺
-	Price      decimal.Decimal `json:"price" form:"price" gorm:"type:decimal(12,2);not null;default 0.00;comment:閲囪喘鍗曚环"`      // 閲囪喘鍗曚环
-	Total      decimal.Decimal `json:"total" form:"total" gorm:"type:decimal(12,2);not null;default 0.00;comment:閲囪喘鎬讳环"`      // 閲囪喘鎬讳环
-	Remark     string          `json:"remark" form:"remark" gorm:"type:varchar(1000);not null; default '';comment:鎻忚堪"`       //鎻忚堪
+	Product    test.Product    `json:"-" gorm:"foreignKey:ProductId"`
+	Amount     decimal.Decimal `json:"amount" form:"amount" gorm:"type:decimal(12,2);not null;default 0;comment:閲囪喘鏁伴噺"`  // 閲囪喘鏁伴噺
+	Price      decimal.Decimal `json:"price" form:"price" gorm:"type:decimal(12,2);not null;default 0.00;comment:閲囪喘鍗曚环"` // 閲囪喘鍗曚环
+	Total      decimal.Decimal `json:"total" form:"total" gorm:"type:decimal(12,2);not null;default 0.00;comment:閲囪喘鎬讳环"` // 閲囪喘鎬讳环
+	Remark     string          `json:"remark" form:"remark" gorm:"type:varchar(1000);not null; default '';comment:鎻忚堪"`  //鎻忚堪
 }
diff --git a/model/purchase/request/purchase.go b/model/purchase/request/purchase.go
index a99c0b8..6bcea8b 100644
--- a/model/purchase/request/purchase.go
+++ b/model/purchase/request/purchase.go
@@ -1,6 +1,7 @@
 package purchaserequest
 
 import (
+	"github.com/shopspring/decimal"
 	"srm/model/common/request"
 	"srm/model/purchase"
 	"time"
@@ -23,15 +24,22 @@
 }
 
 type Purchase struct {
-	ID             uint                 `gorm:"primarykey"`                                                                                 // 涓婚敭ID
-	PurchaseTypeId int                  `json:"purchaseTypeId" form:"purchaseType" gorm:"type:int(11);not null;default 0;comment:閲囪喘绫诲瀷id"`   // 閲囪喘绫诲瀷id
-	SupplierId     int                  `json:"supplierId" form:"supplierId" gorm:"type:int(11);not null;default 0;comment:渚涘簲鍟唅d"`          // 渚涘簲鍟唅d
-	Number         string               `json:"number" form:"number" gorm:"unique;type:varchar(255);not null;default '';comment:閲囪喘缂栧彿"`      // 閲囪喘缂栧彿
-	Name           string               `json:"name" form:"name" gorm:"type:varchar(255);not null;default '';comment:閲囪喘鍚嶇О"`                 // 閲囪喘鍚嶇О
-	Contact        string               `json:"contact" form:"contact" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜�"`            // 鑱旂郴浜�
-	Phone          string               `json:"phone" form:"phone" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜虹數璇�"`              // 鑱旂郴浜虹數璇�
-	SigningDate    string               `json:"signingDate" form:"signingDate" gorm:"type:varchar(255);not null;default '';comment:绛剧害鏃ユ湡"`   // 绛剧害鏃ユ湡
-	DeliveryDate   string               `json:"deliveryDate" form:"deliveryDate" gorm:"type:varchar(255);not null;default '';comment:浜や粯鏃ユ湡"` //浜や粯鏃ユ湡
-	Remark         string               `json:"remark" form:"remark" gorm:"type:varchar(1000);not null;default '';comment:澶囨敞"`              //澶囨敞
-	Status         purchase.OrderStatus `json:"status" form:"status" gorm:"type:tinyint(1);not null;default 0;comment:鐘舵��"`                  //鐘舵��
+	ID                  uint                         `gorm:"primarykey"`                                                                                                 // 涓婚敭ID
+	PurchaseTypeId      int                          `json:"purchaseTypeId" form:"purchaseType" gorm:"type:int(11);not null;default 0;comment:閲囪喘绫诲瀷id"`                   // 閲囪喘绫诲瀷id
+	SupplierId          int                          `json:"supplierId" form:"supplierId" gorm:"type:int(11);not null;default 0;comment:渚涘簲鍟唅d"`                          // 渚涘簲鍟唅d
+	Number              string                       `json:"number" form:"number" gorm:"unique;type:varchar(255);not null;default '';comment:閲囪喘缂栧彿"`                      // 閲囪喘缂栧彿
+	Name                string                       `json:"name" form:"name" gorm:"type:varchar(255);not null;default '';comment:閲囪喘鍚嶇О"`                                 // 閲囪喘鍚嶇О
+	Contact             string                       `json:"contact" form:"contact" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜�"`                            // 鑱旂郴浜�
+	Phone               string                       `json:"phone" form:"phone" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜虹數璇�"`                              // 鑱旂郴浜虹數璇�
+	SigningDate         string                       `json:"signingDate" form:"signingDate" gorm:"type:varchar(255);not null;default '';comment:绛剧害鏃ユ湡"`                   // 绛剧害鏃ユ湡
+	DeliveryDate        string                       `json:"deliveryDate" form:"deliveryDate" gorm:"type:varchar(255);not null;default '';comment:浜や粯鏃ユ湡"`                 //浜や粯鏃ユ湡
+	Remark              string                       `json:"remark" form:"remark" gorm:"type:varchar(1000);not null;default '';comment:澶囨敞"`                              //澶囨敞
+	Status              purchase.OrderStatus         `json:"status" form:"status" gorm:"type:tinyint(1);not null;default 0;comment:鐘舵��"`                                  //鐘舵��
+	Quantity            decimal.Decimal              `json:"quantity" form:"quantity" gorm:"type:decimal(12,2);not null;default 0;comment:閲囪喘鏁伴噺"`                         // 閲囪喘鏁伴噺
+	TotalPrice          decimal.Decimal              `json:"totalPrice" form:"totalPrice" gorm:"type:decimal(12,2);not null;default 0.00;comment:浠风◣鍚堣"`                  //浠风◣鍚堣
+	WholeDiscountType   purchase.WholeDiscountType   `json:"wholeDiscountType" form:"wholeDiscountType" gorm:"type:decimal(12,2);not null;default 0.00;comment:鏁村崟鎶樻墸"`    //鏁村崟鎶樻墸绫诲瀷
+	WholeDiscount       decimal.Decimal              `json:"wholeDiscount" form:"wholeDiscount" gorm:"type:decimal(12,2);not null;default 0;comment:鏁村崟鎶樻墸"`               //鏁村崟鎶樻墸鍊�
+	PriceAdjustmentType purchase.PriceAdjustmentType `json:"priceAdjustmentType" form:"priceAdjustmentType" gorm:"type:decimal(12,2);not null;default 0;comment:浠锋牸璋冩暣绫诲瀷"` //浠锋牸璋冩暣绫诲瀷
+	PriceAdjustment     decimal.Decimal              `json:"priceAdjustment" form:"priceAdjustment" gorm:"type:decimal(12,2);not null;default 0.00;comment:浠锋牸璋冩暣"`        //浠锋牸璋冩暣鍊�
+	RealTotalPrice      decimal.Decimal              `json:"realTotalPrice" form:"realTotalPrice" gorm:"type:decimal(12,2);not null;default 0.00;comment:鏈�缁堜环鏍�"`          //鏈�缁堜环鏍�
 }
diff --git a/model/purchase/response/purchase.go b/model/purchase/response/purchase.go
index dad6b28..043729b 100644
--- a/model/purchase/response/purchase.go
+++ b/model/purchase/response/purchase.go
@@ -1,8 +1,50 @@
 package response
 
-import "srm/model/purchase"
+import (
+	"github.com/shopspring/decimal"
+	"srm/model/purchase"
+	"srm/model/test"
+)
 
 type PurchaseResponse struct {
-	Purchase    purchase.Purchase            `json:"purchase"`
-	ProductList []*purchase.PurchaseProducts `json:"productList"`
+	Purchase    purchase.Purchase   `json:"purchase"`
+	ProductList []*PurchaseProducts `json:"productList"`
+}
+
+type PurchaseProducts struct {
+	PurchaseId       int             `json:"purchaseId" form:"purchaseType" gorm:"type:int(11);not null;default 0;comment:閲囪喘绫诲瀷id"` // 閲囪喘id
+	ProductId        int             `json:"productId" form:"supplierId" gorm:"type:int(11);not null;default 0;comment:渚涘簲鍟唅d"`     // 浜у搧id
+	Amount           decimal.Decimal `json:"amount" form:"amount" gorm:"type:decimal(12,2);not null;default 0;comment:閲囪喘鏁伴噺"`       // 閲囪喘鏁伴噺
+	Price            decimal.Decimal `json:"price" form:"price" gorm:"type:decimal(12,2);not null;default 0.00;comment:閲囪喘鍗曚环"`      // 閲囪喘鍗曚环
+	Total            decimal.Decimal `json:"total" form:"total" gorm:"type:decimal(12,2);not null;default 0.00;comment:閲囪喘鎬讳环"`      // 閲囪喘鎬讳环
+	Name             string          `json:"name" form:"name" gorm:"column:name;comment:鍚嶇О;size:255;"`
+	Number           string          `json:"number" form:"number" gorm:"column:number;comment:缂栫爜;size:255;"`
+	Unit             string          `json:"unit" form:"unit" gorm:"column:unit;comment:璁¢噺鍗曚綅;size:255;"`
+	PurchasePrice    *float64        `json:"purchasePrice" form:"purchasePrice" gorm:"column:purchase_price;comment:閲囪喘浠锋牸;"`
+	DeliveryTime     *int            `json:"deliveryTime" form:"deliveryTime" gorm:"column:delivery_time;comment:;size:11;"`
+	ShippingDuration *int            `json:"shippingDuration" form:"shippingDuration" gorm:"column:shipping_duration;comment:鐗╂祦鏃堕暱;size:11;"`
+	Specifications   string          `json:"specifications" form:"specifications" gorm:"column:specifications;comment:瑙勬牸;size:255;"`
+	ModelNumber      string          `json:"modelNumber" form:"modelNumber" gorm:"column:model_number;comment:鍨嬪彿;size:255;"`
+	ProductType      string          `json:"productType" form:"productType" gorm:"column:product_type;comment:浜у搧绫诲埆;size:255;"`
+}
+
+type QualityInspectList struct {
+	PurchaseTypeId int             `json:"purchaseTypeId" form:"purchaseType" gorm:"type:int(11);not null;default 0;comment:閲囪喘绫诲瀷id"` // 閲囪喘绫诲瀷id
+	OrderSource    string          `json:"orderSource" gorm:"type:varchar(255);not null;default '';comment:鍗曟嵁鏉ユ簮"`                    // 鍗曟嵁鏉ユ簮
+	SupplierId     int             `json:"supplierId" form:"supplierId" gorm:"type:int(11);not null;default 0;comment:渚涘簲鍟唅d"`        // 渚涘簲鍟唅d
+	Supplier       test.Supplier   `json:"supplier" gorm:"foreignKey:SupplierId"`
+	Number         string          `json:"number" form:"number" gorm:"unique;type:varchar(255);not null;default '';comment:閲囪喘缂栧彿"`      // 閲囪喘缂栧彿
+	Name           string          `json:"name" form:"name" gorm:"type:varchar(255);not null;default '';comment:閲囪喘鍚嶇О"`                 // 閲囪喘鍚嶇О
+	Contact        string          `json:"contact" form:"contact" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜�"`            // 鑱旂郴浜�
+	Phone          string          `json:"phone" form:"phone" gorm:"type:varchar(255);not null;default '';comment:鑱旂郴浜虹數璇�"`              // 鑱旂郴浜虹數璇�
+	SigningDate    string          `json:"signingDate" form:"signingDate" gorm:"type:varchar(255);not null;default '';comment:绛剧害鏃ユ湡"`   // 绛剧害鏃ユ湡
+	DeliveryDate   string          `json:"deliveryDate" form:"deliveryDate" gorm:"type:varchar(255);not null;default '';comment:浜や粯鏃ユ湡"` //浜や粯鏃ユ湡
+	Remark         string          `json:"remark" form:"remark" gorm:"type:varchar(1000);not null;default '';comment:澶囨敞"`              //澶囨敞
+	HandledBy      string          `json:"handledBy" form:"handledBy" gorm:"type:varchar(255);not null;default '';comment:缁忓姙浜�"`        //缁忓姙浜�
+	Creator        string          `json:"creator" form:"creator" gorm:"type:varchar(255);not null;default '';comment:鍒跺崟浜�"`            //鍒跺崟浜�
+	Principal      string          `json:"principal" form:"principal" gorm:"type:varchar(255);not null;default '';comment:閲囪喘璐熻矗浜�"`      //閲囪喘璐熻矗浜�
+	OrderType      string          `json:"orderType" form:"orderType" gorm:"type:varchar(255);not null;default '';comment:鍗曟嵁绫诲瀷"`       //鍗曟嵁绫诲瀷
+	Warehouse      string          `json:"warehouse" form:"warehouse" gorm:"type:varchar(255);not null;default '';comment:鏀惰揣浠撳簱"`       //鏀惰揣浠撳簱
+	Quantity       decimal.Decimal `json:"quantity" form:"quantity" gorm:"type:decimal(12,4);not null;comment:閲囪喘鏁伴噺"`                   // 閲囪喘鏁伴噺
+	InspectStatus  string          `json:"inspectStatus" form:"inspectStatus"`                                                         //妫�娴嬬粨鏋�
 }
diff --git a/proto/quality_inspect.proto b/proto/quality_inspect.proto
index 3d8c695..9eb6165 100644
--- a/proto/quality_inspect.proto
+++ b/proto/quality_inspect.proto
@@ -26,7 +26,7 @@
   double report_amount = 13; // 鎶ユ鏁伴噺
   InspectMethod inspect_method = 14; // 妫�楠屾柟寮�
   double inspect_amount = 15; // 妫�楠屾暟閲�
-  int32 status = 16; // 鐘舵��
+  InspectStatus status = 16; // 鐘舵��
   string submit_id = 17; // 鎻愪氦浜篒D
   double reject_amount = 18; // 閫�璐ф暟閲�
   double exchange_amount = 19; // 鎹㈣揣鏁伴噺
@@ -60,6 +60,15 @@
 }
 
 
+// InspectStatus 妫�楠岀姸鎬�
+enum InspectStatus {
+  InspectStatusNull = 0;
+  InspectStatusWaitInspect   = 1; // 寰呮鏌�
+  InspectStatusAuditing      = 2; // 瀹℃牳涓�
+  InspectStatusAuditFinish   = 3; // 瀹℃牳瀹屾垚
+  InspectStatusInspectFinish = 4; // 妫�鏌ュ畬鎴�
+}
+
 
 message SendPurchaseInspectResponse {
   int32   Code  = 1;
@@ -68,9 +77,7 @@
 
 
 message GetInspectListRequest{
-  int32 page = 1;
-  int32 pageSize = 2;
-  string keyword = 3;
+  repeated string purchase_order_id = 1;
 }
 
 message GetInspectListResponse{
diff --git a/proto/qualityinspect/quality_inspect.pb.go b/proto/qualityinspect/quality_inspect.pb.go
index 7d05402..e1f671b 100644
--- a/proto/qualityinspect/quality_inspect.pb.go
+++ b/proto/qualityinspect/quality_inspect.pb.go
@@ -176,6 +176,62 @@
 	return file_quality_inspect_proto_rawDescGZIP(), []int{2}
 }
 
+// InspectStatus 妫�楠岀姸鎬�
+type InspectStatus int32
+
+const (
+	InspectStatus_InspectStatusNull          InspectStatus = 0
+	InspectStatus_InspectStatusWaitInspect   InspectStatus = 1 // 寰呮鏌�
+	InspectStatus_InspectStatusAuditing      InspectStatus = 2 // 瀹℃牳涓�
+	InspectStatus_InspectStatusAuditFinish   InspectStatus = 3 // 瀹℃牳瀹屾垚
+	InspectStatus_InspectStatusInspectFinish InspectStatus = 4 // 妫�鏌ュ畬鎴�
+)
+
+// Enum value maps for InspectStatus.
+var (
+	InspectStatus_name = map[int32]string{
+		0: "InspectStatusNull",
+		1: "InspectStatusWaitInspect",
+		2: "InspectStatusAuditing",
+		3: "InspectStatusAuditFinish",
+		4: "InspectStatusInspectFinish",
+	}
+	InspectStatus_value = map[string]int32{
+		"InspectStatusNull":          0,
+		"InspectStatusWaitInspect":   1,
+		"InspectStatusAuditing":      2,
+		"InspectStatusAuditFinish":   3,
+		"InspectStatusInspectFinish": 4,
+	}
+)
+
+func (x InspectStatus) Enum() *InspectStatus {
+	p := new(InspectStatus)
+	*p = x
+	return p
+}
+
+func (x InspectStatus) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (InspectStatus) Descriptor() protoreflect.EnumDescriptor {
+	return file_quality_inspect_proto_enumTypes[3].Descriptor()
+}
+
+func (InspectStatus) Type() protoreflect.EnumType {
+	return &file_quality_inspect_proto_enumTypes[3]
+}
+
+func (x InspectStatus) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use InspectStatus.Descriptor instead.
+func (InspectStatus) EnumDescriptor() ([]byte, []int) {
+	return file_quality_inspect_proto_rawDescGZIP(), []int{3}
+}
+
 type SendPurchaseInspectRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -243,7 +299,7 @@
 	ReportAmount    float64       `protobuf:"fixed64,13,opt,name=report_amount,json=reportAmount,proto3" json:"report_amount,omitempty"`                      // 鎶ユ鏁伴噺
 	InspectMethod   InspectMethod `protobuf:"varint,14,opt,name=inspect_method,json=inspectMethod,proto3,enum=InspectMethod" json:"inspect_method,omitempty"` // 妫�楠屾柟寮�
 	InspectAmount   float64       `protobuf:"fixed64,15,opt,name=inspect_amount,json=inspectAmount,proto3" json:"inspect_amount,omitempty"`                   // 妫�楠屾暟閲�
-	Status          int32         `protobuf:"varint,16,opt,name=status,proto3" json:"status,omitempty"`                                                       // 鐘舵��
+	Status          InspectStatus `protobuf:"varint,16,opt,name=status,proto3,enum=InspectStatus" json:"status,omitempty"`                                    // 鐘舵��
 	SubmitId        string        `protobuf:"bytes,17,opt,name=submit_id,json=submitId,proto3" json:"submit_id,omitempty"`                                    // 鎻愪氦浜篒D
 	RejectAmount    float64       `protobuf:"fixed64,18,opt,name=reject_amount,json=rejectAmount,proto3" json:"reject_amount,omitempty"`                      // 閫�璐ф暟閲�
 	ExchangeAmount  float64       `protobuf:"fixed64,19,opt,name=exchange_amount,json=exchangeAmount,proto3" json:"exchange_amount,omitempty"`                // 鎹㈣揣鏁伴噺
@@ -389,11 +445,11 @@
 	return 0
 }
 
-func (x *QualityInspect) GetStatus() int32 {
+func (x *QualityInspect) GetStatus() InspectStatus {
 	if x != nil {
 		return x.Status
 	}
-	return 0
+	return InspectStatus_InspectStatusNull
 }
 
 func (x *QualityInspect) GetSubmitId() string {
@@ -498,9 +554,7 @@
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Page     int32  `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"`
-	PageSize int32  `protobuf:"varint,2,opt,name=pageSize,proto3" json:"pageSize,omitempty"`
-	Keyword  string `protobuf:"bytes,3,opt,name=keyword,proto3" json:"keyword,omitempty"`
+	PurchaseOrderId []string `protobuf:"bytes,1,rep,name=purchase_order_id,json=purchaseOrderId,proto3" json:"purchase_order_id,omitempty"`
 }
 
 func (x *GetInspectListRequest) Reset() {
@@ -535,25 +589,11 @@
 	return file_quality_inspect_proto_rawDescGZIP(), []int{3}
 }
 
-func (x *GetInspectListRequest) GetPage() int32 {
+func (x *GetInspectListRequest) GetPurchaseOrderId() []string {
 	if x != nil {
-		return x.Page
+		return x.PurchaseOrderId
 	}
-	return 0
-}
-
-func (x *GetInspectListRequest) GetPageSize() int32 {
-	if x != nil {
-		return x.PageSize
-	}
-	return 0
-}
-
-func (x *GetInspectListRequest) GetKeyword() string {
-	if x != nil {
-		return x.Keyword
-	}
-	return ""
+	return nil
 }
 
 type GetInspectListResponse struct {
@@ -635,7 +675,7 @@
 	0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65,
 	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20,
 	0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x73,
-	0x70, 0x65, 0x63, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xbe, 0x06, 0x0a, 0x0e, 0x51,
+	0x70, 0x65, 0x63, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0xce, 0x06, 0x0a, 0x0e, 0x51,
 	0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x0e, 0x0a,
 	0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2f, 0x0a,
 	0x0c, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20,
@@ -672,7 +712,8 @@
 	0x65, 0x63, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x73,
 	0x70, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28,
 	0x01, 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
-	0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05,
+	0x12, 0x26, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0e,
+	0x32, 0x0e, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
 	0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6d,
 	0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x75, 0x62,
 	0x6d, 0x69, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x5f,
@@ -692,54 +733,62 @@
 	0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f,
 	0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x10,
 	0x0a, 0x03, 0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4d, 0x73, 0x67,
-	0x22, 0x61, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4c, 0x69,
-	0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a,
-	0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
-	0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79,
-	0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77,
-	0x6f, 0x72, 0x64, 0x22, 0x79, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
-	0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a,
-	0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64,
-	0x65, 0x12, 0x10, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x4d, 0x73, 0x67, 0x12, 0x23, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x0f, 0x2e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x73, 0x70, 0x65,
-	0x63, 0x74, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x74, 0x61,
-	0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x2a, 0x86,
-	0x01, 0x0a, 0x0b, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16,
-	0x0a, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74,
-	0x54, 0x79, 0x70, 0x65, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
-	0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x10, 0x01, 0x12, 0x17, 0x0a,
-	0x13, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x50, 0x75, 0x72, 0x63,
-	0x68, 0x61, 0x73, 0x65, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
-	0x74, 0x54, 0x79, 0x70, 0x65, 0x4f, 0x75, 0x74, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x10, 0x03,
-	0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52,
-	0x65, 0x6a, 0x65, 0x63, 0x74, 0x10, 0x04, 0x2a, 0x6c, 0x0a, 0x0c, 0x4d, 0x61, 0x74, 0x65, 0x72,
-	0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x66, 0x61, 0x75,
-	0x6c, 0x74, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x10, 0x00,
-	0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65,
-	0x52, 0x61, 0x77, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61,
-	0x6c, 0x54, 0x79, 0x70, 0x65, 0x53, 0x65, 0x6d, 0x69, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4d,
-	0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73,
-	0x68, 0x65, 0x64, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74,
-	0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c,
-	0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x10, 0x00,
-	0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f,
-	0x64, 0x41, 0x6c, 0x6c, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
-	0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x70, 0x6f, 0x74, 0x10, 0x02, 0x32, 0xb0, 0x01,
-	0x0a, 0x15, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74,
-	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x13, 0x53, 0x65, 0x6e, 0x64, 0x50,
-	0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x1b,
-	0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73,
-	0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x53, 0x65,
-	0x6e, 0x64, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
-	0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x47,
-	0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e,
-	0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65,
-	0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
-	0x42, 0x12, 0x5a, 0x10, 0x2e, 0x2f, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x69, 0x6e, 0x73,
-	0x70, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x22, 0x43, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4c, 0x69,
+	0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x75, 0x72,
+	0x63, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01,
+	0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4f, 0x72,
+	0x64, 0x65, 0x72, 0x49, 0x64, 0x22, 0x79, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43,
+	0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x23, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x73,
+	0x70, 0x65, 0x63, 0x74, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f,
+	0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x54, 0x6f, 0x74, 0x61, 0x6c,
+	0x2a, 0x86, 0x01, 0x0a, 0x0b, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65,
+	0x12, 0x16, 0x0a, 0x12, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65,
+	0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x10, 0x01, 0x12,
+	0x17, 0x0a, 0x13, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x50, 0x75,
+	0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x4f, 0x75, 0x74, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+	0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70,
+	0x65, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x10, 0x04, 0x2a, 0x6c, 0x0a, 0x0c, 0x4d, 0x61, 0x74,
+	0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x65, 0x66,
+	0x61, 0x75, 0x6c, 0x74, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65,
+	0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79,
+	0x70, 0x65, 0x52, 0x61, 0x77, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x61, 0x74, 0x65, 0x72,
+	0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x53, 0x65, 0x6d, 0x69, 0x10, 0x02, 0x12, 0x18, 0x0a,
+	0x14, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x6e,
+	0x69, 0x73, 0x68, 0x65, 0x64, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x70, 0x65,
+	0x63, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x65, 0x66, 0x61,
+	0x75, 0x6c, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64,
+	0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x74,
+	0x68, 0x6f, 0x64, 0x41, 0x6c, 0x6c, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x70, 0x6f, 0x74, 0x10, 0x02, 0x2a,
+	0x9d, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x57, 0x61, 0x69, 0x74, 0x49, 0x6e, 0x73,
+	0x70, 0x65, 0x63, 0x74, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
+	0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x41, 0x75, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x10,
+	0x02, 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x41, 0x75, 0x64, 0x69, 0x74, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x10, 0x03, 0x12,
+	0x1e, 0x0a, 0x1a, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+	0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x10, 0x04, 0x32,
+	0xb0, 0x01, 0x0a, 0x15, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x73, 0x70, 0x65,
+	0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x13, 0x53, 0x65, 0x6e,
+	0x64, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74,
+	0x12, 0x1b, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x49,
+	0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e,
+	0x53, 0x65, 0x6e, 0x64, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a,
+	0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12,
+	0x16, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73,
+	0x70, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x22, 0x00, 0x42, 0x12, 0x5a, 0x10, 0x2e, 0x2f, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x69,
+	0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -754,33 +803,35 @@
 	return file_quality_inspect_proto_rawDescData
 }
 
-var file_quality_inspect_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
+var file_quality_inspect_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
 var file_quality_inspect_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
 var file_quality_inspect_proto_goTypes = []interface{}{
 	(InspectType)(0),                    // 0: InspectType
 	(MaterialType)(0),                   // 1: MaterialType
 	(InspectMethod)(0),                  // 2: InspectMethod
-	(*SendPurchaseInspectRequest)(nil),  // 3: SendPurchaseInspectRequest
-	(*QualityInspect)(nil),              // 4: QualityInspect
-	(*SendPurchaseInspectResponse)(nil), // 5: SendPurchaseInspectResponse
-	(*GetInspectListRequest)(nil),       // 6: GetInspectListRequest
-	(*GetInspectListResponse)(nil),      // 7: GetInspectListResponse
+	(InspectStatus)(0),                  // 3: InspectStatus
+	(*SendPurchaseInspectRequest)(nil),  // 4: SendPurchaseInspectRequest
+	(*QualityInspect)(nil),              // 5: QualityInspect
+	(*SendPurchaseInspectResponse)(nil), // 6: SendPurchaseInspectResponse
+	(*GetInspectListRequest)(nil),       // 7: GetInspectListRequest
+	(*GetInspectListResponse)(nil),      // 8: GetInspectListResponse
 }
 var file_quality_inspect_proto_depIdxs = []int32{
-	4, // 0: SendPurchaseInspectRequest.list:type_name -> QualityInspect
+	5, // 0: SendPurchaseInspectRequest.list:type_name -> QualityInspect
 	0, // 1: QualityInspect.inspect_type:type_name -> InspectType
 	1, // 2: QualityInspect.material_type:type_name -> MaterialType
 	2, // 3: QualityInspect.inspect_method:type_name -> InspectMethod
-	4, // 4: GetInspectListResponse.List:type_name -> QualityInspect
-	3, // 5: QualityInspectService.SendPurchaseInspect:input_type -> SendPurchaseInspectRequest
-	6, // 6: QualityInspectService.GetInspectList:input_type -> GetInspectListRequest
-	5, // 7: QualityInspectService.SendPurchaseInspect:output_type -> SendPurchaseInspectResponse
-	7, // 8: QualityInspectService.GetInspectList:output_type -> GetInspectListResponse
-	7, // [7:9] is the sub-list for method output_type
-	5, // [5:7] is the sub-list for method input_type
-	5, // [5:5] is the sub-list for extension type_name
-	5, // [5:5] is the sub-list for extension extendee
-	0, // [0:5] is the sub-list for field type_name
+	3, // 4: QualityInspect.status:type_name -> InspectStatus
+	5, // 5: GetInspectListResponse.List:type_name -> QualityInspect
+	4, // 6: QualityInspectService.SendPurchaseInspect:input_type -> SendPurchaseInspectRequest
+	7, // 7: QualityInspectService.GetInspectList:input_type -> GetInspectListRequest
+	6, // 8: QualityInspectService.SendPurchaseInspect:output_type -> SendPurchaseInspectResponse
+	8, // 9: QualityInspectService.GetInspectList:output_type -> GetInspectListResponse
+	8, // [8:10] is the sub-list for method output_type
+	6, // [6:8] is the sub-list for method input_type
+	6, // [6:6] is the sub-list for extension type_name
+	6, // [6:6] is the sub-list for extension extendee
+	0, // [0:6] is the sub-list for field type_name
 }
 
 func init() { file_quality_inspect_proto_init() }
@@ -855,7 +906,7 @@
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_quality_inspect_proto_rawDesc,
-			NumEnums:      3,
+			NumEnums:      4,
 			NumMessages:   5,
 			NumExtensions: 0,
 			NumServices:   1,
diff --git a/router/purchase/purchase.go b/router/purchase/purchase.go
index a7b3728..fc32f6a 100644
--- a/router/purchase/purchase.go
+++ b/router/purchase/purchase.go
@@ -18,4 +18,12 @@
 		purchaseRouter.POST("purchaseType", PurchaseApi.SavePurchaseType)       // 淇濆瓨閲囪喘绫诲瀷
 		purchaseRouter.GET("purchaseTypeList", PurchaseApi.GetPurchaseTypeList) // 鏌ヨ閲囪喘绫诲瀷
 	}
+
+	qualityInspectRouter := Router.Group("purchase")
+	qualityInspectApi := purchase.QualityInspectApi{}
+	{
+		//qualityInspectRouter.GET("purchase/:id", qualityInspectApi.GetPurchase)             // 鑾峰彇鍗曚竴閲囪喘鍗曚俊鎭�
+		qualityInspectRouter.GET("qualityInspectList", qualityInspectApi.GetQualityInspectList) // 鑾峰彇閲囪喘鍗曞垪琛�
+	}
+
 }
diff --git a/service/purchase/purchase.go b/service/purchase/purchase.go
index bbef0f1..2251d8e 100644
--- a/service/purchase/purchase.go
+++ b/service/purchase/purchase.go
@@ -2,6 +2,7 @@
 
 import (
 	"context"
+	"errors"
 	"github.com/shopspring/decimal"
 	"github.com/spf13/cast"
 	"gorm.io/gorm"
@@ -23,24 +24,44 @@
 //@param: params *purchaserequest.AddPurchase
 //@return: err error
 
-func (slf *PurchaseService) CreatePurchase(params *purchase.Purchase, productList []*purchase.PurchaseProducts) (err error) {
+func (slf *PurchaseService) CreatePurchase(record *purchase.Purchase, productList []*purchase.PurchaseProducts) (err error) {
+	err = DealPrice(record, productList)
+	if err != nil {
+		return err
+	}
 	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
-		var quantity decimal.Decimal
-		for _, product := range productList {
-			quantity = quantity.Add(product.Amount)
-		}
-		params.Quantity = quantity
-		err = tx.Create(&params).Error
+		err = tx.Create(&record).Error
 		if err != nil {
 			return err
 		}
 		for _, product := range productList {
-			product.PurchaseId = cast.ToInt(params.ID)
+			product.PurchaseId = cast.ToInt(record.ID)
 		}
 		return tx.Create(productList).Error
 	})
 
 	return err
+}
+
+func DealPrice(record *purchase.Purchase, productList []*purchase.PurchaseProducts) error {
+	var quantity decimal.Decimal
+	var totalPrice decimal.Decimal
+	var realTotalPrice decimal.Decimal
+	for _, product := range productList {
+		quantity = quantity.Add(product.Amount)
+		totalPrice = totalPrice.Add(product.Price.Mul(product.Amount))
+	}
+	record.Quantity = quantity
+	if !totalPrice.Equal(record.TotalPrice) {
+		return errors.New("浠风◣鎬昏璁$畻閿欒")
+	}
+	realTotalPrice = record.CalcRealTotalPrice()
+	if !realTotalPrice.Equal(record.RealTotalPrice) {
+		return errors.New("鏈�缁堜环鏍艰绠楅敊璇�")
+	}
+	record.UnInvoiceAmount = record.RealTotalPrice
+	record.ShouldPayAmount = record.RealTotalPrice
+	return nil
 }
 
 //@function: DeletePurchase
@@ -65,12 +86,11 @@
 //@return: err error
 
 func (slf *PurchaseService) UpdatePurchase(params *purchase.Purchase, productList []*purchase.PurchaseProducts) (err error) {
+	err = DealPrice(params, productList)
+	if err != nil {
+		return err
+	}
 	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
-		var quantity decimal.Decimal
-		for _, product := range productList {
-			quantity = quantity.Add(product.Amount)
-		}
-		params.Quantity = quantity
 		err = tx.Where("id = ?", params.ID).Updates(params).Error
 		if err != nil {
 			return err
@@ -115,7 +135,7 @@
 			Or("Product.name like ?", "%"+info.Keyword+"%").
 			Or("supplier.name like ?", "%"+info.Keyword+"%")
 	}
-	var purchaseList []purchase.Purchase
+	var purchaseList []*purchase.Purchase
 	err = db.Count(&total).Error
 	if err != nil {
 		return purchaseList, total, err
@@ -132,7 +152,7 @@
 func (slf *PurchaseService) GetPurchaseProductList(purchaseId uint) (list []*purchase.PurchaseProducts, err error) {
 	db := global.GVA_DB.Model(&purchase.PurchaseProducts{})
 	list = make([]*purchase.PurchaseProducts, 0)
-	err = db.Where("purchase_id = ?", purchaseId).Find(&list).Error
+	err = db.Where("purchase_id = ?", purchaseId).Preload("Product").Find(&list).Error
 	return list, err
 }
 
@@ -194,19 +214,23 @@
 			continue
 		}
 		inspectOrder := &qualityinspect.QualityInspect{
-			InspectType:   qualityinspect.InspectType_InspectTypePurchase,
-			MaterialType:  qualityinspect.MaterialType_MaterialTypeRaw,
-			MaterialName:  product.Name,
-			MaterialId:    product.Number,
-			MaterialTp:    product.ModelNumber,
-			MaterialUnit:  product.Unit,
-			Supplier:      record.Supplier.Name,
-			WarehouseName: "閲囪喘鎬讳粨",
-			ReportAmount:  productItem.Amount.InexactFloat64(),
-			InspectMethod: qualityinspect.InspectMethod_InspectMethodAll,
-			InspectAmount: productItem.Amount.InexactFloat64(),
+			InspectType:     qualityinspect.InspectType_InspectTypePurchase,
+			MaterialType:    qualityinspect.MaterialType_MaterialTypeRaw,
+			MaterialName:    product.Name,
+			MaterialId:      product.Number,
+			MaterialTp:      product.ModelNumber,
+			MaterialUnit:    product.Unit,
+			Supplier:        record.Supplier.Name,
+			WarehouseName:   "閲囪喘鎬讳粨",
+			ReportAmount:    productItem.Amount.InexactFloat64(),
+			InspectMethod:   qualityinspect.InspectMethod_InspectMethodAll,
+			InspectAmount:   productItem.Amount.InexactFloat64(),
+			PurchaseOrderId: record.Number,
 		}
 		inspectOrders = append(inspectOrders, inspectOrder)
+	}
+	if len(inspectOrders) == 0 {
+		return nil
 	}
 	inspectRequest := qualityinspect.SendPurchaseInspectRequest{List: inspectOrders}
 	_, err = qualityinspect.NewQualityInspectServiceClient(qualityinspect.Conn).SendPurchaseInspect(context.Background(), &inspectRequest)
@@ -214,15 +238,36 @@
 }
 
 func (slf *PurchaseService) SavePurchaseType(list []*purchase.PurchaseType) (err error) {
+	ids := make([]uint, 0)
+	newRecords := make([]*purchase.PurchaseType, 0)
+	for _, item := range list {
+		if item.ID != 0 {
+			ids = append(ids, item.ID)
+		} else {
+			newRecords = append(newRecords, item)
+		}
+	}
 	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
-		err = tx.Where("1 = ?", 1).Delete(&purchase.PurchaseType{}).Error
+		err = tx.Where("id not in ?", ids).Delete(&purchase.PurchaseType{}).Error
 		if err != nil {
 			return err
 		}
-		for _, item := range list {
-			item.ID = 0
+		if len(newRecords) > 0 {
+			err = tx.Create(newRecords).Error
+			if err != nil {
+				return err
+			}
 		}
-		return tx.Create(list).Error
+
+		for _, item := range list {
+			if item.ID != 0 {
+				err = tx.Save(item).Error
+				if err != nil {
+					return err
+				}
+			}
+		}
+		return nil
 	})
 	return err
 }
diff --git a/service/purchase/quality_inspect.go b/service/purchase/quality_inspect.go
new file mode 100644
index 0000000..ce17a43
--- /dev/null
+++ b/service/purchase/quality_inspect.go
@@ -0,0 +1,61 @@
+package purchase
+
+//
+//import (
+//	"srm/global"
+//	"srm/model/common/request"
+//)
+//
+//type QualityInspect struct{}
+//
+//func NewQualityInspect() *QualityInspect {
+//	return &QualityInspect{}
+//}
+//
+////@function: GetQualityInspect
+////@description: 鑾峰彇閲囪喘鍗曚俊鎭�
+////@param: id uint
+////@return: QualityInspect model.QualityInspect, err error
+//
+//func (slf *QualityInspect) GetQualityInspect(id uint) (QualityInspect QualityInspect.QualityInspect, err error) {
+//	err = global.GVA_DB.Where("id = ?", id).Preload("Supplier").First(&QualityInspect).Error
+//	return
+//}
+//
+////@function: GetQualityInspectList
+////@description: 鍒嗛〉鑾峰彇閲囪喘鍗曞垪琛�
+////@param: info request.PageInfo
+////@return: list interface{}, total int64, err error
+//
+//func (slf *QualityInspect) GetQualityInspectList(info request.PageInfo) (list interface{}, total int64, err error) {
+//	limit := info.PageSize
+//	offset := info.PageSize * (info.Page - 1)
+//	db := global.GVA_DB.Model(&QualityInspect.QualityInspect{})
+//	if info.Keyword != "" {
+//		db.Distinct("QualityInspects.id").Joins("left join QualityInspect_products on QualityInspect_products.QualityInspect_id = QualityInspects.id").
+//			Joins("left join Product on Product.Id = QualityInspect_products.product_id").
+//			Joins("left join supplier on supplier.Id = QualityInspects.supplier_id").
+//			Where("QualityInspects.name like ?", "%"+info.Keyword+"%").
+//			Or("Product.name like ?", "%"+info.Keyword+"%").
+//			Or("supplier.name like ?", "%"+info.Keyword+"%")
+//	}
+//	var QualityInspectList []QualityInspect.QualityInspect
+//	err = db.Count(&total).Error
+//	if err != nil {
+//		return QualityInspectList, total, err
+//	}
+//	err = db.Limit(limit).Offset(offset).Find(&QualityInspectList).Error
+//	return QualityInspectList, total, err
+//}
+//
+////@function: GetQualityInspectProductList
+////@description: 鍒嗛〉鑾峰彇閲囪喘鍗曚骇鍝佸垪琛�
+////@param: QualityInspectId int
+////@return: list interface{},  err error
+//
+//func (slf *QualityInspect) GetQualityInspectProductList(QualityInspectId uint) (list []*QualityInspect.QualityInspectProducts, err error) {
+//	db := global.GVA_DB.Model(&QualityInspect.QualityInspectProducts{})
+//	list = make([]*QualityInspect.QualityInspectProducts, 0)
+//	err = db.Where("QualityInspect_id = ?", QualityInspectId).Preload("Product").Find(&list).Error
+//	return list, err
+//}
diff --git a/utils/structx.go b/utils/structx.go
new file mode 100644
index 0000000..b7b0aec
--- /dev/null
+++ b/utils/structx.go
@@ -0,0 +1,16 @@
+package utils
+
+import "encoding/json"
+
+func AssignTo(from interface{}, to interface{}) error {
+	data, err := json.Marshal(from)
+	if err != nil {
+		return err
+	}
+
+	err = json.Unmarshal(data, to)
+	if err != nil {
+		return err
+	}
+	return nil
+}

--
Gitblit v1.8.0