From f1842bf9b5bb69b5078a215c02cb16b7e33f893a Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期一, 08 一月 2024 14:38:46 +0800
Subject: [PATCH] Merge branch 'master' of http://192.168.5.5:10010/r/aps/crm

---
 proto/crm_aps/server.go                         |  100 +
 model/contract.go                               |   15 
 service/system_set_service.go                   |   20 
 model/request/salesDetails.go                   |    3 
 model/response/salesDetails.go                  |   39 
 proto/client/server.go                          |   22 
 api/v1/contract.go                              |    8 
 docs/swagger.yaml                               |  256 +++
 api/v1/quotation.go                             |   36 
 model/request/system_set_request.go             |    7 
 conf/aps-crm.json                               |    2 
 model/product.go                                |    4 
 model/request/contract.go                       |    1 
 proto/client.proto                              |   20 
 proto/product_inventory/product_inventory.pb.go |  188 +-
 api/v1/salesLeads.go                            |   17 
 service/contract.go                             |    4 
 api/v1/salesDetails.go                          |  113 +
 model/client.go                                 |    8 
 proto/product/product.pb.go                     |  316 ++-
 proto/crm_aps.proto                             |   83 +
 proto/product_inventory.proto                   |    7 
 api/v1/index.go                                 |    1 
 model/request/product.go                        |    5 
 api/v1/product.go                               |  133 +
 proto/crm_aps/crm_aps.pb.go                     |  996 ++++++++++++++
 api/v1/code.go                                  |   42 
 proto/client/client_grpc.pb.go                  |  109 +
 router/salesDetails.go                          |    4 
 model/quotation.go                              |   13 
 docs/docs.go                                    |  402 ++++
 docs/swagger.json                               |  402 ++++
 model/grpc_init/crm_aps_init.go                 |   25 
 constvar/const.go                               |   40 
 model/salesDetails.go                           |   52 
 proto/product.proto                             |   19 
 proto/client/client.pb.go                       |  275 +++
 model/index.go                                  |    1 
 proto/crm_aps/crm_aps_grpc.pb.go                |  209 ++
 router/index.go                                 |   10 
 router/quotation.go                             |    9 
 main.go                                         |   11 
 api/v1/system_set.go                            |  116 +
 model/system_set.go                             |   97 +
 44 files changed, 3,719 insertions(+), 521 deletions(-)

diff --git a/api/v1/code.go b/api/v1/code.go
index a94cb5a..941623b 100644
--- a/api/v1/code.go
+++ b/api/v1/code.go
@@ -1,9 +1,9 @@
 package v1
 
 import (
-	"aps_crm/conf"
 	"aps_crm/constvar"
 	"aps_crm/model"
+	"aps_crm/model/grpc_init"
 	"aps_crm/model/request"
 	"aps_crm/model/response"
 	"aps_crm/pkg/contextx"
@@ -12,30 +12,28 @@
 	"aps_crm/proto/code"
 	"github.com/gin-gonic/gin"
 	"github.com/spf13/cast"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/credentials/insecure"
 )
 
 type CodeApi struct{}
 
-var (
-	codeServiceConn *grpc.ClientConn
-)
-
-func InitCodeServiceConn() {
-	var err error
-	codeServiceConn, err = grpc.Dial(conf.Conf.GrpcServiceAddr.Aps, grpc.WithTransportCredentials(insecure.NewCredentials()))
-	if err != nil {
-		logx.Errorf("grpc dial product service error: %v", err.Error())
-		return
-	}
-}
-
-func CloseCodeServiceConn() {
-	if codeServiceConn != nil {
-		codeServiceConn.Close()
-	}
-}
+//var (
+//	codeServiceConn *grpc.ClientConn
+//)
+//
+//func InitCodeServiceConn() {
+//	var err error
+//	codeServiceConn, err = grpc.Dial(conf.Conf.GrpcServiceAddr.Aps, grpc.WithTransportCredentials(insecure.NewCredentials()))
+//	if err != nil {
+//		logx.Errorf("grpc dial product service error: %v", err.Error())
+//		return
+//	}
+//}
+//
+//func CloseCodeServiceConn() {
+//	if codeServiceConn != nil {
+//		codeServiceConn.Close()
+//	}
+//}
 
 // GetCodeList
 //
@@ -55,7 +53,7 @@
 	params.CodeStandID = c.Query("codeStandID")
 	params.Name = c.Query("name")
 	params.Type = c.Query("type")
-	client := code.NewCodeServiceClient(codeServiceConn)
+	client := code.NewCodeServiceClient(grpc_init.CrmApsGrpcServiceConn)
 	list, err := client.GetCodeList(ctx.GetCtx(), &code.GetCodeListRequest{
 		Page:        cast.ToInt32(params.Page),
 		PageSize:    cast.ToInt32(params.PageSize),
diff --git a/api/v1/contract.go b/api/v1/contract.go
index 5cfdd31..a0228fc 100644
--- a/api/v1/contract.go
+++ b/api/v1/contract.go
@@ -161,15 +161,15 @@
 		return
 	}
 
+	if params.SearchMap == nil {
+		params.SearchMap = make(map[string]interface{}, 0)
+	}
 	userInfo := utils.GetUserInfo(c)
 	if userInfo.UserType == constvar.UserTypeSub {
-		if params.SearchMap == nil {
-			params.SearchMap = make(map[string]interface{}, 0)
-		}
 		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
-	contracts, total, errCode := contractService.GetContractList(params.Page, params.PageSize, params.SearchMap)
+	contracts, total, errCode := contractService.GetContractList(params.Page, params.PageSize, params.SearchMap, params.Keyword)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
 		return
diff --git a/api/v1/index.go b/api/v1/index.go
index b7d9326..a25ded4 100644
--- a/api/v1/index.go
+++ b/api/v1/index.go
@@ -67,6 +67,7 @@
 	AssignApi
 	CollectionProjectionApi
 	ContactInformationApi
+	SystemSetApi
 }
 
 var ApiGroup = new(Group)
diff --git a/api/v1/product.go b/api/v1/product.go
index f1d1f7b..ee678df 100644
--- a/api/v1/product.go
+++ b/api/v1/product.go
@@ -1,44 +1,39 @@
 package v1
 
 import (
-	"aps_crm/conf"
 	"aps_crm/model"
+	"aps_crm/model/grpc_init"
 	"aps_crm/model/request"
 	"aps_crm/model/response"
 	"aps_crm/pkg/contextx"
 	"aps_crm/pkg/ecode"
 	"aps_crm/pkg/logx"
 	"aps_crm/proto/product"
-	"aps_crm/utils"
-	"fmt"
 	"github.com/gin-gonic/gin"
 	"github.com/shopspring/decimal"
 	"github.com/spf13/cast"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/credentials/insecure"
 )
 
 type ProductApi struct{}
 
-var (
-	productServiceConn *grpc.ClientConn
-)
-
-func InitProductServiceConn() {
-	fmt.Println(conf.Conf.GrpcServiceAddr.Aps)
-	var err error
-	productServiceConn, err = grpc.Dial(conf.Conf.GrpcServiceAddr.Aps, grpc.WithTransportCredentials(insecure.NewCredentials()))
-	if err != nil {
-		logx.Errorf("grpc dial product service error: %v", err.Error())
-		return
-	}
-}
-
-func CloseProductServiceConn() {
-	if productServiceConn != nil {
-		productServiceConn.Close()
-	}
-}
+//var (
+//	productServiceConn *grpc.ClientConn
+//)
+//
+//func InitProductServiceConn() {
+//	var err error
+//	productServiceConn, err = grpc.Dial(conf.Conf.GrpcServiceAddr.Aps, grpc.WithTransportCredentials(insecure.NewCredentials()))
+//	if err != nil {
+//		logx.Errorf("grpc dial product service error: %v", err.Error())
+//		return
+//	}
+//}
+//
+//func CloseProductServiceConn() {
+//	if productServiceConn != nil {
+//		productServiceConn.Close()
+//	}
+//}
 
 // List
 //
@@ -60,13 +55,36 @@
 		return
 	}
 
-	cli := product.NewProductServiceClient(productServiceConn)
+	if params.QuotationNumber != "" {
+		find, err := model.NewQuotationSearch(nil).SetNumber(params.QuotationNumber).Find()
+		if err != nil {
+			ctx.FailWithMsg(ecode.UnknownErr, "鎶ヤ环鍗曚俊鎭煡璇㈠け璐�")
+			return
+		}
+		products := find.Products
+		ctx.OkWithDetailed(response.ListResponse{
+			Data:  products,
+			Count: int64(len(products)),
+		})
+		return
+	}
+	cli := product.NewProductServiceClient(grpc_init.CrmApsGrpcServiceConn)
 	getProductListResponse, err := cli.GetProductList(ctx.GetCtx(), &product.GetProductListRequest{
 		Page:          cast.ToInt32(params.Page),
 		PageSize:      cast.ToInt32(params.PageSize),
 		ProductNumber: params.ProductNumber,
 		ProductName:   params.ProductName,
 	})
+	if err != nil {
+		logx.Errorf("grpc GetProductList err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "鍐呴儴閿欒")
+		return
+	}
+	if getProductListResponse.Code != 0 {
+		logx.Errorf("grpc GetProductList err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "鍐呴儴閿欒")
+		return
+	}
 	rawProductList := getProductListResponse.List
 	productList := make([]model.Product, len(rawProductList))
 
@@ -76,18 +94,9 @@
 		productList[k].Price = decimal.NewFromFloat(v.SalePrice).Round(2)
 		productList[k].Amount = decimal.NewFromFloat(1)
 		productList[k].Total = productList[k].Price.Mul(productList[k].Amount).Round(2)
+		productList[k].Unit = v.Unit
 	}
 
-	if err != nil {
-		logx.Errorf("GetProductList err: %v", err.Error())
-		ctx.FailWithMsg(ecode.UnknownErr, "鍐呴儴閿欒")
-		return
-	}
-	if getProductListResponse.Code != 0 {
-		logx.Errorf("GetProductList err: %v", err.Error())
-		ctx.FailWithMsg(ecode.UnknownErr, "鍐呴儴閿欒")
-		return
-	}
 	ctx.OkWithDetailed(response.ListResponse{
 		Data:  productList,
 		Count: getProductListResponse.Total,
@@ -109,16 +118,16 @@
 
 	// 鑾峰彇浜у搧ID
 	productId := c.Query("productNumber")
-	cli := product.NewProductServiceClient(productServiceConn)
+	cli := product.NewProductServiceClient(grpc_init.CrmApsGrpcServiceConn)
 
 	getProductInfoResponse, err := cli.GetProductInfo(ctx.GetCtx(), &product.GetProductInfoRequest{ProductId: productId})
 	if err != nil {
-		logx.Errorf("GetProductInfo err: %v", err.Error())
+		logx.Errorf(" grpc GetProductInfo err: %v", err.Error())
 		ctx.FailWithMsg(ecode.UnknownErr, "鍐呴儴閿欒")
 		return
 	}
 	if getProductInfoResponse.Code != 0 {
-		logx.Errorf("GetProductInfo err: %v", err.Error())
+		logx.Errorf("grpc GetProductInfo err: %v", err.Error())
 		ctx.FailWithMsg(ecode.UnknownErr, "鍐呴儴閿欒")
 		return
 	}
@@ -131,7 +140,7 @@
 // @Summary	鑾峰彇浜у搧璁㈠崟淇℃伅
 // @Produce	application/json
 // @Param		number	path		string	true	"鏄庣粏缂栫爜"
-// @Success	200	{object}	contextx.Response{data=[]product.WorkOrderInfo}	"鎴愬姛"
+// @Success	200	{object}	contextx.Response{data=response.Info}	"鎴愬姛"
 //
 //	@Router		/api/product/getProductOrderInfo/{number} [get]
 func (ci *ProductApi) GetProductOrderInfo(c *gin.Context) {
@@ -140,25 +149,41 @@
 		return
 	}
 	number := c.Param("number")
-	first, err := model.NewSalesDetailsSearch().SetNumber(number).SetPreload(true).First()
-	if err != nil {
-		ctx.FailWithMsg(ecode.UnknownErr, "鏄庣粏璇︽儏鏌ユ壘澶辫触")
+	if number == "" || number == "undefined" {
+		ctx.Ok()
 		return
 	}
-	params := make([]*product.Info, 0)
-	for _, p := range first.Products {
-		var pa product.Info
-		pa.ProductId = p.Number
-		pa.StartTime = utils.TimeToString(first.UpdatedAt)
-		pa.EndTime = first.DeliveryDate
-		params = append(params, &pa)
-	}
-	client := product.NewProductServiceClient(productServiceConn)
-	info, err := client.GetProductOrder(ctx.GetCtx(), &product.GetProductOrderRequest{Params: params})
+	client := product.NewProductServiceClient(grpc_init.CrmApsGrpcServiceConn)
+	info, err := client.GetProductOrder(ctx.GetCtx(), &product.GetProductOrderRequest{SalesDetailsNumber: number})
 	if err != nil {
-		logx.Errorf("GetProductOrder err: %v", err.Error())
+		logx.Errorf("grpc GetProductOrder err: %v", err.Error())
 		ctx.FailWithMsg(ecode.UnknownErr, "鍐呴儴閿欒")
 		return
 	}
-	ctx.OkWithDetailed(info.List)
+	var result response.Info
+	var list []response.WorkOrderInfo
+	for _, orderInfo := range info.List {
+		var wo response.WorkOrderInfo
+		wo.OrderId = orderInfo.OrderId
+		wo.ProductName = orderInfo.ProductName
+		wo.OrderStatus = orderInfo.OrderStatus
+		wo.WorkOrderId = orderInfo.WorkOrderId
+		wo.WorkOrderStatus = orderInfo.WorkOrderStatus
+		wo.StartTime = orderInfo.StartTime
+		wo.EndTime = orderInfo.EndTime
+		list = append(list, wo)
+	}
+	result.MakeInfo = list
+	var purchaseInfo []response.Purchase
+	for _, pl := range info.PurchaseList {
+		var p response.Purchase
+		p.Amount = pl.Amount
+		p.Status = pl.Status
+		p.PurchaseName = pl.PurchaseName
+		p.PurchaseNumber = pl.PurchaseNumber
+		p.SupplierName = pl.SupplierName
+		purchaseInfo = append(purchaseInfo, p)
+	}
+	result.PurchaseInfo = purchaseInfo
+	ctx.OkWithDetailed(result)
 }
diff --git a/api/v1/quotation.go b/api/v1/quotation.go
index d237955..ecbe7da 100644
--- a/api/v1/quotation.go
+++ b/api/v1/quotation.go
@@ -9,6 +9,7 @@
 	"aps_crm/pkg/ecode"
 	"aps_crm/utils"
 	"github.com/gin-gonic/gin"
+	"github.com/shopspring/decimal"
 )
 
 type QuotationApi struct{}
@@ -195,8 +196,43 @@
 		return
 	}
 
+	for _, quotation := range quotations {
+		amount := decimal.NewFromInt(0)
+		for _, product := range quotation.Products {
+			amount = amount.Add(product.Total)
+		}
+		quotation.AmountTotal = amount
+	}
+
 	ctx.OkWithDetailed(response.QuotationResponse{
 		List:  quotations,
 		Count: int(total),
 	})
 }
+
+// Statistics
+//
+//	@Tags		Quotation
+//	@Summary	鎶ヤ环鍗曠粺璁�
+//	@Produce	application/json
+//	@Success	200		{object}	contextx.Response{data=map[string]int64}
+//	@Router		/api/quotation/statistics [get]
+func (con *QuotationApi) Statistics(c *gin.Context) {
+	ctx, ok := contextx.NewContext(c, nil)
+	if !ok {
+		return
+	}
+	m := make(map[string]int64)
+	total, _ := model.NewQuotationSearch(nil).Count()
+	m["total"] = total
+	//宸插垱寤�
+	created, _ := model.NewQuotationSearch(nil).SetQuotationStatusId(1).Count()
+	m["created"] = created
+	//宸插鎵�
+	approved, _ := model.NewQuotationSearch(nil).SetQuotationStatusId(3).Count()
+	m["approved"] = approved
+	//宸叉帴鍙�
+	accepted, _ := model.NewQuotationSearch(nil).SetQuotationStatusId(5).Count()
+	m["accepted"] = accepted
+	ctx.OkWithDetailed(m)
+}
diff --git a/api/v1/salesDetails.go b/api/v1/salesDetails.go
index afe5746..cab0091 100644
--- a/api/v1/salesDetails.go
+++ b/api/v1/salesDetails.go
@@ -4,17 +4,22 @@
 	"aps_crm/conf"
 	"aps_crm/constvar"
 	"aps_crm/model"
+	"aps_crm/model/grpc_init"
 	"aps_crm/model/request"
 	"aps_crm/model/response"
 	"aps_crm/pkg/contextx"
 	"aps_crm/pkg/ecode"
 	"aps_crm/pkg/logx"
+	"aps_crm/pkg/structx"
+	"aps_crm/proto/crm_aps"
 	"aps_crm/proto/product_inventory"
 	"aps_crm/utils"
 	"github.com/gin-gonic/gin"
+	"github.com/shopspring/decimal"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials/insecure"
 	"strconv"
+	"strings"
 )
 
 type SalesDetailsApi struct{}
@@ -166,7 +171,12 @@
 	salesDetailsModel.DeliverType = salesDetails.DeliverType
 	salesDetailsModel.QuotationId = salesDetails.QuotationId
 	salesDetailsModel.Status = salesDetails.Status
-	salesDetailsModel.Source = salesDetails.Source
+	if salesDetails.Source == "" {
+		salesDetailsModel.Source = "CRM鑷缓"
+	} else {
+		salesDetailsModel.Source = salesDetails.Source
+	}
+	salesDetailsModel.ProjectId = salesDetails.ProjectId
 
 	return ecode.OK, salesDetailsModel
 }
@@ -267,55 +277,132 @@
 	client := product_inventory.NewProductInventoryServiceClient(ProductInventoryServiceConn)
 	info, err := client.GetInventoryProductInfo(ctx.GetCtx(), &product_inventory.GetInventoryProductInfoRequest{Number: number})
 	if err != nil {
+		if strings.Contains(err.Error(), "record not found") {
+			ctx.Ok()
+			return
+		}
 		logx.Errorf("GetProductInfo err: %v", err.Error())
 		ctx.FailWithMsg(ecode.UnknownErr, "grpc璋冪敤閿欒")
 		return
 	}
-	ctx.OkWithDetailed(info.ProductList)
+	var list []response.ProductInfo
+	err = structx.AssignTo(info.ProductList, &list)
+	if err != nil {
+		ctx.FailWithMsg(ecode.UnknownErr, "杞崲閿欒")
+		return
+	}
+	ctx.OkWithDetailed(list)
 }
 
