fix
zhangqian
2024-03-21 3288c6f7bbb3cc6cf101238a453479a9d9b8a795
api/v1/salesDetails.go
@@ -1,20 +1,23 @@
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"
   "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"
   "google.golang.org/grpc"
   "google.golang.org/grpc/credentials/insecure"
   "github.com/shopspring/decimal"
   "gorm.io/gorm"
   "strconv"
   "strings"
)
type SalesDetailsApi struct{}
@@ -166,7 +169,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
}
@@ -189,7 +197,7 @@
   var memberIds []int
   userInfo := utils.GetUserInfo(c)
   if userInfo.UserType == constvar.UserTypeSub {
      memberIds = []int{userInfo.CrmUserId}
      memberIds = userInfo.SubUserIds
   }
   salesDetailss, total, errCode := salesDetailsService.GetSalesDetailsList(params, memberIds)
@@ -209,18 +217,18 @@
//   @Tags      SalesDetails
//   @Summary   更新销售明细状态
//   @Produce   application/json
//   @Param      object   body      request.UpdateSalesDetails   true   "查询参数"
//   @Param      object   body      request.UpdateSalesDetailsStatus   true   "查询参数"
//   @Success   200      {object}   contextx.Response{}
//   @Router      /api/salesDetails/update [post]
//   @Router      /api/salesDetails/updateStatus [post]
func (s *SalesDetailsApi) UpdateStatus(c *gin.Context) {
   var params request.UpdateSalesDetails
   var params request.UpdateSalesDetailsStatus
   ctx, ok := contextx.NewContext(c, &params)
   if !ok {
      return
   }
   m := make(map[string]interface{})
   m["status"] = params.SalesDetails.Status
   m["status"] = params.Status
   err := model.NewSalesDetailsSearch().SetId(params.Id).UpdateByMap(m)
   if err != nil {
      ctx.FailWithMsg(ecode.UnknownErr, "更新失败")
@@ -230,29 +238,10 @@
   ctx.Ok()
}
var (
   ProductInventoryServiceConn *grpc.ClientConn
)
func InitProductInventoryServiceConn() {
   var err error
   ProductInventoryServiceConn, err = grpc.Dial(conf.Conf.GrpcServiceAddr.WMS, grpc.WithTransportCredentials(insecure.NewCredentials()))
   if err != nil {
      logx.Errorf("grpc dial product service error: %v", err.Error())
      return
   }
}
func CloseProductInventoryServiceConn() {
   if ProductInventoryServiceConn != nil {
      ProductInventoryServiceConn.Close()
   }
}
// GetProductInventoryInfo
//
// @Tags      SalesDetails
// @Summary   获取产品库存信息
// @Summary   获取产品发货信息
// @Produce   application/json
// @Param      number   path      string   true   "明细编码"
// @Success   200   {object}   response.ListResponse
@@ -264,51 +253,405 @@
      return
   }
   number := c.Param("number")
   client := product_inventory.NewProductInventoryServiceClient(ProductInventoryServiceConn)
   info, err := client.GetInventoryProductInfo(ctx.GetCtx(), &product_inventory.GetInventoryProductInfoRequest{Number: 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
   }
   ctx.OkWithDetailed(info.ProductList)
   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)
}
// CreateOperation
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   创建产品出库信息
// @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
   }
   client := product_inventory.NewProductInventoryServiceClient(ProductInventoryServiceConn)
   products := 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)
   //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
   }
   _, err := client.CreateOperation(ctx.GetCtx(), &product_inventory.CreateOperationRequest{
      Number:      params.Number,
      Addressee:   params.Addressee,
      Address:     params.Address,
      Phone:       params.Phone,
      DeliverType: int32(params.DeliverType),
      ProductList: products,
   //推送到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 {
      logx.Errorf("CreateOperation err: %v", err.Error())
      ctx.FailWithMsg(ecode.UnknownErr, "grpc调用错误")
      //状态还原
      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()