From 3288c6f7bbb3cc6cf101238a453479a9d9b8a795 Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期四, 21 三月 2024 14:31:19 +0800
Subject: [PATCH] fix

---
 api/v1/salesDetails.go |  497 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 488 insertions(+), 9 deletions(-)

diff --git a/api/v1/salesDetails.go b/api/v1/salesDetails.go
index 4ce0f39..29dc637 100644
--- a/api/v1/salesDetails.go
+++ b/api/v1/salesDetails.go
@@ -1,13 +1,23 @@
 package v1
 
 import (
+	"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"
+	"gorm.io/gorm"
 	"strconv"
+	"strings"
 )
 
 type SalesDetailsApi struct{}
@@ -33,18 +43,27 @@
 		return
 	}
 
+	count, err := model.NewSalesDetailsSearch().SetNumber(params.Number).Count()
+	if err != nil {
+		ctx.FailWithMsg(ecode.UnknownErr, "缂栫爜楠岃瘉澶辫触")
+		return
+	}
+	if count > 0 {
+		ctx.FailWithMsg(ecode.UnknownErr, "缂栫爜宸插瓨鍦�")
+		return
+	}
+
+	if salesDetails.MemberId == 0 {
+		userInfo := utils.GetUserInfo(c)
+		if userInfo.UserType == constvar.UserTypeSub {
+			salesDetails.MemberId = userInfo.CrmUserId
+		}
+	}
+
 	errCode = salesDetailsService.AddSalesDetails(&salesDetails)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
 		return
-	}
-
-	if params.CodeRule.Method == 1 {
-		autoCode := model.GetAutoCode(salesDetails.Id, &params.CodeRule)
-		m := map[string]interface{}{
-			"number": autoCode,
-		}
-		_ = model.NewSalesDetailsSearch().SetId(salesDetails.Id).UpdateByMap(m)
 	}
 
 	ctx.OkWithDetailed(salesDetails)
@@ -147,6 +166,15 @@
 	salesDetailsModel.LogisticNumber = salesDetails.LogisticNumber
 	salesDetailsModel.LogisticCost = salesDetails.LogisticCost
 	salesDetailsModel.CodeStandID = salesDetails.CodeStandID
+	salesDetailsModel.DeliverType = salesDetails.DeliverType
+	salesDetailsModel.QuotationId = salesDetails.QuotationId
+	salesDetailsModel.Status = salesDetails.Status
+	if salesDetails.Source == "" {
+		salesDetailsModel.Source = "CRM鑷缓"
+	} else {
+		salesDetailsModel.Source = salesDetails.Source
+	}
+	salesDetailsModel.ProjectId = salesDetails.ProjectId
 
 	return ecode.OK, salesDetailsModel
 }
@@ -166,7 +194,13 @@
 		return
 	}
 
-	salesDetailss, total, errCode := salesDetailsService.GetSalesDetailsList(params)
+	var memberIds []int
+	userInfo := utils.GetUserInfo(c)
+	if userInfo.UserType == constvar.UserTypeSub {
+		memberIds = userInfo.SubUserIds
+	}
+
+	salesDetailss, total, errCode := salesDetailsService.GetSalesDetailsList(params, memberIds)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
 		return
@@ -177,3 +211,448 @@
 		Count: int(total),
 	})
 }
