From 2eb20330dfbda6136f1b8cc804cc21438ae4dc13 Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期五, 15 三月 2024 16:37:00 +0800
Subject: [PATCH] 发货明细和准备发货接口

---
 service/salesDetails.go                              |   10 
 model/response/salesDetails.go                       |   50 ++
 router/salesDetails.go                               |    4 
 docs/swagger.yaml                                    |   47 ++
 docs/docs.go                                         |   73 +++
 docs/swagger.json                                    |   73 +++
 conf/aps-crm.json                                    |    2 
 model/product.go                                     |    8 
 proto/product_inventory/product_inventory.pb.go      |  497 +++++++++++++++++++++++--
 proto/product_inventory/product_inventory_grpc.pb.go |   59 ++
 api/v1/salesDetails.go                               |  169 ++++++++
 proto/product_inventory.proto                        |   35 +
 model/deliveryOrder.go                               |   90 ++++
 13 files changed, 1,058 insertions(+), 59 deletions(-)

diff --git a/api/v1/salesDetails.go b/api/v1/salesDetails.go
index 874d2c4..b57b78d 100644
--- a/api/v1/salesDetails.go
+++ b/api/v1/salesDetails.go
@@ -15,6 +15,7 @@
 	"aps_crm/utils"
 	"github.com/gin-gonic/gin"
 	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
 	"strconv"
 	"strings"
 )
@@ -240,7 +241,7 @@
 // GetProductInventoryInfo
 //
 // @Tags		SalesDetails
-// @Summary	鑾峰彇浜у搧搴撳瓨淇℃伅
+// @Summary	鑾峰彇浜у搧鍙戣揣淇℃伅
 // @Produce	application/json
 // @Param		number	path		string	true	"鏄庣粏缂栫爜"
 // @Success	200	{object}	response.ListResponse
@@ -272,6 +273,172 @@
 	ctx.OkWithDetailed(list)
 }
 
+type GetWarehouseProductInfoReq struct {
+	SaleDetailID     int    `json:"saleDetailID,omitempty"`
+	SaleDetailNumber string `json:"saleDetailNumber,omitempty"`
+}
+
+// GetDeliveryPrepareInfo
+// @Tags		SalesDetails
+// @Summary	鑾峰彇浜у搧鍏ュ簱淇℃伅
+// @Produce	application/json
+// @Param		object 	body GetWarehouseProductInfoReq	true	"鏄庣粏缂栫爜"
+// @Success	200	{object}	response.ListResponse
+// @Router		/api/salesDetails/getDeliveryPrepareInfo [post]
+func (s *SalesDetailsApi) GetDeliveryPrepareInfo(c *gin.Context) {
+	var params GetWarehouseProductInfoReq
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+	if params.SaleDetailID == 0 {
+		ctx.FailWithMsg(ecode.ParamsErr, "鍙傛暟缂哄け")
+		return
+	}
+
+	salesDetails, err := salesDetailsService.GetSalesDetails(params.SaleDetailID)
+	if err == gorm.ErrRecordNotFound || salesDetails.Number != params.SaleDetailNumber {
+		ctx.FailWithMsg(ecode.ParamsErr, "閿�鍞鍗曚笉瀛樺湪")
+		return
+	}
+
+	productMap := model.ProductMap(salesDetails.Products)
+	client := product_inventory.NewProductInventoryServiceClient(grpc_init.ProductInventoryServiceConn)
+	grpcResp, err := client.GetOrderInputAndOutputInfo(ctx.GetCtx(), &product_inventory.GetOrderInputAndOutputInfoRequest{
+		Number: params.SaleDetailNumber,
+	})
+	if err != nil {
+		if strings.Contains(err.Error(), "record not found") {
+			ctx.Ok()
+			return
+		}
+		logx.Errorf("GetOrderInputAndOutputInfo err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "grpc璋冪敤閿欒")
+		return
+	}
+
+	grpcOutputList := grpcResp.OutputList
+	grpcInputList := grpcResp.InputList
+	inputProductMap := make(map[string]*response.StoreInfo)
+	outputProductMap := make(map[string]*response.OutputSimpleInfo)
+	for _, v := range grpcOutputList {
+		if outputProductMap[v.Number] == nil {
+			simpleInfo := &response.OutputSimpleInfo{
+				Number: v.Number,
+			}
+			amount, _ := decimal.NewFromString(v.Amount)
+			simpleInfo.Amount = amount
+			outputProductMap[v.Number] = simpleInfo
+		} else {
+			amount, _ := decimal.NewFromString(v.Amount)
+			outputProductMap[v.Number].Amount = outputProductMap[v.Number].Amount.Add(amount)
+		}
+	}
+	for _, v := range grpcInputList {
+		if inputProductMap[v.Number] == nil {
+			storeInfo := &response.StoreInfo{
+				Number:      v.Number,
+				Name:        v.Name,
+				OrderAmount: productMap[v.Number].Amount,
+			}
+			finishAmount, _ := decimal.NewFromString(v.Amount)
+			storeInfo.FinishAmount = finishAmount
+			storeInfo.AvailableAmount = finishAmount
+			storeInfo.LeftAmount = storeInfo.OrderAmount
+			inputProductMap[v.Number] = storeInfo
+		} else {
+			finishAmount, _ := decimal.NewFromString(v.Amount)
+			inputProductMap[v.Number].FinishAmount = inputProductMap[v.Number].FinishAmount.Add(finishAmount)
+			inputProductMap[v.Number].AvailableAmount = inputProductMap[v.Number].FinishAmount
+		}
+	}
+	storeList := make([]*response.StoreInfo, 0, len(salesDetails.Products))
+	for _, product := range salesDetails.Products {
+		storeInfo := inputProductMap[product.Number]
+		if storeInfo == nil { //娌℃湁鍏ュ簱淇℃伅
+			storeInfo = &response.StoreInfo{
+				Name:            product.Number,
+				Number:          product.Number,
+				OrderAmount:     product.Amount,
+				FinishAmount:    decimal.Decimal{},
+				LeftAmount:      product.Amount,
+				AvailableAmount: decimal.Decimal{},
+			}
+		} else { //鏈夊叆搴撴暟閲忓啀鏌ュ嚭搴擄紝绠楀嚭鏈彂璐ф暟閲�
+			if outputProductMap[product.Number] != nil {
+				outputInfo := outputProductMap[product.Number]
+				storeInfo.LeftAmount = storeInfo.LeftAmount.Sub(outputInfo.Amount)           //鍓╀綑鍙戣揣鏁伴噺 = 璁㈠崟鏁伴噺 - 宸插彂璐ф暟閲�
+				storeInfo.AvailableAmount = storeInfo.AvailableAmount.Sub(outputInfo.Amount) //鍙敤鏁伴噺 = 鍏ュ簱瀹屾垚鏁伴噺 - 宸插彂璐ф暟閲�
+			}
+		}
+		storeList = append(storeList, storeInfo)
+	}
+	ctx.OkWithDetailed(storeList)
+}
+
+// GetDeliveryList
+// @Tags		SalesDetails
+// @Summary	鍙戣揣鏄庣粏
+// @Produce	application/json
+// @Param		object 	body GetWarehouseProductInfoReq	true	"鏄庣粏缂栫爜"
+// @Success	200	{object}	response.ListResponse
+// @Router		/api/salesDetails/getDeliveryList [post]
+func (s *SalesDetailsApi) GetDeliveryList(c *gin.Context) {
+	var params GetWarehouseProductInfoReq
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+	if params.SaleDetailID == 0 {
+		ctx.FailWithMsg(ecode.ParamsErr, "鍙傛暟缂哄け")
+		return
+	}
+
+	salesDetails, err := salesDetailsService.GetSalesDetails(params.SaleDetailID)
+	if err == gorm.ErrRecordNotFound || salesDetails.Number != params.SaleDetailNumber {
+		ctx.FailWithMsg(ecode.ParamsErr, "閿�鍞鍗曚笉瀛樺湪")
+		return
+	}
+
+	productMap := model.ProductMap(salesDetails.Products)
+	client := product_inventory.NewProductInventoryServiceClient(grpc_init.ProductInventoryServiceConn)
+	grpcResp, err := client.GetOrderInputAndOutputInfo(ctx.GetCtx(), &product_inventory.GetOrderInputAndOutputInfoRequest{
+		Number: params.SaleDetailNumber,
+	})
+	if err != nil {
+		if strings.Contains(err.Error(), "record not found") {
+			ctx.Ok()
+			return
+		}
+		logx.Errorf("GetOrderInputAndOutputInfo err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "grpc璋冪敤閿欒")
+		return
+	}
+
+	grpcOutputList := grpcResp.OutputList
+	outputList := make([]*response.OutputInfo, 0, len(grpcOutputList))
+	for _, v := range grpcOutputList {
+		outputInfo := &response.OutputInfo{
+			Number:      v.Number,
+			Name:        v.Name,
+			OrderAmount: productMap[v.Number].Amount.String(),
+			Unit:        v.Unit,
+			Invoice:     v.Invoice,
+			Carrier:     v.Carrier,
+			Waybill:     v.Waybill,
+			SalePrice:   v.SalePrice,
+			Valorem:     v.Valorem,
+			Warehouse:   v.Warehouse,
+			Amount:      v.Amount,
+			Status:      int(v.Status),
+			Specs:       productMap[v.Number].Specs,
+			CreateTime:  v.CreateTime,
+		}
+		outputList = append(outputList, outputInfo)
+	}
+	ctx.OkWithDetailed(outputList)
+}
+
 // GetApsProjectList
 //
 // @Tags		SalesDetails
diff --git a/conf/aps-crm.json b/conf/aps-crm.json
index 0269872..e11e09f 100644
--- a/conf/aps-crm.json
+++ b/conf/aps-crm.json
@@ -51,7 +51,7 @@
   "GrpcServiceAddr": {
     "Aps": "192.168.20.119:9091",
     "Admin": "192.168.20.119:50051",
-    "WMS": "192.168.20.119:8006"
+    "WMS": "192.168.20.120:8006"
   }
 }
 
diff --git a/docs/docs.go b/docs/docs.go
index 4bf4310..56d1440 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -7085,6 +7085,66 @@
                 }
             }
         },
