From 1cd1206c18ed14dd9ebf2baf477f46c847a271b0 Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期五, 15 三月 2024 16:39:19 +0800
Subject: [PATCH] merge

---
 conf/aps-crm.json                |    3 
 proto/crm_aps/server.go          |   32 +
 api/v1/product.go                |   62 +++
 model/response/salesDetails.go   |   29 +
 proto/crm_aps.proto              |   42 ++
 proto/crm_aps/crm_aps_grpc.pb.go |  124 +++++-
 conf/config.go                   |    5 
 proto/crm_aps/crm_aps.pb.go      |  622 +++++++++++++++++++++++++++++++++--
 docs/swagger.yaml                |   18 +
 docs/docs.go                     |   28 +
 docs/swagger.json                |   28 +
 11 files changed, 904 insertions(+), 89 deletions(-)

diff --git a/api/v1/product.go b/api/v1/product.go
index 8f11a30..a61ea18 100644
--- a/api/v1/product.go
+++ b/api/v1/product.go
@@ -156,6 +156,31 @@
 		ctx.Ok()
 		return
 	}
+	first, err := model.NewSalesDetailsSearch().SetPreload(true).SetNumber(number).First()
+	if err != nil {
+		ctx.FailWithMsg(ecode.DBErr, "鏌ヨ閿�鍞槑缁嗗嚭閿�")
+		return
+	}
+	productInfo := make([]response.SalesDetailsProductInfo, 0)
+	amountMap := make(map[string]int64)
+	overMap := make(map[string]int64)
+	for _, p := range first.Products {
+		amountMap[p.Number] = 0
+		overMap[p.Number] = 0
+		var sdpi response.SalesDetailsProductInfo
+		sdpi.ProductId = p.Number
+		sdpi.ProductName = p.Name
+		sdpi.Specs = p.Specs
+		sdpi.Unit = p.Unit
+		sdpi.Amount = p.Amount
+		sdpi.Cost = p.Cost
+		sdpi.Price = p.Price
+		sdpi.Total = p.Total
+		sdpi.Profit = p.Profit
+		sdpi.Margin = p.Margin
+		productInfo = append(productInfo, sdpi)
+	}
+
 	client := product.NewProductServiceClient(grpc_init.CrmApsGrpcServiceConn)
 	info, err := client.GetProductOrder(ctx.GetCtx(), &product.GetProductOrderRequest{SalesDetailsNumber: number})
 	if err != nil {
@@ -164,6 +189,7 @@
 		return
 	}
 	var result response.Info
+	//鍒堕�犱俊鎭�
 	var list []response.WorkOrderInfo
 	for _, orderInfo := range info.List {
 		var wo response.WorkOrderInfo
@@ -179,10 +205,22 @@
 		wo.Unit = orderInfo.Unit
 		wo.Amount = orderInfo.Amount
 		wo.FinishAmount = orderInfo.FinishAmount
+		at := amountMap[orderInfo.ProductId] + orderInfo.Amount
+		amountMap[orderInfo.ProductId] = at
+		fat := overMap[orderInfo.ProductId] + orderInfo.FinishAmount
+		overMap[orderInfo.ProductId] = fat
 		list = append(list, wo)
+	}
+	for i := 0; i < len(productInfo); i++ {
+		productInfo[i].MakeAmount = amountMap[productInfo[i].ProductId]
+		amountMap[productInfo[i].ProductId] = 0
+		productInfo[i].MakeFinishAmount = overMap[productInfo[i].ProductId]
+		productInfo[i].FinishAmount = productInfo[i].FinishAmount + overMap[productInfo[i].ProductId]
+		overMap[productInfo[i].ProductId] = 0
 	}
 	result.MakeInfo = list
 
+	//閲囪喘淇℃伅
 	var purchaseInfo []response.Purchase
 	for _, pl := range info.PurchaseList {
 		var p response.Purchase
@@ -197,10 +235,22 @@
 		p.Unit = pl.Unit
 		p.Amount = pl.Amount
 		p.FinishAmount = pl.FinishAmount
+		at := amountMap[pl.ProductId] + pl.Amount
+		amountMap[pl.ProductId] = at
+		fat := overMap[pl.ProductId] + pl.FinishAmount
+		overMap[pl.ProductId] = fat
 		purchaseInfo = append(purchaseInfo, p)
+	}
+	for i := 0; i < len(productInfo); i++ {
+		productInfo[i].PurchaseAmount = amountMap[productInfo[i].ProductId]
+		amountMap[productInfo[i].ProductId] = 0
+		productInfo[i].PurchaseFinishAmount = overMap[productInfo[i].ProductId]
+		productInfo[i].FinishAmount = productInfo[i].FinishAmount + overMap[productInfo[i].ProductId]
+		overMap[productInfo[i].ProductId] = 0
 	}
 	result.PurchaseInfo = purchaseInfo
 
+	//濮斿淇℃伅
 	var outsourcingList []response.OutsourcingInfo
 	for _, outsourcingInfo := range info.OutsourcingList {
 		var oi response.OutsourcingInfo
@@ -215,8 +265,20 @@
 		oi.Unit = outsourcingInfo.Unit
 		oi.Amount = outsourcingInfo.Amount
 		oi.FinishAmount = outsourcingInfo.FinishAmount
+		at := amountMap[outsourcingInfo.ProductId] + outsourcingInfo.Amount
+		amountMap[outsourcingInfo.ProductId] = at
+		fat := overMap[outsourcingInfo.ProductId] + outsourcingInfo.FinishAmount
+		overMap[outsourcingInfo.ProductId] = fat
 		outsourcingList = append(outsourcingList, oi)
 	}
+	for i := 0; i < len(productInfo); i++ {
+		productInfo[i].OutsourcingAmount = amountMap[productInfo[i].ProductId]
+		amountMap[productInfo[i].ProductId] = 0
+		productInfo[i].OutsourcingFinishAmount = overMap[productInfo[i].ProductId]
+		productInfo[i].FinishAmount = productInfo[i].FinishAmount + overMap[productInfo[i].ProductId]
+		overMap[productInfo[i].ProductId] = 0
+	}
 	result.OutsourcingInfo = outsourcingList
+	result.ProductInfo = productInfo
 	ctx.OkWithDetailed(result)
 }
diff --git a/conf/aps-crm.json b/conf/aps-crm.json
index e11e09f..e9fc5a4 100644
--- a/conf/aps-crm.json
+++ b/conf/aps-crm.json
@@ -51,7 +51,8 @@
   "GrpcServiceAddr": {
     "Aps": "192.168.20.119:9091",
     "Admin": "192.168.20.119:50051",
-    "WMS": "192.168.20.120:8006"
+    "WMS": "192.168.20.119:8006",
+    "SRM": "192.168.20.119:9093"
   }
 }
 