+
+// UpdateStatus
+//
+//	@Tags		SalesDetails
+//	@Summary	鏇存柊閿�鍞槑缁嗙姸鎬�
+//	@Produce	application/json
+//	@Param		object	body		request.UpdateSalesDetailsStatus	true	"鏌ヨ鍙傛暟"
+//	@Success	200		{object}	contextx.Response{}
+//	@Router		/api/salesDetails/updateStatus [post]
+func (s *SalesDetailsApi) UpdateStatus(c *gin.Context) {
+	var params request.UpdateSalesDetailsStatus
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+
+	m := make(map[string]interface{})
+	m["status"] = params.Status
+	err := model.NewSalesDetailsSearch().SetId(params.Id).UpdateByMap(m)
+	if err != nil {
+		ctx.FailWithMsg(ecode.UnknownErr, "鏇存柊澶辫触")
+		return
+	}
+
+	ctx.Ok()
+}
+
+// GetProductInventoryInfo
+//
+// @Tags		SalesDetails
+// @Summary	鑾峰彇浜у搧鍙戣揣淇℃伅
+// @Produce	application/json
+// @Param		number	path		string	true	"鏄庣粏缂栫爜"
+// @Success	200	{object}	response.ListResponse
+//
+//	@Router		/api/salesDetails/getProductInventoryInfo/{number} [get]
+func (s *SalesDetailsApi) GetProductInventoryInfo(c *gin.Context) {
+	ctx, ok := contextx.NewContext(c, nil)
+	if !ok {
+		return
+	}
+	number := c.Param("number")
+	client := product_inventory.NewProductInventoryServiceClient(grpc_init.ProductInventoryServiceConn)
+	info, err := client.GetOrderInputAndOutputInfo(ctx.GetCtx(), &product_inventory.GetOrderInputAndOutputInfoRequest{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
+	}
+	var list []response.ProductInfo
+	err = structx.AssignTo(info.OutputList, &list)
+	if err != nil {
+		ctx.FailWithMsg(ecode.UnknownErr, "杞崲閿欒")
+		return
+	}
+
+	products, err := salesDetailsService.GetProducts(number)
+	m := make(map[string]*model.Product)
+
+	for _, product := range products {
+		m[product.Number] = product
+	}
+	for k, v := range list {
+		if m[v.Number] == nil {
+			continue
+		}
+		list[k].OrderAmount = m[v.Number].Amount.String()
+	}
+
+	ctx.OkWithDetailed(list)
+}
+
+type GetWarehouseProductInfoReq struct {
+	SaleDetailID     int    `json:"saleDetailID,omitempty"`
+	SaleDetailNumber string `json:"saleDetailNumber,omitempty"`
+}
+
+// GetDeliveryPrepareInfo
+// @Tags		SalesDetails
+// @Summary	鑾峰彇浜у搧鍏ュ簱淇℃伅
+// @Produce	application/json
+// @Param		object 	body GetWarehouseProductInfoReq	true	"鏄庣粏缂栫爜"
+// @Success	200	{object}	response.ListResponse
+// @Router		/api/salesDetails/getDeliveryPrepareInfo [post]
+func (s *SalesDetailsApi) GetDeliveryPrepareInfo(c *gin.Context) {
+	var params GetWarehouseProductInfoReq
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+	if params.SaleDetailID == 0 {
+		ctx.FailWithMsg(ecode.ParamsErr, "鍙傛暟缂哄け")
+		return
+	}
+
+	salesDetails, err := salesDetailsService.GetSalesDetails(params.SaleDetailID)
+	if err == gorm.ErrRecordNotFound || salesDetails.Number != params.SaleDetailNumber {
+		ctx.FailWithMsg(ecode.ParamsErr, "閿�鍞鍗曚笉瀛樺湪")
+		return
+	}
+
+	productMap := model.ProductMap(salesDetails.Products)
+	client := product_inventory.NewProductInventoryServiceClient(grpc_init.ProductInventoryServiceConn)
+	grpcResp, err := client.GetOrderInputAndOutputInfo(ctx.GetCtx(), &product_inventory.GetOrderInputAndOutputInfoRequest{
+		Number: params.SaleDetailNumber,
+	})
+	if err != nil {
+		if strings.Contains(err.Error(), "record not found") {
+			ctx.Ok()
+			return
+		}
+		logx.Errorf("GetOrderInputAndOutputInfo err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "grpc璋冪敤閿欒")
+		return
+	}
+
+	grpcOutputList := grpcResp.OutputList
+	grpcInputList := grpcResp.InputList
+	inputProductMap := make(map[string]*response.StoreInfo)
+	outputProductMap := make(map[string]*response.OutputSimpleInfo)
+	for _, v := range grpcOutputList {
+		if productMap[v.Number] == nil {
+			continue
+		}
+		if outputProductMap[v.Number] == nil {
+			simpleInfo := &response.OutputSimpleInfo{
+				Number: v.Number,
+			}
+			amount, _ := decimal.NewFromString(v.Amount)
+			simpleInfo.Amount = amount
+			outputProductMap[v.Number] = simpleInfo
+		} else {
+			amount, _ := decimal.NewFromString(v.Amount)
+			outputProductMap[v.Number].Amount = outputProductMap[v.Number].Amount.Add(amount)
+		}
+	}
+	for _, v := range grpcInputList {
+		if productMap[v.Number] == nil {
+			continue
+		}
+		if inputProductMap[v.Number] == nil {
+			storeInfo := &response.StoreInfo{
+				Number:      v.Number,
+				Name:        v.Name,
+				OrderAmount: productMap[v.Number].Amount,
+			}
+			finishAmount, _ := decimal.NewFromString(v.Amount)
+			storeInfo.FinishAmount = finishAmount
+			storeInfo.AvailableAmount = finishAmount
+			storeInfo.LeftAmount = storeInfo.OrderAmount
+			inputProductMap[v.Number] = storeInfo
+		} else {
+			finishAmount, _ := decimal.NewFromString(v.Amount)
+			inputProductMap[v.Number].FinishAmount = inputProductMap[v.Number].FinishAmount.Add(finishAmount)
+			inputProductMap[v.Number].AvailableAmount = inputProductMap[v.Number].FinishAmount
+		}
+	}
+	storeList := make([]*response.StoreInfo, 0, len(salesDetails.Products))
+	for _, product := range salesDetails.Products {
+		storeInfo := inputProductMap[product.Number]
+		if storeInfo == nil { //娌℃湁鍏ュ簱淇℃伅
+			storeInfo = &response.StoreInfo{
+				Name:            product.Name,
+				Number:          product.Number,
+				OrderAmount:     product.Amount,
+				FinishAmount:    decimal.Decimal{},
+				LeftAmount:      product.Amount,
+				AvailableAmount: decimal.Decimal{},
+			}
+		} else { //鏈夊叆搴撴暟閲忓啀鏌ュ嚭搴擄紝绠楀嚭鏈彂璐ф暟閲�
+			if outputProductMap[product.Number] != nil {
+				outputInfo := outputProductMap[product.Number]
+				storeInfo.LeftAmount = storeInfo.LeftAmount.Sub(outputInfo.Amount)           //鍓╀綑鍙戣揣鏁伴噺 = 璁㈠崟鏁伴噺 - 宸插彂璐ф暟閲�
+				storeInfo.AvailableAmount = storeInfo.AvailableAmount.Sub(outputInfo.Amount) //鍙敤鏁伴噺 = 鍏ュ簱瀹屾垚鏁伴噺 - 宸插彂璐ф暟閲�
+			}
+		}
+		storeList = append(storeList, storeInfo)
+	}
+	ctx.OkWithDetailed(storeList)
+}
+
+// ConfirmOutput
+// @Tags		SalesDetails
+// @Summary	纭鍙戣揣
+// @Produce	application/json
+// @Param		object 	body request.ConfirmOutput	true	"鏄庣粏缂栫爜"
+// @Success	200	{object}	response.ListResponse
+// @Router		/api/salesDetails/confirmOutput [post]
+func (s *SalesDetailsApi) ConfirmOutput(c *gin.Context) {
+	var params request.ConfirmOutput
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+	if len(params.Products) == 0 || params.SaleDetailNumber == "" {
+		ctx.FailWithMsg(ecode.ParamsErr, "鍙傛暟缂哄け")
+		return
+	}
+	var flag bool
+	for _, p := range params.Products {
+		if p.OutputAmount.GreaterThan(decimal.Zero) {
+			flag = true
+		}
+	}
+	if !flag {
+		ctx.FailWithMsg(ecode.ParamsErr, "鍙戣揣鏁伴噺缂哄け")
+		return
+	}
+
+	products := make([]*product_inventory.OutputProduct, 0, len(params.Products))
+	for _, product := range params.Products {
+		products = append(products, &product_inventory.OutputProduct{
+			Number: product.Number,
+			Amount: product.OutputAmount.String(),
+		})
+	}
+	client := product_inventory.NewProductInventoryServiceClient(grpc_init.ProductInventoryServiceConn)
+	_, err := client.OrderProductOutput(ctx.GetCtx(), &product_inventory.OrderProductOutputRequest{
+		OrderNumber: params.SaleDetailNumber,
+		Products:    products,
+	})
+
+	if err != nil {
+		logx.Errorf("product_inventory.OrderProductOutput err:%v, params:%v", err, params)
+		ctx.FailWithMsg(ecode.UnknownErr, "鍙戣揣澶辫触"+err.Error())
+		return
+	}
+
+	ctx.OkWithDetailed(nil)
+}
+
+// confirmOutputOver
+// @Tags    SalesDetails
+// @Summary	纭鍙戣揣
+// @Produce	application/json
+// @Param		object 	body request.ConfirmOutputOver	true	"鏄庣粏缂栫爜"
+// @Success	200	{object}	response.ListResponse
+// @Router		/api/salesDetails/confirmOutputOver [post]
+func (s *SalesDetailsApi) ConfirmOutputOver(c *gin.Context) {
+	var params request.ConfirmOutput
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+	if params.SaleDetailNumber == "" {
+		ctx.FailWithMsg(ecode.ParamsErr, "鍙傛暟缂哄け")
+		return
+	}
+
+	salesDetails, err := salesDetailsService.GetSalesDetailsByNumber(params.SaleDetailNumber)
+	if err == gorm.ErrRecordNotFound || salesDetails.Number != params.SaleDetailNumber {
+		ctx.FailWithMsg(ecode.ParamsErr, "閿�鍞鍗曚笉瀛樺湪")
+		return
+	}
+
+	err = model.NewSalesDetailsSearch().SetId(salesDetails.Id).UpdateByMap(map[string]interface{}{"status": constvar.OverOutbound})
+
+	if err != nil {
+		ctx.FailWithMsg(ecode.DBErr, "淇敼澶辫触")
+		return
+	}
+
+	ctx.OkWithDetailed(nil)
+}
+
+// GetDeliveryList
+// @Tags		SalesDetails
+// @Summary	鍙戣揣鏄庣粏
+// @Produce	application/json
+// @Param		object 	body GetWarehouseProductInfoReq	true	"鏄庣粏缂栫爜"
+// @Success	200	{object}	response.ListResponse
+// @Router		/api/salesDetails/getDeliveryList [post]
+func (s *SalesDetailsApi) GetDeliveryList(c *gin.Context) {
+	var params GetWarehouseProductInfoReq
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+	if params.SaleDetailID == 0 {
+		ctx.FailWithMsg(ecode.ParamsErr, "鍙傛暟缂哄け")
+		return
+	}
+
+	salesDetails, err := salesDetailsService.GetSalesDetails(params.SaleDetailID)
+	if err == gorm.ErrRecordNotFound || salesDetails.Number != params.SaleDetailNumber {
+		ctx.FailWithMsg(ecode.ParamsErr, "閿�鍞鍗曚笉瀛樺湪")
+		return
+	}
+
+	productMap := model.ProductMap(salesDetails.Products)
+	client := product_inventory.NewProductInventoryServiceClient(grpc_init.ProductInventoryServiceConn)
+	grpcResp, err := client.GetOrderInputAndOutputInfo(ctx.GetCtx(), &product_inventory.GetOrderInputAndOutputInfoRequest{
+		Number: params.SaleDetailNumber,
+	})
+	if err != nil {
+		if strings.Contains(err.Error(), "record not found") {
+			ctx.Ok()
+			return
+		}
+		logx.Errorf("GetOrderInputAndOutputInfo err: %v", err.Error())
+		ctx.FailWithMsg(ecode.UnknownErr, "grpc璋冪敤閿欒")
+		return
+	}
+
+	grpcOutputList := grpcResp.OutputList
+	outputList := make([]*response.OutputInfo, 0, len(grpcOutputList))
+	for _, v := range grpcOutputList {
+		outputInfo := &response.OutputInfo{
+			Number:      v.Number,
+			Name:        v.Name,
+			OrderAmount: productMap[v.Number].Amount.String(),
+			Unit:        v.Unit,
+			Invoice:     v.Invoice,
+			Carrier:     v.Carrier,
+			Waybill:     v.Waybill,
+			SalePrice:   v.SalePrice,
+			Valorem:     v.Valorem,
+			Warehouse:   v.Warehouse,
+			Amount:      v.Amount,
+			Status:      int(v.Status),
+			Specs:       productMap[v.Number].Specs,
+			CreateTime:  v.CreateTime,
+		}
+		outputList = append(outputList, outputInfo)
+	}
+	ctx.OkWithDetailed(outputList)
+}
+
+// GetApsProjectList
+//
+// @Tags		SalesDetails
+// @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/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
+	}
+
+	//鎺ㄩ�佸埌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()
+	//	wmsProducts = append(wmsProducts, &p)
+	//}
+	//clientWms := product_inventory.NewProductInventoryServiceClient(grpc_init.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),
+	//	Source:      "CRM",
+	//	ClientId:    int64(params.ClientId),
+	//	ClientName:  clientName,
+	//	ProductList: wmsProducts,
+	//})
+	//if err != nil {
+	//	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()
+}

--
Gitblit v1.8.0