+        "/api/salesDetails/getDeliveryList": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鍙戣揣鏄庣粏",
+                "parameters": [
+                    {
+                        "description": "鏄庣粏缂栫爜",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/v1.GetWarehouseProductInfoReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/salesDetails/getDeliveryPrepareInfo": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鑾峰彇浜у搧鍏ュ簱淇℃伅",
+                "parameters": [
+                    {
+                        "description": "鏄庣粏缂栫爜",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/v1.GetWarehouseProductInfoReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/api/salesDetails/getProductInventoryInfo/{number}": {
             "get": {
                 "produces": [
@@ -7093,7 +7153,7 @@
                 "tags": [
                     "SalesDetails"
                 ],
-                "summary": "鑾峰彇浜у搧搴撳瓨淇℃伅",
+                "summary": "鑾峰彇浜у搧鍙戣揣淇℃伅",
                 "parameters": [
                     {
                         "type": "string",
@@ -19919,6 +19979,17 @@
                     "type": "string"
                 }
             }
+        },
+        "v1.GetWarehouseProductInfoReq": {
+            "type": "object",
+            "properties": {
+                "saleDetailID": {
+                    "type": "integer"
+                },
+                "saleDetailNumber": {
+                    "type": "string"
+                }
+            }
         }
     }
 }`
diff --git a/docs/swagger.json b/docs/swagger.json
index 2165c6a..d3df7a9 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -7073,6 +7073,66 @@
                 }
             }
         },
+        "/api/salesDetails/getDeliveryList": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鍙戣揣鏄庣粏",
+                "parameters": [
+                    {
+                        "description": "鏄庣粏缂栫爜",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/v1.GetWarehouseProductInfoReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/salesDetails/getDeliveryPrepareInfo": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鑾峰彇浜у搧鍏ュ簱淇℃伅",
+                "parameters": [
+                    {
+                        "description": "鏄庣粏缂栫爜",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/v1.GetWarehouseProductInfoReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/api/salesDetails/getProductInventoryInfo/{number}": {
             "get": {
                 "produces": [
@@ -7081,7 +7141,7 @@
                 "tags": [
                     "SalesDetails"
                 ],
-                "summary": "鑾峰彇浜у搧搴撳瓨淇℃伅",
+                "summary": "鑾峰彇浜у搧鍙戣揣淇℃伅",
                 "parameters": [
                     {
                         "type": "string",
@@ -19907,6 +19967,17 @@
                     "type": "string"
                 }
             }
+        },
+        "v1.GetWarehouseProductInfoReq": {
+            "type": "object",
+            "properties": {
+                "saleDetailID": {
+                    "type": "integer"
+                },
+                "saleDetailNumber": {
+                    "type": "string"
+                }
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index c0cc151..4c7a6e1 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -6494,6 +6494,13 @@
       workOrderStatus:
         type: string
     type: object
+  v1.GetWarehouseProductInfoReq:
+    properties:
+      saleDetailID:
+        type: integer
+      saleDetailNumber:
+        type: string
+    type: object
 info:
   contact: {}
 paths:
@@ -10850,6 +10857,44 @@
       summary: 鑾峰彇aps椤圭洰鍒楄〃
       tags:
       - SalesDetails
+  /api/salesDetails/getDeliveryList:
+    post:
+      parameters:
+      - description: 鏄庣粏缂栫爜
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/v1.GetWarehouseProductInfoReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/response.ListResponse'
+      summary: 鍙戣揣鏄庣粏
+      tags:
+      - SalesDetails
+  /api/salesDetails/getDeliveryPrepareInfo:
+    post:
+      parameters:
+      - description: 鏄庣粏缂栫爜
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/v1.GetWarehouseProductInfoReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/response.ListResponse'
+      summary: 鑾峰彇浜у搧鍏ュ簱淇℃伅
+      tags:
+      - SalesDetails
   /api/salesDetails/getProductInventoryInfo/{number}:
     get:
       parameters:
@@ -10865,7 +10910,7 @@
           description: OK
           schema:
             $ref: '#/definitions/response.ListResponse'
-      summary: 鑾峰彇浜у搧搴撳瓨淇℃伅
+      summary: 鑾峰彇浜у搧鍙戣揣淇℃伅
       tags:
       - SalesDetails
   /api/salesDetails/list:
diff --git a/model/deliveryOrder.go b/model/deliveryOrder.go
new file mode 100644
index 0000000..3b9db3a
--- /dev/null
+++ b/model/deliveryOrder.go
@@ -0,0 +1,90 @@
+package model
+
+import (
+	"aps_crm/pkg/mysqlx"
+	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
+)
+
+type (
+	DeliveryOrder struct {
+		Id              int             `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
+		MemberId        int             `json:"memberId" gorm:"column:member_id;type:int;comment:鏈嶅姟浜哄憳id"`
+		SalesDetailsId  int             `json:"salesDetailsId" gorm:"column:sales_details_id;type:int;comment:閿�鍞槑缁唅d"`
+		ProductID       uint            `json:"productID" gorm:"column:product_id"`
+		Name            string          `json:"name" gorm:"column:name;type:varchar(255);comment:浜у搧鍚嶇О"`
+		Number          string          `json:"number" gorm:"column:number;type:varchar(255);comment:浜у搧缂栧彿"`  //浜у搧缂栧彿
+		Amount          decimal.Decimal `json:"amount" gorm:"column:amount;type:decimal(12,2);comment:浜у搧鏁伴噺"` //璁㈠崟鏁伴噺
+		FinishAmount    decimal.Decimal `json:"finishAmount" gorm:"-"`                                       //璁㈠崟瀹屾垚鏁伴噺
+		AvailableAmount decimal.Decimal `json:"availableAmount" gorm:"-"`                                    //鍙敤搴撳瓨
+		DeliveryAmount  decimal.Decimal `json:"deliveryAmount" gorm:"-"`                                     //鏈鍙戣揣鏁伴噺
+		LeftAmount      decimal.Decimal `json:"leftAmount" gorm:"column:left_amount;type:decimal(12,2);comment:鍓╀綑鍙戣揣鏁伴噺"`
+		gorm.Model      `json:"-"`
+	}
+
+	DeliveryOrderSearch struct {
+		DeliveryOrder
+		Orm *gorm.DB
+	}
+)
+
+func (DeliveryOrder) TableName() string {
+	return "delivery_order"
+}
+
+func NewDeliveryOrderSearch() *DeliveryOrderSearch {
+	return &DeliveryOrderSearch{
+		Orm: mysqlx.GetDB(),
+	}
+}
+
+func (css *DeliveryOrderSearch) build() *gorm.DB {
+	var db = css.Orm.Model(&DeliveryOrder{})
+	if css.Id != 0 {
+		db = db.Where("id = ?", css.Id)
+	}
+	if css.SalesDetailsId != 0 {
+		db = db.Where("sales_details_id = ?", css.SalesDetailsId)
+	}
+
+	return db
+}
+
+func (css *DeliveryOrderSearch) Create(record *DeliveryOrder) error {
+	var db = css.build()
+	return db.Create(record).Error
+}
+
+func (css *DeliveryOrderSearch) Update(record *DeliveryOrder) error {
+	var db = css.build()
+	return db.Updates(record).Error
+}
+
+func (css *DeliveryOrderSearch) Delete() error {
+	var db = css.build()
+	return db.Delete(&DeliveryOrder{}).Error
+}
+
+func (css *DeliveryOrderSearch) Find() (*DeliveryOrder, error) {
+	var db = css.build()
+	var record = &DeliveryOrder{}
+	err := db.First(record).Error
+	return record, err
+}
+
+func (css *DeliveryOrderSearch) FindAll() ([]*DeliveryOrder, error) {
+	var db = css.build()
+	var records = make([]*DeliveryOrder, 0)
+	err := db.Find(&records).Error
+	return records, err
+}
+
+func (css *DeliveryOrderSearch) SetId(id int) *DeliveryOrderSearch {
+	css.Id = id
+	return css
+}
+
+func (css *DeliveryOrderSearch) SetSalesDetailsID(id int) *DeliveryOrderSearch {
+	css.SalesDetailsId = id
+	return css
+}
diff --git a/model/product.go b/model/product.go
index fa92985..e864148 100644
--- a/model/product.go
+++ b/model/product.go
@@ -129,3 +129,11 @@
 	var db = slf.build()
 	return db.Updates(m).Error
 }