diff --git a/conf/config.go b/conf/config.go
index 96fe2b2..7526045 100644
--- a/conf/config.go
+++ b/conf/config.go
@@ -63,6 +63,7 @@
 		Aps   string // aps鏈嶅姟鍦板潃
 		Admin string // admin鏈嶅姟鍦板潃
 		WMS   string //wms鏈嶅姟鍦板潃
+		SRM   string //srm鏈嶅姟鍦板潃
 	}
 
 	config struct {
@@ -137,6 +138,10 @@
 	if len(GrpcPort) > 0 {
 		Conf.GrpcServiceAddr.WMS = GrpcPort
 	}
+	srmPort := os.Getenv("SRM_GRPC")
+	if len(srmPort) > 0 {
+		Conf.GrpcServiceAddr.SRM = srmPort
+	}
 	ApsGrpc := os.Getenv("GRPC_PORT")
 	Host := os.Getenv("HOST")
 
diff --git a/docs/docs.go b/docs/docs.go
index 56d1440..35d02d0 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -7173,6 +7173,34 @@
                 }
             }
         },
+        "/api/salesDetails/getSalesDetailsProductInfo/{number}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鑾峰彇閿�鍞槑缁嗕骇鍝佷俊鎭�",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "鏄庣粏缂栫爜",
+                        "name": "number",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/api/salesDetails/list": {
             "post": {
                 "produces": [
diff --git a/docs/swagger.json b/docs/swagger.json
index d3df7a9..857484f 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -7161,6 +7161,34 @@
                 }
             }
         },
+        "/api/salesDetails/getSalesDetailsProductInfo/{number}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鑾峰彇閿�鍞槑缁嗕骇鍝佷俊鎭�",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "鏄庣粏缂栫爜",
+                        "name": "number",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/api/salesDetails/list": {
             "post": {
                 "produces": [
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 4c7a6e1..9f0261d 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -10913,6 +10913,24 @@
       summary: 鑾峰彇浜у搧鍙戣揣淇℃伅
       tags:
       - SalesDetails
+  /api/salesDetails/getSalesDetailsProductInfo/{number}:
+    get:
+      parameters:
+      - description: 鏄庣粏缂栫爜
+        in: path
+        name: number
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/response.ListResponse'
+      summary: 鑾峰彇閿�鍞槑缁嗕骇鍝佷俊鎭�
+      tags:
+      - SalesDetails
   /api/salesDetails/list:
     post:
       parameters:
diff --git a/model/response/salesDetails.go b/model/response/salesDetails.go
index e8035a0..515af69 100644
--- a/model/response/salesDetails.go
+++ b/model/response/salesDetails.go
@@ -6,9 +6,10 @@
 )
 
 type Info struct {
-	MakeInfo        []WorkOrderInfo   `json:"makeInfo"`
-	PurchaseInfo    []Purchase        `json:"purchaseInfo"`
-	OutsourcingInfo []OutsourcingInfo `json:"outsourcingInfo"`
+	MakeInfo        []WorkOrderInfo           `json:"makeInfo"`
+	PurchaseInfo    []Purchase                `json:"purchaseInfo"`
+	OutsourcingInfo []OutsourcingInfo         `json:"outsourcingInfo"`
+	ProductInfo     []SalesDetailsProductInfo `json:"productInfo"`
 }
 
 type WorkOrderInfo struct {
@@ -67,7 +68,6 @@
 	Amount          string `json:"amount"`          //鍦ㄥ簱鏁伴噺
 	AvailableNumber string `json:"availableNumber"` //鍙敤搴撳瓨
 }
-
 type OutputInfo struct {
 	Number      string `json:"number"`
 	Name        string `json:"name"`
@@ -112,3 +112,24 @@
 	WarehouseName string                 `json:"WarehouseName,omitempty"`
 	ProductList   []*model.DeliveryOrder `json:"ProductList,omitempty"`
 }
+type SalesDetailsProductInfo struct {
+	ProductId               string          `json:"productId"`
+	ProductName             string          `json:"productName"`
+	Specs                   string          `json:"specs"`                   //鐗╂枡瑙勬牸
+	Unit                    string          `json:"unit"`                    //鍗曚綅
+	Amount                  decimal.Decimal `json:"amount"`                  //璁㈠崟鏁伴噺
+	FinishAmount            int64           `json:"finishAmount"`            //瀹屾垚鏁伴噺
+	DeliveryAmount          int64           `json:"deliveryAmount"`          //鍙戣揣鏁伴噺
+	PurchaseAmount          int64           `json:"purchaseAmount"`          //閲囪喘鏁伴噺
+	PurchaseFinishAmount    int64           `json:"purchaseFinishAmount"`    //閲囪喘瀹屾垚鏁伴噺
+	MakeAmount              int64           `json:"makeAmount"`              //鍒堕�犳暟閲�
+	MakeFinishAmount        int64           `json:"makeFinishAmount"`        //鍒堕�犲畬鎴愭暟閲�
+	OutsourcingAmount       int64           `json:"outsourcingAmount"`       //濮斿鏁伴噺
+	OutsourcingFinishAmount int64           `json:"outsourcingFinishAmount"` //濮斿瀹屾垚鏁伴噺
+	Cost                    string          `json:"cost"`                    //浜у搧鎴愭湰
+	Price                   decimal.Decimal `json:"price"`                   //浜у搧浠锋牸
+	Total                   decimal.Decimal `json:"total"`                   //浜у搧鎬讳环
+	Profit                  string          `json:"profit"`                  //姣涘埄
+	Margin                  string          `json:"margin"`                  //姣涘埄鐜�
+
+}
diff --git a/proto/crm_aps.proto b/proto/crm_aps.proto
index 1676907..a5b4424 100644
--- a/proto/crm_aps.proto
+++ b/proto/crm_aps.proto
@@ -9,7 +9,9 @@
   rpc SendSalesDetailsAndProjectToCrm(SendSalesDetailsAndProjectToCrmRequest) returns(SendSalesDetailsAndProjectToCrmResponse) {}
   rpc GetClientList(GetClientListRequest) returns(GetClientListResponse) {}
   rpc UpdateSalesDetail(UpdateSalesDetailRequest) returns(UpdateSalesDetailResponse) {}
-  rpc RemoveSalesDetail(RemoveSalesDetailRequest) returns(RemoveSalesDetailRequest) {}
+  rpc RemoveSalesDetail(RemoveSalesDetailRequest) returns(RemoveSalesDetailResponse) {}
+  rpc CrmGetMakeAndOutsourcingProductInfo(CrmGetMakeAndOutsourcingProductInfoRequest) returns(CrmGetMakeAndOutsourcingProductInfoResponse) {}
+  rpc GetCrmSalesDetailsProductInfo(GetCrmSalesDetailsProductInfoRequest) returns(GetCrmSalesDetailsProductInfoResponse) {}
 }
 
 //-----------------------------------------------------GetApsProjectList--------------------------------------
@@ -113,4 +115,40 @@
   string number = 1;//閿�鍞槑缁嗗崟鍙�
 }
 