-// CreateOperation
+// GetApsProjectList
 //
 // @Tags		SalesDetails
-// @Summary	鍒涘缓浜у搧鍑哄簱淇℃伅
+// @Summary	    鑾峰彇aps椤圭洰鍒楄〃
+// @Produce	application/json
+// @Success	200	{object}	response.Response
+//
+//	@Router		/api/salesDetails/getApsProjectList [get]
+func (s *SalesDetailsApi) GetApsProjectList(c *gin.Context) {
+	ctx, ok := contextx.NewContext(c, nil)
+	if !ok {
+		return
+	}
+	client := crm_aps.NewCrmAndApsGrpcServiceClient(grpc_init.CrmApsGrpcServiceConn)
+	projectList, err := client.GetApsProjectList(c, &crm_aps.GetApsProjectListRequest{})
+	if err != nil {
+		logx.Errorf("grpc GetApsProjectList err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "鑾峰彇aps椤圭洰鍒楄〃澶辫触")
+		return
+	}
+	ctx.OkWithDetailed(projectList.List)
+}
+
+// SendSalesDetailsToOtherSystem
+//
+// @Tags		SalesDetails
+// @Summary	  鎺ㄩ�侀攢鍞槑缁嗕俊鎭埌鍏朵粬绯荤粺
 // @Produce	application/json
 // @Param		object	body		request.SalesDetails	true	"鏌ヨ鍙傛暟"
 // @Success	200	{object}	response.ListResponse
 //
-//	@Router		/api/salesDetails/createOperation [post]
-func (s *SalesDetailsApi) CreateOperation(c *gin.Context) {
+//	@Router		/api/salesDetails/sendSalesDetailsToOtherSystem [post]
+func (s *SalesDetailsApi) SendSalesDetailsToOtherSystem(c *gin.Context) {
 	var params request.SalesDetails
 	ctx, ok := contextx.NewContext(c, &params)
 	if !ok {
 		return
 	}
+	clientName := ""
+	if params.ClientId > 0 {
+		first, err := model.NewClientSearch(nil).SetId(params.ClientId).First()
+		if err != nil {
+			ctx.FailWithMsg(ecode.UnknownErr, "瀹㈡埛淇℃伅鏌ヨ澶辫触")
+			return
+		}
+		clientName = first.Name
+	}
 	m := make(map[string]interface{})
 	m["status"] = params.Status
+	m["project_id"] = params.ProjectId
 	err := model.NewSalesDetailsSearch().SetNumber(params.Number).UpdateByMap(m)
 	if err != nil {
 		ctx.FailWithMsg(ecode.UnknownErr, "鐘舵�佹洿鏂板け璐�")
 		return
 	}
 
-	client := product_inventory.NewProductInventoryServiceClient(ProductInventoryServiceConn)
-	products := make([]*product_inventory.InventoryProduct, 0)
+	//鎺ㄩ�佸埌wms
+	wmsProducts := make([]*product_inventory.InventoryProduct, 0)
 	for _, product := range params.Products {
 		var p product_inventory.InventoryProduct
 		p.Id = product.Number
 		p.Amount = product.Amount.String()
-		products = append(products, &p)
+		wmsProducts = append(wmsProducts, &p)
 	}
-	_, err = client.CreateOperation(ctx.GetCtx(), &product_inventory.CreateOperationRequest{
+	clientWms := product_inventory.NewProductInventoryServiceClient(ProductInventoryServiceConn)
+	_, err = clientWms.CreateOperation(ctx.GetCtx(), &product_inventory.CreateOperationRequest{
 		Number:      params.Number,
 		Addressee:   params.Addressee,
 		Address:     params.Address,
 		Phone:       params.Phone,
 		DeliverType: int32(params.DeliverType),
-		ProductList: products,
+		Source:      "CRM",
+		ClientId:    int64(params.ClientId),
+		ClientName:  clientName,
+		ProductList: wmsProducts,
 	})
 	if err != nil {
-		logx.Errorf("CreateOperation err: %v", err.Error())
-		ctx.FailWithMsg(ecode.UnknownErr, "grpc璋冪敤閿欒")
+		logx.Errorf("grpc CreateOperation err: %v", err.Error())
+	}
+
+	//鎺ㄩ�佸埌aps
+	ApsProducts := make([]*crm_aps.SalesDetailsProduct, 0)
+	var total decimal.Decimal
+	for _, product := range params.Products {
+		var sp crm_aps.SalesDetailsProduct
+		sp.ProductId = product.Number
+		sp.Amount = product.Amount.IntPart()
+		ApsProducts = append(ApsProducts, &sp)
+		total = total.Add(product.Amount)
+	}
+
+	clientAps := crm_aps.NewCrmAndApsGrpcServiceClient(grpc_init.CrmApsGrpcServiceConn)
+	_, err = clientAps.SendSalesDetailsToApsProject(c, &crm_aps.SendSalesDetailsToApsProjectRequest{
+		Number:       params.Number,
+		ClientName:   params.Client.Name,
+		MemberName:   params.Member.Username,
+		SignTime:     params.SignTime,
+		DeliveryDate: params.DeliveryDate,
+		Source:       params.Source,
+		ProductTotal: total.IntPart(),
+		ProjectId:    params.ProjectId,
+		Products:     ApsProducts,
+	})
+	if err != nil {
+		//鐘舵�佽繕鍘�
+		m["status"] = constvar.WaitConfirmed
+		_ = model.NewSalesDetailsSearch().SetNumber(params.Number).UpdateByMap(m)
+		logx.Errorf("grpc SendSalesDetailsToApsProject err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "鎺ㄩ�佸け璐�,璇锋鏌ュ弬鏁版槸鍚︽纭�")
 		return
 	}
 	ctx.Ok()
diff --git a/api/v1/salesLeads.go b/api/v1/salesLeads.go
index f12b2a9..530a1bf 100644
--- a/api/v1/salesLeads.go
+++ b/api/v1/salesLeads.go
@@ -205,10 +205,19 @@
 		return
 	}
 
-	errCode := salesLeadsService.PushSalesLeads(params.Id, params.Step, params.Reason)
-	if errCode != ecode.OK {
-		ctx.Fail(errCode)
-		return
+	if params.Step == constvar.SalesStatusFail {
+		errCode := salesLeadsService.DeleteSalesLeads([]int{params.Id})
+		if errCode != ecode.OK {
+			ctx.Fail(errCode)
+			return
+		}
+	} else {
+		errCode := salesLeadsService.PushSalesLeads(params.Id, params.Step, params.Reason)
+		if errCode != ecode.OK {
+			ctx.Fail(errCode)
+			return
+		}
 	}
+
 	ctx.Ok()
 }
diff --git a/api/v1/system_set.go b/api/v1/system_set.go
new file mode 100644
index 0000000..53403e8
--- /dev/null
+++ b/api/v1/system_set.go
@@ -0,0 +1,116 @@
+package v1
+
+import (
+	"aps_crm/constvar"
+	"aps_crm/model"
+	"aps_crm/model/request"
+	"aps_crm/pkg/contextx"
+	"aps_crm/pkg/ecode"
+	"aps_crm/service"
+	"github.com/gin-gonic/gin"
+	"gorm.io/gorm"
+)
+
+type SystemSetApi struct{}
+
+// GetSystemSet
+//
+//	@Tags		绯荤粺璁剧疆
+//	@Summary	鑾峰彇绯荤粺璁剧疆
+//	@Produce	application/json
+//	@Success	200		{object}	contextx.Response{data=map[string]interface{}}	"鎴愬姛"
+//	@Router		/api/system/getSystemSet [get]
+func (slf SystemSetApi) GetSystemSet(c *gin.Context) {
+	ctx, ok := contextx.NewContext(c, nil)
+	if !ok {
+		return
+	}
+	systemSet, err := service.GetSystemSet()
+	if err != nil {
+		ctx.FailWithMsg(ecode.UnknownErr, "鏌ヨ澶辫触")
+		return
+	}
+	constvar.SystemSet["CRM"] = systemSet
+	ctx.OkWithDetailed(constvar.SystemSet)
+}
+
+// SaveSystemSet
+//
+//	@Tags		绯荤粺璁剧疆
+//	@Summary	淇濆瓨绯荤粺璁剧疆
+//	@Produce	application/json
+//	@Param		object	body		request.SaveSystemSet	true	"鏌ヨ鍙傛暟"
+//	@Success	200		{object}	contextx.Response{}	"鎴愬姛"
+//	@Router		/api/system/saveSystemSet [post]
+func (slf SystemSetApi) SaveSystemSet(c *gin.Context) {
+	var params request.SaveSystemSet
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+	err := model.WithTransaction(func(db *gorm.DB) error {
+		err := model.NewSystemSetSearch().SetOrm(db).DeleteAll()
+		if err != nil {
+			return err
+		}
+		err = model.NewSystemSetSearch().SetOrm(db).CreateBatch(params.Sets)
+		return err
+	})
+	if err != nil {
+		ctx.FailWithMsg(ecode.UnknownErr, "淇濆瓨澶辫触")
+		return
+	}
+	ctx.Ok()
+}
+
+// UseSystemSet
+//
+//	@Tags			绯荤粺璁剧疆
+//	@Summary		浣跨敤绯荤粺璁剧疆
+//	@Produce		application/json
+//	@Param			modeType	path		string	true	"鏌ヨ鍙傛暟"
+//	@Success		200	{object}	response.ListResponse
+//	@Router			/api/system/useSystemSet/{modeType} [get]
+func (slf *SystemSetApi) UseSystemSet(c *gin.Context) {
+	ctx, ok := contextx.NewContext(c, nil)
+	if !ok {
+		return
+	}
+	modeType := c.Param("modeType")
+	if modeType == "" {
+		ctx.FailWithMsg(ecode.UnknownErr, "鍙傛暟閿欒")
+		return
+	}
+	m := make(map[string]string)
+	systemSet, err := service.GetSystemSet()
+	if err != nil {
+		ctx.FailWithMsg(ecode.UnknownErr, "鏌ヨ澶辫触")
+		return
+	}
+	switch constvar.ModeType(modeType) {
+	case constvar.BjdMode:
+		value := systemSet["鎶ヤ环鍗曟槸鍚﹀繀椤诲叧鑱旈攢鍞満浼�"].((map[string]interface{}))["value"]
+		if value == "鏄�" {
+			m["Xsjh"] = "yes"
+		} else {
+			m["Xsjh"] = "no"
+		}
+	case constvar.XsmxMode:
+		value := systemSet["閿�鍞槑缁嗗崟鏄惁蹇呴』鍏宠仈鎶ヤ环鍗�"].((map[string]interface{}))["value"]
+		if value == "鏄�" {
+			m["Bjd"] = "yes"
+		} else {
+			m["Bjd"] = "no"
+		}
+		value = systemSet["閿�鍞槑缁嗗崟鏄惁蹇呴』鍏宠仈涓氬姟鏈轰細"].((map[string]interface{}))["value"]
+		if value == "鏄�" {
+			m["Ywjh"] = "yes"
+		} else {
+			m["Ywjh"] = "no"
+		}
+	default:
+		ctx.FailWithMsg(ecode.UnknownErr, "鍙傛暟閿欒")
+		return
+	}
+	ctx.OkWithDetailed(m)
+}
diff --git a/conf/aps-crm.json b/conf/aps-crm.json
index a56afa5..0269872 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.118:8006"
+    "WMS": "192.168.20.119:8006"
   }
 }
 
diff --git a/constvar/const.go b/constvar/const.go
index 1107c6f..c81270e 100644
--- a/constvar/const.go
+++ b/constvar/const.go
@@ -207,3 +207,43 @@
 const (
 	SystemType = 2
 )
+
+// ModeType 妯″潡绫诲瀷
+type ModeType string
+
+const (
+	BjdMode  ModeType = "bjd"
+	XsmxMode ModeType = "xsmx"
+)
+
+var SystemSet = map[string]interface{}{
+	"CRM": map[string]interface{}{
+		"鎶ヤ环鍗曟槸鍚﹀繀椤诲叧鑱旈攢鍞満浼�": map[string]interface{}{
+			"value": "鏄�",
+			"type":  "select",
+			"select": map[string]string{
+				"1": "鏄�",
+				"2": "鍚�",
+			},
+			"modeType": "bjd",
+		},
+		"閿�鍞槑缁嗗崟鏄惁蹇呴』鍏宠仈鎶ヤ环鍗�": map[string]interface{}{
+			"value": "鏄�",
+			"type":  "select",
+			"select": map[string]string{
+				"1": "鏄�",
+				"2": "鍚�",
+			},
+			"modeType": "xsmx",
+		},
+		"閿�鍞槑缁嗗崟鏄惁蹇呴』鍏宠仈涓氬姟鏈轰細": map[string]interface{}{
+			"value": "鏄�",
+			"type":  "select",
+			"select": map[string]string{
+				"1": "鏄�",
+				"2": "鍚�",
+			},
+			"modeType": "xsmx",
+		},
+	},
+}
diff --git a/docs/docs.go b/docs/docs.go
index 294962d..1455302 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -4947,10 +4947,7 @@
                                     "type": "object",
                                     "properties": {
                                         "data": {
-                                            "type": "array",
-                                            "items": {
-                                                "$ref": "#/definitions/product.WorkOrderInfo"
-                                            }
+                                            "$ref": "#/definitions/response.Info"
                                         }
                                     }
                                 }
@@ -5032,6 +5029,12 @@
                         "type": "string",
                         "description": "浜у搧缂栫爜",
                         "name": "productNumber",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "鎶ヤ环鍗曠紪鐮�",
+                        "name": "quotationNumber",
                         "in": "query"
                     }
                 ],
@@ -5320,6 +5323,40 @@
                 }
             }
         },
+        "/api/quotation/statistics": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Quotation"
+                ],
+                "summary": "鎶ヤ环鍗曠粺璁�",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/contextx.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "object",
+                                            "additionalProperties": {
+                                                "type": "integer"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
         "/api/quotation/update": {
             "put": {
                 "produces": [
@@ -5553,6 +5590,15 @@
                         "type": "integer",
                         "description": "姣忛〉澶у皬",
                         "name": "pageSize",
+                        "in": "query"
+                    },
+                    {
+                        "type": "array",
+                        "items": {
+                            "type": "integer"
+                        },
+                        "collectionFormat": "csv",
+                        "name": "principleIds",
                         "in": "query"
                     },
                     {
@@ -6962,36 +7008,6 @@
                 }
             }
         },
-        "/api/salesDetails/createOperation": {
-            "post": {
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "SalesDetails"
-                ],
-                "summary": "鍒涘缓浜у搧鍑哄簱淇℃伅",
-                "parameters": [
-                    {
-                        "description": "鏌ヨ鍙傛暟",
-                        "name": "object",
-                        "in": "body",
-                        "required": true,
-                        "schema": {
-                            "$ref": "#/definitions/request.SalesDetails"
-                        }
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "$ref": "#/definitions/response.ListResponse"
-                        }
-                    }
-                }
-            }
-        },
         "/api/salesDetails/delete": {
             "delete": {
                 "produces": [
@@ -7045,6 +7061,25 @@
                         "description": "OK",
                         "schema": {
                             "$ref": "#/definitions/contextx.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/salesDetails/getApsProjectList": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鑾峰彇aps椤圭洰鍒楄〃",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.Response"
                         }
                     }
                 }
@@ -7115,6 +7150,36 @@
                                     }
                                 }
                             ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api/salesDetails/sendSalesDetailsToOtherSystem": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鎺ㄩ�侀攢鍞槑缁嗕俊鎭埌鍏朵粬绯荤粺",
+                "parameters": [
+                    {
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.SalesDetails"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
                         }
                     }
                 }
@@ -9758,6 +9823,96 @@
                 }
             }
         },
+        "/api/system/getSystemSet": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "绯荤粺璁剧疆"
+                ],
+                "summary": "鑾峰彇绯荤粺璁剧疆",
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/contextx.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "object",
+                                            "additionalProperties": true
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api/system/saveSystemSet": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "绯荤粺璁剧疆"
+                ],
+                "summary": "淇濆瓨绯荤粺璁剧疆",
+                "parameters": [
+                    {
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.SaveSystemSet"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/contextx.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/system/useSystemSet/{modeType}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "绯荤粺璁剧疆"
+                ],
+                "summary": "浣跨敤绯荤粺璁剧疆",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "modeType",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/api/timeSpent/add": {
             "post": {
                 "produces": [
@@ -11815,11 +11970,17 @@
                 "amount": {
                     "type": "number"
                 },
+                "cost": {
+                    "type": "string"
+                },
                 "desc": {
                     "type": "string"
                 },
                 "id": {
                     "type": "integer"
+                },
+                "margin": {
+                    "type": "string"
                 },
                 "name": {
                     "type": "string"
@@ -11830,8 +11991,14 @@
                 "price": {
                     "type": "number"
                 },
+                "profit": {
+                    "type": "string"
+                },
                 "total": {
                     "type": "number"
+                },
+                "unit": {
+                    "type": "string"
                 }
             }
         },
@@ -11855,6 +12022,10 @@
         "model.Quotation": {
             "type": "object",
             "properties": {
+                "amountTotal": {
+                    "description": "浠锋牸鍚堣",
+                    "type": "number"
+                },
                 "client": {
                     "$ref": "#/definitions/model.Client"
                 },
@@ -12365,6 +12536,9 @@
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
+                },
+                "projectId": {
+                    "type": "string"
                 },
                 "quotation": {
                     "$ref": "#/definitions/model.Quotation"
@@ -13301,6 +13475,23 @@
                 }
             }
         },
+        "model.SystemSet": {
+            "type": "object",
+            "properties": {
+                "id": {
+                    "type": "integer"
+                },
+                "modeType": {
+                    "type": "string"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "value": {
+                    "type": "string"
+                }
+            }
+        },
         "model.TimeSpent": {
             "type": "object",
             "properties": {
@@ -13362,6 +13553,10 @@
                     "type": "string"
                 },
                 "realName": {
+                    "type": "string"
+                },
+                "subUserIds": {
+                    "description": "涓嬪睘鍛樺伐鐢ㄦ埛id,鐢ㄩ�楀彿鍒嗗紑",
                     "type": "string"
                 },
                 "userType": {
@@ -13436,32 +13631,6 @@
                     "type": "string"
                 },
                 "Unit": {
-                    "type": "string"
-                }
-            }
-        },
-        "product.WorkOrderInfo": {
-            "type": "object",
-            "properties": {
-                "EndTime": {
-                    "type": "string"
-                },
-                "OrderId": {
-                    "type": "string"
-                },
-                "OrderStatus": {
-                    "type": "string"
-                },
-                "ProductName": {
-                    "type": "string"
-                },
-                "StartTime": {
-                    "type": "string"
-                },
-                "WorkOrderId": {
-                    "type": "string"
-                },
-                "WorkOrderStatus": {
                     "type": "string"
                 }
             }
@@ -14497,11 +14666,17 @@
         "request.AddSalesDetails": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "address": {
                     "type": "string"
                 },
                 "addressee": {
                     "type": "string"
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
                 },
                 "clientId": {
                     "type": "integer"
@@ -14543,6 +14718,9 @@
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
+                },
+                "projectId": {
+                    "type": "string"
                 },
                 "quotationId": {
                     "type": "integer"
@@ -15582,6 +15760,9 @@
         "request.GetContractList": {
             "type": "object",
             "properties": {
+                "keyword": {
+                    "type": "string"
+                },
                 "page": {
                     "description": "椤电爜",
                     "type": "integer"
@@ -15647,6 +15828,12 @@
                 "pageSize": {
                     "description": "姣忛〉澶у皬",
                     "type": "integer"
+                },
+                "principalIds": {
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
                 },
                 "sourceId": {
                     "type": "integer"
@@ -16066,11 +16253,17 @@
         "request.SalesDetails": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "address": {
                     "type": "string"
                 },
                 "addressee": {
                     "type": "string"
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
                 },
                 "clientId": {
                     "type": "integer"
@@ -16112,6 +16305,9 @@
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
+                },
+                "projectId": {
+                    "type": "string"
                 },
                 "quotationId": {
                     "type": "integer"
@@ -16245,6 +16441,17 @@
                             "$ref": "#/definitions/constvar.SalesReturnSourceType"
                         }
                     ]
+                }
+            }
+        },
+        "request.SaveSystemSet": {
+            "type": "object",
+            "properties": {
+                "sets": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/model.SystemSet"
+                    }
                 }
             }
         },
@@ -19108,6 +19315,23 @@
                 }
             }
         },
