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{}
|
|
// Add
|
//
|
// @Tags SalesDetails
|
// @Summary 添加销售明细
|
// @Produce application/json
|
// @Param object body request.AddSalesDetails true "查询参数"
|
// @Success 200 {object} contextx.Response{data=request.AddSalesDetails}
|
// @Router /api/salesDetails/add [post]
|
func (s *SalesDetailsApi) Add(c *gin.Context) {
|
var params request.AddSalesDetails
|
ctx, ok := contextx.NewContext(c, ¶ms)
|
if !ok {
|
return
|
}
|
|
errCode, salesDetails := checkSalesDetailsParams(params.SalesDetails)
|
if errCode != ecode.OK {
|
ctx.Fail(errCode)
|
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
|
}
|
|
ctx.OkWithDetailed(salesDetails)
|
}
|
|
// Delete
|
//
|
// @Tags SalesDetails
|
// @Summary 删除销售明细
|
// @Produce application/json
|
// @Param id path int true "查询参数"
|
// @Success 200 {object} contextx.Response{}
|
// @Router /api/salesDetails/delete/{id} [delete]
|
func (s *SalesDetailsApi) Delete(c *gin.Context) {
|
ctx, ok := contextx.NewContext(c, nil)
|
if !ok {
|
return
|
}
|
|
id, _ := strconv.Atoi(c.Param("id"))
|
errCode := salesDetailsService.DeleteSalesDetails(id)
|
if errCode != ecode.OK {
|
ctx.Fail(errCode)
|
return
|
}
|
|
ctx.Ok()
|
}
|
|
// BatchDelete
|
// @Tags SalesDetails 销售明细
|
// @Summary 批量删除销售明细
|
// @Produce application/json
|
// @Param object body request.CommonIds true "参数"
|
// @Success 200 {object} contextx.Response{}
|
// @Router /api/salesDetails/delete [delete]
|
func (s *SalesDetailsApi) BatchDelete(c *gin.Context) {
|
var params request.CommonIds
|
ctx, ok := contextx.NewContext(c, ¶ms)
|
if !ok {
|
return
|
}
|
|
errCode := salesDetailsService.BatchDeleteSalesDetails(params.Ids)
|
if errCode != ecode.OK {
|
ctx.Fail(errCode)
|
return
|
}
|
|
ctx.Ok()
|
}
|
|
// Update
|
//
|
// @Tags SalesDetails
|
// @Summary 更新销售明细
|
// @Produce application/json
|
// @Param object body request.UpdateSalesDetails true "查询参数"
|
// @Success 200 {object} contextx.Response{}
|
// @Router /api/salesDetails/update [put]
|
func (s *SalesDetailsApi) Update(c *gin.Context) {
|
var params request.UpdateSalesDetails
|
ctx, ok := contextx.NewContext(c, ¶ms)
|
if !ok {
|
return
|
}
|
|
errCode, salesDetails := checkSalesDetailsParams(params.SalesDetails)
|
if errCode != ecode.OK {
|
ctx.Fail(errCode)
|
return
|
}
|
|
salesDetails.Id = params.Id
|
errCode = salesDetailsService.UpdateSalesDetails(&salesDetails)
|
if errCode != ecode.OK {
|
ctx.Fail(errCode)
|
return
|
}
|
|
ctx.Ok()
|
}
|
|
func checkSalesDetailsParams(salesDetails request.SalesDetails) (errCode int, salesDetailsModel model.SalesDetails) {
|
salesDetailsModel.ClientId = salesDetails.ClientId
|
salesDetailsModel.Number = salesDetails.Number
|
salesDetailsModel.SaleChanceId = salesDetails.SaleChanceId
|
salesDetailsModel.SaleType = salesDetails.SaleType
|
salesDetailsModel.SignTime = salesDetails.SignTime
|
salesDetailsModel.MemberId = salesDetails.MemberId
|
salesDetailsModel.DeliveryDate = salesDetails.DeliveryDate
|
salesDetailsModel.WechatOrderStatusId = salesDetails.WechatOrderStatusId
|
salesDetailsModel.Address = salesDetails.Address
|
salesDetailsModel.Phone = salesDetails.Phone
|
salesDetailsModel.Remark = salesDetails.Remark
|
salesDetailsModel.Addressee = salesDetails.Addressee
|
salesDetailsModel.Conditions = salesDetails.Conditions
|
salesDetailsModel.Products = salesDetails.Products
|
salesDetailsModel.LogisticCompany = salesDetails.LogisticCompany
|
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
|
}
|
|
// List
|
//
|
// @Tags SalesDetails
|
// @Summary 销售明细单列表
|
// @Produce application/json
|
// @Param object body request.GetSalesDetailsList true "参数"
|
// @Success 200 {object} contextx.Response{data=response.SalesDetailsResponse}
|
// @Router /api/salesDetails/list [post]
|
func (con *SalesDetailsApi) List(c *gin.Context) {
|
var params request.GetSalesDetailsList
|
ctx, ok := contextx.NewContext(c, ¶ms)
|
if !ok {
|
return
|
}
|
|
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
|
}
|
|
ctx.OkWithDetailed(response.SalesDetailsResponse{
|
List: salesDetailss,
|
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, ¶ms)
|
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.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
|
}
|
var list []response.ProductInfo
|
err = structx.AssignTo(info.ProductList, &list)
|
if err != nil {
|
ctx.FailWithMsg(ecode.UnknownErr, "转换错误")
|
return
|
}
|
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, ¶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
|
grpcInputList := grpcResp.InputList
|
inputProductMap := make(map[string]*response.StoreInfo)
|
outputProductMap := make(map[string]*response.OutputSimpleInfo)
|
for _, v := range grpcOutputList {
|
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 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.Number,
|
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)
|
}
|
|
// 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
|
//
|
// @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, ¶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
|
}
|
|
//推送到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()
|
}
|