+
+func ProductMap(products []*Product) (pm map[string]*Product) {
+	pm = make(map[string]*Product, len(products))
+	for _, p := range products {
+		pm[p.Number] = p
+	}
+	return pm
+}
diff --git a/model/response/salesDetails.go b/model/response/salesDetails.go
index 5d91ce3..e8035a0 100644
--- a/model/response/salesDetails.go
+++ b/model/response/salesDetails.go
@@ -1,5 +1,10 @@
 package response
 
+import (
+	"aps_crm/model"
+	"github.com/shopspring/decimal"
+)
+
 type Info struct {
 	MakeInfo        []WorkOrderInfo   `json:"makeInfo"`
 	PurchaseInfo    []Purchase        `json:"purchaseInfo"`
@@ -62,3 +67,48 @@
 	Amount          string `json:"amount"`          //鍦ㄥ簱鏁伴噺
 	AvailableNumber string `json:"availableNumber"` //鍙敤搴撳瓨
 }
+
+type OutputInfo struct {
+	Number      string `json:"number"`
+	Name        string `json:"name"`
+	OrderAmount string `json:"orderAmount"` //璁㈠崟鏁伴噺
+	Unit        string `json:"unit"`
+	Invoice     string `json:"invoice"`   //鍙戣揣鍗�
+	Carrier     string `json:"carrier"`   //鎵胯繍鍟�
+	Waybill     string `json:"waybill"`   //杩愬崟鍙�
+	SalePrice   string `json:"salePrice"` //閿�鍞崟浠�
+	Valorem     string `json:"valorem"`   //浠风◣鍚堣
+	Warehouse   string `json:"warehouse"`
+	Amount      string `json:"amount"`     //鍦ㄥ簱鏁伴噺
+	Status      int    `json:"status"`     //0灏辩华 1瀹屾垚
+	Specs       string `json:"specs"`      //瑙勬牸
+	CreateTime  string `json:"createTime"` //鍒涘缓鏃堕棿
+}
+
+type StoreInfo struct {
+	Name            string          `json:"name"`            //浜у搧鍚嶇О
+	Number          string          `json:"number"`          //浜у搧缂栧彿
+	OrderAmount     decimal.Decimal `json:"orderAmount"`     //璁㈠崟鏁伴噺
+	FinishAmount    decimal.Decimal `json:"finishAmount"`    //璁㈠崟瀹屾垚鏁伴噺
+	LeftAmount      decimal.Decimal `json:"leftAmount"`      //鏈彂璐ф暟閲�
+	AvailableAmount decimal.Decimal `json:"availableAmount"` //鍓╀綑鍙敤鏁伴噺
+}
+
+type OutputSimpleInfo struct {
+	Number string          `json:"number"` //浜у搧缂栧彿
+	Amount decimal.Decimal `json:"amount"` //鍦ㄥ簱鏁伴噺
+	Status int             `json:"status"` //0灏辩华 1瀹屾垚
+}
+
+type WarehouseProducts struct {
+	WarehouseID    string         `protobuf:"bytes,1,opt,name=WarehouseID,proto3" json:"WarehouseID,omitempty"`
+	WarehouseName  string         `protobuf:"bytes,2,opt,name=WarehouseName,proto3" json:"WarehouseName,omitempty"`
+	ProductList    []*ProductInfo `protobuf:"bytes,3,rep,name=ProductList,proto3" json:"ProductList,omitempty"`
+	ProductInfoMap map[string]*ProductInfo
+}
+
+type WarehouseProductInfo struct {
+	WarehouseID   string                 `json:"WarehouseID,omitempty"`
+	WarehouseName string                 `json:"WarehouseName,omitempty"`
+	ProductList   []*model.DeliveryOrder `json:"ProductList,omitempty"`
+}
diff --git a/proto/product_inventory.proto b/proto/product_inventory.proto
index 66cab98..79be0f7 100644
--- a/proto/product_inventory.proto
+++ b/proto/product_inventory.proto
@@ -6,6 +6,7 @@
   rpc CreateOperation(CreateOperationRequest) returns(CreateOperationResponse) {}
   rpc GetInventoryProductInfo(GetInventoryProductInfoRequest) returns (GetInventoryProductInfoResponse) {}
   rpc UpdateSalesDetailStatus(UpdateSalesDetailStatusRequest) returns (UpdateSalesDetailStatusResponse) {}