-message RemoveSalesDetailResponse {}
\ No newline at end of file
+message RemoveSalesDetailResponse {}
+
+message CrmGetMakeAndOutsourcingProductInfoRequest{
+  string SalesDetailsNumber = 1;
+}
+
+message CrmGetMakeAndOutsourcingProductInfo {
+  int64 Amount = 1;
+  int64 FinishAmount = 2;
+  string ProductId = 3;
+  int64 Type = 4;
+}
+
+message CrmGetMakeAndOutsourcingProductInfoResponse{
+  repeated CrmGetMakeAndOutsourcingProductInfo Info = 1;
+}
+
+message GetCrmSalesDetailsProductInfoRequest{
+  string SalesDetailsNumber = 1;
+}
+
+message CrmSalesDetailsProductInfo{
+  string ProductId = 1;
+  string ProductName = 2;
+  string Specs = 3;
+  string Unit = 4;
+  int64 Amount = 5;
+  string Cost = 6; //浜у搧鎴愭湰
+  int64 Price = 7; //浜у搧浠锋牸
+  int64 Total = 8;//浜у搧鎬讳环
+  string Profit = 9;//姣涘埄
+  string Margin = 10;//姣涘埄鐜�
+}
+
+message GetCrmSalesDetailsProductInfoResponse{
+  repeated CrmSalesDetailsProductInfo List = 1;
+}
\ No newline at end of file
diff --git a/proto/crm_aps/crm_aps.pb.go b/proto/crm_aps/crm_aps.pb.go
index dec896d..0192c68 100644
--- a/proto/crm_aps/crm_aps.pb.go
+++ b/proto/crm_aps/crm_aps.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
-// 	protoc        v3.19.0
+// 	protoc-gen-go v1.26.0
+// 	protoc        v4.24.0
 // source: crm_aps.proto
 
 package crm_aps
@@ -1029,6 +1029,384 @@
 	return file_crm_aps_proto_rawDescGZIP(), []int{17}
 }
 
