jiangshuai
2023-11-03 015c07410b59bafd606bd4f567a61355c4f15958
controllers/reorder_rule_controller.go
New file
@@ -0,0 +1,311 @@
package controllers
import (
   "github.com/gin-gonic/gin"
   "github.com/shopspring/decimal"
   "gorm.io/gorm"
   "strconv"
   "strings"
   "time"
   "wms/constvar"
   "wms/extend/code"
   "wms/extend/util"
   "wms/models"
   "wms/pkg/timex"
   "wms/request"
)
type ReorderRuleController struct {
}
// AddReorderRule
// @Tags      重订货规则
// @Summary   添加重订货规则
// @Produce   application/json
// @Param     object  body  models.ReorderRule true  "重订货规则"
// @Success   200 {object} util.Response "成功"
// @Router    /api-wms/v1/reorderRule/addReorderRule [post]
func (slf ReorderRuleController) AddReorderRule(c *gin.Context) {
   var params models.ReorderRule
   if err := c.BindJSON(&params); err != nil {
      util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
      return
   }
   count, err := models.NewReorderRuleSearch().SetProductId(params.ProductId).SetLocationId(params.LocationId).Count()
   if err != nil {
      util.ResponseFormat(c, code.RequestError, "数据验证错误")
      return
   }
   if count > 0 {
      util.ResponseFormat(c, code.RequestError, "当前位置已存在相同产品的重订货规则")
      return
   }
   err = models.NewReorderRuleSearch().Create(&params)
   if err != nil {
      util.ResponseFormat(c, code.RequestError, "重订货规则保存失败")
      return
   }
   util.ResponseFormat(c, code.Success, "保存成功")
}
// GetReorderRuleList
// @Tags      重订货规则
// @Summary   获取重订货规则列表
// @Produce   application/json
// @Param     object  body  request.GetReorderRuleList true  "参数"
// @Success   200 {object} util.ResponseList{data=[]models.ReorderRule} "成功"
// @Router    /api-wms/v1/reorderRule/getReorderRuleList [post]
func (slf ReorderRuleController) GetReorderRuleList(c *gin.Context) {
   var params request.GetReorderRuleList
   if err := c.BindJSON(&params); err != nil {
      util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
      return
   }
   search := models.NewReorderRuleSearch()
   if params.PageInfo.Check() {
      search.SetPage(params.Page, params.PageSize)
   }
   rules, total, err := search.SetPreload(true).SetKeyword(params.KeyWord).SetLocationId(params.LocationId).SetProductId(params.ProductId).Find()
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询重订货规则列表失败")
      return
   }
   productIds := make([]string, 0)
   locationIds := make([]int, 0)
   for _, rule := range rules {
      productIds = append(productIds, rule.ProductId)
      locationIds = append(locationIds, rule.LocationId)
   }
   if params.LocationId != 0 {
      locationIds = []int{params.LocationId}
   }
   if params.ProductId != "" {
      productIds = []string{params.ProductId}
   }
   //在库
   amounts, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).SetLocationIds(locationIds).Find()
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询在库数量失败")
      return
   }
   for _, rule := range rules {
      for _, amount := range amounts {
         if rule.ProductId == amount.ProductId && rule.LocationId == amount.LocationId {
            rule.Amount = rule.Amount.Add(amount.Amount)
         }
      }
   }
   //预测
   //入库就绪
   var status = []constvar.OperationStatus{constvar.OperationStatus_Ready}
   var operationType = []constvar.BaseOperationType{constvar.BaseOperationTypeIncoming, constvar.BaseOperationTypeInternal}
   amount, err := GetProductAmount(productIds, locationIds, nil, status, operationType)
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询重订货规则列表失败")
      return
   }
   for _, rule := range rules {
      for _, productAmount := range amount {
         if rule.ProductId == productAmount.ProductId && rule.LocationId == productAmount.ToLocationId {
            rule.Prediction = rule.Prediction.Add(productAmount.Amount)
         }
      }
      rule.Prediction = rule.Amount.Add(rule.Prediction)
   }
   //出库就绪
   operationType = []constvar.BaseOperationType{constvar.BaseOperationTypeOutgoing, constvar.BaseOperationTypeInternal}
   amount, err = GetProductAmount(productIds, nil, locationIds, status, operationType)
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询重订货规则列表失败")
      return
   }
   for _, rule := range rules {
      for _, productAmount := range amount {
         if rule.ProductId == productAmount.ProductId && rule.LocationId == productAmount.FromLocationId {
            rule.Prediction = rule.Prediction.Sub(productAmount.Amount)
         }
      }
   }
   var result []*models.ReorderRule
   if params.Type == "" {
      result = rules
   } else {
      for _, rule := range rules {
         if rule.MinInventory.GreaterThan(rule.Prediction) {
            result = append(result, rule)
         }
      }
   }
   util.ResponseFormatList(c, code.Success, result, int(total))
}
// 计算在库与预测数量
func GetProductAmount(productIds []string, toLocationIds []int, fromLocationIds []int, status []constvar.OperationStatus,
   operationType []constvar.BaseOperationType) ([]request.ProductAmount, error) {
   var pa []request.ProductAmount
   search := models.NewOperationDetailsSearch()
   search.Orm = search.Orm.Model(&models.OperationDetails{}).
      Select("wms_operation_details.product_id, wms_operation_details.amount, wms_operation.to_location_id as to_location_id, " +
         "wms_operation.from_location_id as from_location_id, wms_operation.base_operation_type").
      Joins("left join wms_operation on wms_operation_details.operation_id = wms_operation.id")
   if len(productIds) > 0 {
      search.Orm.Where("wms_operation_details.product_id in (?)", productIds)
   }
   if len(toLocationIds) > 0 {
      search.Orm.Where("wms_operation.to_location_id in (?)", toLocationIds)
   }
   if len(fromLocationIds) > 0 {
      search.Orm.Where("wms_operation.from_location_id in (?)", fromLocationIds)
   }
   if len(status) > 0 {
      search.Orm.Where("wms_operation.status in (?)", status)
   }
   if len(operationType) > 0 {
      search.Orm.Where("wms_operation.base_operation_type in (?)", operationType)
   }
   err := search.Orm.Find(&pa).Error
   return pa, err
}
// GetAmountAndPrediction
// @Tags      重订货规则
// @Summary   获取在库与预测数量
// @Produce   application/json
// @Param     object  body  request.GetAmountAndPrediction true  "重订货规则"
// @Success   200 {object} util.ResponseList{data=[]map[string]interface{}} "成功"
// @Router    /api-wms/v1/reorderRule/getAmountAndPrediction [post]
func (slf ReorderRuleController) GetAmountAndPrediction(c *gin.Context) {
   var params request.GetAmountAndPrediction
   if err := c.BindJSON(&params); err != nil {
      util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
      return
   }
   productIds := make([]string, 0)
   locationIds := make([]int, 0)
   productIds = append(productIds, params.ProductId)
   locationIds = append(locationIds, params.LocationId)
   amount := decimal.NewFromInt(0)
   prediction := decimal.NewFromInt(0)
   //在库
   find, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).SetLocationIds(locationIds).Find()
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询在库数量失败")
      return
   }
   for _, productAmount := range find {
      if params.ProductId == productAmount.ProductId && params.LocationId == productAmount.LocationId {
         amount = amount.Add(productAmount.Amount)
      }
   }
   //预测
   //入库就绪
   var status = []constvar.OperationStatus{constvar.OperationStatus_Ready}
   var operationType = []constvar.BaseOperationType{constvar.BaseOperationTypeIncoming, constvar.BaseOperationTypeInternal}
   list, err := GetProductAmount(productIds, locationIds, nil, status, operationType)
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询重订货规则列表失败")
      return
   }
   for _, productAmount := range list {
      if params.ProductId == productAmount.ProductId && params.LocationId == productAmount.ToLocationId {
         prediction = prediction.Add(productAmount.Amount)
      }
   }
   prediction = amount.Add(prediction)
   //出库就绪
   operationType = []constvar.BaseOperationType{constvar.BaseOperationTypeOutgoing, constvar.BaseOperationTypeInternal}
   list, err = GetProductAmount(productIds, nil, locationIds, status, operationType)
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询重订货规则列表失败")
      return
   }
   for _, productAmount := range list {
      if params.ProductId == productAmount.ProductId && params.LocationId == productAmount.FromLocationId {
         prediction = prediction.Sub(productAmount.Amount)
      }
   }
   m := make(map[string]int64)
   m["amount"] = amount.IntPart()
   m["prediction"] = prediction.IntPart()
   util.ResponseFormat(c, code.Success, m)
}
// UpdateReorderRule
// @Tags      重订货规则
// @Summary   更新重订货规则
// @Produce   application/json
// @Param     object  body  models.ReorderRule true  "重订货规则"
// @Success   200 {object} util.Response "成功"
// @Router    /api-wms/v1/reorderRule/updateReorderRule [post]
func (slf ReorderRuleController) UpdateReorderRule(c *gin.Context) {
   var params models.ReorderRule
   if err := c.BindJSON(&params); err != nil {
      util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
      return
   }
   err := models.NewReorderRuleSearch().SetID(params.Id).Update(&params)
   if err != nil {
      util.ResponseFormat(c, code.RequestError, "重订货规则更新失败")
      return
   }
   util.ResponseFormat(c, code.Success, "更新成功")
}
// OrderAgain
// @Tags      重订货规则
// @Summary   再订一次
// @Produce   application/json
// @Param     object  body  models.ReorderRule true  "重订货规则"
// @Success   200 {object} util.Response "成功"
// @Router    /api-wms/v1/reorderRule/orderAgain [post]
func (slf ReorderRuleController) OrderAgain(c *gin.Context) {
   var params models.ReorderRule
   if err := c.BindJSON(&params); err != nil {
      util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
      return
   }
   location, err := models.NewLocationSearch().SetID(params.LocationId).First()
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询位置信息失败")
      return
   }
   houseCode := strings.Split(location.JointName, "/")[0]
   var operationType models.OperationType
   err = models.NewOperationTypeSearch().Orm.Model(&models.OperationType{}).Joins("left join wms_warehouse on wms_job_type.warehouse_id = wms_warehouse.id").
      Where("wms_job_type.base_operation_type = 1 and wms_warehouse.code = ?", houseCode).First(&operationType).Error
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "查询位置信息失败")
      return
   }
   var operation models.Operation
   var details models.OperationDetails
   details.ProductId = params.ProductId
   details.Amount = params.OrderNumber
   operation.Details = append(operation.Details, &details)
   operation.BaseOperationType = constvar.BaseOperationTypeIncoming
   operation.Status = constvar.OperationStatus_Ready
   operation.OperationTypeId = operationType.Id
   operation.OperationTypeName = operationType.Name
   operation.OperationDate = timex.TimeToString2(time.Now())
   //todo 供应商位置
   operation.FromLocationID = 1
   operation.Number = strconv.FormatInt(time.Now().Unix(), 10)
   operation.ToLocationID = params.LocationId
   err = models.WithTransaction(func(db *gorm.DB) error {
      if err = models.NewOperationSearch().SetOrm(db).Create(&operation); err != nil {
         return err
      }
      params.OrderNumber = decimal.NewFromInt(0)
      err = models.NewReorderRuleSearch().SetID(params.Id).Update(&params)
      return err
   })
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "重订失败")
      return
   }
   util.ResponseFormat(c, code.Success, "重订成功")
}