+  rpc GetOrderInputAndOutputInfo(GetOrderInputAndOutputInfoRequest) returns (GetOrderInputAndOutputInfoResponse) {}
 }
 
 message CreateOperationRequest{
@@ -51,6 +52,11 @@
   string AvailableNumber = 12;//鍙敤搴撳瓨
 }
 
+enum FinishStatus {
+  Ready = 0;
+  Finish = 1;
+}
+
 message GetInventoryProductInfoResponse{
   int32   Code = 1;
   string  Msg = 2;
@@ -67,4 +73,33 @@
 message UpdateSalesDetailStatusResponse{
   int32   Code = 1;
   string  Msg = 2;
+}
+
+
+//--------------------------------------------------
+
+message InputAndOutputInfo{
+  string Number = 1;
+  string Name = 2;
+  string OrderAmount = 3;//璁㈠崟鏁伴噺
+  string Unit = 4;
+  string Invoice = 5;//鍙戣揣鍗�
+  string Carrier = 6;//鎵胯繍鍟�
+  string Waybill = 7;//杩愬崟鍙�
+  string SalePrice = 8;//閿�鍞崟浠�
+  string Valorem = 9;//浠风◣鍚堣
+  string Warehouse = 10;
+  string Amount = 11; //鏁伴噺
+  FinishStatus Status = 13;
+  string CreateTime = 14;
+}
+message GetOrderInputAndOutputInfoRequest {
+  string Number = 1;//鏄庣粏鍗曠紪鐮�
+}
+
+message GetOrderInputAndOutputInfoResponse {
+  int32   Code = 1;
+  string  Msg = 2;
+  repeated InputAndOutputInfo InputList = 3;
+  repeated InputAndOutputInfo OutputList = 4;
 }
\ No newline at end of file
diff --git a/proto/product_inventory/product_inventory.pb.go b/proto/product_inventory/product_inventory.pb.go
index 82e965a..3ef9721 100644
--- a/proto/product_inventory/product_inventory.pb.go
+++ b/proto/product_inventory/product_inventory.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.26.0
-// 	protoc        v4.24.0
+// 	protoc-gen-go v1.31.0
+// 	protoc        v3.19.0
 // source: product_inventory.proto
 
 package product_inventory
@@ -19,6 +19,52 @@
 	// Verify that runtime/protoimpl is sufficiently up-to-date.
 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
+
+type FinishStatus int32
+
+const (
+	FinishStatus_Ready  FinishStatus = 0
+	FinishStatus_Finish FinishStatus = 1
+)
+
+// Enum value maps for FinishStatus.
+var (
+	FinishStatus_name = map[int32]string{
+		0: "Ready",
+		1: "Finish",
+	}
+	FinishStatus_value = map[string]int32{
+		"Ready":  0,
+		"Finish": 1,
+	}
+)
+
+func (x FinishStatus) Enum() *FinishStatus {
+	p := new(FinishStatus)
+	*p = x
+	return p
+}
+
+func (x FinishStatus) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FinishStatus) Descriptor() protoreflect.EnumDescriptor {
+	return file_product_inventory_proto_enumTypes[0].Descriptor()
+}
+
+func (FinishStatus) Type() protoreflect.EnumType {
+	return &file_product_inventory_proto_enumTypes[0]
+}
+
+func (x FinishStatus) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use FinishStatus.Descriptor instead.
+func (FinishStatus) EnumDescriptor() ([]byte, []int) {
+	return file_product_inventory_proto_rawDescGZIP(), []int{0}
+}
 
 type CreateOperationRequest struct {
 	state         protoimpl.MessageState
@@ -596,6 +642,267 @@
 	return ""
 }
 