+type CrmGetMakeAndOutsourcingProductInfoRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SalesDetailsNumber string `protobuf:"bytes,1,opt,name=SalesDetailsNumber,proto3" json:"SalesDetailsNumber,omitempty"`
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoRequest) Reset() {
+	*x = CrmGetMakeAndOutsourcingProductInfoRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[18]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CrmGetMakeAndOutsourcingProductInfoRequest) ProtoMessage() {}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[18]
+	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 CrmGetMakeAndOutsourcingProductInfoRequest.ProtoReflect.Descriptor instead.
+func (*CrmGetMakeAndOutsourcingProductInfoRequest) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoRequest) GetSalesDetailsNumber() string {
+	if x != nil {
+		return x.SalesDetailsNumber
+	}
+	return ""
+}
+
+type CrmGetMakeAndOutsourcingProductInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Amount       int64  `protobuf:"varint,1,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	FinishAmount int64  `protobuf:"varint,2,opt,name=FinishAmount,proto3" json:"FinishAmount,omitempty"`
+	ProductId    string `protobuf:"bytes,3,opt,name=ProductId,proto3" json:"ProductId,omitempty"`
+	Type         int64  `protobuf:"varint,4,opt,name=Type,proto3" json:"Type,omitempty"`
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfo) Reset() {
+	*x = CrmGetMakeAndOutsourcingProductInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[19]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CrmGetMakeAndOutsourcingProductInfo) ProtoMessage() {}
+
+func (x *CrmGetMakeAndOutsourcingProductInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[19]
+	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 CrmGetMakeAndOutsourcingProductInfo.ProtoReflect.Descriptor instead.
+func (*CrmGetMakeAndOutsourcingProductInfo) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfo) GetAmount() int64 {
+	if x != nil {
+		return x.Amount
+	}
+	return 0
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfo) GetFinishAmount() int64 {
+	if x != nil {
+		return x.FinishAmount
+	}
+	return 0
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfo) GetProductId() string {
+	if x != nil {
+		return x.ProductId
+	}
+	return ""
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfo) GetType() int64 {
+	if x != nil {
+		return x.Type
+	}
+	return 0
+}
+
+type CrmGetMakeAndOutsourcingProductInfoResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Info []*CrmGetMakeAndOutsourcingProductInfo `protobuf:"bytes,1,rep,name=Info,proto3" json:"Info,omitempty"`
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoResponse) Reset() {
+	*x = CrmGetMakeAndOutsourcingProductInfoResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[20]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CrmGetMakeAndOutsourcingProductInfoResponse) ProtoMessage() {}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[20]
+	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 CrmGetMakeAndOutsourcingProductInfoResponse.ProtoReflect.Descriptor instead.
+func (*CrmGetMakeAndOutsourcingProductInfoResponse) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *CrmGetMakeAndOutsourcingProductInfoResponse) GetInfo() []*CrmGetMakeAndOutsourcingProductInfo {
+	if x != nil {
+		return x.Info
+	}
+	return nil
+}
+
+type GetCrmSalesDetailsProductInfoRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SalesDetailsNumber string `protobuf:"bytes,1,opt,name=SalesDetailsNumber,proto3" json:"SalesDetailsNumber,omitempty"`
+}
+
+func (x *GetCrmSalesDetailsProductInfoRequest) Reset() {
+	*x = GetCrmSalesDetailsProductInfoRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[21]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetCrmSalesDetailsProductInfoRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetCrmSalesDetailsProductInfoRequest) ProtoMessage() {}
+
+func (x *GetCrmSalesDetailsProductInfoRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[21]
+	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 GetCrmSalesDetailsProductInfoRequest.ProtoReflect.Descriptor instead.
+func (*GetCrmSalesDetailsProductInfoRequest) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{21}
+}
+
+func (x *GetCrmSalesDetailsProductInfoRequest) GetSalesDetailsNumber() string {
+	if x != nil {
+		return x.SalesDetailsNumber
+	}
+	return ""
+}
+
+type CrmSalesDetailsProductInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ProductId   string `protobuf:"bytes,1,opt,name=ProductId,proto3" json:"ProductId,omitempty"`
+	ProductName string `protobuf:"bytes,2,opt,name=ProductName,proto3" json:"ProductName,omitempty"`
+	Specs       string `protobuf:"bytes,3,opt,name=Specs,proto3" json:"Specs,omitempty"`
+	Unit        string `protobuf:"bytes,4,opt,name=Unit,proto3" json:"Unit,omitempty"`
+	Amount      int64  `protobuf:"varint,5,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	Cost        string `protobuf:"bytes,6,opt,name=Cost,proto3" json:"Cost,omitempty"`      //浜у搧鎴愭湰
+	Price       int64  `protobuf:"varint,7,opt,name=Price,proto3" json:"Price,omitempty"`   //浜у搧浠锋牸
+	Total       int64  `protobuf:"varint,8,opt,name=Total,proto3" json:"Total,omitempty"`   //浜у搧鎬讳环
+	Profit      string `protobuf:"bytes,9,opt,name=Profit,proto3" json:"Profit,omitempty"`  //姣涘埄
+	Margin      string `protobuf:"bytes,10,opt,name=Margin,proto3" json:"Margin,omitempty"` //姣涘埄鐜�
+}
+
+func (x *CrmSalesDetailsProductInfo) Reset() {
+	*x = CrmSalesDetailsProductInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[22]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CrmSalesDetailsProductInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CrmSalesDetailsProductInfo) ProtoMessage() {}
+
+func (x *CrmSalesDetailsProductInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[22]
+	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 CrmSalesDetailsProductInfo.ProtoReflect.Descriptor instead.
+func (*CrmSalesDetailsProductInfo) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{22}
+}
+
+func (x *CrmSalesDetailsProductInfo) GetProductId() string {
+	if x != nil {
+		return x.ProductId
+	}
+	return ""
+}
+
+func (x *CrmSalesDetailsProductInfo) GetProductName() string {
+	if x != nil {
+		return x.ProductName
+	}
+	return ""
+}
+
+func (x *CrmSalesDetailsProductInfo) GetSpecs() string {
+	if x != nil {
+		return x.Specs
+	}
+	return ""
+}
+
+func (x *CrmSalesDetailsProductInfo) GetUnit() string {
+	if x != nil {
+		return x.Unit
+	}
+	return ""
+}
+
+func (x *CrmSalesDetailsProductInfo) GetAmount() int64 {
+	if x != nil {
+		return x.Amount
+	}
+	return 0
+}
+
+func (x *CrmSalesDetailsProductInfo) GetCost() string {
+	if x != nil {
+		return x.Cost
+	}
+	return ""
+}
+
+func (x *CrmSalesDetailsProductInfo) GetPrice() int64 {
+	if x != nil {
+		return x.Price
+	}
+	return 0
+}
+
+func (x *CrmSalesDetailsProductInfo) GetTotal() int64 {
+	if x != nil {
+		return x.Total
+	}
+	return 0
+}
+
+func (x *CrmSalesDetailsProductInfo) GetProfit() string {
+	if x != nil {
+		return x.Profit
+	}
+	return ""
+}
+
+func (x *CrmSalesDetailsProductInfo) GetMargin() string {
+	if x != nil {
+		return x.Margin
+	}
+	return ""
+}
+
+type GetCrmSalesDetailsProductInfoResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	List []*CrmSalesDetailsProductInfo `protobuf:"bytes,1,rep,name=List,proto3" json:"List,omitempty"`
+}
+
+func (x *GetCrmSalesDetailsProductInfoResponse) Reset() {
+	*x = GetCrmSalesDetailsProductInfoResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[23]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetCrmSalesDetailsProductInfoResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetCrmSalesDetailsProductInfoResponse) ProtoMessage() {}
+
+func (x *GetCrmSalesDetailsProductInfoResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[23]
+	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 GetCrmSalesDetailsProductInfoResponse.ProtoReflect.Descriptor instead.
+func (*GetCrmSalesDetailsProductInfoResponse) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{23}
+}
+
+func (x *GetCrmSalesDetailsProductInfoResponse) GetList() []*CrmSalesDetailsProductInfo {
+	if x != nil {
+		return x.List
+	}
+	return nil
+}
+
 var File_crm_aps_proto protoreflect.FileDescriptor
 
 var file_crm_aps_proto_rawDesc = []byte{
@@ -1137,7 +1515,57 @@
 	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65,
 	0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22,
 	0x1b, 0x0a, 0x19, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65,
-	0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x85, 0x05, 0x0a,
+	0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5c, 0x0a, 0x2a,
+	0x43, 0x72, 0x6d, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74,
+	0x73, 0x6f, 0x75, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49,
+	0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x53, 0x61,
+	0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74,
+	0x61, 0x69, 0x6c, 0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x93, 0x01, 0x0a, 0x23, 0x43,
+	0x72, 0x6d, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x73,
+	0x6f, 0x75, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e,
+	0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x03, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x46, 0x69,
+	0x6e, 0x69, 0x73, 0x68, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
+	0x52, 0x0c, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c,
+	0x0a, 0x09, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
+	0x54, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65,
+	0x22, 0x67, 0x0a, 0x2b, 0x43, 0x72, 0x6d, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x6e,
+	0x64, 0x4f, 0x75, 0x74, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x64,
+	0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x38, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
+	0x43, 0x72, 0x6d, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74,
+	0x73, 0x6f, 0x75, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49,
+	0x6e, 0x66, 0x6f, 0x52, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x56, 0x0a, 0x24, 0x47, 0x65, 0x74,
+	0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x50,
+	0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x2e, 0x0a, 0x12, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c,
+	0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x53,
+	0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65,
+	0x72, 0x22, 0x8e, 0x02, 0x0a, 0x1a, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65,
+	0x74, 0x61, 0x69, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f,
+	0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x20,
+	0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65,
+	0x12, 0x14, 0x0a, 0x05, 0x53, 0x70, 0x65, 0x63, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x05, 0x53, 0x70, 0x65, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d,
+	0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75,
+	0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05,
+	0x54, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x54, 0x6f, 0x74,
+	0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x06, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x61,
+	0x72, 0x67, 0x69, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4d, 0x61, 0x72, 0x67,
+	0x69, 0x6e, 0x22, 0x58, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65,
+	0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49,
+	0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x4c,
+	0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x43, 0x72, 0x6d, 0x53,
+	0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75,
+	0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x32, 0xfd, 0x06, 0x0a,
 	0x14, 0x43, 0x72, 0x6d, 0x41, 0x6e, 0x64, 0x41, 0x70, 0x73, 0x47, 0x72, 0x70, 0x63, 0x53, 0x65,
 	0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x70, 0x73, 0x50,
 	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x47, 0x65, 0x74,
@@ -1173,13 +1601,29 @@
 	0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61,
 	0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x55, 0x70, 0x64, 0x61,
 	0x74, 0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76,
 	0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x19, 0x2e, 0x52,
 	0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
-	0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x63, 0x72, 0x6d, 0x5f, 0x61, 0x70,
-	0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
+	0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x82, 0x01, 0x0a, 0x23, 0x43, 0x72, 0x6d, 0x47, 0x65, 0x74,
+	0x4d, 0x61, 0x6b, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x69,
+	0x6e, 0x67, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x2e,
+	0x43, 0x72, 0x6d, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74,
+	0x73, 0x6f, 0x75, 0x72, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49,
+	0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x43, 0x72, 0x6d,
+	0x47, 0x65, 0x74, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x75, 0x74, 0x73, 0x6f, 0x75,
+	0x72, 0x63, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x70, 0x0a, 0x1d, 0x47, 0x65,
+	0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+	0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x25, 0x2e, 0x47, 0x65,
+	0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+	0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x26, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73,
+	0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e,
+	0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09,
+	0x2e, 0x2f, 0x63, 0x72, 0x6d, 0x5f, 0x61, 0x70, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x33,
 }
 
 var (
@@ -1194,51 +1638,63 @@
 	return file_crm_aps_proto_rawDescData
 }
 