+        "response.Info": {
+            "type": "object",
+            "properties": {
+                "makeInfo": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/response.WorkOrderInfo"
+                    }
+                },
+                "purchaseInfo": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/response.Purchase"
+                    }
+                }
+            }
+        },
         "response.IsInvoiceResponse": {
             "type": "object",
             "properties": {
@@ -19245,6 +19469,26 @@
                 }
             }
         },
+        "response.Purchase": {
+            "type": "object",
+            "properties": {
+                "amount": {
+                    "type": "integer"
+                },
+                "purchaseName": {
+                    "type": "string"
+                },
+                "purchaseNumber": {
+                    "type": "string"
+                },
+                "status": {
+                    "type": "integer"
+                },
+                "supplierName": {
+                    "type": "string"
+                }
+            }
+        },
         "response.QuotationResponse": {
             "type": "object",
             "properties": {
@@ -19322,6 +19566,18 @@
                     "items": {
                         "$ref": "#/definitions/model.Repository"
                     }
+                }
+            }
+        },
+        "response.Response": {
+            "type": "object",
+            "properties": {
+                "code": {
+                    "type": "integer"
+                },
+                "data": {},
+                "msg": {
+                    "type": "string"
                 }
             }
         },
@@ -19538,6 +19794,32 @@
                     }
                 }
             }
+        },
+        "response.WorkOrderInfo": {
+            "type": "object",
+            "properties": {
+                "endTime": {
+                    "type": "string"
+                },
+                "orderId": {
+                    "type": "string"
+                },
+                "orderStatus": {
+                    "type": "string"
+                },
+                "productName": {
+                    "type": "string"
+                },
+                "startTime": {
+                    "type": "string"
+                },
+                "workOrderId": {
+                    "type": "string"
+                },
+                "workOrderStatus": {
+                    "type": "string"
+                }
+            }
         }
     }
 }`
diff --git a/docs/swagger.json b/docs/swagger.json
index 95efe8d..431fd5d 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -4935,10 +4935,7 @@
                                     "type": "object",
                                     "properties": {
                                         "data": {
-                                            "type": "array",
-                                            "items": {
-                                                "$ref": "#/definitions/product.WorkOrderInfo"
-                                            }
+                                            "$ref": "#/definitions/response.Info"
                                         }
                                     }
                                 }
@@ -5020,6 +5017,12 @@
                         "type": "string",
                         "description": "浜у搧缂栫爜",
                         "name": "productNumber",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "鎶ヤ环鍗曠紪鐮�",
+                        "name": "quotationNumber",
                         "in": "query"
                     }
                 ],
@@ -5308,6 +5311,40 @@
                 }
             }
         },
+        "/api/quotation/statistics": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Quotation"
+                ],
+                "summary": "鎶ヤ环鍗曠粺璁�",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/contextx.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "object",
+                                            "additionalProperties": {
+                                                "type": "integer"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
         "/api/quotation/update": {
             "put": {
                 "produces": [
@@ -5541,6 +5578,15 @@
                         "type": "integer",
                         "description": "姣忛〉澶у皬",
                         "name": "pageSize",
+                        "in": "query"
+                    },
+                    {
+                        "type": "array",
+                        "items": {
+                            "type": "integer"
+                        },
+                        "collectionFormat": "csv",
+                        "name": "principleIds",
                         "in": "query"
                     },
                     {
@@ -6950,36 +6996,6 @@
                 }
             }
         },
-        "/api/salesDetails/createOperation": {
-            "post": {
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "SalesDetails"
-                ],
-                "summary": "鍒涘缓浜у搧鍑哄簱淇℃伅",
-                "parameters": [
-                    {
-                        "description": "鏌ヨ鍙傛暟",
-                        "name": "object",
-                        "in": "body",
-                        "required": true,
-                        "schema": {
-                            "$ref": "#/definitions/request.SalesDetails"
-                        }
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "$ref": "#/definitions/response.ListResponse"
-                        }
-                    }
-                }
-            }
-        },
         "/api/salesDetails/delete": {
             "delete": {
                 "produces": [
@@ -7033,6 +7049,25 @@
                         "description": "OK",
                         "schema": {
                             "$ref": "#/definitions/contextx.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/salesDetails/getApsProjectList": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鑾峰彇aps椤圭洰鍒楄〃",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.Response"
                         }
                     }
                 }
@@ -7103,6 +7138,36 @@
                                     }
                                 }
                             ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api/salesDetails/sendSalesDetailsToOtherSystem": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SalesDetails"
+                ],
+                "summary": "鎺ㄩ�侀攢鍞槑缁嗕俊鎭埌鍏朵粬绯荤粺",
+                "parameters": [
+                    {
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.SalesDetails"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
                         }
                     }
                 }
@@ -9746,6 +9811,96 @@
                 }
             }
         },
+        "/api/system/getSystemSet": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "绯荤粺璁剧疆"
+                ],
+                "summary": "鑾峰彇绯荤粺璁剧疆",
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/contextx.Response"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "object",
+                                            "additionalProperties": true
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/api/system/saveSystemSet": {
+            "post": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "绯荤粺璁剧疆"
+                ],
+                "summary": "淇濆瓨绯荤粺璁剧疆",
+                "parameters": [
+                    {
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "object",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/request.SaveSystemSet"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "鎴愬姛",
+                        "schema": {
+                            "$ref": "#/definitions/contextx.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/system/useSystemSet/{modeType}": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "绯荤粺璁剧疆"
+                ],
+                "summary": "浣跨敤绯荤粺璁剧疆",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "鏌ヨ鍙傛暟",
+                        "name": "modeType",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/response.ListResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/api/timeSpent/add": {
             "post": {
                 "produces": [
@@ -11803,11 +11958,17 @@
                 "amount": {
                     "type": "number"
                 },
+                "cost": {
+                    "type": "string"
+                },
                 "desc": {
                     "type": "string"
                 },
                 "id": {
                     "type": "integer"
+                },
+                "margin": {
+                    "type": "string"
                 },
                 "name": {
                     "type": "string"
@@ -11818,8 +11979,14 @@
                 "price": {
                     "type": "number"
                 },
+                "profit": {
+                    "type": "string"
+                },
                 "total": {
                     "type": "number"
+                },
+                "unit": {
+                    "type": "string"
                 }
             }
         },
@@ -11843,6 +12010,10 @@
         "model.Quotation": {
             "type": "object",
             "properties": {
+                "amountTotal": {
+                    "description": "浠锋牸鍚堣",
+                    "type": "number"
+                },
                 "client": {
                     "$ref": "#/definitions/model.Client"
                 },
@@ -12353,6 +12524,9 @@
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
+                },
+                "projectId": {
+                    "type": "string"
                 },
                 "quotation": {
                     "$ref": "#/definitions/model.Quotation"
@@ -13289,6 +13463,23 @@
                 }
             }
         },
+        "model.SystemSet": {
+            "type": "object",
+            "properties": {
+                "id": {
+                    "type": "integer"
+                },
+                "modeType": {
+                    "type": "string"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "value": {
+                    "type": "string"
+                }
+            }
+        },
         "model.TimeSpent": {
             "type": "object",
             "properties": {
@@ -13350,6 +13541,10 @@
                     "type": "string"
                 },
                 "realName": {
+                    "type": "string"
+                },
+                "subUserIds": {
+                    "description": "涓嬪睘鍛樺伐鐢ㄦ埛id,鐢ㄩ�楀彿鍒嗗紑",
                     "type": "string"
                 },
                 "userType": {
@@ -13424,32 +13619,6 @@
                     "type": "string"
                 },
                 "Unit": {
-                    "type": "string"
-                }
-            }
-        },
-        "product.WorkOrderInfo": {
-            "type": "object",
-            "properties": {
-                "EndTime": {
-                    "type": "string"
-                },
-                "OrderId": {
-                    "type": "string"
-                },
-                "OrderStatus": {
-                    "type": "string"
-                },
-                "ProductName": {
-                    "type": "string"
-                },
-                "StartTime": {
-                    "type": "string"
-                },
-                "WorkOrderId": {
-                    "type": "string"
-                },
-                "WorkOrderStatus": {
                     "type": "string"
                 }
             }
@@ -14485,11 +14654,17 @@
         "request.AddSalesDetails": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "address": {
                     "type": "string"
                 },
                 "addressee": {
                     "type": "string"
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
                 },
                 "clientId": {
                     "type": "integer"
@@ -14531,6 +14706,9 @@
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
+                },
+                "projectId": {
+                    "type": "string"
                 },
                 "quotationId": {
                     "type": "integer"
@@ -15570,6 +15748,9 @@
         "request.GetContractList": {
             "type": "object",
             "properties": {
+                "keyword": {
+                    "type": "string"
+                },
                 "page": {
                     "description": "椤电爜",
                     "type": "integer"
@@ -15635,6 +15816,12 @@
                 "pageSize": {
                     "description": "姣忛〉澶у皬",
                     "type": "integer"
+                },
+                "principalIds": {
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
                 },
                 "sourceId": {
                     "type": "integer"
@@ -16054,11 +16241,17 @@
         "request.SalesDetails": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "address": {
                     "type": "string"
                 },
                 "addressee": {
                     "type": "string"
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
                 },
                 "clientId": {
                     "type": "integer"
@@ -16100,6 +16293,9 @@
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
+                },
+                "projectId": {
+                    "type": "string"
                 },
                 "quotationId": {
                     "type": "integer"
@@ -16233,6 +16429,17 @@
                             "$ref": "#/definitions/constvar.SalesReturnSourceType"
                         }
                     ]
+                }
+            }
+        },
+        "request.SaveSystemSet": {
+            "type": "object",
+            "properties": {
+                "sets": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/model.SystemSet"
+                    }
                 }
             }
         },
@@ -19096,6 +19303,23 @@
                 }
             }
         },
+        "response.Info": {
+            "type": "object",
+            "properties": {
+                "makeInfo": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/response.WorkOrderInfo"
+                    }
+                },
+                "purchaseInfo": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/response.Purchase"
+                    }
+                }
+            }
+        },
         "response.IsInvoiceResponse": {
             "type": "object",
             "properties": {
@@ -19233,6 +19457,26 @@
                 }
             }
         },
+        "response.Purchase": {
+            "type": "object",
+            "properties": {
+                "amount": {
+                    "type": "integer"
+                },
+                "purchaseName": {
+                    "type": "string"
+                },
+                "purchaseNumber": {
+                    "type": "string"
+                },
+                "status": {
+                    "type": "integer"
+                },
+                "supplierName": {
+                    "type": "string"
+                }
+            }
+        },
         "response.QuotationResponse": {
             "type": "object",
             "properties": {
@@ -19310,6 +19554,18 @@
                     "items": {
                         "$ref": "#/definitions/model.Repository"
                     }
+                }
+            }
+        },
+        "response.Response": {
+            "type": "object",
+            "properties": {
+                "code": {
+                    "type": "integer"
+                },
+                "data": {},
+                "msg": {
+                    "type": "string"
                 }
             }
         },
@@ -19526,6 +19782,32 @@
                     }
                 }
             }
+        },
+        "response.WorkOrderInfo": {
+            "type": "object",
+            "properties": {
+                "endTime": {
+                    "type": "string"
+                },
+                "orderId": {
+                    "type": "string"
+                },
+                "orderStatus": {
+                    "type": "string"
+                },
+                "productName": {
+                    "type": "string"
+                },
+                "startTime": {
+                    "type": "string"
+                },
+                "workOrderId": {
+                    "type": "string"
+                },
+                "workOrderStatus": {
+                    "type": "string"
+                }
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index aa85bd5..cd49b10 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -1118,18 +1118,26 @@
     properties:
       amount:
         type: number
+      cost:
+        type: string
       desc:
         type: string
       id:
         type: integer
+      margin:
+        type: string
       name:
         type: string
       number:
         type: string
       price:
         type: number
+      profit:
+        type: string
       total:
         type: number
+      unit:
+        type: string
     type: object
   model.Province:
     properties:
@@ -1144,6 +1152,9 @@
     type: object
   model.Quotation:
     properties:
+      amountTotal:
+        description: 浠锋牸鍚堣
+        type: number
       client:
         $ref: '#/definitions/model.Client'
       client_id:
@@ -1480,6 +1491,8 @@
         items:
           $ref: '#/definitions/model.Product'
         type: array
+      projectId:
+        type: string
       quotation:
         $ref: '#/definitions/model.Quotation'
       quotationId:
@@ -2107,6 +2120,17 @@
           $ref: '#/definitions/model.Product'
         type: array
     type: object
+  model.SystemSet:
+    properties:
+      id:
+        type: integer
+      modeType:
+        type: string
+      name:
+        type: string
+      value:
+        type: string
+    type: object
   model.TimeSpent:
     properties:
       id:
@@ -2148,6 +2172,9 @@
       pos:
         type: string
       realName:
+        type: string
+      subUserIds:
+        description: 涓嬪睘鍛樺伐鐢ㄦ埛id,鐢ㄩ�楀彿鍒嗗紑
         type: string
       userType:
         $ref: '#/definitions/constvar.UserType'
@@ -2200,23 +2227,6 @@
         description: 鍨嬪彿
         type: string
       Unit:
-        type: string
-    type: object
-  product.WorkOrderInfo:
-    properties:
-      EndTime:
-        type: string
-      OrderId:
-        type: string
-      OrderStatus:
-        type: string
-      ProductName:
-        type: string
-      StartTime:
-        type: string
-      WorkOrderId:
-        type: string
-      WorkOrderStatus:
         type: string
     type: object
   request.AddAccountId:
@@ -2910,10 +2920,14 @@
     type: object
   request.AddSalesDetails:
     properties:
+      Member:
+        $ref: '#/definitions/model.User'
       address:
         type: string
       addressee:
         type: string
+      client:
+        $ref: '#/definitions/model.Client'
       clientId:
         type: integer
       codeStandID:
@@ -2942,6 +2956,8 @@
         items:
           $ref: '#/definitions/model.Product'
         type: array
+      projectId:
+        type: string
       quotationId:
         type: integer
       remark:
@@ -3661,6 +3677,8 @@
     type: object
   request.GetContractList:
     properties:
+      keyword:
+        type: string
       page:
         description: 椤电爜
         type: integer
@@ -3712,6 +3730,10 @@
       pageSize:
         description: 姣忛〉澶у皬
         type: integer
+      principalIds:
+        items:
+          type: integer
+        type: array
       sourceId:
         type: integer
       sourceType:
@@ -4008,10 +4030,14 @@
     type: object
   request.SalesDetails:
     properties:
+      Member:
+        $ref: '#/definitions/model.User'
       address:
         type: string
       addressee:
         type: string
+      client:
+        $ref: '#/definitions/model.Client'
       clientId:
         type: integer
       codeStandID:
@@ -4040,6 +4066,8 @@
         items:
           $ref: '#/definitions/model.Product'
         type: array
+      projectId:
+        type: string
       quotationId:
         type: integer
       remark:
@@ -4129,6 +4157,13 @@
         allOf:
         - $ref: '#/definitions/constvar.SalesReturnSourceType'
         description: 婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級
+    type: object
+  request.SaveSystemSet:
+    properties:
+      sets:
+        items:
+          $ref: '#/definitions/model.SystemSet'
+        type: array
     type: object
   request.SetAuthorityMenu:
     properties:
@@ -6062,6 +6097,17 @@
           $ref: '#/definitions/model.Industry'
         type: array
     type: object
+  response.Info:
+    properties:
+      makeInfo:
+        items:
+          $ref: '#/definitions/response.WorkOrderInfo'
+        type: array
+      purchaseInfo:
+        items:
+          $ref: '#/definitions/response.Purchase'
+        type: array
+    type: object
   response.IsInvoiceResponse:
     properties:
       list:
@@ -6150,6 +6196,19 @@
           $ref: '#/definitions/model.Province'
         type: array
     type: object
+  response.Purchase:
+    properties:
+      amount:
+        type: integer
+      purchaseName:
+        type: string
+      purchaseNumber:
+        type: string
+      status:
+        type: integer
+      supplierName:
+        type: string
+    type: object
   response.QuotationResponse:
     properties:
       count:
@@ -6200,6 +6259,14 @@
         items:
           $ref: '#/definitions/model.Repository'
         type: array
+    type: object
+  response.Response:
+    properties:
+      code:
+        type: integer
+      data: {}
+      msg:
+        type: string
     type: object
   response.SaleChanceResponse:
     properties:
@@ -6337,6 +6404,23 @@
         items:
           $ref: '#/definitions/model.TimelyRate'
         type: array
+    type: object
+  response.WorkOrderInfo:
+    properties:
+      endTime:
+        type: string
+      orderId:
+        type: string
+      orderStatus:
+        type: string
+      productName:
+        type: string
+      startTime:
+        type: string
+      workOrderId:
+        type: string
+      workOrderStatus:
+        type: string
     type: object
 info:
   contact: {}
@@ -9375,9 +9459,7 @@
             - $ref: '#/definitions/contextx.Response'
             - properties:
                 data:
-                  items:
-                    $ref: '#/definitions/product.WorkOrderInfo'
-                  type: array
+                  $ref: '#/definitions/response.Info'
               type: object
       summary: 鑾峰彇浜у搧璁㈠崟淇℃伅
       tags:
@@ -9423,6 +9505,10 @@
       - description: 浜у搧缂栫爜
         in: query
         name: productNumber
+        type: string
+      - description: 鎶ヤ环鍗曠紪鐮�
+        in: query
+        name: quotationNumber
         type: string
       produces:
       - application/json
@@ -9601,6 +9687,25 @@
       summary: 鎶ヤ环鍗曞垪琛�
       tags:
       - Quotation
+  /api/quotation/statistics:
+    get:
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/contextx.Response'
+            - properties:
+                data:
+                  additionalProperties:
+                    type: integer
+                  type: object
+              type: object
+      summary: 鎶ヤ环鍗曠粺璁�
+      tags:
+      - Quotation
   /api/quotation/update:
     put:
       parameters:
@@ -9745,6 +9850,12 @@
         in: query
         name: pageSize
         type: integer
+      - collectionFormat: csv
+        in: query
+        items:
+          type: integer
+        name: principleIds
+        type: array
       - in: query
         name: sourceId
         type: integer
@@ -10618,25 +10729,6 @@
       summary: 娣诲姞閿�鍞槑缁�
       tags:
       - SalesDetails
-  /api/salesDetails/createOperation:
-    post:
-      parameters:
-      - description: 鏌ヨ鍙傛暟
-        in: body
-        name: object
-        required: true
-        schema:
-          $ref: '#/definitions/request.SalesDetails'
-      produces:
-      - application/json
-      responses:
-        "200":
-          description: OK
-          schema:
-            $ref: '#/definitions/response.ListResponse'
-      summary: 鍒涘缓浜у搧鍑哄簱淇℃伅
-      tags:
-      - SalesDetails
   /api/salesDetails/delete:
     delete:
       parameters:
@@ -10672,6 +10764,18 @@
           schema:
             $ref: '#/definitions/contextx.Response'
       summary: 鍒犻櫎閿�鍞槑缁�
+      tags:
+      - SalesDetails
+  /api/salesDetails/getApsProjectList:
+    get:
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/response.Response'
+      summary: 鑾峰彇aps椤圭洰鍒楄〃
       tags:
       - SalesDetails
   /api/salesDetails/getProductInventoryInfo/{number}:
@@ -10714,6 +10818,25 @@
                   $ref: '#/definitions/response.SalesDetailsResponse'
               type: object
       summary: 閿�鍞槑缁嗗崟鍒楄〃
+      tags:
+      - SalesDetails
+  /api/salesDetails/sendSalesDetailsToOtherSystem:
+    post:
+      parameters:
+      - description: 鏌ヨ鍙傛暟
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/request.SalesDetails'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/response.ListResponse'
+      summary: 鎺ㄩ�侀攢鍞槑缁嗕俊鎭埌鍏朵粬绯荤粺
       tags:
       - SalesDetails
   /api/salesDetails/update:
@@ -12344,6 +12467,61 @@
       summary: 鏇存柊瀛愯鍗�
       tags:
       - SubOrder
+  /api/system/getSystemSet:
+    get:
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            allOf:
+            - $ref: '#/definitions/contextx.Response'
+            - properties:
+                data:
+                  additionalProperties: true
+                  type: object
+              type: object
+      summary: 鑾峰彇绯荤粺璁剧疆
+      tags:
+      - 绯荤粺璁剧疆
+  /api/system/saveSystemSet:
+    post:
+      parameters:
+      - description: 鏌ヨ鍙傛暟
+        in: body
+        name: object
+        required: true
+        schema:
+          $ref: '#/definitions/request.SaveSystemSet'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: 鎴愬姛
+          schema:
+            $ref: '#/definitions/contextx.Response'
+      summary: 淇濆瓨绯荤粺璁剧疆
+      tags:
+      - 绯荤粺璁剧疆
+  /api/system/useSystemSet/{modeType}:
+    get:
+      parameters:
+      - description: 鏌ヨ鍙傛暟
+        in: path
+        name: modeType
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/response.ListResponse'
+      summary: 浣跨敤绯荤粺璁剧疆
+      tags:
+      - 绯荤粺璁剧疆
   /api/timeSpent/add:
     post:
       parameters:
diff --git a/main.go b/main.go
index 9bdf14c..bd94e74 100644
--- a/main.go
+++ b/main.go
@@ -6,7 +6,10 @@
 	"aps_crm/initialize"
 	"aps_crm/middleware"
 	"aps_crm/model"
+	"aps_crm/model/grpc_init"
 	"aps_crm/pkg/logx"
+	"aps_crm/proto/client"
+	"aps_crm/proto/crm_aps"
 	"aps_crm/proto/product_inventory"
 	"aps_crm/router"
 	"fmt"
@@ -49,10 +52,9 @@
 		WriteTimeout: 5 * time.Second,
 	}
 	//鍚姩grpc瀹㈡埛绔�
-	go v1.InitProductServiceConn()
 	go middleware.InitUserConn()
-	go v1.InitCodeServiceConn()
 	go v1.InitProductInventoryServiceConn()
+	go grpc_init.InitCrmApsGrpcServiceConn()
 	//鍚姩grpc鏈嶅姟
 	go func() {
 		ln, err := net.Listen("tcp", ":"+conf.Conf.System.GrpcPort)
@@ -63,6 +65,8 @@
 		s := grpc.NewServer()
 		//todo 娣诲姞鍏蜂綋鏈嶅姟
 		product_inventory.RegisterProductInventoryServiceServer(s, &product_inventory.Server{})
+		crm_aps.RegisterCrmAndApsGrpcServiceServer(s, &crm_aps.Server{})
+		client.RegisterClientServiceServer(s, &client.Server{})
 		err = s.Serve(ln)
 		if err != nil {
 			logx.Errorf("grpc server init error: %v", err.Error())
@@ -82,10 +86,9 @@
 	<-quit
 
 	middleware.StopRefreshUser()
-	v1.CloseProductServiceConn()
-	v1.CloseCodeServiceConn()
 	v1.CloseProductInventoryServiceConn()
 	middleware.CloseUserConn()
+	grpc_init.CloseCrmApsGrpcServiceConn()
 
 	logx.Infof("aps-crm exited...")
 	os.Exit(0)
diff --git a/model/client.go b/model/client.go
index dea1044..2f40162 100644
--- a/model/client.go
+++ b/model/client.go
@@ -241,3 +241,11 @@
 	slf.Orm = slf.Orm.Where("id in (?)", ids)
 	return slf
 }
+
+func (slf *ClientSearch) FindAll() ([]*Client, error) {
+	var db = slf.build()
+	var records = make([]*Client, 0)
+
+	err := db.Find(&records).Error
+	return records, err
+}
diff --git a/model/contract.go b/model/contract.go
index e437c6c..92bd5e7 100644
--- a/model/contract.go
+++ b/model/contract.go
@@ -28,7 +28,7 @@
 
 	ContractSearch struct {
 		Contract
-
+		Keyword   string
 		Orm       *gorm.DB
 		SearchMap map[string]interface{}
 		OrderBy   string
@@ -47,6 +47,11 @@
 	}
 }
 
+func (slf *ContractSearch) SetKeyword(keyword string) *ContractSearch {
+	slf.Keyword = keyword
+	return slf
+}
+
 func (slf *ContractSearch) build() *gorm.DB {
 	var db = slf.Orm.Model(&Contract{})
 
@@ -55,6 +60,10 @@
 	}
 	if slf.Number != "" {
 		db = db.Where("number = ?", slf.Number)
+	}
+
+	if slf.Keyword != "" {
+		db = db.Joins("Client").Where("contract_name like ? or contract.number like ? or Client.name like ?", fmt.Sprintf("%%%v%%", slf.Keyword), fmt.Sprintf("%%%v%%", slf.Keyword), fmt.Sprintf("%%%v%%", slf.Keyword))
 	}
 
 	if len(slf.SearchMap) > 0 {
@@ -76,6 +85,10 @@
 				if key == "created_at" {
 					db = db.Where(key+"= ?", v)
 				}
+
+				if key == "contract_name" {
+					db = db.Where("contract_name=?", "%"+v+"%")
+				}
 			case int:
 				if key == "member_id" {
 					db = db.Where(key+"= ?", v)
diff --git a/model/grpc_init/crm_aps_init.go b/model/grpc_init/crm_aps_init.go
new file mode 100644
index 0000000..6e82ec6
--- /dev/null
+++ b/model/grpc_init/crm_aps_init.go
@@ -0,0 +1,25 @@
+package grpc_init
+
+import (
+	"aps_crm/conf"
+	"aps_crm/pkg/logx"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
+)
+
+var CrmApsGrpcServiceConn *grpc.ClientConn
+
+func InitCrmApsGrpcServiceConn() {
+	var err error
+	CrmApsGrpcServiceConn, err = grpc.Dial(conf.Conf.GrpcServiceAddr.Aps, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		logx.Errorf("grpc dial InitCrmApsGrpcServiceConn service error: %v", err.Error())
+		return
+	}
+}
+
+func CloseCrmApsGrpcServiceConn() {
+	if CrmApsGrpcServiceConn != nil {
+		CrmApsGrpcServiceConn.Close()
+	}
+}
diff --git a/model/index.go b/model/index.go
index 2258728..f526a3b 100644
--- a/model/index.go
+++ b/model/index.go
@@ -95,6 +95,7 @@
 		InvoiceType{},
 		Invoice{},
 		RefundType{},
+		SystemSet{},
 	)
 	return err
 }
diff --git a/model/product.go b/model/product.go
index 2880731..a656777 100644
--- a/model/product.go
+++ b/model/product.go
@@ -15,6 +15,10 @@
 		Amount     decimal.Decimal `json:"amount" gorm:"column:amount;type:decimal(12,2);comment:浜у搧鏁伴噺"`
 		Total      decimal.Decimal `json:"total" gorm:"column:total;type:decimal(10,2);comment:浜у搧鎬讳环"`
 		Desc       string          `json:"desc" gorm:"column:desc;type:varchar(255);comment:浜у搧鎻忚堪"`
+		Unit       string          `json:"unit" gorm:"column:unit;type:varchar(255);comment:鍗曚綅"`
+		Cost       string          `json:"cost" gorm:"column:cost;type:varchar(255);comment:浜у搧鎴愭湰"`
+		Profit     string          `json:"profit" gorm:"column:profit;type:varchar(255);comment:姣涘埄"`
+		Margin     string          `json:"margin" gorm:"column:margin;type:varchar(255);comment:姣涘埄鐜�"`
 		gorm.Model `json:"-"`
 	}
 
diff --git a/model/quotation.go b/model/quotation.go
index 1c45c24..c4618ee 100644
--- a/model/quotation.go
+++ b/model/quotation.go
@@ -3,6 +3,7 @@
 import (
 	"aps_crm/pkg/mysqlx"
 	"fmt"
+	"github.com/shopspring/decimal"
 	"gorm.io/gorm"
 )
 
@@ -27,6 +28,7 @@
 		SaleChance        SaleChance      `json:"sale_chance" gorm:"foreignKey:SaleChanceId"`
 		Products          []Product       `json:"products" gorm:"many2many:quotation_product"`
 		CodeStandID       string          `json:"codeStandID" gorm:"column:code_stand_id;type:varchar(255);comment:缂栫爜id"`
+		AmountTotal       decimal.Decimal `gorm:"-" json:"amountTotal"` //浠锋牸鍚堣
 		gorm.Model        `json:"-"`
 	}
 
@@ -62,6 +64,9 @@
 	}
 	if slf.Number != "" {
 		db = db.Where("number = ?", slf.Number)
+	}
+	if slf.QuotationStatusId != 0 {
+		db = db.Where("quotation_status_id = ?", slf.QuotationStatusId)
 	}
 
 	if len(slf.SearchMap) > 0 {
@@ -132,7 +137,7 @@
 		db = db.Limit(slf.PageSize).Offset((slf.PageNum - 1) * slf.PageSize)
 	}
 
-	err := db.Preload("Products").Preload("Member").Preload("QuotationStatus").Preload("Client").Preload("Contact").Order("id desc").Find(&records).Error
+	err := db.Preload("Products").Preload("Member").Preload("QuotationStatus").Preload("Client").Preload("Contact").Preload("SaleChance").Order("id desc").Find(&records).Error
 	return records, total, err
 }
 
@@ -189,7 +194,13 @@
 	slf.Number = number
 	return slf
 }
+
 func (slf *QuotationSearch) SetIds(ids []int) *QuotationSearch {
 	slf.Orm = slf.Orm.Where("id in (?)", ids)
 	return slf
 }
+
+func (slf *QuotationSearch) SetQuotationStatusId(id int) *QuotationSearch {
+	slf.QuotationStatusId = id
+	return slf
+}
diff --git a/model/request/contract.go b/model/request/contract.go
index ef09ea2..acc26ef 100644
--- a/model/request/contract.go
+++ b/model/request/contract.go
@@ -24,6 +24,7 @@
 type GetContractList struct {
 	PageInfo
 	SearchMap map[string]interface{} `json:"search_map"` // 鎼滅储鏉′欢: map[string]interface{} {"member_name": "閿�鍞礋璐d汉", "number": "鍚堝悓缂栧彿", "created_at": "鍒涘缓鏃堕棿"}
+	Keyword   string                 `json:"keyword"`
 }
 
 type DeleteContract struct {
diff --git a/model/request/product.go b/model/request/product.go
index a81e429..1cce9d0 100644
--- a/model/request/product.go
+++ b/model/request/product.go
@@ -2,6 +2,7 @@
 
 type GetProductList struct {
 	PageInfo
-	ProductNumber string `json:"productNumber" form:"productNumber"` // 浜у搧缂栫爜
-	ProductName   string `json:"productName" form:"productName"`     // 浜у搧鍚嶇О
+	ProductNumber   string `json:"productNumber" form:"productNumber"`     // 浜у搧缂栫爜
+	ProductName     string `json:"productName" form:"productName"`         // 浜у搧鍚嶇О
+	QuotationNumber string `json:"quotationNumber" form:"quotationNumber"` //鎶ヤ环鍗曠紪鐮�
 }
diff --git a/model/request/salesDetails.go b/model/request/salesDetails.go
index 4915b69..ed2b4b6 100644
--- a/model/request/salesDetails.go
+++ b/model/request/salesDetails.go
@@ -11,11 +11,13 @@
 
 type SalesDetails struct {
 	ClientId            int                         `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