+type InputAndOutputInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Number      string       `protobuf:"bytes,1,opt,name=Number,proto3" json:"Number,omitempty"`
+	Name        string       `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
+	OrderAmount string       `protobuf:"bytes,3,opt,name=OrderAmount,proto3" json:"OrderAmount,omitempty"` //璁㈠崟鏁伴噺
+	Unit        string       `protobuf:"bytes,4,opt,name=Unit,proto3" json:"Unit,omitempty"`
+	Invoice     string       `protobuf:"bytes,5,opt,name=Invoice,proto3" json:"Invoice,omitempty"`     //鍙戣揣鍗�
+	Carrier     string       `protobuf:"bytes,6,opt,name=Carrier,proto3" json:"Carrier,omitempty"`     //鎵胯繍鍟�
+	Waybill     string       `protobuf:"bytes,7,opt,name=Waybill,proto3" json:"Waybill,omitempty"`     //杩愬崟鍙�
+	SalePrice   string       `protobuf:"bytes,8,opt,name=SalePrice,proto3" json:"SalePrice,omitempty"` //閿�鍞崟浠�
+	Valorem     string       `protobuf:"bytes,9,opt,name=Valorem,proto3" json:"Valorem,omitempty"`     //浠风◣鍚堣
+	Warehouse   string       `protobuf:"bytes,10,opt,name=Warehouse,proto3" json:"Warehouse,omitempty"`
+	Amount      string       `protobuf:"bytes,11,opt,name=Amount,proto3" json:"Amount,omitempty"` //鏁伴噺
+	Status      FinishStatus `protobuf:"varint,13,opt,name=Status,proto3,enum=FinishStatus" json:"Status,omitempty"`
+	CreateTime  string       `protobuf:"bytes,14,opt,name=CreateTime,proto3" json:"CreateTime,omitempty"`
+}
+
+func (x *InputAndOutputInfo) Reset() {
+	*x = InputAndOutputInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_product_inventory_proto_msgTypes[8]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *InputAndOutputInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*InputAndOutputInfo) ProtoMessage() {}
+
+func (x *InputAndOutputInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_product_inventory_proto_msgTypes[8]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use InputAndOutputInfo.ProtoReflect.Descriptor instead.
+func (*InputAndOutputInfo) Descriptor() ([]byte, []int) {
+	return file_product_inventory_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *InputAndOutputInfo) GetNumber() string {
+	if x != nil {
+		return x.Number
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetOrderAmount() string {
+	if x != nil {
+		return x.OrderAmount
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetUnit() string {
+	if x != nil {
+		return x.Unit
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetInvoice() string {
+	if x != nil {
+		return x.Invoice
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetCarrier() string {
+	if x != nil {
+		return x.Carrier
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetWaybill() string {
+	if x != nil {
+		return x.Waybill
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetSalePrice() string {
+	if x != nil {
+		return x.SalePrice
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetValorem() string {
+	if x != nil {
+		return x.Valorem
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetWarehouse() string {
+	if x != nil {
+		return x.Warehouse
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetAmount() string {
+	if x != nil {
+		return x.Amount
+	}
+	return ""
+}
+
+func (x *InputAndOutputInfo) GetStatus() FinishStatus {
+	if x != nil {
+		return x.Status
+	}
+	return FinishStatus_Ready
+}
+
+func (x *InputAndOutputInfo) GetCreateTime() string {
+	if x != nil {
+		return x.CreateTime
+	}
+	return ""
+}
+
+type GetOrderInputAndOutputInfoRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Number string `protobuf:"bytes,1,opt,name=Number,proto3" json:"Number,omitempty"` //鏄庣粏鍗曠紪鐮�
+}
+
+func (x *GetOrderInputAndOutputInfoRequest) Reset() {
+	*x = GetOrderInputAndOutputInfoRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_product_inventory_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetOrderInputAndOutputInfoRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetOrderInputAndOutputInfoRequest) ProtoMessage() {}
+
+func (x *GetOrderInputAndOutputInfoRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_product_inventory_proto_msgTypes[9]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetOrderInputAndOutputInfoRequest.ProtoReflect.Descriptor instead.
+func (*GetOrderInputAndOutputInfoRequest) Descriptor() ([]byte, []int) {
+	return file_product_inventory_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *GetOrderInputAndOutputInfoRequest) GetNumber() string {
+	if x != nil {
+		return x.Number
+	}
+	return ""
+}
+
+type GetOrderInputAndOutputInfoResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Code       int32                 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
+	Msg        string                `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"`
+	InputList  []*InputAndOutputInfo `protobuf:"bytes,3,rep,name=InputList,proto3" json:"InputList,omitempty"`
+	OutputList []*InputAndOutputInfo `protobuf:"bytes,4,rep,name=OutputList,proto3" json:"OutputList,omitempty"`
+}
+
+func (x *GetOrderInputAndOutputInfoResponse) Reset() {
+	*x = GetOrderInputAndOutputInfoResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_product_inventory_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetOrderInputAndOutputInfoResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetOrderInputAndOutputInfoResponse) ProtoMessage() {}
+
+func (x *GetOrderInputAndOutputInfoResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_product_inventory_proto_msgTypes[10]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetOrderInputAndOutputInfoResponse.ProtoReflect.Descriptor instead.
+func (*GetOrderInputAndOutputInfoResponse) Descriptor() ([]byte, []int) {
+	return file_product_inventory_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *GetOrderInputAndOutputInfoResponse) GetCode() int32 {
+	if x != nil {
+		return x.Code
+	}
+	return 0
+}
+
+func (x *GetOrderInputAndOutputInfoResponse) GetMsg() string {
+	if x != nil {
+		return x.Msg
+	}
+	return ""
+}
+
+func (x *GetOrderInputAndOutputInfoResponse) GetInputList() []*InputAndOutputInfo {
+	if x != nil {
+		return x.InputList
+	}
+	return nil
+}
+
+func (x *GetOrderInputAndOutputInfoResponse) GetOutputList() []*InputAndOutputInfo {
+	if x != nil {
+		return x.OutputList
+	}
+	return nil
+}
+
 var File_product_inventory_proto protoreflect.FileDescriptor
 
 var file_product_inventory_proto_rawDesc = []byte{
@@ -670,28 +977,75 @@
 	0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
 	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, 0x32, 0xa1,
-	0x02, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74,
-	0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x46, 0x0a, 0x0f, 0x43, 0x72,
-	0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x2e,
-	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f,
-	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x22, 0x00, 0x12, 0x5e, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f,
-	0x72, 0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e,
-	0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x64,
-	0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20,
-	0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72, 0x6f,
-	0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x22, 0x00, 0x12, 0x5e, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x61, 0x6c, 0x65,
-	0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e,
-	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69,
-	0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20,
-	0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61,
-	0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x22, 0x00, 0x42, 0x15, 0x5a, 0x13, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f,
-	0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x33,
+	0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4d, 0x73, 0x67, 0x22, 0xf9,
+	0x02, 0x0a, 0x12, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75,
+	0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a,
+	0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d,
+	0x65, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f,
+	0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x49, 0x6e, 0x76, 0x6f, 0x69,
+	0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63,
+	0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x57,
+	0x61, 0x79, 0x62, 0x69, 0x6c, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x57, 0x61,
+	0x79, 0x62, 0x69, 0x6c, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x61, 0x6c, 0x65, 0x50, 0x72, 0x69,
+	0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x61, 0x6c, 0x65, 0x50, 0x72,
+	0x69, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x61, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x18, 0x09,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x56, 0x61, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x12, 0x1c, 0x0a,
+	0x09, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x09, 0x57, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x41,
+	0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x41, 0x6d, 0x6f,
+	0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20,
+	0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x3b, 0x0a, 0x21, 0x47, 0x65,
+	0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6e, 0x64, 0x4f, 0x75,
+	0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x16, 0x0a, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xb2, 0x01, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x4f,
+	0x72, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x70,
+	0x75, 0x74, 0x49, 0x6e, 0x66, 0x6f, 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, 0x31, 0x0a, 0x09, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73,
+	0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41,
+	0x6e, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x49, 0x6e,
+	0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x4f, 0x75, 0x74, 0x70, 0x75,
+	0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x49, 0x6e,
+	0x70, 0x75, 0x74, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x66, 0x6f,
+	0x52, 0x0a, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x2a, 0x25, 0x0a, 0x0c,
+	0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x09, 0x0a, 0x05,
+	0x52, 0x65, 0x61, 0x64, 0x79, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x69, 0x6e, 0x69, 0x73,
+	0x68, 0x10, 0x01, 0x32, 0x8a, 0x03, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49,
+	0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
+	0x46, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x12, 0x17, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x43, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x49, 0x6e,
+	0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e,
+	0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72,
+	0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f,
+	0x72, 0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74,
+	0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74,
+	0x75, 0x73, 0x12, 0x1f, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x61, 0x6c, 0x65, 0x73,
+	0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x61, 0x6c, 0x65,
+	0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4f, 0x72,
+	0x64, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75,
+	0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72,
+	0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e,
+	0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x47, 0x65, 0x74, 0x4f,
+	0x72, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x70,
+	0x75, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
+	0x42, 0x15, 0x5a, 0x13, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x69, 0x6e,
+	0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -706,31 +1060,41 @@
 	return file_product_inventory_proto_rawDescData
 }
 
-var file_product_inventory_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
+var file_product_inventory_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_product_inventory_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
 var file_product_inventory_proto_goTypes = []interface{}{
-	(*CreateOperationRequest)(nil),          // 0: CreateOperationRequest
-	(*InventoryProduct)(nil),                // 1: InventoryProduct
-	(*CreateOperationResponse)(nil),         // 2: CreateOperationResponse
-	(*GetInventoryProductInfoRequest)(nil),  // 3: GetInventoryProductInfoRequest
-	(*ProductInfo)(nil),                     // 4: ProductInfo
-	(*GetInventoryProductInfoResponse)(nil), // 5: GetInventoryProductInfoResponse
-	(*UpdateSalesDetailStatusRequest)(nil),  // 6: UpdateSalesDetailStatusRequest
-	(*UpdateSalesDetailStatusResponse)(nil), // 7: UpdateSalesDetailStatusResponse
+	(FinishStatus)(0),                          // 0: FinishStatus
+	(*CreateOperationRequest)(nil),             // 1: CreateOperationRequest
+	(*InventoryProduct)(nil),                   // 2: InventoryProduct
+	(*CreateOperationResponse)(nil),            // 3: CreateOperationResponse
+	(*GetInventoryProductInfoRequest)(nil),     // 4: GetInventoryProductInfoRequest
+	(*ProductInfo)(nil),                        // 5: ProductInfo
+	(*GetInventoryProductInfoResponse)(nil),    // 6: GetInventoryProductInfoResponse
+	(*UpdateSalesDetailStatusRequest)(nil),     // 7: UpdateSalesDetailStatusRequest
+	(*UpdateSalesDetailStatusResponse)(nil),    // 8: UpdateSalesDetailStatusResponse
+	(*InputAndOutputInfo)(nil),                 // 9: InputAndOutputInfo
+	(*GetOrderInputAndOutputInfoRequest)(nil),  // 10: GetOrderInputAndOutputInfoRequest
+	(*GetOrderInputAndOutputInfoResponse)(nil), // 11: GetOrderInputAndOutputInfoResponse
 }
 var file_product_inventory_proto_depIdxs = []int32{
-	1, // 0: CreateOperationRequest.ProductList:type_name -> InventoryProduct
-	4, // 1: GetInventoryProductInfoResponse.ProductList:type_name -> ProductInfo
-	0, // 2: productInventoryService.CreateOperation:input_type -> CreateOperationRequest
-	3, // 3: productInventoryService.GetInventoryProductInfo:input_type -> GetInventoryProductInfoRequest
-	6, // 4: productInventoryService.UpdateSalesDetailStatus:input_type -> UpdateSalesDetailStatusRequest
-	2, // 5: productInventoryService.CreateOperation:output_type -> CreateOperationResponse
-	5, // 6: productInventoryService.GetInventoryProductInfo:output_type -> GetInventoryProductInfoResponse
-	7, // 7: productInventoryService.UpdateSalesDetailStatus:output_type -> UpdateSalesDetailStatusResponse
-	5, // [5:8] is the sub-list for method output_type
-	2, // [2:5] is the sub-list for method input_type
-	2, // [2:2] is the sub-list for extension type_name
-	2, // [2:2] is the sub-list for extension extendee
-	0, // [0:2] is the sub-list for field type_name
+	2,  // 0: CreateOperationRequest.ProductList:type_name -> InventoryProduct
+	5,  // 1: GetInventoryProductInfoResponse.ProductList:type_name -> ProductInfo
+	0,  // 2: InputAndOutputInfo.Status:type_name -> FinishStatus
+	9,  // 3: GetOrderInputAndOutputInfoResponse.InputList:type_name -> InputAndOutputInfo
+	9,  // 4: GetOrderInputAndOutputInfoResponse.OutputList:type_name -> InputAndOutputInfo
+	1,  // 5: productInventoryService.CreateOperation:input_type -> CreateOperationRequest
+	4,  // 6: productInventoryService.GetInventoryProductInfo:input_type -> GetInventoryProductInfoRequest
+	7,  // 7: productInventoryService.UpdateSalesDetailStatus:input_type -> UpdateSalesDetailStatusRequest
+	10, // 8: productInventoryService.GetOrderInputAndOutputInfo:input_type -> GetOrderInputAndOutputInfoRequest
+	3,  // 9: productInventoryService.CreateOperation:output_type -> CreateOperationResponse
+	6,  // 10: productInventoryService.GetInventoryProductInfo:output_type -> GetInventoryProductInfoResponse
+	8,  // 11: productInventoryService.UpdateSalesDetailStatus:output_type -> UpdateSalesDetailStatusResponse
+	11, // 12: productInventoryService.GetOrderInputAndOutputInfo:output_type -> GetOrderInputAndOutputInfoResponse
+	9,  // [9:13] is the sub-list for method output_type
+	5,  // [5:9] 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
 }
 
 func init() { file_product_inventory_proto_init() }
@@ -835,19 +1199,56 @@
 				return nil
 			}
 		}
