| | |
| | | package v1 |
| | | |
| | | import ( |
| | | "aps_crm/conf" |
| | | "aps_crm/constvar" |
| | | "aps_crm/model" |
| | | "aps_crm/model/grpc_init" |
| | |
| | | "aps_crm/utils" |
| | | "github.com/gin-gonic/gin" |
| | | "github.com/shopspring/decimal" |
| | | "google.golang.org/grpc" |
| | | "google.golang.org/grpc/credentials/insecure" |
| | | "gorm.io/gorm" |
| | | "strconv" |
| | | "strings" |
| | | ) |
| | | |
| | | type SalesDetailsApi struct{} |
| | |
| | | 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 |
| | |
| | | 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 |
| | |
| | | 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 |
| | | } |
| | | var list []response.ProductInfo |
| | | err = structx.AssignTo(info.ProductList, &list) |
| | | 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 创建产品出库信息 |
| | | // @Summary 获取产品入库信息 |
| | | // @Produce application/json |
| | | // @Param object body request.SalesDetails true "查询参数" |
| | | // @Param object body GetWarehouseProductInfoReq true "明细编码" |
| | | // @Success 200 {object} response.ListResponse |
| | | // |
| | | // @Router /api/salesDetails/createOperation [post] |
| | | func (s *SalesDetailsApi) CreateOperation(c *gin.Context) { |
| | | var params request.SalesDetails |
| | | // @Router /api/salesDetails/getDeliveryPrepareInfo [post] |
| | | func (s *SalesDetailsApi) GetDeliveryPrepareInfo(c *gin.Context) { |
| | | var params GetWarehouseProductInfoReq |
| | | ctx, ok := contextx.NewContext(c, ¶ms) |
| | | if !ok { |
| | | return |
| | | } |
| | | m := make(map[string]interface{}) |
| | | m["status"] = params.Status |
| | | err := model.NewSalesDetailsSearch().SetNumber(params.Number).UpdateByMap(m) |
| | | if err != nil { |
| | | ctx.FailWithMsg(ecode.UnknownErr, "状态更新失败") |
| | | if params.SaleDetailID == 0 { |
| | | ctx.FailWithMsg(ecode.ParamsErr, "参数缺失") |
| | | 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) |
| | | salesDetails, err := salesDetailsService.GetSalesDetails(params.SaleDetailID) |
| | | if err == gorm.ErrRecordNotFound || salesDetails.Number != params.SaleDetailNumber { |
| | | ctx.FailWithMsg(ecode.ParamsErr, "销售订单不存在") |
| | | 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, |
| | | |
| | | 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 { |
| | | logx.Errorf("CreateOperation err: %v", err.Error()) |
| | | if strings.Contains(err.Error(), "record not found") { |
| | | ctx.Ok() |
| | | return |
| | | } |
| | | logx.Errorf("GetOrderInputAndOutputInfo err: %v", err.Error()) |
| | | ctx.FailWithMsg(ecode.UnknownErr, "grpc调用错误") |
| | | return |
| | | } |
| | | ctx.Ok() |
| | | |
| | | 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, ¶ms) |
| | | 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, ¶ms) |
| | | 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, ¶ms) |
| | | 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 |
| | |
| | | client := crm_aps.NewCrmAndApsGrpcServiceClient(grpc_init.CrmApsGrpcServiceConn) |
| | | projectList, err := client.GetApsProjectList(c, &crm_aps.GetApsProjectListRequest{}) |
| | | if err != nil { |
| | | ctx.FailWithMsg(ecode.UnknownErr, "grpc调用错误: "+err.Error()) |
| | | logx.Errorf("grpc GetApsProjectList err: %v", err.Error()) |
| | | ctx.FailWithMsg(ecode.UnknownErr, "获取aps项目列表失败") |
| | | return |
| | | } |
| | | ctx.OkWithDetailed(projectList.List) |
| | | } |
| | | |
| | | // SendSalesDetailsToApsProject |
| | | // SendSalesDetailsToOtherSystem |
| | | // |
| | | // @Tags SalesDetails |
| | | // @Summary 推送销售明细信息到aps项目模块 |
| | | // @Summary 推送销售明细信息到其他系统 |
| | | // @Produce application/json |
| | | // @Param object body request.SalesDetails true "查询参数" |
| | | // @Success 200 {object} response.ListResponse |
| | | // |
| | | // @Router /api/salesDetails/sendSalesDetailsToApsProject [post] |
| | | func (s *SalesDetailsApi) SendSalesDetailsToApsProject(c *gin.Context) { |
| | | // @Router /api/salesDetails/sendSalesDetailsToOtherSystem [post] |
| | | func (s *SalesDetailsApi) SendSalesDetailsToOtherSystem(c *gin.Context) { |
| | | var params request.SalesDetails |
| | | ctx, ok := contextx.NewContext(c, ¶ms) |
| | | 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 |
| | | } |
| | | |
| | | products := make([]*crm_aps.SalesDetailsProduct, 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() |
| | | // 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() |
| | | products = append(products, &sp) |
| | | ApsProducts = append(ApsProducts, &sp) |
| | | total = total.Add(product.Amount) |
| | | } |
| | | |
| | | client := crm_aps.NewCrmAndApsGrpcServiceClient(grpc_init.CrmApsGrpcServiceConn) |
| | | _, err = client.SendSalesDetailsToApsProject(c, &crm_aps.SendSalesDetailsToApsProjectRequest{ |
| | | 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, |
| | |
| | | Source: params.Source, |
| | | ProductTotal: total.IntPart(), |
| | | ProjectId: params.ProjectId, |
| | | Products: products, |
| | | Products: ApsProducts, |
| | | }) |
| | | if err != nil { |
| | | ctx.FailWithMsg(ecode.UnknownErr, "grpc调用错误: "+err.Error()) |
| | | //状态还原 |
| | | 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() |