+	Client              model.Client                `json:"client" gorm:"foreignKey:ClientId"`
 	Number              string                      `json:"number" gorm:"column:number;type:varchar(255);comment:閿�鍞槑缁嗗崟鍙�"`
 	SaleChanceId        int                         `json:"saleChanceId" gorm:"column:sale_chance_id;type:int;comment:閿�鍞満浼歩d"`
 	SaleType            int                         `json:"saleType" gorm:"column:sale_type;type:int;comment:閿�鍞被鍨�"`
 	SignTime            string                      `json:"signTime" gorm:"column:sign_time;type:datetime;comment:绛惧崟鏃堕棿"`
 	MemberId            int                         `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
+	Member              model.User                  `json:"Member"  gorm:"foreignKey:MemberId"`
 	DeliveryDate        string                      `json:"deliveryDate" gorm:"column:delivery_date;type:datetime;comment:浜よ揣鏃ユ湡"`
 	WechatOrderStatusId int                         `json:"wechatOrderStatusId" gorm:"column:wechat_order_status_id;type:int;comment:寰俊璁㈠崟鐘舵�乮d"`
 	Address             string                      `json:"address" gorm:"column:address;type:varchar(255);comment:鍦板潃"`
@@ -32,6 +34,7 @@
 	QuotationId         int                         `json:"quotationId" gorm:"column:quotation_id;type:int;comment:鎶ヤ环鍗昳d"`
 	Status              constvar.SalesDetailsStatus `json:"status" gorm:"column:status;type:int;comment:鐘舵��"`
 	Source              string                      `json:"source" gorm:"column:source;type:varchar(255);comment:璁㈠崟鏉ユ簮"`
+	ProjectId           string                      `json:"projectId" gorm:"column:project_id;type:varchar(255);comment:aps椤圭洰id"`
 }
 
 type UpdateSalesDetails struct {
diff --git a/model/request/system_set_request.go b/model/request/system_set_request.go
new file mode 100644
index 0000000..326aa7e
--- /dev/null
+++ b/model/request/system_set_request.go
@@ -0,0 +1,7 @@
+package request
+
+import "aps_crm/model"
+
+type SaveSystemSet struct {
+	Sets []*model.SystemSet `json:"sets"`
+}
diff --git a/model/response/salesDetails.go b/model/response/salesDetails.go
new file mode 100644
index 0000000..2c57379
--- /dev/null
+++ b/model/response/salesDetails.go
@@ -0,0 +1,39 @@
+package response
+
+type Info struct {
+	MakeInfo     []WorkOrderInfo `json:"makeInfo"`
+	PurchaseInfo []Purchase      `json:"purchaseInfo"`
+}
+
+type WorkOrderInfo struct {
+	OrderId         string `json:"orderId"`
+	ProductName     string `json:"productName"`
+	OrderStatus     string `json:"orderStatus"`
+	WorkOrderId     string `json:"workOrderId"`
+	WorkOrderStatus string `json:"workOrderStatus"`
+	StartTime       string `json:"startTime"`
+	EndTime         string `json:"endTime"`
+}
+
+type Purchase struct {
+	PurchaseNumber string `json:"purchaseNumber"`
+	PurchaseName   string `json:"purchaseName"`
+	SupplierName   string `json:"supplierName"`
+	Amount         int64  `json:"amount"`
+	Status         int64  `json:"status"`
+}
+
+type ProductInfo 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"`          //鍦ㄥ簱鏁伴噺
+	AvailableNumber string `json:"availableNumber"` //鍙敤搴撳瓨
+}
diff --git a/model/salesDetails.go b/model/salesDetails.go
index d45be06..0d92c39 100644
--- a/model/salesDetails.go
+++ b/model/salesDetails.go
@@ -45,6 +45,7 @@
 		Quotation           Quotation                   `json:"quotation" gorm:"foreignKey:QuotationId"`
 		Status              constvar.SalesDetailsStatus `json:"status" gorm:"column:status;type:int;comment:鐘舵��"`
 		Source              string                      `json:"source" gorm:"column:source;type:varchar(255);comment:璁㈠崟鏉ユ簮"`