+		file_product_inventory_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*InputAndOutputInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_product_inventory_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetOrderInputAndOutputInfoRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_product_inventory_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetOrderInputAndOutputInfoResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_product_inventory_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   8,
+			NumEnums:      1,
+			NumMessages:   11,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
 		GoTypes:           file_product_inventory_proto_goTypes,
 		DependencyIndexes: file_product_inventory_proto_depIdxs,
+		EnumInfos:         file_product_inventory_proto_enumTypes,
 		MessageInfos:      file_product_inventory_proto_msgTypes,
 	}.Build()
 	File_product_inventory_proto = out.File
diff --git a/proto/product_inventory/product_inventory_grpc.pb.go b/proto/product_inventory/product_inventory_grpc.pb.go
index bd4da08..f010022 100644
--- a/proto/product_inventory/product_inventory_grpc.pb.go
+++ b/proto/product_inventory/product_inventory_grpc.pb.go
@@ -1,4 +1,8 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc             v3.19.0
+// source: product_inventory.proto
 
 package product_inventory
 
@@ -14,6 +18,13 @@
 // Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
+const (
+	ProductInventoryService_CreateOperation_FullMethodName            = "/productInventoryService/CreateOperation"
+	ProductInventoryService_GetInventoryProductInfo_FullMethodName    = "/productInventoryService/GetInventoryProductInfo"
+	ProductInventoryService_UpdateSalesDetailStatus_FullMethodName    = "/productInventoryService/UpdateSalesDetailStatus"
+	ProductInventoryService_GetOrderInputAndOutputInfo_FullMethodName = "/productInventoryService/GetOrderInputAndOutputInfo"
+)
+
 // ProductInventoryServiceClient is the client API for ProductInventoryService service.
 //
 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