-var file_crm_aps_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
+var file_crm_aps_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
 var file_crm_aps_proto_goTypes = []interface{}{
-	(*GetApsProjectListRequest)(nil),                // 0: GetApsProjectListRequest
-	(*ApsProject)(nil),                              // 1: ApsProject
-	(*GetApsProjectListResponse)(nil),               // 2: GetApsProjectListResponse
-	(*SalesDetailsProduct)(nil),                     // 3: SalesDetailsProduct
-	(*SendSalesDetailsToApsProjectRequest)(nil),     // 4: SendSalesDetailsToApsProjectRequest
-	(*SendSalesDetailsToApsProjectResponse)(nil),    // 5: SendSalesDetailsToApsProjectResponse
-	(*GetCrmSalesDetailsListRequest)(nil),           // 6: GetCrmSalesDetailsListRequest
-	(*CrmSalesDetails)(nil),                         // 7: CrmSalesDetails
-	(*GetCrmSalesDetailsListResponse)(nil),          // 8: GetCrmSalesDetailsListResponse
-	(*SendSalesDetailsAndProjectToCrmRequest)(nil),  // 9: SendSalesDetailsAndProjectToCrmRequest
-	(*SendSalesDetailsAndProjectToCrmResponse)(nil), // 10: SendSalesDetailsAndProjectToCrmResponse
-	(*GetClientListRequest)(nil),                    // 11: GetClientListRequest
-	(*GetClientListResponse)(nil),                   // 12: GetClientListResponse
-	(*Client)(nil),                                  // 13: Client
-	(*UpdateSalesDetailRequest)(nil),                // 14: UpdateSalesDetailRequest
-	(*UpdateSalesDetailResponse)(nil),               // 15: UpdateSalesDetailResponse
-	(*RemoveSalesDetailRequest)(nil),                // 16: RemoveSalesDetailRequest
-	(*RemoveSalesDetailResponse)(nil),               // 17: RemoveSalesDetailResponse
+	(*GetApsProjectListRequest)(nil),                    // 0: GetApsProjectListRequest
+	(*ApsProject)(nil),                                  // 1: ApsProject
+	(*GetApsProjectListResponse)(nil),                   // 2: GetApsProjectListResponse
+	(*SalesDetailsProduct)(nil),                         // 3: SalesDetailsProduct
+	(*SendSalesDetailsToApsProjectRequest)(nil),         // 4: SendSalesDetailsToApsProjectRequest
+	(*SendSalesDetailsToApsProjectResponse)(nil),        // 5: SendSalesDetailsToApsProjectResponse
+	(*GetCrmSalesDetailsListRequest)(nil),               // 6: GetCrmSalesDetailsListRequest
+	(*CrmSalesDetails)(nil),                             // 7: CrmSalesDetails
+	(*GetCrmSalesDetailsListResponse)(nil),              // 8: GetCrmSalesDetailsListResponse
+	(*SendSalesDetailsAndProjectToCrmRequest)(nil),      // 9: SendSalesDetailsAndProjectToCrmRequest
+	(*SendSalesDetailsAndProjectToCrmResponse)(nil),     // 10: SendSalesDetailsAndProjectToCrmResponse
+	(*GetClientListRequest)(nil),                        // 11: GetClientListRequest
+	(*GetClientListResponse)(nil),                       // 12: GetClientListResponse
+	(*Client)(nil),                                      // 13: Client
+	(*UpdateSalesDetailRequest)(nil),                    // 14: UpdateSalesDetailRequest
+	(*UpdateSalesDetailResponse)(nil),                   // 15: UpdateSalesDetailResponse
+	(*RemoveSalesDetailRequest)(nil),                    // 16: RemoveSalesDetailRequest
+	(*RemoveSalesDetailResponse)(nil),                   // 17: RemoveSalesDetailResponse
+	(*CrmGetMakeAndOutsourcingProductInfoRequest)(nil),  // 18: CrmGetMakeAndOutsourcingProductInfoRequest
+	(*CrmGetMakeAndOutsourcingProductInfo)(nil),         // 19: CrmGetMakeAndOutsourcingProductInfo
+	(*CrmGetMakeAndOutsourcingProductInfoResponse)(nil), // 20: CrmGetMakeAndOutsourcingProductInfoResponse
+	(*GetCrmSalesDetailsProductInfoRequest)(nil),        // 21: GetCrmSalesDetailsProductInfoRequest
+	(*CrmSalesDetailsProductInfo)(nil),                  // 22: CrmSalesDetailsProductInfo
+	(*GetCrmSalesDetailsProductInfoResponse)(nil),       // 23: GetCrmSalesDetailsProductInfoResponse
 }
 var file_crm_aps_proto_depIdxs = []int32{
 	1,  // 0: GetApsProjectListResponse.List:type_name -> ApsProject
 	3,  // 1: SendSalesDetailsToApsProjectRequest.Products:type_name -> SalesDetailsProduct
 	7,  // 2: GetCrmSalesDetailsListResponse.SalesDetails:type_name -> CrmSalesDetails
 	13, // 3: GetClientListResponse.list:type_name -> Client
-	0,  // 4: CrmAndApsGrpcService.GetApsProjectList:input_type -> GetApsProjectListRequest
-	4,  // 5: CrmAndApsGrpcService.SendSalesDetailsToApsProject:input_type -> SendSalesDetailsToApsProjectRequest
-	6,  // 6: CrmAndApsGrpcService.GetCrmSalesDetailsList:input_type -> GetCrmSalesDetailsListRequest
-	9,  // 7: CrmAndApsGrpcService.SendSalesDetailsAndProjectToCrm:input_type -> SendSalesDetailsAndProjectToCrmRequest
-	11, // 8: CrmAndApsGrpcService.GetClientList:input_type -> GetClientListRequest
-	14, // 9: CrmAndApsGrpcService.UpdateSalesDetail:input_type -> UpdateSalesDetailRequest
-	16, // 10: CrmAndApsGrpcService.RemoveSalesDetail:input_type -> RemoveSalesDetailRequest
-	2,  // 11: CrmAndApsGrpcService.GetApsProjectList:output_type -> GetApsProjectListResponse
-	5,  // 12: CrmAndApsGrpcService.SendSalesDetailsToApsProject:output_type -> SendSalesDetailsToApsProjectResponse
-	8,  // 13: CrmAndApsGrpcService.GetCrmSalesDetailsList:output_type -> GetCrmSalesDetailsListResponse
-	10, // 14: CrmAndApsGrpcService.SendSalesDetailsAndProjectToCrm:output_type -> SendSalesDetailsAndProjectToCrmResponse
-	12, // 15: CrmAndApsGrpcService.GetClientList:output_type -> GetClientListResponse
-	15, // 16: CrmAndApsGrpcService.UpdateSalesDetail:output_type -> UpdateSalesDetailResponse
-	16, // 17: CrmAndApsGrpcService.RemoveSalesDetail:output_type -> RemoveSalesDetailRequest
-	11, // [11:18] is the sub-list for method output_type
-	4,  // [4:11] is the sub-list for method input_type
-	4,  // [4:4] is the sub-list for extension type_name
-	4,  // [4:4] is the sub-list for extension extendee
-	0,  // [0:4] is the sub-list for field type_name
+	19, // 4: CrmGetMakeAndOutsourcingProductInfoResponse.Info:type_name -> CrmGetMakeAndOutsourcingProductInfo
+	22, // 5: GetCrmSalesDetailsProductInfoResponse.List:type_name -> CrmSalesDetailsProductInfo
+	0,  // 6: CrmAndApsGrpcService.GetApsProjectList:input_type -> GetApsProjectListRequest
+	4,  // 7: CrmAndApsGrpcService.SendSalesDetailsToApsProject:input_type -> SendSalesDetailsToApsProjectRequest
+	6,  // 8: CrmAndApsGrpcService.GetCrmSalesDetailsList:input_type -> GetCrmSalesDetailsListRequest
+	9,  // 9: CrmAndApsGrpcService.SendSalesDetailsAndProjectToCrm:input_type -> SendSalesDetailsAndProjectToCrmRequest
+	11, // 10: CrmAndApsGrpcService.GetClientList:input_type -> GetClientListRequest
+	14, // 11: CrmAndApsGrpcService.UpdateSalesDetail:input_type -> UpdateSalesDetailRequest
+	16, // 12: CrmAndApsGrpcService.RemoveSalesDetail:input_type -> RemoveSalesDetailRequest
+	18, // 13: CrmAndApsGrpcService.CrmGetMakeAndOutsourcingProductInfo:input_type -> CrmGetMakeAndOutsourcingProductInfoRequest
+	21, // 14: CrmAndApsGrpcService.GetCrmSalesDetailsProductInfo:input_type -> GetCrmSalesDetailsProductInfoRequest
+	2,  // 15: CrmAndApsGrpcService.GetApsProjectList:output_type -> GetApsProjectListResponse
+	5,  // 16: CrmAndApsGrpcService.SendSalesDetailsToApsProject:output_type -> SendSalesDetailsToApsProjectResponse
+	8,  // 17: CrmAndApsGrpcService.GetCrmSalesDetailsList:output_type -> GetCrmSalesDetailsListResponse
+	10, // 18: CrmAndApsGrpcService.SendSalesDetailsAndProjectToCrm:output_type -> SendSalesDetailsAndProjectToCrmResponse
+	12, // 19: CrmAndApsGrpcService.GetClientList:output_type -> GetClientListResponse
+	15, // 20: CrmAndApsGrpcService.UpdateSalesDetail:output_type -> UpdateSalesDetailResponse
+	17, // 21: CrmAndApsGrpcService.RemoveSalesDetail:output_type -> RemoveSalesDetailResponse
+	20, // 22: CrmAndApsGrpcService.CrmGetMakeAndOutsourcingProductInfo:output_type -> CrmGetMakeAndOutsourcingProductInfoResponse
+	23, // 23: CrmAndApsGrpcService.GetCrmSalesDetailsProductInfo:output_type -> GetCrmSalesDetailsProductInfoResponse
+	15, // [15:24] is the sub-list for method output_type
+	6,  // [6:15] 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_crm_aps_proto_init() }
@@ -1463,6 +1919,78 @@
 				return nil
 			}
 		}