+		ProjectId           string                      `json:"projectId" gorm:"column:project_id;type:varchar(255);comment:aps椤圭洰id"`
 		CrmModel
 	}
 
@@ -58,6 +59,7 @@
 		PageSize    int
 		Preload     bool
 		MemberIds   []int
+		Numbers     []string
 	}
 )
 
@@ -86,6 +88,9 @@
 	}
 	if slf.Number != "" {
 		db = db.Where("number = ?", slf.Number)
+	}
+	if len(slf.Numbers) > 0 {
+		db = db.Where("number in (?)", slf.Numbers)
 	}
 
 	switch slf.KeywordType {
@@ -163,21 +168,6 @@
 	return result.Max, nil
 }
 
-func (slf *SalesDetailsSearch) SetId(id int) *SalesDetailsSearch {
-	slf.Id = id
-	return slf
-}
-
-func (slf *SalesDetailsSearch) SetClientId(clientId int) *SalesDetailsSearch {
-	slf.ClientId = clientId
-	return slf
-}
-
-func (slf *SalesDetailsSearch) SetSaleChanceId(saleChanceId int) *SalesDetailsSearch {
-	slf.SaleChanceId = saleChanceId
-	return slf
-}
-
 func (slf *SalesDetailsSearch) First() (*SalesDetails, error) {
 	var db = slf.build()
 	var record = new(SalesDetails)
@@ -196,12 +186,31 @@
 		db = db.Limit(slf.PageSize).Offset((slf.PageNum - 1) * slf.PageSize)
 	}
 
-	if slf.PageNum > 0 && slf.PageSize > 0 {
-		db = db.Limit(slf.PageSize).Offset((slf.PageNum - 1) * slf.PageSize)
-	}
-
 	err := db.Order("id desc").Find(&records).Error
 	return records, total, err
+}
+
+func (slf *SalesDetailsSearch) FindNotTotal() ([]*SalesDetails, error) {
+	var db = slf.build()
+	var records = make([]*SalesDetails, 0)
+
+	err := db.Order("id desc").Find(&records).Error
+	return records, err
+}
+
+func (slf *SalesDetailsSearch) SetId(id int) *SalesDetailsSearch {
+	slf.Id = id
+	return slf
+}
+
+func (slf *SalesDetailsSearch) SetClientId(clientId int) *SalesDetailsSearch {
+	slf.ClientId = clientId
+	return slf
+}
+
+func (slf *SalesDetailsSearch) SetSaleChanceId(saleChanceId int) *SalesDetailsSearch {
+	slf.SaleChanceId = saleChanceId
+	return slf
 }
 
 func (slf *SalesDetailsSearch) SetKeyword(keyword string) *SalesDetailsSearch {
@@ -239,6 +248,11 @@
 	return slf
 }
 