@@ -21,6 +32,7 @@
 	CreateOperation(ctx context.Context, in *CreateOperationRequest, opts ...grpc.CallOption) (*CreateOperationResponse, error)
 	GetInventoryProductInfo(ctx context.Context, in *GetInventoryProductInfoRequest, opts ...grpc.CallOption) (*GetInventoryProductInfoResponse, error)
 	UpdateSalesDetailStatus(ctx context.Context, in *UpdateSalesDetailStatusRequest, opts ...grpc.CallOption) (*UpdateSalesDetailStatusResponse, error)
+	GetOrderInputAndOutputInfo(ctx context.Context, in *GetOrderInputAndOutputInfoRequest, opts ...grpc.CallOption) (*GetOrderInputAndOutputInfoResponse, error)
 }
 
 type productInventoryServiceClient struct {
@@ -33,7 +45,7 @@
 
 func (c *productInventoryServiceClient) CreateOperation(ctx context.Context, in *CreateOperationRequest, opts ...grpc.CallOption) (*CreateOperationResponse, error) {
 	out := new(CreateOperationResponse)
-	err := c.cc.Invoke(ctx, "/productInventoryService/CreateOperation", in, out, opts...)
+	err := c.cc.Invoke(ctx, ProductInventoryService_CreateOperation_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -42,7 +54,7 @@
 
 func (c *productInventoryServiceClient) GetInventoryProductInfo(ctx context.Context, in *GetInventoryProductInfoRequest, opts ...grpc.CallOption) (*GetInventoryProductInfoResponse, error) {
 	out := new(GetInventoryProductInfoResponse)
-	err := c.cc.Invoke(ctx, "/productInventoryService/GetInventoryProductInfo", in, out, opts...)
+	err := c.cc.Invoke(ctx, ProductInventoryService_GetInventoryProductInfo_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -51,7 +63,16 @@
 
 func (c *productInventoryServiceClient) UpdateSalesDetailStatus(ctx context.Context, in *UpdateSalesDetailStatusRequest, opts ...grpc.CallOption) (*UpdateSalesDetailStatusResponse, error) {
 	out := new(UpdateSalesDetailStatusResponse)
-	err := c.cc.Invoke(ctx, "/productInventoryService/UpdateSalesDetailStatus", in, out, opts...)
+	err := c.cc.Invoke(ctx, ProductInventoryService_UpdateSalesDetailStatus_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *productInventoryServiceClient) GetOrderInputAndOutputInfo(ctx context.Context, in *GetOrderInputAndOutputInfoRequest, opts ...grpc.CallOption) (*GetOrderInputAndOutputInfoResponse, error) {
+	out := new(GetOrderInputAndOutputInfoResponse)
+	err := c.cc.Invoke(ctx, ProductInventoryService_GetOrderInputAndOutputInfo_FullMethodName, in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -65,6 +86,7 @@
 	CreateOperation(context.Context, *CreateOperationRequest) (*CreateOperationResponse, error)
 	GetInventoryProductInfo(context.Context, *GetInventoryProductInfoRequest) (*GetInventoryProductInfoResponse, error)
 	UpdateSalesDetailStatus(context.Context, *UpdateSalesDetailStatusRequest) (*UpdateSalesDetailStatusResponse, error)
+	GetOrderInputAndOutputInfo(context.Context, *GetOrderInputAndOutputInfoRequest) (*GetOrderInputAndOutputInfoResponse, error)
 	mustEmbedUnimplementedProductInventoryServiceServer()
 }
 
@@ -80,6 +102,9 @@
 }
 func (UnimplementedProductInventoryServiceServer) UpdateSalesDetailStatus(context.Context, *UpdateSalesDetailStatusRequest) (*UpdateSalesDetailStatusResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method UpdateSalesDetailStatus not implemented")
+}
+func (UnimplementedProductInventoryServiceServer) GetOrderInputAndOutputInfo(context.Context, *GetOrderInputAndOutputInfoRequest) (*GetOrderInputAndOutputInfoResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetOrderInputAndOutputInfo not implemented")
 }
 func (UnimplementedProductInventoryServiceServer) mustEmbedUnimplementedProductInventoryServiceServer() {
 }
@@ -105,7 +130,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/productInventoryService/CreateOperation",
+		FullMethod: ProductInventoryService_CreateOperation_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(ProductInventoryServiceServer).CreateOperation(ctx, req.(*CreateOperationRequest))
@@ -123,7 +148,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/productInventoryService/GetInventoryProductInfo",
+		FullMethod: ProductInventoryService_GetInventoryProductInfo_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(ProductInventoryServiceServer).GetInventoryProductInfo(ctx, req.(*GetInventoryProductInfoRequest))
@@ -141,10 +166,28 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/productInventoryService/UpdateSalesDetailStatus",
+		FullMethod: ProductInventoryService_UpdateSalesDetailStatus_FullMethodName,
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(ProductInventoryServiceServer).UpdateSalesDetailStatus(ctx, req.(*UpdateSalesDetailStatusRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _ProductInventoryService_GetOrderInputAndOutputInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetOrderInputAndOutputInfoRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ProductInventoryServiceServer).GetOrderInputAndOutputInfo(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: ProductInventoryService_GetOrderInputAndOutputInfo_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ProductInventoryServiceServer).GetOrderInputAndOutputInfo(ctx, req.(*GetOrderInputAndOutputInfoRequest))
 	}
 	return interceptor(ctx, in, info, handler)
 }
@@ -168,6 +211,10 @@
 			MethodName: "UpdateSalesDetailStatus",
 			Handler:    _ProductInventoryService_UpdateSalesDetailStatus_Handler,
 		},
+		{
+			MethodName: "GetOrderInputAndOutputInfo",
+			Handler:    _ProductInventoryService_GetOrderInputAndOutputInfo_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "product_inventory.proto",
diff --git a/router/salesDetails.go b/router/salesDetails.go
index 7d7db0c..e50ac57 100644
--- a/router/salesDetails.go
+++ b/router/salesDetails.go
@@ -21,5 +21,9 @@
 		//salesDetailsRouter.POST("createOperation", salesDetailsApi.CreateOperation)                           // 鍒涘缓浜у搧鍑哄簱淇℃伅
 		salesDetailsRouter.GET("getApsProjectList", salesDetailsApi.GetApsProjectList)                          // 鑾峰彇aps椤圭洰鍒楄〃
 		salesDetailsRouter.POST("sendSalesDetailsToOtherSystem", salesDetailsApi.SendSalesDetailsToOtherSystem) // 鎺ㄩ�侀攢鍞槑缁嗕俊鎭埌鍏朵粬绯荤粺                    // 鍒涘缓浜у搧鍑哄簱淇℃伅
+
+		salesDetailsRouter.POST("getDeliveryPrepareInfo", salesDetailsApi.GetDeliveryPrepareInfo) // 鍙戣揣鍑嗗
+		salesDetailsRouter.POST("getDeliveryList", salesDetailsApi.GetDeliveryList)               // 鍙戣揣鏄庣粏
+
 	}
 }
diff --git a/service/salesDetails.go b/service/salesDetails.go
index dec2d36..eb7933f 100644
--- a/service/salesDetails.go
+++ b/service/salesDetails.go
@@ -132,3 +132,13 @@
 	}
 	return contacts, total, ecode.OK
 }
+
+func (SalesDetailsService) GetSalesDetails(saleDetailID int) (*model.SalesDetails, error) {
+	return model.NewSalesDetailsSearch().SetId(saleDetailID).SetPreload(true).First()
+}
+
+func (SalesDetailsService) GetDeliveryOrder(saleDetailID int) ([]*model.DeliveryOrder, error) {
+	// get contact list
+	orders, err := model.NewDeliveryOrderSearch().SetSalesDetailsID(saleDetailID).FindAll()
+	return orders, err
+}

--
Gitblit v1.8.0