+		file_crm_aps_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CrmGetMakeAndOutsourcingProductInfoRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CrmGetMakeAndOutsourcingProductInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CrmGetMakeAndOutsourcingProductInfoResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetCrmSalesDetailsProductInfoRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CrmSalesDetailsProductInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetCrmSalesDetailsProductInfoResponse); 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{
@@ -1470,7 +1998,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_crm_aps_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   18,
+			NumMessages:   24,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
diff --git a/proto/crm_aps/crm_aps_grpc.pb.go b/proto/crm_aps/crm_aps_grpc.pb.go
index 718cf76..9b6d7ec 100644
--- a/proto/crm_aps/crm_aps_grpc.pb.go
+++ b/proto/crm_aps/crm_aps_grpc.pb.go
@@ -1,8 +1,4 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
-// versions:
-// - protoc-gen-go-grpc v1.3.0
-// - protoc             v3.19.0
-// source: crm_aps.proto
 
 package crm_aps
 
@@ -18,16 +14,6 @@
 // Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
-const (
-	CrmAndApsGrpcService_GetApsProjectList_FullMethodName               = "/CrmAndApsGrpcService/GetApsProjectList"
-	CrmAndApsGrpcService_SendSalesDetailsToApsProject_FullMethodName    = "/CrmAndApsGrpcService/SendSalesDetailsToApsProject"
-	CrmAndApsGrpcService_GetCrmSalesDetailsList_FullMethodName          = "/CrmAndApsGrpcService/GetCrmSalesDetailsList"
-	CrmAndApsGrpcService_SendSalesDetailsAndProjectToCrm_FullMethodName = "/CrmAndApsGrpcService/SendSalesDetailsAndProjectToCrm"
-	CrmAndApsGrpcService_GetClientList_FullMethodName                   = "/CrmAndApsGrpcService/GetClientList"
-	CrmAndApsGrpcService_UpdateSalesDetail_FullMethodName               = "/CrmAndApsGrpcService/UpdateSalesDetail"
-	CrmAndApsGrpcService_RemoveSalesDetail_FullMethodName               = "/CrmAndApsGrpcService/RemoveSalesDetail"
-)
-
 // CrmAndApsGrpcServiceClient is the client API for CrmAndApsGrpcService 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.
@@ -38,7 +24,9 @@
 	SendSalesDetailsAndProjectToCrm(ctx context.Context, in *SendSalesDetailsAndProjectToCrmRequest, opts ...grpc.CallOption) (*SendSalesDetailsAndProjectToCrmResponse, error)
 	GetClientList(ctx context.Context, in *GetClientListRequest, opts ...grpc.CallOption) (*GetClientListResponse, error)
 	UpdateSalesDetail(ctx context.Context, in *UpdateSalesDetailRequest, opts ...grpc.CallOption) (*UpdateSalesDetailResponse, error)
-	RemoveSalesDetail(ctx context.Context, in *RemoveSalesDetailRequest, opts ...grpc.CallOption) (*RemoveSalesDetailRequest, error)
+	RemoveSalesDetail(ctx context.Context, in *RemoveSalesDetailRequest, opts ...grpc.CallOption) (*RemoveSalesDetailResponse, error)
+	CrmGetMakeAndOutsourcingProductInfo(ctx context.Context, in *CrmGetMakeAndOutsourcingProductInfoRequest, opts ...grpc.CallOption) (*CrmGetMakeAndOutsourcingProductInfoResponse, error)
+	GetCrmSalesDetailsProductInfo(ctx context.Context, in *GetCrmSalesDetailsProductInfoRequest, opts ...grpc.CallOption) (*GetCrmSalesDetailsProductInfoResponse, error)
 }
 
 type crmAndApsGrpcServiceClient struct {
@@ -51,7 +39,7 @@
 
 func (c *crmAndApsGrpcServiceClient) GetApsProjectList(ctx context.Context, in *GetApsProjectListRequest, opts ...grpc.CallOption) (*GetApsProjectListResponse, error) {
 	out := new(GetApsProjectListResponse)
-	err := c.cc.Invoke(ctx, CrmAndApsGrpcService_GetApsProjectList_FullMethodName, in, out, opts...)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/GetApsProjectList", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -60,7 +48,7 @@
 
 func (c *crmAndApsGrpcServiceClient) SendSalesDetailsToApsProject(ctx context.Context, in *SendSalesDetailsToApsProjectRequest, opts ...grpc.CallOption) (*SendSalesDetailsToApsProjectResponse, error) {
 	out := new(SendSalesDetailsToApsProjectResponse)
-	err := c.cc.Invoke(ctx, CrmAndApsGrpcService_SendSalesDetailsToApsProject_FullMethodName, in, out, opts...)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/SendSalesDetailsToApsProject", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -69,7 +57,7 @@
 
 func (c *crmAndApsGrpcServiceClient) GetCrmSalesDetailsList(ctx context.Context, in *GetCrmSalesDetailsListRequest, opts ...grpc.CallOption) (*GetCrmSalesDetailsListResponse, error) {
 	out := new(GetCrmSalesDetailsListResponse)
-	err := c.cc.Invoke(ctx, CrmAndApsGrpcService_GetCrmSalesDetailsList_FullMethodName, in, out, opts...)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/GetCrmSalesDetailsList", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -78,7 +66,7 @@
 
 func (c *crmAndApsGrpcServiceClient) SendSalesDetailsAndProjectToCrm(ctx context.Context, in *SendSalesDetailsAndProjectToCrmRequest, opts ...grpc.CallOption) (*SendSalesDetailsAndProjectToCrmResponse, error) {
 	out := new(SendSalesDetailsAndProjectToCrmResponse)
-	err := c.cc.Invoke(ctx, CrmAndApsGrpcService_SendSalesDetailsAndProjectToCrm_FullMethodName, in, out, opts...)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/SendSalesDetailsAndProjectToCrm", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -87,7 +75,7 @@
 
 func (c *crmAndApsGrpcServiceClient) GetClientList(ctx context.Context, in *GetClientListRequest, opts ...grpc.CallOption) (*GetClientListResponse, error) {
 	out := new(GetClientListResponse)
-	err := c.cc.Invoke(ctx, CrmAndApsGrpcService_GetClientList_FullMethodName, in, out, opts...)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/GetClientList", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -96,16 +84,34 @@
 
 func (c *crmAndApsGrpcServiceClient) UpdateSalesDetail(ctx context.Context, in *UpdateSalesDetailRequest, opts ...grpc.CallOption) (*UpdateSalesDetailResponse, error) {
 	out := new(UpdateSalesDetailResponse)
-	err := c.cc.Invoke(ctx, CrmAndApsGrpcService_UpdateSalesDetail_FullMethodName, in, out, opts...)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/UpdateSalesDetail", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
 	return out, nil
 }
 
-func (c *crmAndApsGrpcServiceClient) RemoveSalesDetail(ctx context.Context, in *RemoveSalesDetailRequest, opts ...grpc.CallOption) (*RemoveSalesDetailRequest, error) {
-	out := new(RemoveSalesDetailRequest)
-	err := c.cc.Invoke(ctx, CrmAndApsGrpcService_RemoveSalesDetail_FullMethodName, in, out, opts...)
+func (c *crmAndApsGrpcServiceClient) RemoveSalesDetail(ctx context.Context, in *RemoveSalesDetailRequest, opts ...grpc.CallOption) (*RemoveSalesDetailResponse, error) {
+	out := new(RemoveSalesDetailResponse)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/RemoveSalesDetail", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *crmAndApsGrpcServiceClient) CrmGetMakeAndOutsourcingProductInfo(ctx context.Context, in *CrmGetMakeAndOutsourcingProductInfoRequest, opts ...grpc.CallOption) (*CrmGetMakeAndOutsourcingProductInfoResponse, error) {
+	out := new(CrmGetMakeAndOutsourcingProductInfoResponse)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/CrmGetMakeAndOutsourcingProductInfo", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *crmAndApsGrpcServiceClient) GetCrmSalesDetailsProductInfo(ctx context.Context, in *GetCrmSalesDetailsProductInfoRequest, opts ...grpc.CallOption) (*GetCrmSalesDetailsProductInfoResponse, error) {
+	out := new(GetCrmSalesDetailsProductInfoResponse)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/GetCrmSalesDetailsProductInfo", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -122,7 +128,9 @@
 	SendSalesDetailsAndProjectToCrm(context.Context, *SendSalesDetailsAndProjectToCrmRequest) (*SendSalesDetailsAndProjectToCrmResponse, error)
 	GetClientList(context.Context, *GetClientListRequest) (*GetClientListResponse, error)
 	UpdateSalesDetail(context.Context, *UpdateSalesDetailRequest) (*UpdateSalesDetailResponse, error)
-	RemoveSalesDetail(context.Context, *RemoveSalesDetailRequest) (*RemoveSalesDetailRequest, error)
+	RemoveSalesDetail(context.Context, *RemoveSalesDetailRequest) (*RemoveSalesDetailResponse, error)
+	CrmGetMakeAndOutsourcingProductInfo(context.Context, *CrmGetMakeAndOutsourcingProductInfoRequest) (*CrmGetMakeAndOutsourcingProductInfoResponse, error)
+	GetCrmSalesDetailsProductInfo(context.Context, *GetCrmSalesDetailsProductInfoRequest) (*GetCrmSalesDetailsProductInfoResponse, error)
 	mustEmbedUnimplementedCrmAndApsGrpcServiceServer()
 }
 
@@ -148,8 +156,14 @@
 func (UnimplementedCrmAndApsGrpcServiceServer) UpdateSalesDetail(context.Context, *UpdateSalesDetailRequest) (*UpdateSalesDetailResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method UpdateSalesDetail not implemented")
 }
-func (UnimplementedCrmAndApsGrpcServiceServer) RemoveSalesDetail(context.Context, *RemoveSalesDetailRequest) (*RemoveSalesDetailRequest, error) {
+func (UnimplementedCrmAndApsGrpcServiceServer) RemoveSalesDetail(context.Context, *RemoveSalesDetailRequest) (*RemoveSalesDetailResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method RemoveSalesDetail not implemented")
+}
+func (UnimplementedCrmAndApsGrpcServiceServer) CrmGetMakeAndOutsourcingProductInfo(context.Context, *CrmGetMakeAndOutsourcingProductInfoRequest) (*CrmGetMakeAndOutsourcingProductInfoResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method CrmGetMakeAndOutsourcingProductInfo not implemented")
+}
+func (UnimplementedCrmAndApsGrpcServiceServer) GetCrmSalesDetailsProductInfo(context.Context, *GetCrmSalesDetailsProductInfoRequest) (*GetCrmSalesDetailsProductInfoResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetCrmSalesDetailsProductInfo not implemented")
 }
 func (UnimplementedCrmAndApsGrpcServiceServer) mustEmbedUnimplementedCrmAndApsGrpcServiceServer() {}
 
@@ -174,7 +188,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: CrmAndApsGrpcService_GetApsProjectList_FullMethodName,
+		FullMethod: "/CrmAndApsGrpcService/GetApsProjectList",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(CrmAndApsGrpcServiceServer).GetApsProjectList(ctx, req.(*GetApsProjectListRequest))
@@ -192,7 +206,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: CrmAndApsGrpcService_SendSalesDetailsToApsProject_FullMethodName,
+		FullMethod: "/CrmAndApsGrpcService/SendSalesDetailsToApsProject",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(CrmAndApsGrpcServiceServer).SendSalesDetailsToApsProject(ctx, req.(*SendSalesDetailsToApsProjectRequest))
@@ -210,7 +224,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: CrmAndApsGrpcService_GetCrmSalesDetailsList_FullMethodName,
+		FullMethod: "/CrmAndApsGrpcService/GetCrmSalesDetailsList",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(CrmAndApsGrpcServiceServer).GetCrmSalesDetailsList(ctx, req.(*GetCrmSalesDetailsListRequest))
@@ -228,7 +242,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: CrmAndApsGrpcService_SendSalesDetailsAndProjectToCrm_FullMethodName,
+		FullMethod: "/CrmAndApsGrpcService/SendSalesDetailsAndProjectToCrm",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(CrmAndApsGrpcServiceServer).SendSalesDetailsAndProjectToCrm(ctx, req.(*SendSalesDetailsAndProjectToCrmRequest))
@@ -246,7 +260,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: CrmAndApsGrpcService_GetClientList_FullMethodName,
+		FullMethod: "/CrmAndApsGrpcService/GetClientList",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(CrmAndApsGrpcServiceServer).GetClientList(ctx, req.(*GetClientListRequest))
@@ -264,7 +278,7 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: CrmAndApsGrpcService_UpdateSalesDetail_FullMethodName,
+		FullMethod: "/CrmAndApsGrpcService/UpdateSalesDetail",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(CrmAndApsGrpcServiceServer).UpdateSalesDetail(ctx, req.(*UpdateSalesDetailRequest))
@@ -282,10 +296,46 @@
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: CrmAndApsGrpcService_RemoveSalesDetail_FullMethodName,
+		FullMethod: "/CrmAndApsGrpcService/RemoveSalesDetail",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
 		return srv.(CrmAndApsGrpcServiceServer).RemoveSalesDetail(ctx, req.(*RemoveSalesDetailRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _CrmAndApsGrpcService_CrmGetMakeAndOutsourcingProductInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(CrmGetMakeAndOutsourcingProductInfoRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(CrmAndApsGrpcServiceServer).CrmGetMakeAndOutsourcingProductInfo(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/CrmAndApsGrpcService/CrmGetMakeAndOutsourcingProductInfo",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(CrmAndApsGrpcServiceServer).CrmGetMakeAndOutsourcingProductInfo(ctx, req.(*CrmGetMakeAndOutsourcingProductInfoRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _CrmAndApsGrpcService_GetCrmSalesDetailsProductInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetCrmSalesDetailsProductInfoRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(CrmAndApsGrpcServiceServer).GetCrmSalesDetailsProductInfo(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/CrmAndApsGrpcService/GetCrmSalesDetailsProductInfo",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(CrmAndApsGrpcServiceServer).GetCrmSalesDetailsProductInfo(ctx, req.(*GetCrmSalesDetailsProductInfoRequest))
 	}
 	return interceptor(ctx, in, info, handler)
 }
@@ -325,6 +375,14 @@
 			MethodName: "RemoveSalesDetail",
 			Handler:    _CrmAndApsGrpcService_RemoveSalesDetail_Handler,
 		},
+		{
+			MethodName: "CrmGetMakeAndOutsourcingProductInfo",
+			Handler:    _CrmAndApsGrpcService_CrmGetMakeAndOutsourcingProductInfo_Handler,
+		},
+		{
+			MethodName: "GetCrmSalesDetailsProductInfo",
+			Handler:    _CrmAndApsGrpcService_GetCrmSalesDetailsProductInfo_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "crm_aps.proto",
diff --git a/proto/crm_aps/server.go b/proto/crm_aps/server.go
index 562dee5..c88b98e 100644
--- a/proto/crm_aps/server.go
+++ b/proto/crm_aps/server.go
@@ -193,7 +193,7 @@
 	return &UpdateSalesDetailResponse{}, nil
 }
 
-func (s *Server) RemoveSalesDetail(ctx context.Context, req *RemoveSalesDetailRequest) (*RemoveSalesDetailRequest, error) {
+func (s *Server) RemoveSalesDetail(ctx context.Context, req *RemoveSalesDetailRequest) (*RemoveSalesDetailResponse, error) {
 	if req.Number == "" {
 		return nil, errors.New("閿�鍞槑缁嗙紪鍙蜂负绌�")
 	}
@@ -208,5 +208,33 @@
 		return nil, errors.New("閿�鍞槑缁嗗垹闄ゅけ璐�")
 	}
 
-	return &RemoveSalesDetailRequest{}, nil
+	return &RemoveSalesDetailResponse{}, nil
+}
+
+func (s *Server) GetCrmSalesDetailsProductInfo(ctx context.Context, req *GetCrmSalesDetailsProductInfoRequest) (*GetCrmSalesDetailsProductInfoResponse, error) {
+	if req.SalesDetailsNumber == "" {
+		return nil, errors.New("閿�鍞槑缁嗙紪鍙蜂负绌�")
+	}
+	first, err := model.NewSalesDetailsSearch().SetPreload(true).SetNumber(req.SalesDetailsNumber).First()
+	if err != nil {
+		return nil, err
+	}
+	list := make([]*CrmSalesDetailsProductInfo, 0)
+	for _, product := range first.Products {
+		var csp CrmSalesDetailsProductInfo
+		csp.ProductId = product.Number
+		csp.ProductName = product.Name
+		csp.Specs = product.Specs
+		csp.Unit = product.Unit
+		csp.Amount = product.Amount.IntPart()
+		csp.Cost = product.Cost
+		csp.Price = product.Price.IntPart()
+		csp.Total = product.Total.IntPart()
+		csp.Profit = product.Profit
+		csp.Margin = product.Margin
+		list = append(list, &csp)
+	}
+	resp := new(GetCrmSalesDetailsProductInfoResponse)
+	resp.List = list
+	return resp, nil
 }

--
Gitblit v1.8.0