+func (slf *SalesDetailsSearch) SetNumbers(numbers []string) *SalesDetailsSearch {
+	slf.Numbers = numbers
+	return slf
+}
+
 func (slf *SalesDetailsSearch) UpdateByMap(upMap map[string]interface{}) error {
 	var (
 		db = slf.build()
diff --git a/model/system_set.go b/model/system_set.go
new file mode 100644
index 0000000..d623e96
--- /dev/null
+++ b/model/system_set.go
@@ -0,0 +1,97 @@
+package model
+
+import (
+	"aps_crm/pkg/mysqlx"
+	"fmt"
+	"gorm.io/gorm"
+)
+
+type (
+	SystemSet struct {
+		Id       int    `json:"id" gorm:"column:id;primaryKey;autoIncrement;not null"`
+		Name     string `json:"name" gorm:"type:varchar(255);comment:鍚嶇О"`
+		Value    string `json:"value" gorm:"type:varchar(255);comment:鍊�"`
+		ModeType string `json:"modeType" gorm:"type:varchar(255);comment:妯″潡绫诲瀷"`
+	}
+	SystemSetSearch struct {
+		SystemSet
+		Orm *gorm.DB
+	}
+)
+
+func (slf SystemSet) TableName() string {
+	return "system_set"
+}
+
+func NewSystemSetSearch() *SystemSetSearch {
+	return &SystemSetSearch{Orm: mysqlx.GetDB()}
+}
+
+func (slf *SystemSetSearch) SetOrm(tx *gorm.DB) *SystemSetSearch {
+	slf.Orm = tx
+	return slf
+}
+func (slf *SystemSetSearch) SetName(name string) *SystemSetSearch {
+	slf.Name = name
+	return slf
+}
+func (slf *SystemSetSearch) SetModeType(modeType string) *SystemSetSearch {
+	slf.ModeType = modeType
+	return slf
+}
+
+func (slf *SystemSetSearch) build() *gorm.DB {
+	var db = slf.Orm.Table(slf.TableName())
+
+	if slf.Name != "" {
+		db = db.Where("name = ?", slf.Name)
+	}
+	if slf.ModeType != "" {
+		db = db.Where("mode_type = ?", slf.ModeType)
+	}
+
+	return db
+}
+
+// CreateBatch 鎵归噺鎻掑叆
+func (slf *SystemSetSearch) CreateBatch(records []*SystemSet) error {
+	var db = slf.build()
+
+	if err := db.Create(&records).Error; err != nil {
+		return fmt.Errorf("create batch err: %v, records: %+v", err, records)
+	}
+
+	return nil
+}
+
+func (slf *SystemSetSearch) DeleteAll() (err error) {
+	var db = slf.build()
+	err = db.Where("1=1").Delete(&SystemSet{}).Error
+	return err
+}
+
+func (slf *SystemSetSearch) First() (*SystemSet, error) {
+	var (
+		record = new(SystemSet)
+		db     = slf.build()
+	)
+
+	if err := db.First(record).Error; err != nil {
+		return record, err
+	}
+
+	return record, nil
+}
+
+func (slf *SystemSetSearch) FindAll() ([]*SystemSet, error) {
+	var (
+		records = make([]*SystemSet, 0)
+		db      = slf.build()
+	)
+
+	if err := db.Find(&records).Error; err != nil {
+		return records, fmt.Errorf("find records err: %v", err)
+	}
+
+	return records, nil
+}
diff --git a/proto/client.proto b/proto/client.proto
new file mode 100644
index 0000000..c374a41
--- /dev/null
+++ b/proto/client.proto
@@ -0,0 +1,20 @@
+syntax = "proto3";
+
+option go_package = "./client";
+
+service ClientService {
+  rpc GetClientList(ClientListRequest) returns (ClientListResponse);
+}
+
+message ClientListRequest {
+
+}
+
+message ClientInfo {
+  int32 ClientId =1;
+  string ClientName =2;
+}
+
+message ClientListResponse {
+  repeated ClientInfo List =1;
+}
\ No newline at end of file
diff --git a/proto/client/client.pb.go b/proto/client/client.pb.go
new file mode 100644
index 0000000..b162ae7
--- /dev/null
+++ b/proto/client/client.pb.go
@@ -0,0 +1,275 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.30.0
+// 	protoc        v3.8.0
+// source: client.proto
+
+package client
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type ClientListRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *ClientListRequest) Reset() {
+	*x = ClientListRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_client_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientListRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientListRequest) ProtoMessage() {}
+
+func (x *ClientListRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_client_proto_msgTypes[0]
+	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 ClientListRequest.ProtoReflect.Descriptor instead.
+func (*ClientListRequest) Descriptor() ([]byte, []int) {
+	return file_client_proto_rawDescGZIP(), []int{0}
+}
+
+type ClientInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ClientId   int32  `protobuf:"varint,1,opt,name=ClientId,proto3" json:"ClientId,omitempty"`
+	ClientName string `protobuf:"bytes,2,opt,name=ClientName,proto3" json:"ClientName,omitempty"`
+}
+
+func (x *ClientInfo) Reset() {
+	*x = ClientInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_client_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientInfo) ProtoMessage() {}
+
+func (x *ClientInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_client_proto_msgTypes[1]
+	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 ClientInfo.ProtoReflect.Descriptor instead.
+func (*ClientInfo) Descriptor() ([]byte, []int) {
+	return file_client_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *ClientInfo) GetClientId() int32 {
+	if x != nil {
+		return x.ClientId
+	}
+	return 0
+}
+
+func (x *ClientInfo) GetClientName() string {
+	if x != nil {
+		return x.ClientName
+	}
+	return ""
+}
+
+type ClientListResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	List []*ClientInfo `protobuf:"bytes,1,rep,name=List,proto3" json:"List,omitempty"`
+}
+
+func (x *ClientListResponse) Reset() {
+	*x = ClientListResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_client_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientListResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientListResponse) ProtoMessage() {}
+
+func (x *ClientListResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_client_proto_msgTypes[2]
+	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 ClientListResponse.ProtoReflect.Descriptor instead.
+func (*ClientListResponse) Descriptor() ([]byte, []int) {
+	return file_client_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ClientListResponse) GetList() []*ClientInfo {
+	if x != nil {
+		return x.List
+	}
+	return nil
+}
+
+var File_client_proto protoreflect.FileDescriptor
+
+var file_client_proto_rawDesc = []byte{
+	0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13,
+	0x0a, 0x11, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66,
+	0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x05, 0x52, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1e, 0x0a,
+	0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x35, 0x0a,
+	0x12, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x0b, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04,
+	0x4c, 0x69, 0x73, 0x74, 0x32, 0x49, 0x0a, 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c,
+	0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x43, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
+	0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
+}
+
+var (
+	file_client_proto_rawDescOnce sync.Once
+	file_client_proto_rawDescData = file_client_proto_rawDesc
+)
+
+func file_client_proto_rawDescGZIP() []byte {
+	file_client_proto_rawDescOnce.Do(func() {
+		file_client_proto_rawDescData = protoimpl.X.CompressGZIP(file_client_proto_rawDescData)
+	})
+	return file_client_proto_rawDescData
+}
+
+var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_client_proto_goTypes = []interface{}{
+	(*ClientListRequest)(nil),  // 0: ClientListRequest
+	(*ClientInfo)(nil),         // 1: ClientInfo
+	(*ClientListResponse)(nil), // 2: ClientListResponse
+}
+var file_client_proto_depIdxs = []int32{
+	1, // 0: ClientListResponse.List:type_name -> ClientInfo
+	0, // 1: ClientService.GetClientList:input_type -> ClientListRequest
+	2, // 2: ClientService.GetClientList:output_type -> ClientListResponse
+	2, // [2:3] is the sub-list for method output_type
+	1, // [1:2] is the sub-list for method input_type
+	1, // [1:1] is the sub-list for extension type_name
+	1, // [1:1] is the sub-list for extension extendee
+	0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_client_proto_init() }
+func file_client_proto_init() {
+	if File_client_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientListRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_client_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_client_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientListResponse); 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_client_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   3,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_client_proto_goTypes,
+		DependencyIndexes: file_client_proto_depIdxs,
+		MessageInfos:      file_client_proto_msgTypes,
+	}.Build()
+	File_client_proto = out.File
+	file_client_proto_rawDesc = nil
+	file_client_proto_goTypes = nil
+	file_client_proto_depIdxs = nil
+}
diff --git a/proto/client/client_grpc.pb.go b/proto/client/client_grpc.pb.go
new file mode 100644
index 0000000..c161f18
--- /dev/null
+++ b/proto/client/client_grpc.pb.go
@@ -0,0 +1,109 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc             v3.8.0
+// source: client.proto
+
+package client
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+const (
+	ClientService_GetClientList_FullMethodName = "/ClientService/GetClientList"
+)
+
+// ClientServiceClient is the client API for ClientService 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.
+type ClientServiceClient interface {
+	GetClientList(ctx context.Context, in *ClientListRequest, opts ...grpc.CallOption) (*ClientListResponse, error)
+}
+
+type clientServiceClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewClientServiceClient(cc grpc.ClientConnInterface) ClientServiceClient {
+	return &clientServiceClient{cc}
+}
+
+func (c *clientServiceClient) GetClientList(ctx context.Context, in *ClientListRequest, opts ...grpc.CallOption) (*ClientListResponse, error) {
+	out := new(ClientListResponse)
+	err := c.cc.Invoke(ctx, ClientService_GetClientList_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// ClientServiceServer is the server API for ClientService service.
+// All implementations must embed UnimplementedClientServiceServer
+// for forward compatibility
+type ClientServiceServer interface {
+	GetClientList(context.Context, *ClientListRequest) (*ClientListResponse, error)
+	mustEmbedUnimplementedClientServiceServer()
+}
+
+// UnimplementedClientServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedClientServiceServer struct {
+}
+
+func (UnimplementedClientServiceServer) GetClientList(context.Context, *ClientListRequest) (*ClientListResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetClientList not implemented")
+}
+func (UnimplementedClientServiceServer) mustEmbedUnimplementedClientServiceServer() {}
+
+// UnsafeClientServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to ClientServiceServer will
+// result in compilation errors.
+type UnsafeClientServiceServer interface {
+	mustEmbedUnimplementedClientServiceServer()
+}
+
+func RegisterClientServiceServer(s grpc.ServiceRegistrar, srv ClientServiceServer) {
+	s.RegisterService(&ClientService_ServiceDesc, srv)
+}
+
+func _ClientService_GetClientList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientListRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ClientServiceServer).GetClientList(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: ClientService_GetClientList_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ClientServiceServer).GetClientList(ctx, req.(*ClientListRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// ClientService_ServiceDesc is the grpc.ServiceDesc for ClientService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var ClientService_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "ClientService",
+	HandlerType: (*ClientServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "GetClientList",
+			Handler:    _ClientService_GetClientList_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "client.proto",
+}
diff --git a/proto/client/server.go b/proto/client/server.go
new file mode 100644
index 0000000..cb42484
--- /dev/null
+++ b/proto/client/server.go
@@ -0,0 +1,22 @@
+package client
+
+import (
+	"aps_crm/model"
+	"context"
+)
+
+type Server struct {
+	UnimplementedClientServiceServer
+}
+
+func (s *Server) GetClientList(c context.Context, req *ClientListRequest) (*ClientListResponse, error) {
+	resp := new(ClientListResponse)
+	clientList, err := model.NewClientSearch(nil).FindAll()
+	if err != nil {
+		return resp, err
+	}
+	for _, v := range clientList {
+		resp.List = append(resp.List, &ClientInfo{ClientId: int32(v.Id), ClientName: v.Name})
+	}
+	return resp, nil
+}
diff --git a/proto/crm_aps.proto b/proto/crm_aps.proto
new file mode 100644
index 0000000..f740c1c
--- /dev/null
+++ b/proto/crm_aps.proto
@@ -0,0 +1,83 @@
+syntax = "proto3";
+
+option go_package = "./crm_aps";
+
+service CrmAndApsGrpcService {
+  rpc GetApsProjectList(GetApsProjectListRequest) returns(GetApsProjectListResponse) {}
+  rpc SendSalesDetailsToApsProject(SendSalesDetailsToApsProjectRequest) returns(SendSalesDetailsToApsProjectResponse) {}
+  rpc GetCrmSalesDetailsList(GetCrmSalesDetailsListRequest) returns(GetCrmSalesDetailsListResponse) {}
+  rpc SendSalesDetailsAndProjectToCrm(SendSalesDetailsAndProjectToCrmRequest) returns(SendSalesDetailsAndProjectToCrmResponse) {}
+}
+
+//-----------------------------------------------------GetApsProjectList--------------------------------------
+
+message GetApsProjectListRequest{
+}
+
+message ApsProject{
+  string projectId = 1;
+  string projectName = 2;
+}
+
+message GetApsProjectListResponse{
+  repeated ApsProject List = 1;
+}
+
+//-----------------------------------------------------SendSalesDetailsToApsProject---------------------------------------
+
+message SalesDetailsProduct {
+  string ProductId = 1;
+  int64 Amount = 2;
+}
+
+message SendSalesDetailsToApsProjectRequest{
+  string Number = 1;//閿�鍞槑缁嗗崟鍙�
+  string ClientName = 2;
+  string MemberName = 3;//閿�鍞礋璐d汉
+  string SignTime = 4;//绛惧崟鏃堕棿
+  string DeliveryDate = 5;//浜よ揣鏃ユ湡
+  string Source = 6;//璁㈠崟鏉ユ簮
+  int64 ProductTotal = 7;//浜у搧鎬绘暟
+  string ProjectId = 8;//椤圭洰id
+  repeated SalesDetailsProduct Products = 9;
+}
+
+message SendSalesDetailsToApsProjectResponse{
+}
+
+//-----------------------------------------------------GetCrmSalesDetailsList--------------------------------------------
+
+message GetCrmSalesDetailsListRequest {
+  string TimeType = 1;  //鏃堕棿绫诲瀷:绛剧害鏃ユ湡,浜や粯鏃ユ湡
+  string StartTime = 2;
+  string EndTime = 3;
+  string ClientName = 4;
+  int64 Page = 5;
+  int64 PageSize = 6;
+}
+
+message CrmSalesDetails {
+  string number = 1;//閿�鍞槑缁嗗崟鍙�
+  string clientName = 2;
+  string memberName = 3;//閿�鍞礋璐d汉
+  string signTime = 4;//绛惧崟鏃堕棿
+  string deliveryDate = 5;//浜よ揣鏃ユ湡
+}
+
+message GetCrmSalesDetailsListResponse {
+  repeated CrmSalesDetails SalesDetails = 1;
+  int64 Total = 2;
+}
+
+//------------------------------------------------------------SendSalesDetailsAndProjectToCrm-----------------------------------
+
+message SendSalesDetailsAndProjectToCrmRequest{
+  repeated string SalesDetailsNumbers = 1;
+  string ProjectId = 2;
+}
+
+message SendSalesDetailsAndProjectToCrmResponse{
+
+}
+
+
diff --git a/proto/crm_aps/crm_aps.pb.go b/proto/crm_aps/crm_aps.pb.go
new file mode 100644
index 0000000..dd584ea
--- /dev/null
+++ b/proto/crm_aps/crm_aps.pb.go
@@ -0,0 +1,996 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.26.0
+// 	protoc        v4.24.0
+// source: crm_aps.proto
+
+package crm_aps
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type GetApsProjectListRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *GetApsProjectListRequest) Reset() {
+	*x = GetApsProjectListRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetApsProjectListRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetApsProjectListRequest) ProtoMessage() {}
+
+func (x *GetApsProjectListRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[0]
+	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 GetApsProjectListRequest.ProtoReflect.Descriptor instead.
+func (*GetApsProjectListRequest) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{0}
+}
+
+type ApsProject struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ProjectId   string `protobuf:"bytes,1,opt,name=projectId,proto3" json:"projectId,omitempty"`
+	ProjectName string `protobuf:"bytes,2,opt,name=projectName,proto3" json:"projectName,omitempty"`
+}
+
+func (x *ApsProject) Reset() {
+	*x = ApsProject{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ApsProject) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ApsProject) ProtoMessage() {}
+
+func (x *ApsProject) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[1]
+	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 ApsProject.ProtoReflect.Descriptor instead.
+func (*ApsProject) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *ApsProject) GetProjectId() string {
+	if x != nil {
+		return x.ProjectId
+	}
+	return ""
+}
+
+func (x *ApsProject) GetProjectName() string {
+	if x != nil {
+		return x.ProjectName
+	}
+	return ""
+}
+
+type GetApsProjectListResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	List []*ApsProject `protobuf:"bytes,1,rep,name=List,proto3" json:"List,omitempty"`
+}
+
+func (x *GetApsProjectListResponse) Reset() {
+	*x = GetApsProjectListResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetApsProjectListResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetApsProjectListResponse) ProtoMessage() {}
+
+func (x *GetApsProjectListResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[2]
+	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 GetApsProjectListResponse.ProtoReflect.Descriptor instead.
+func (*GetApsProjectListResponse) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *GetApsProjectListResponse) GetList() []*ApsProject {
+	if x != nil {
+		return x.List
+	}
+	return nil
+}
+
+type SalesDetailsProduct struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	ProductId string `protobuf:"bytes,1,opt,name=ProductId,proto3" json:"ProductId,omitempty"`
+	Amount    int64  `protobuf:"varint,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
+}
+
+func (x *SalesDetailsProduct) Reset() {
+	*x = SalesDetailsProduct{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SalesDetailsProduct) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SalesDetailsProduct) ProtoMessage() {}
+
+func (x *SalesDetailsProduct) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[3]
+	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 SalesDetailsProduct.ProtoReflect.Descriptor instead.
+func (*SalesDetailsProduct) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *SalesDetailsProduct) GetProductId() string {
+	if x != nil {
+		return x.ProductId
+	}
+	return ""
+}
+
+func (x *SalesDetailsProduct) GetAmount() int64 {
+	if x != nil {
+		return x.Amount
+	}
+	return 0
+}
+
+type SendSalesDetailsToApsProjectRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Number       string                 `protobuf:"bytes,1,opt,name=Number,proto3" json:"Number,omitempty"` //閿�鍞槑缁嗗崟鍙�
+	ClientName   string                 `protobuf:"bytes,2,opt,name=ClientName,proto3" json:"ClientName,omitempty"`
+	MemberName   string                 `protobuf:"bytes,3,opt,name=MemberName,proto3" json:"MemberName,omitempty"`      //閿�鍞礋璐d汉
+	SignTime     string                 `protobuf:"bytes,4,opt,name=SignTime,proto3" json:"SignTime,omitempty"`          //绛惧崟鏃堕棿
+	DeliveryDate string                 `protobuf:"bytes,5,opt,name=DeliveryDate,proto3" json:"DeliveryDate,omitempty"`  //浜よ揣鏃ユ湡
+	Source       string                 `protobuf:"bytes,6,opt,name=Source,proto3" json:"Source,omitempty"`              //璁㈠崟鏉ユ簮
+	ProductTotal int64                  `protobuf:"varint,7,opt,name=ProductTotal,proto3" json:"ProductTotal,omitempty"` //浜у搧鎬绘暟
+	ProjectId    string                 `protobuf:"bytes,8,opt,name=ProjectId,proto3" json:"ProjectId,omitempty"`        //椤圭洰id
+	Products     []*SalesDetailsProduct `protobuf:"bytes,9,rep,name=Products,proto3" json:"Products,omitempty"`
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) Reset() {
+	*x = SendSalesDetailsToApsProjectRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendSalesDetailsToApsProjectRequest) ProtoMessage() {}
+
+func (x *SendSalesDetailsToApsProjectRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[4]
+	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 SendSalesDetailsToApsProjectRequest.ProtoReflect.Descriptor instead.
+func (*SendSalesDetailsToApsProjectRequest) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetNumber() string {
+	if x != nil {
+		return x.Number
+	}
+	return ""
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetClientName() string {
+	if x != nil {
+		return x.ClientName
+	}
+	return ""
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetMemberName() string {
+	if x != nil {
+		return x.MemberName
+	}
+	return ""
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetSignTime() string {
+	if x != nil {
+		return x.SignTime
+	}
+	return ""
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetDeliveryDate() string {
+	if x != nil {
+		return x.DeliveryDate
+	}
+	return ""
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetSource() string {
+	if x != nil {
+		return x.Source
+	}
+	return ""
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetProductTotal() int64 {
+	if x != nil {
+		return x.ProductTotal
+	}
+	return 0
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetProjectId() string {
+	if x != nil {
+		return x.ProjectId
+	}
+	return ""
+}
+
+func (x *SendSalesDetailsToApsProjectRequest) GetProducts() []*SalesDetailsProduct {
+	if x != nil {
+		return x.Products
+	}
+	return nil
+}
+
+type SendSalesDetailsToApsProjectResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *SendSalesDetailsToApsProjectResponse) Reset() {
+	*x = SendSalesDetailsToApsProjectResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SendSalesDetailsToApsProjectResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendSalesDetailsToApsProjectResponse) ProtoMessage() {}
+
+func (x *SendSalesDetailsToApsProjectResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[5]
+	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 SendSalesDetailsToApsProjectResponse.ProtoReflect.Descriptor instead.
+func (*SendSalesDetailsToApsProjectResponse) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{5}
+}
+
+type GetCrmSalesDetailsListRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	TimeType   string `protobuf:"bytes,1,opt,name=TimeType,proto3" json:"TimeType,omitempty"` //鏃堕棿绫诲瀷:绛剧害鏃ユ湡,浜や粯鏃ユ湡
+	StartTime  string `protobuf:"bytes,2,opt,name=StartTime,proto3" json:"StartTime,omitempty"`
+	EndTime    string `protobuf:"bytes,3,opt,name=EndTime,proto3" json:"EndTime,omitempty"`
+	ClientName string `protobuf:"bytes,4,opt,name=ClientName,proto3" json:"ClientName,omitempty"`
+	Page       int64  `protobuf:"varint,5,opt,name=Page,proto3" json:"Page,omitempty"`
+	PageSize   int64  `protobuf:"varint,6,opt,name=PageSize,proto3" json:"PageSize,omitempty"`
+}
+
+func (x *GetCrmSalesDetailsListRequest) Reset() {
+	*x = GetCrmSalesDetailsListRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[6]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetCrmSalesDetailsListRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetCrmSalesDetailsListRequest) ProtoMessage() {}
+
+func (x *GetCrmSalesDetailsListRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[6]
+	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 GetCrmSalesDetailsListRequest.ProtoReflect.Descriptor instead.
+func (*GetCrmSalesDetailsListRequest) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *GetCrmSalesDetailsListRequest) GetTimeType() string {
+	if x != nil {
+		return x.TimeType
+	}
+	return ""
+}
+
+func (x *GetCrmSalesDetailsListRequest) GetStartTime() string {
+	if x != nil {
+		return x.StartTime
+	}
+	return ""
+}
+
+func (x *GetCrmSalesDetailsListRequest) GetEndTime() string {
+	if x != nil {
+		return x.EndTime
+	}
+	return ""
+}
+
+func (x *GetCrmSalesDetailsListRequest) GetClientName() string {
+	if x != nil {
+		return x.ClientName
+	}
+	return ""
+}
+
+func (x *GetCrmSalesDetailsListRequest) GetPage() int64 {
+	if x != nil {
+		return x.Page
+	}
+	return 0
+}
+
+func (x *GetCrmSalesDetailsListRequest) GetPageSize() int64 {
+	if x != nil {
+		return x.PageSize
+	}
+	return 0
+}
+
+type CrmSalesDetails struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Number       string `protobuf:"bytes,1,opt,name=number,proto3" json:"number,omitempty"` //閿�鍞槑缁嗗崟鍙�
+	ClientName   string `protobuf:"bytes,2,opt,name=clientName,proto3" json:"clientName,omitempty"`
+	MemberName   string `protobuf:"bytes,3,opt,name=memberName,proto3" json:"memberName,omitempty"`     //閿�鍞礋璐d汉
+	SignTime     string `protobuf:"bytes,4,opt,name=signTime,proto3" json:"signTime,omitempty"`         //绛惧崟鏃堕棿
+	DeliveryDate string `protobuf:"bytes,5,opt,name=deliveryDate,proto3" json:"deliveryDate,omitempty"` //浜よ揣鏃ユ湡
+}
+
+func (x *CrmSalesDetails) Reset() {
+	*x = CrmSalesDetails{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[7]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CrmSalesDetails) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CrmSalesDetails) ProtoMessage() {}
+
+func (x *CrmSalesDetails) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_proto_msgTypes[7]
+	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 CrmSalesDetails.ProtoReflect.Descriptor instead.
+func (*CrmSalesDetails) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *CrmSalesDetails) GetNumber() string {
+	if x != nil {
+		return x.Number
+	}
+	return ""
+}
+
+func (x *CrmSalesDetails) GetClientName() string {
+	if x != nil {
+		return x.ClientName
+	}
+	return ""
+}
+
+func (x *CrmSalesDetails) GetMemberName() string {
+	if x != nil {
+		return x.MemberName
+	}
+	return ""
+}
+
+func (x *CrmSalesDetails) GetSignTime() string {
+	if x != nil {
+		return x.SignTime
+	}
+	return ""
+}
+
+func (x *CrmSalesDetails) GetDeliveryDate() string {
+	if x != nil {
+		return x.DeliveryDate
+	}
+	return ""
+}
+
+type GetCrmSalesDetailsListResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SalesDetails []*CrmSalesDetails `protobuf:"bytes,1,rep,name=SalesDetails,proto3" json:"SalesDetails,omitempty"`
+	Total        int64              `protobuf:"varint,2,opt,name=Total,proto3" json:"Total,omitempty"`
+}
+
+func (x *GetCrmSalesDetailsListResponse) Reset() {
+	*x = GetCrmSalesDetailsListResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[8]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetCrmSalesDetailsListResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetCrmSalesDetailsListResponse) ProtoMessage() {}
+
+func (x *GetCrmSalesDetailsListResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_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 GetCrmSalesDetailsListResponse.ProtoReflect.Descriptor instead.
+func (*GetCrmSalesDetailsListResponse) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *GetCrmSalesDetailsListResponse) GetSalesDetails() []*CrmSalesDetails {
+	if x != nil {
+		return x.SalesDetails
+	}
+	return nil
+}
+
+func (x *GetCrmSalesDetailsListResponse) GetTotal() int64 {
+	if x != nil {
+		return x.Total
+	}
+	return 0
+}
+
+type SendSalesDetailsAndProjectToCrmRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SalesDetailsNumbers []string `protobuf:"bytes,1,rep,name=SalesDetailsNumbers,proto3" json:"SalesDetailsNumbers,omitempty"`
+	ProjectId           string   `protobuf:"bytes,2,opt,name=ProjectId,proto3" json:"ProjectId,omitempty"`
+}
+
+func (x *SendSalesDetailsAndProjectToCrmRequest) Reset() {
+	*x = SendSalesDetailsAndProjectToCrmRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SendSalesDetailsAndProjectToCrmRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendSalesDetailsAndProjectToCrmRequest) ProtoMessage() {}
+
+func (x *SendSalesDetailsAndProjectToCrmRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_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 SendSalesDetailsAndProjectToCrmRequest.ProtoReflect.Descriptor instead.
+func (*SendSalesDetailsAndProjectToCrmRequest) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *SendSalesDetailsAndProjectToCrmRequest) GetSalesDetailsNumbers() []string {
+	if x != nil {
+		return x.SalesDetailsNumbers
+	}
+	return nil
+}
+
+func (x *SendSalesDetailsAndProjectToCrmRequest) GetProjectId() string {
+	if x != nil {
+		return x.ProjectId
+	}
+	return ""
+}
+
+type SendSalesDetailsAndProjectToCrmResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *SendSalesDetailsAndProjectToCrmResponse) Reset() {
+	*x = SendSalesDetailsAndProjectToCrmResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_crm_aps_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SendSalesDetailsAndProjectToCrmResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SendSalesDetailsAndProjectToCrmResponse) ProtoMessage() {}
+
+func (x *SendSalesDetailsAndProjectToCrmResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_crm_aps_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 SendSalesDetailsAndProjectToCrmResponse.ProtoReflect.Descriptor instead.
+func (*SendSalesDetailsAndProjectToCrmResponse) Descriptor() ([]byte, []int) {
+	return file_crm_aps_proto_rawDescGZIP(), []int{10}
+}
+
+var File_crm_aps_proto protoreflect.FileDescriptor
+
+var file_crm_aps_proto_rawDesc = []byte{
+	0x0a, 0x0d, 0x63, 0x72, 0x6d, 0x5f, 0x61, 0x70, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+	0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4c, 0x0a, 0x0a, 0x41,
+	0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f,
+	0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72,
+	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+	0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72,
+	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x3c, 0x0a, 0x19, 0x47, 0x65, 0x74,
+	0x41, 0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x41, 0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+	0x74, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x4b, 0x0a, 0x13, 0x53, 0x61, 0x6c, 0x65, 0x73,
+	0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 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, 0x16, 0x0a, 0x06,
+	0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x41, 0x6d,
+	0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x23, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c,
+	0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x54, 0x6f, 0x41, 0x70, 0x73, 0x50, 0x72,
+	0x6f, 0x6a, 0x65, 0x63, 0x74, 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, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61,
+	0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+	0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4e, 0x61,
+	0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72,
+	0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x69, 0x6d, 0x65,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x69, 0x6d, 0x65,
+	0x12, 0x22, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x44, 0x61, 0x74, 0x65,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79,
+	0x44, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0c,
+	0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01,
+	0x28, 0x03, 0x52, 0x0c, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c,
+	0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x18, 0x08, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x30,
+	0x0a, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x14, 0x2e, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x50,
+	0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73,
+	0x22, 0x26, 0x0a, 0x24, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74,
+	0x61, 0x69, 0x6c, 0x73, 0x54, 0x6f, 0x41, 0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc3, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74,
+	0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4c,
+	0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x69,
+	0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x54, 0x69,
+	0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54,
+	0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74,
+	0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1e,
+	0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12,
+	0x0a, 0x04, 0x50, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x50, 0x61,
+	0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x06,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xa9,
+	0x01, 0x0a, 0x0f, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69,
+	0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6c,
+	0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x65,
+	0x6d, 0x62, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x69,
+	0x67, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x69,
+	0x67, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65,
+	0x72, 0x79, 0x44, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65,
+	0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x44, 0x61, 0x74, 0x65, 0x22, 0x6c, 0x0a, 0x1e, 0x47, 0x65,
+	0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0c,
+	0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x10, 0x2e, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74,
+	0x61, 0x69, 0x6c, 0x73, 0x52, 0x0c, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69,
+	0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x05, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x78, 0x0a, 0x26, 0x53, 0x65, 0x6e, 0x64,
+	0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x50,
+	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x6f, 0x43, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x30, 0x0a, 0x13, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69,
+	0x6c, 0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
+	0x13, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4e, 0x75, 0x6d,
+	0x62, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49,
+	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x49, 0x64, 0x22, 0x29, 0x0a, 0x27, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44,
+	0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x54, 0x6f, 0x43, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa8, 0x03,
+	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, 0x41, 0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x73, 0x50,
+	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x1c, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c, 0x65,
+	0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x54, 0x6f, 0x41, 0x70, 0x73, 0x50, 0x72, 0x6f,
+	0x6a, 0x65, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c, 0x65, 0x73,
+	0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x54, 0x6f, 0x41, 0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x53, 0x65, 0x6e,
+	0x64, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x54, 0x6f, 0x41,
+	0x70, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c,
+	0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1e, 0x2e,
+	0x47, 0x65, 0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69,
+	0x6c, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
+	0x47, 0x65, 0x74, 0x43, 0x72, 0x6d, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69,
+	0x6c, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
+	0x12, 0x76, 0x0a, 0x1f, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74,
+	0x61, 0x69, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x6f,
+	0x43, 0x72, 0x6d, 0x12, 0x27, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44,
+	0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x54, 0x6f, 0x43, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x53,
+	0x65, 0x6e, 0x64, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x41,
+	0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x6f, 0x43, 0x72, 0x6d, 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 (
+	file_crm_aps_proto_rawDescOnce sync.Once
+	file_crm_aps_proto_rawDescData = file_crm_aps_proto_rawDesc
+)
+
+func file_crm_aps_proto_rawDescGZIP() []byte {
+	file_crm_aps_proto_rawDescOnce.Do(func() {
+		file_crm_aps_proto_rawDescData = protoimpl.X.CompressGZIP(file_crm_aps_proto_rawDescData)
+	})
+	return file_crm_aps_proto_rawDescData
+}
+
+var file_crm_aps_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
+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
+}
+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
+	0,  // 3: CrmAndApsGrpcService.GetApsProjectList:input_type -> GetApsProjectListRequest
+	4,  // 4: CrmAndApsGrpcService.SendSalesDetailsToApsProject:input_type -> SendSalesDetailsToApsProjectRequest
+	6,  // 5: CrmAndApsGrpcService.GetCrmSalesDetailsList:input_type -> GetCrmSalesDetailsListRequest
+	9,  // 6: CrmAndApsGrpcService.SendSalesDetailsAndProjectToCrm:input_type -> SendSalesDetailsAndProjectToCrmRequest
+	2,  // 7: CrmAndApsGrpcService.GetApsProjectList:output_type -> GetApsProjectListResponse
+	5,  // 8: CrmAndApsGrpcService.SendSalesDetailsToApsProject:output_type -> SendSalesDetailsToApsProjectResponse
+	8,  // 9: CrmAndApsGrpcService.GetCrmSalesDetailsList:output_type -> GetCrmSalesDetailsListResponse
+	10, // 10: CrmAndApsGrpcService.SendSalesDetailsAndProjectToCrm:output_type -> SendSalesDetailsAndProjectToCrmResponse
+	7,  // [7:11] is the sub-list for method output_type
+	3,  // [3:7] is the sub-list for method input_type
+	3,  // [3:3] is the sub-list for extension type_name
+	3,  // [3:3] is the sub-list for extension extendee
+	0,  // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_crm_aps_proto_init() }
+func file_crm_aps_proto_init() {
+	if File_crm_aps_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_crm_aps_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetApsProjectListRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ApsProject); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetApsProjectListResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SalesDetailsProduct); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SendSalesDetailsToApsProjectRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SendSalesDetailsToApsProjectResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetCrmSalesDetailsListRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CrmSalesDetails); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetCrmSalesDetailsListResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SendSalesDetailsAndProjectToCrmRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_crm_aps_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SendSalesDetailsAndProjectToCrmResponse); 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_crm_aps_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   11,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_crm_aps_proto_goTypes,
+		DependencyIndexes: file_crm_aps_proto_depIdxs,
+		MessageInfos:      file_crm_aps_proto_msgTypes,
+	}.Build()
+	File_crm_aps_proto = out.File
+	file_crm_aps_proto_rawDesc = nil
+	file_crm_aps_proto_goTypes = nil
+	file_crm_aps_proto_depIdxs = nil
+}
diff --git a/proto/crm_aps/crm_aps_grpc.pb.go b/proto/crm_aps/crm_aps_grpc.pb.go
new file mode 100644
index 0000000..b5e0c95
--- /dev/null
+++ b/proto/crm_aps/crm_aps_grpc.pb.go
@@ -0,0 +1,209 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+
+package crm_aps
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// 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.
+type CrmAndApsGrpcServiceClient interface {
+	GetApsProjectList(ctx context.Context, in *GetApsProjectListRequest, opts ...grpc.CallOption) (*GetApsProjectListResponse, error)
+	SendSalesDetailsToApsProject(ctx context.Context, in *SendSalesDetailsToApsProjectRequest, opts ...grpc.CallOption) (*SendSalesDetailsToApsProjectResponse, error)
+	GetCrmSalesDetailsList(ctx context.Context, in *GetCrmSalesDetailsListRequest, opts ...grpc.CallOption) (*GetCrmSalesDetailsListResponse, error)
+	SendSalesDetailsAndProjectToCrm(ctx context.Context, in *SendSalesDetailsAndProjectToCrmRequest, opts ...grpc.CallOption) (*SendSalesDetailsAndProjectToCrmResponse, error)
+}
+
+type crmAndApsGrpcServiceClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewCrmAndApsGrpcServiceClient(cc grpc.ClientConnInterface) CrmAndApsGrpcServiceClient {
+	return &crmAndApsGrpcServiceClient{cc}
+}
+
+func (c *crmAndApsGrpcServiceClient) GetApsProjectList(ctx context.Context, in *GetApsProjectListRequest, opts ...grpc.CallOption) (*GetApsProjectListResponse, error) {
+	out := new(GetApsProjectListResponse)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/GetApsProjectList", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *crmAndApsGrpcServiceClient) SendSalesDetailsToApsProject(ctx context.Context, in *SendSalesDetailsToApsProjectRequest, opts ...grpc.CallOption) (*SendSalesDetailsToApsProjectResponse, error) {
+	out := new(SendSalesDetailsToApsProjectResponse)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/SendSalesDetailsToApsProject", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *crmAndApsGrpcServiceClient) GetCrmSalesDetailsList(ctx context.Context, in *GetCrmSalesDetailsListRequest, opts ...grpc.CallOption) (*GetCrmSalesDetailsListResponse, error) {
+	out := new(GetCrmSalesDetailsListResponse)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/GetCrmSalesDetailsList", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *crmAndApsGrpcServiceClient) SendSalesDetailsAndProjectToCrm(ctx context.Context, in *SendSalesDetailsAndProjectToCrmRequest, opts ...grpc.CallOption) (*SendSalesDetailsAndProjectToCrmResponse, error) {
+	out := new(SendSalesDetailsAndProjectToCrmResponse)
+	err := c.cc.Invoke(ctx, "/CrmAndApsGrpcService/SendSalesDetailsAndProjectToCrm", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// CrmAndApsGrpcServiceServer is the server API for CrmAndApsGrpcService service.
+// All implementations must embed UnimplementedCrmAndApsGrpcServiceServer
+// for forward compatibility
+type CrmAndApsGrpcServiceServer interface {
+	GetApsProjectList(context.Context, *GetApsProjectListRequest) (*GetApsProjectListResponse, error)
+	SendSalesDetailsToApsProject(context.Context, *SendSalesDetailsToApsProjectRequest) (*SendSalesDetailsToApsProjectResponse, error)
+	GetCrmSalesDetailsList(context.Context, *GetCrmSalesDetailsListRequest) (*GetCrmSalesDetailsListResponse, error)
+	SendSalesDetailsAndProjectToCrm(context.Context, *SendSalesDetailsAndProjectToCrmRequest) (*SendSalesDetailsAndProjectToCrmResponse, error)
+	mustEmbedUnimplementedCrmAndApsGrpcServiceServer()
+}
+
+// UnimplementedCrmAndApsGrpcServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedCrmAndApsGrpcServiceServer struct {
+}
+
+func (UnimplementedCrmAndApsGrpcServiceServer) GetApsProjectList(context.Context, *GetApsProjectListRequest) (*GetApsProjectListResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetApsProjectList not implemented")
+}
+func (UnimplementedCrmAndApsGrpcServiceServer) SendSalesDetailsToApsProject(context.Context, *SendSalesDetailsToApsProjectRequest) (*SendSalesDetailsToApsProjectResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method SendSalesDetailsToApsProject not implemented")
+}
+func (UnimplementedCrmAndApsGrpcServiceServer) GetCrmSalesDetailsList(context.Context, *GetCrmSalesDetailsListRequest) (*GetCrmSalesDetailsListResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetCrmSalesDetailsList not implemented")
+}
+func (UnimplementedCrmAndApsGrpcServiceServer) SendSalesDetailsAndProjectToCrm(context.Context, *SendSalesDetailsAndProjectToCrmRequest) (*SendSalesDetailsAndProjectToCrmResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method SendSalesDetailsAndProjectToCrm not implemented")
+}
+func (UnimplementedCrmAndApsGrpcServiceServer) mustEmbedUnimplementedCrmAndApsGrpcServiceServer() {}
+
+// UnsafeCrmAndApsGrpcServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to CrmAndApsGrpcServiceServer will
+// result in compilation errors.
+type UnsafeCrmAndApsGrpcServiceServer interface {
+	mustEmbedUnimplementedCrmAndApsGrpcServiceServer()
+}
+
+func RegisterCrmAndApsGrpcServiceServer(s grpc.ServiceRegistrar, srv CrmAndApsGrpcServiceServer) {
+	s.RegisterService(&CrmAndApsGrpcService_ServiceDesc, srv)
+}
+
+func _CrmAndApsGrpcService_GetApsProjectList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetApsProjectListRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(CrmAndApsGrpcServiceServer).GetApsProjectList(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/CrmAndApsGrpcService/GetApsProjectList",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(CrmAndApsGrpcServiceServer).GetApsProjectList(ctx, req.(*GetApsProjectListRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _CrmAndApsGrpcService_SendSalesDetailsToApsProject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SendSalesDetailsToApsProjectRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(CrmAndApsGrpcServiceServer).SendSalesDetailsToApsProject(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/CrmAndApsGrpcService/SendSalesDetailsToApsProject",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(CrmAndApsGrpcServiceServer).SendSalesDetailsToApsProject(ctx, req.(*SendSalesDetailsToApsProjectRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _CrmAndApsGrpcService_GetCrmSalesDetailsList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetCrmSalesDetailsListRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(CrmAndApsGrpcServiceServer).GetCrmSalesDetailsList(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/CrmAndApsGrpcService/GetCrmSalesDetailsList",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(CrmAndApsGrpcServiceServer).GetCrmSalesDetailsList(ctx, req.(*GetCrmSalesDetailsListRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _CrmAndApsGrpcService_SendSalesDetailsAndProjectToCrm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SendSalesDetailsAndProjectToCrmRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(CrmAndApsGrpcServiceServer).SendSalesDetailsAndProjectToCrm(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/CrmAndApsGrpcService/SendSalesDetailsAndProjectToCrm",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(CrmAndApsGrpcServiceServer).SendSalesDetailsAndProjectToCrm(ctx, req.(*SendSalesDetailsAndProjectToCrmRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// CrmAndApsGrpcService_ServiceDesc is the grpc.ServiceDesc for CrmAndApsGrpcService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var CrmAndApsGrpcService_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "CrmAndApsGrpcService",
+	HandlerType: (*CrmAndApsGrpcServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "GetApsProjectList",
+			Handler:    _CrmAndApsGrpcService_GetApsProjectList_Handler,
+		},
+		{
+			MethodName: "SendSalesDetailsToApsProject",
+			Handler:    _CrmAndApsGrpcService_SendSalesDetailsToApsProject_Handler,
+		},
+		{
+			MethodName: "GetCrmSalesDetailsList",
+			Handler:    _CrmAndApsGrpcService_GetCrmSalesDetailsList_Handler,
+		},
+		{
+			MethodName: "SendSalesDetailsAndProjectToCrm",
+			Handler:    _CrmAndApsGrpcService_SendSalesDetailsAndProjectToCrm_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "crm_aps.proto",
+}
diff --git a/proto/crm_aps/server.go b/proto/crm_aps/server.go
new file mode 100644
index 0000000..fd51bc1
--- /dev/null
+++ b/proto/crm_aps/server.go
@@ -0,0 +1,100 @@
+package crm_aps
+
+import (
+	"aps_crm/constvar"
+	"aps_crm/model"
+	"aps_crm/model/grpc_init"
+	"context"
+	"github.com/shopspring/decimal"
+)
+
+type Server struct {
+	UnimplementedCrmAndApsGrpcServiceServer
+}
+
+func (s *Server) GetCrmSalesDetailsList(ctx context.Context, req *GetCrmSalesDetailsListRequest) (*GetCrmSalesDetailsListResponse, error) {
+	search := model.NewSalesDetailsSearch().Orm.Model(model.SalesDetails{})
+	if req.StartTime != "" && req.EndTime != "" {
+		if req.TimeType == "绛剧害鏃ユ湡" {
+			search = search.Where("sign_time between ? and ?", req.StartTime, req.EndTime)
+		} else if req.TimeType == "浜や粯鏃ユ湡" {
+			search = search.Where("delivery_date between ? and ?", req.StartTime, req.EndTime)
+		}
+	}
+	if req.ClientName != "" {
+		search = search.Joins("Client", "LEFT").Where("Client.name like ?", "%"+req.ClientName+"%")
+	}
+	search = search.Preload("Member").Preload("Client").Where("status = ?", constvar.WaitConfirmed).Where("project_id = ?", "")
+
+	var records = make([]*model.SalesDetails, 0)
+	var total int64
+	err := search.Count(&total).Error
+	if err != nil {
+		return nil, err
+	}
+	if req.Page*req.PageSize > 0 {
+		search = search.Limit(int(req.PageSize)).Offset(int((req.Page - 1) * req.PageSize))
+	}
+	err = search.Order("id desc").Find(&records).Error
+	if err != nil {
+		return nil, err
+	}
+	sds := make([]*CrmSalesDetails, 0)
+	for _, record := range records {
+		var sd CrmSalesDetails
+		sd.Number = record.Number
+		sd.ClientName = record.Client.Name
+		sd.MemberName = record.Member.Username
+		sd.SignTime = record.SignTime
+		sd.DeliveryDate = record.DeliveryDate
+		sds = append(sds, &sd)
+	}
+	resp := new(GetCrmSalesDetailsListResponse)
+	resp.SalesDetails = sds
+	resp.Total = total
+	return resp, nil
+}
+
+func (s *Server) SendSalesDetailsAndProjectToCrm(ctx context.Context, req *SendSalesDetailsAndProjectToCrmRequest) (*SendSalesDetailsAndProjectToCrmResponse, error) {
+	details, err := model.NewSalesDetailsSearch().SetNumbers(req.SalesDetailsNumbers).SetPreload(true).FindNotTotal()
+	if err != nil {
+		return nil, err
+	}
+	for _, detail := range details {
+		m := make(map[string]interface{})
+		m["status"] = constvar.WaitOutbound
+		m["project_id"] = req.ProjectId
+
+		err := model.NewSalesDetailsSearch().SetNumber(detail.Number).UpdateByMap(m)
+		if err != nil {
+			return nil, err
+		}
+
+		products := make([]*SalesDetailsProduct, 0)
+		var total decimal.Decimal
+		for _, product := range detail.Products {
+			var sp SalesDetailsProduct
+			sp.ProductId = product.Number
+			sp.Amount = product.Amount.IntPart()
+			products = append(products, &sp)
+			total = total.Add(product.Amount)
+		}
+
+		client := NewCrmAndApsGrpcServiceClient(grpc_init.CrmApsGrpcServiceConn)
+		_, err = client.SendSalesDetailsToApsProject(ctx, &SendSalesDetailsToApsProjectRequest{
+			Number:       detail.Number,
+			ClientName:   detail.Client.Name,
+			MemberName:   detail.Member.Username,
+			SignTime:     detail.SignTime,
+			DeliveryDate: detail.DeliveryDate,
+			Source:       detail.Source,
+			ProductTotal: total.IntPart(),
+			ProjectId:    req.ProjectId,
+			Products:     products,
+		})
+		if err != nil {
+			return nil, err
+		}
+	}
+	return new(SendSalesDetailsAndProjectToCrmResponse), nil
+}
diff --git a/proto/product.proto b/proto/product.proto
index 559ca32..0cb50ec 100644
--- a/proto/product.proto
+++ b/proto/product.proto
@@ -49,14 +49,8 @@
 
 //-------------------------------------------------------------
 
-message Info {
-  string ProductId = 1;
-  string StartTime = 2;
-  string EndTime = 3;
-}
-
 message GetProductOrderRequest {
-  repeated Info Params = 1;
+  string SalesDetailsNumber= 1;
 }
 
 message WorkOrderInfo{
@@ -69,8 +63,17 @@
   string EndTime = 7;
 }
 
+message CrmGetPurchaseInfo {
+  string PurchaseNumber = 1;
+  string PurchaseName = 2;
+  string SupplierName = 3;
+  int64 Amount = 4;
+  int64 Status = 5;
+}
+
 message GetProductOrderResponse{
   int32   Code = 1;
   string  Msg = 2;
-  repeated WorkOrderInfo List = 3;
+  repeated WorkOrderInfo List = 3;//鍒堕�犱俊鎭�
+  repeated CrmGetPurchaseInfo PurchaseList = 4;//閲囪喘淇℃伅
 }
\ No newline at end of file
diff --git a/proto/product/product.pb.go b/proto/product/product.pb.go
index 104f5a8..ba02bd1 100644
--- a/proto/product/product.pb.go
+++ b/proto/product/product.pb.go
@@ -415,81 +415,18 @@
 	return 0
 }
 
-type Info struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	ProductId string `protobuf:"bytes,1,opt,name=ProductId,proto3" json:"ProductId,omitempty"`
-	StartTime string `protobuf:"bytes,2,opt,name=StartTime,proto3" json:"StartTime,omitempty"`
-	EndTime   string `protobuf:"bytes,3,opt,name=EndTime,proto3" json:"EndTime,omitempty"`
-}
-
-func (x *Info) Reset() {
-	*x = Info{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_product_proto_msgTypes[5]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Info) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Info) ProtoMessage() {}
-
-func (x *Info) ProtoReflect() protoreflect.Message {
-	mi := &file_product_proto_msgTypes[5]
-	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 Info.ProtoReflect.Descriptor instead.
-func (*Info) Descriptor() ([]byte, []int) {
-	return file_product_proto_rawDescGZIP(), []int{5}
-}
-
-func (x *Info) GetProductId() string {
-	if x != nil {
-		return x.ProductId
-	}
-	return ""
-}
-
-func (x *Info) GetStartTime() string {
-	if x != nil {
-		return x.StartTime
-	}
-	return ""
-}
-
-func (x *Info) GetEndTime() string {
-	if x != nil {
-		return x.EndTime
-	}
-	return ""
-}
-
 type GetProductOrderRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Params []*Info `protobuf:"bytes,1,rep,name=Params,proto3" json:"Params,omitempty"`
+	SalesDetailsNumber string `protobuf:"bytes,1,opt,name=SalesDetailsNumber,proto3" json:"SalesDetailsNumber,omitempty"`
 }
 
 func (x *GetProductOrderRequest) Reset() {
 	*x = GetProductOrderRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_product_proto_msgTypes[6]
+		mi := &file_product_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -502,7 +439,7 @@
 func (*GetProductOrderRequest) ProtoMessage() {}
 
 func (x *GetProductOrderRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_product_proto_msgTypes[6]
+	mi := &file_product_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -515,14 +452,14 @@
 
 // Deprecated: Use GetProductOrderRequest.ProtoReflect.Descriptor instead.
 func (*GetProductOrderRequest) Descriptor() ([]byte, []int) {
-	return file_product_proto_rawDescGZIP(), []int{6}
+	return file_product_proto_rawDescGZIP(), []int{5}
 }
 
-func (x *GetProductOrderRequest) GetParams() []*Info {
+func (x *GetProductOrderRequest) GetSalesDetailsNumber() string {
 	if x != nil {
-		return x.Params
+		return x.SalesDetailsNumber
 	}
-	return nil
+	return ""
 }
 
 type WorkOrderInfo struct {
@@ -542,7 +479,7 @@
 func (x *WorkOrderInfo) Reset() {
 	*x = WorkOrderInfo{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_product_proto_msgTypes[7]
+		mi := &file_product_proto_msgTypes[6]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -555,7 +492,7 @@
 func (*WorkOrderInfo) ProtoMessage() {}
 
 func (x *WorkOrderInfo) ProtoReflect() protoreflect.Message {
-	mi := &file_product_proto_msgTypes[7]
+	mi := &file_product_proto_msgTypes[6]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -568,7 +505,7 @@
 
 // Deprecated: Use WorkOrderInfo.ProtoReflect.Descriptor instead.
 func (*WorkOrderInfo) Descriptor() ([]byte, []int) {
-	return file_product_proto_rawDescGZIP(), []int{7}
+	return file_product_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *WorkOrderInfo) GetOrderId() string {
@@ -620,14 +557,94 @@
 	return ""
 }
 
+type CrmGetPurchaseInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	PurchaseNumber string `protobuf:"bytes,1,opt,name=PurchaseNumber,proto3" json:"PurchaseNumber,omitempty"`
+	PurchaseName   string `protobuf:"bytes,2,opt,name=PurchaseName,proto3" json:"PurchaseName,omitempty"`
+	SupplierName   string `protobuf:"bytes,3,opt,name=SupplierName,proto3" json:"SupplierName,omitempty"`
+	Amount         int64  `protobuf:"varint,4,opt,name=Amount,proto3" json:"Amount,omitempty"`
+	Status         int64  `protobuf:"varint,5,opt,name=Status,proto3" json:"Status,omitempty"`
+}
+
+func (x *CrmGetPurchaseInfo) Reset() {
+	*x = CrmGetPurchaseInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_product_proto_msgTypes[7]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CrmGetPurchaseInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CrmGetPurchaseInfo) ProtoMessage() {}
+
+func (x *CrmGetPurchaseInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_product_proto_msgTypes[7]
+	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 CrmGetPurchaseInfo.ProtoReflect.Descriptor instead.
+func (*CrmGetPurchaseInfo) Descriptor() ([]byte, []int) {
+	return file_product_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *CrmGetPurchaseInfo) GetPurchaseNumber() string {
+	if x != nil {
+		return x.PurchaseNumber
+	}
+	return ""
+}
+
+func (x *CrmGetPurchaseInfo) GetPurchaseName() string {
+	if x != nil {
+		return x.PurchaseName
+	}
+	return ""
+}
+
+func (x *CrmGetPurchaseInfo) GetSupplierName() string {
+	if x != nil {
+		return x.SupplierName
+	}
+	return ""
+}
+
+func (x *CrmGetPurchaseInfo) GetAmount() int64 {
+	if x != nil {
+		return x.Amount
+	}
+	return 0
+}
+
+func (x *CrmGetPurchaseInfo) GetStatus() int64 {
+	if x != nil {
+		return x.Status
+	}
+	return 0
+}
+
 type GetProductOrderResponse 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"`
-	List []*WorkOrderInfo `protobuf:"bytes,3,rep,name=List,proto3" json:"List,omitempty"`
+	Code         int32                 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
+	Msg          string                `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"`
+	List         []*WorkOrderInfo      `protobuf:"bytes,3,rep,name=List,proto3" json:"List,omitempty"`                 //鍒堕�犱俊鎭�
+	PurchaseList []*CrmGetPurchaseInfo `protobuf:"bytes,4,rep,name=PurchaseList,proto3" json:"PurchaseList,omitempty"` //閲囪喘淇℃伅
 }
 
 func (x *GetProductOrderResponse) Reset() {
@@ -679,6 +696,13 @@
 func (x *GetProductOrderResponse) GetList() []*WorkOrderInfo {
 	if x != nil {
 		return x.List
+	}
+	return nil
+}
+
+func (x *GetProductOrderResponse) GetPurchaseList() []*CrmGetPurchaseInfo {
+	if x != nil {
+		return x.PurchaseList
 	}
 	return nil
 }
@@ -735,53 +759,63 @@
 	0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x50,
 	0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05,
 	0x54, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x54, 0x6f, 0x74,
-	0x61, 0x6c, 0x22, 0x5c, 0x0a, 0x04, 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, 0x1c, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x72,
-	0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x74, 0x61,
+	0x61, 0x6c, 0x22, 0x48, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
+	0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0xf1, 0x01, 0x0a,
+	0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18,
+	0x0a, 0x07, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x20, 0x0a, 0x0b, 0x4f, 0x72,
+	0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b,
+	0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0b, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28,
+	0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64,
+	0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x72,
+	0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x74, 0x61,
 	0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d,
-	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65,
-	0x22, 0x37, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x72,
-	0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x06, 0x50, 0x61,
-	0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x49, 0x6e, 0x66,
-	0x6f, 0x52, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x57, 0x6f,
-	0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x4f,
-	0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4f, 0x72,
-	0x64, 0x65, 0x72, 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, 0x20, 0x0a, 0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72,
-	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x72,
-	0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x57, 0x6f, 0x72,
-	0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
-	0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x57,
-	0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53,
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69,
-	0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54,
-	0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x07,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x63, 0x0a,
-	0x17, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72,
-	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, 0x22,
-	0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x57,
-	0x6f, 0x72, 0x6b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x4c, 0x69,
-	0x73, 0x74, 0x32, 0xe2, 0x01, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x53, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64,
-	0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f,
-	0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x17, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x47, 0x65,
-	0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x47,
-	0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63,
-	0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
-	0x46, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x72, 0x64,
-	0x65, 0x72, 0x12, 0x17, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f,
-	0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x47, 0x65,
-	0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x70, 0x72, 0x6f,
-	0x64, 0x75, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65,
+	0x22, 0xb4, 0x01, 0x0a, 0x12, 0x43, 0x72, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x75, 0x72, 0x63, 0x68,
+	0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x75, 0x72, 0x63, 0x68,
+	0x61, 0x73, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12,
+	0x22, 0x0a, 0x0c, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4e,
+	0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x4e,
+	0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x53, 0x75, 0x70, 0x70, 0x6c,
+	0x69, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e,
+	0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+	0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x50,
+	0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x22, 0x0a, 0x04, 0x4c, 0x69, 0x73,
+	0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x72,
+	0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x37, 0x0a,
+	0x0c, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x43, 0x72, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x75, 0x72, 0x63,
+	0x68, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61,
+	0x73, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x32, 0xe2, 0x01, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x64, 0x75,
+	0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0e, 0x47, 0x65, 0x74,
+	0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x47, 0x65,
+	0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
+	0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43,
+	0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74,
+	0x12, 0x16, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72,
+	0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63,
+	0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64,
+	0x75, 0x63, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x18, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x72, 0x64, 0x65,
+	0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e,
+	0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -803,19 +837,19 @@
 	(*Product)(nil),                 // 2: Product
 	(*GetProductListRequest)(nil),   // 3: GetProductListRequest
 	(*GetProductListResponse)(nil),  // 4: GetProductListResponse
-	(*Info)(nil),                    // 5: Info
-	(*GetProductOrderRequest)(nil),  // 6: GetProductOrderRequest
-	(*WorkOrderInfo)(nil),           // 7: WorkOrderInfo
+	(*GetProductOrderRequest)(nil),  // 5: GetProductOrderRequest
+	(*WorkOrderInfo)(nil),           // 6: WorkOrderInfo
+	(*CrmGetPurchaseInfo)(nil),      // 7: CrmGetPurchaseInfo
 	(*GetProductOrderResponse)(nil), // 8: GetProductOrderResponse
 }
 var file_product_proto_depIdxs = []int32{
 	2, // 0: GetProductInfoResponse.Data:type_name -> Product
 	2, // 1: GetProductListResponse.List:type_name -> Product
-	5, // 2: GetProductOrderRequest.Params:type_name -> Info
-	7, // 3: GetProductOrderResponse.List:type_name -> WorkOrderInfo
+	6, // 2: GetProductOrderResponse.List:type_name -> WorkOrderInfo
+	7, // 3: GetProductOrderResponse.PurchaseList:type_name -> CrmGetPurchaseInfo
 	0, // 4: productService.GetProductInfo:input_type -> GetProductInfoRequest
 	3, // 5: productService.GetProductList:input_type -> GetProductListRequest
-	6, // 6: productService.GetProductOrder:input_type -> GetProductOrderRequest
+	5, // 6: productService.GetProductOrder:input_type -> GetProductOrderRequest
 	1, // 7: productService.GetProductInfo:output_type -> GetProductInfoResponse
 	4, // 8: productService.GetProductList:output_type -> GetProductListResponse
 	8, // 9: productService.GetProductOrder:output_type -> GetProductOrderResponse
@@ -893,18 +927,6 @@
 			}
 		}
 		file_product_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Info); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_product_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GetProductOrderRequest); i {
 			case 0:
 				return &v.state
@@ -916,7 +938,7 @@
 				return nil
 			}
 		}
-		file_product_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+		file_product_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*WorkOrderInfo); i {
 			case 0:
 				return &v.state
@@ -928,6 +950,18 @@
 				return nil
 			}
 		}
+		file_product_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CrmGetPurchaseInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 		file_product_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GetProductOrderResponse); i {
 			case 0:
diff --git a/proto/product_inventory.proto b/proto/product_inventory.proto
index 7da35cb..66cab98 100644
--- a/proto/product_inventory.proto
+++ b/proto/product_inventory.proto
@@ -14,7 +14,10 @@
   string Address = 3;//鏀惰揣鍦板潃
   string Phone = 4;
   int32 DeliverType = 5;//浜や粯绫诲瀷
-  repeated InventoryProduct ProductList = 6;
+  string Source = 6;
+  int64 ClientId = 7;
+  string ClientName = 8;
+  repeated InventoryProduct ProductList = 9;
 }
 
 message InventoryProduct{
@@ -34,7 +37,7 @@
 }
 
 message ProductInfo{
-  string Id = 1;
+  string Number = 1;
   string Name = 2;
   string OrderAmount = 3;//璁㈠崟鏁伴噺
   string Unit = 4;
diff --git a/proto/product_inventory/product_inventory.pb.go b/proto/product_inventory/product_inventory.pb.go
index 26c7209..82e965a 100644
--- a/proto/product_inventory/product_inventory.pb.go
+++ b/proto/product_inventory/product_inventory.pb.go
@@ -30,7 +30,10 @@
 	Address     string              `protobuf:"bytes,3,opt,name=Address,proto3" json:"Address,omitempty"`     //鏀惰揣鍦板潃
 	Phone       string              `protobuf:"bytes,4,opt,name=Phone,proto3" json:"Phone,omitempty"`
 	DeliverType int32               `protobuf:"varint,5,opt,name=DeliverType,proto3" json:"DeliverType,omitempty"` //浜や粯绫诲瀷
-	ProductList []*InventoryProduct `protobuf:"bytes,6,rep,name=ProductList,proto3" json:"ProductList,omitempty"`
+	Source      string              `protobuf:"bytes,6,opt,name=Source,proto3" json:"Source,omitempty"`
+	ClientId    int64               `protobuf:"varint,7,opt,name=ClientId,proto3" json:"ClientId,omitempty"`
+	ClientName  string              `protobuf:"bytes,8,opt,name=ClientName,proto3" json:"ClientName,omitempty"`
+	ProductList []*InventoryProduct `protobuf:"bytes,9,rep,name=ProductList,proto3" json:"ProductList,omitempty"`
 }
 
 func (x *CreateOperationRequest) Reset() {
@@ -98,6 +101,27 @@
 		return x.DeliverType
 	}
 	return 0
+}
+
+func (x *CreateOperationRequest) GetSource() string {
+	if x != nil {
+		return x.Source
+	}
+	return ""
+}
+
+func (x *CreateOperationRequest) GetClientId() int64 {
+	if x != nil {
+		return x.ClientId
+	}
+	return 0
+}
+
+func (x *CreateOperationRequest) GetClientName() string {
+	if x != nil {
+		return x.ClientName
+	}
+	return ""
 }
 
 func (x *CreateOperationRequest) GetProductList() []*InventoryProduct {
@@ -269,7 +293,7 @@
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Id              string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"`
+	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"`
@@ -315,9 +339,9 @@
 	return file_product_inventory_proto_rawDescGZIP(), []int{4}
 }
 
-func (x *ProductInfo) GetId() string {
+func (x *ProductInfo) GetNumber() string {
 	if x != nil {
-		return x.Id
+		return x.Number
 	}
 	return ""
 }
@@ -576,7 +600,7 @@
 
 var file_product_inventory_proto_rawDesc = []byte{
 	0x0a, 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74,
-	0x6f, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd5, 0x01, 0x0a, 0x16, 0x43, 0x72,
+	0x6f, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x43, 0x72,
 	0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, 0x1c, 0x0a, 0x09,
@@ -586,82 +610,88 @@
 	0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20,
 	0x01, 0x28, 0x09, 0x52, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65,
 	0x6c, 0x69, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
-	0x0b, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x0b,
-	0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x11, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72, 0x6f,
-	0x64, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73,
-	0x74, 0x22, 0x3a, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x72,
-	0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x02, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3f, 0x0a,
-	0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03,
-	0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4d, 0x73, 0x67, 0x22, 0x38,
-	0x0a, 0x1e, 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,
-	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, 0xcd, 0x02, 0x0a, 0x0b, 0x50, 0x72, 0x6f,
-	0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 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, 0x28,
-	0x0a, 0x0f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
-	0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
-	0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x77, 0x0a, 0x1f, 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, 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, 0x2e, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74,
-	0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
-	0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73,
-	0x74, 0x22, 0x66, 0x0a, 0x1e, 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, 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, 0x2c, 0x0a, 0x11, 0x53,
-	0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74,
-	0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x47, 0x0a, 0x1f, 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, 0x12, 0x12, 0x0a, 0x04,
+	0x0b, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06,
+	0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64,
+	0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64,
+	0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65,
+	0x12, 0x33, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18,
+	0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72,
+	0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63,
+	0x74, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3a, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f,
+	0x72, 0x79, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f,
+	0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e,
+	0x74, 0x22, 0x3f, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 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,
+	0x73, 0x67, 0x22, 0x38, 0x0a, 0x1e, 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, 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, 0xd5, 0x02, 0x0a,
+	0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 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, 0x28, 0x0a, 0x0f, 0x41, 0x76,
+	0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0c, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x75,
+	0x6d, 0x62, 0x65, 0x72, 0x22, 0x77, 0x0a, 0x1f, 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, 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, 0x2e, 0x0a,
+	0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f,
+	0x52, 0x0b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x66, 0x0a,
+	0x1e, 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, 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, 0x2c, 0x0a, 0x11, 0x53, 0x61, 0x6c, 0x65, 0x73,
+	0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x11, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x53,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x47, 0x0a, 0x1f, 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, 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,
 }
 
 var (
diff --git a/router/index.go b/router/index.go
index 94aae0a..2758b73 100644
--- a/router/index.go
+++ b/router/index.go
@@ -200,5 +200,15 @@
 		codeGroup.GET("getCodeList", codeApi.GetCodeList)  //鑾峰彇缂栫爜鍒楄〃
 		codeGroup.POST("getAutoCode", codeApi.GetAutoCode) //鑾峰彇缂栫爜鍒楄〃
 	}
+
+	//绯荤粺璁剧疆
+	systemSetGroup := PrivateGroup.Group("system")
+	systemSetApi := v1.SystemSetApi{}
+	{
+		systemSetGroup.GET("getSystemSet", systemSetApi.GetSystemSet)
+		systemSetGroup.POST("saveSystemSet", systemSetApi.SaveSystemSet)
+		systemSetGroup.GET("useSystemSet/:modeType", systemSetApi.UseSystemSet)
+	}
+
 	return Router
 }
diff --git a/router/quotation.go b/router/quotation.go
index 83068cd..06f98df 100644
--- a/router/quotation.go
+++ b/router/quotation.go
@@ -11,9 +11,10 @@
 	quotationRouter := router.Group("quotation")
 	quotationApi := v1.ApiGroup.QuotationApi
 	{
-		quotationRouter.POST("add", quotationApi.Add)         // 娣诲姞鎶ヤ环鍗�
-		quotationRouter.DELETE("delete", quotationApi.Delete) // 鍒犻櫎鎶ヤ环鍗�
-		quotationRouter.PUT("update", quotationApi.Update)    // 鏇存柊鎶ヤ环鍗�
-		quotationRouter.POST("list", quotationApi.List)       // 鑾峰彇鎶ヤ环鍗曞垪琛�
+		quotationRouter.POST("add", quotationApi.Add)              // 娣诲姞鎶ヤ环鍗�
+		quotationRouter.DELETE("delete", quotationApi.Delete)      // 鍒犻櫎鎶ヤ环鍗�
+		quotationRouter.PUT("update", quotationApi.Update)         // 鏇存柊鎶ヤ环鍗�
+		quotationRouter.POST("list", quotationApi.List)            // 鑾峰彇鎶ヤ环鍗曞垪琛�
+		quotationRouter.GET("statistics", quotationApi.Statistics) // 鎶ヤ环鍗曠粺璁�
 	}
 }
diff --git a/router/salesDetails.go b/router/salesDetails.go
index 3ce17bd..7d7db0c 100644
--- a/router/salesDetails.go
+++ b/router/salesDetails.go
@@ -18,6 +18,8 @@
 		salesDetailsRouter.POST("updateStatus", salesDetailsApi.UpdateStatus)                              // 鏇存柊閿�鍞槑缁嗙姸鎬�
 		salesDetailsRouter.POST("list", salesDetailsApi.List)                                              // 鑾峰彇閿�鍞槑缁嗗崟鍒楄〃
 		salesDetailsRouter.GET("getProductInventoryInfo/:number", salesDetailsApi.GetProductInventoryInfo) // 鑾峰彇浜у搧搴撳瓨淇℃伅
-		salesDetailsRouter.POST("createOperation", salesDetailsApi.CreateOperation)                        // 鍒涘缓浜у搧鍑哄簱淇℃伅
+		//salesDetailsRouter.POST("createOperation", salesDetailsApi.CreateOperation)                           // 鍒涘缓浜у搧鍑哄簱淇℃伅
+		salesDetailsRouter.GET("getApsProjectList", salesDetailsApi.GetApsProjectList)                          // 鑾峰彇aps椤圭洰鍒楄〃
+		salesDetailsRouter.POST("sendSalesDetailsToOtherSystem", salesDetailsApi.SendSalesDetailsToOtherSystem) // 鎺ㄩ�侀攢鍞槑缁嗕俊鎭埌鍏朵粬绯荤粺                    // 鍒涘缓浜у搧鍑哄簱淇℃伅
 	}
 }
diff --git a/service/contract.go b/service/contract.go
index 2910f87..b6825ef 100644
--- a/service/contract.go
+++ b/service/contract.go
@@ -31,9 +31,9 @@
 	return ecode.OK
 }
 
-func (ContractService) GetContractList(page, pageSize int, data map[string]interface{}) ([]*model.Contract, int64, int) {
+func (ContractService) GetContractList(page, pageSize int, data map[string]interface{}, keyword string) ([]*model.Contract, int64, int) {
 	// get contact list
-	contacts, total, err := model.NewContractSearch().SetPage(page, pageSize).SetSearchMap(data).FindAll()
+	contacts, total, err := model.NewContractSearch().SetPage(page, pageSize).SetSearchMap(data).SetKeyword(keyword).FindAll()
 	if err != nil {
 		return nil, 0, ecode.ContractListErr
 	}
diff --git a/service/system_set_service.go b/service/system_set_service.go
new file mode 100644
index 0000000..924e7aa
--- /dev/null
+++ b/service/system_set_service.go
@@ -0,0 +1,20 @@
+package service
+
+import (
+	"aps_crm/constvar"
+	"aps_crm/model"
+)
+
+func GetSystemSet() (map[string]interface{}, error) {
+	all, err := model.NewSystemSetSearch().FindAll()
+	if err != nil {
+		return nil, err
+	}
+	crmMap := constvar.SystemSet[`CRM`].(map[string]interface{})
+	for _, set := range all {
+		if _, ok := crmMap[set.Name]; ok {
+			crmMap[set.Name].(map[string]interface{})["value"] = set.Value
+		}
+	}
+	return crmMap, nil
+}

--
Gitblit v1.8.0