zhangqian
2024-03-15 5083f183f6f2695198c02027640c0f98e067522e
proto/product_inventory/server.go
@@ -5,6 +5,7 @@
   "errors"
   "github.com/shopspring/decimal"
   "strconv"
   "strings"
   "time"
   "wms/constvar"
   "wms/models"
@@ -20,8 +21,6 @@
   ProductId      string          `json:"productId"`
   Amount         decimal.Decimal `json:"amount"`
   LocationId     int             `json:"locationId"`
   FromLocationId int             `json:"fromLocationId"`
   ToLocationId   int             `json:"toLocationId"`
   Number         string          `json:"number"`
   WaybillNumber  string          `json:"waybillNumber"`
   Name           string          `json:"name"`
@@ -35,47 +34,49 @@
   var details []ProductAndLocationInfo
   var productIds []string
   resp := new(GetInventoryProductInfoResponse)
   search := models.NewOperationDetailsSearch().Orm.Model(&models.OperationDetails{}).
      Select("wms_operation_details.product_id,wms_operation_details.amount,wms_operation_details.from_location_id,wms_operation_details.to_location_id"+
   err := models.NewOperationDetailsSearch().Orm.Model(&models.OperationDetails{}).
      Select("wms_operation_details.product_id,wms_operation_details.amount,wms_operation_details.from_location_id as location_id,"+
         "wms_operation.number,wms_operation.waybill_number, logistic_company.name").
      Joins("left join wms_operation on wms_operation.id = wms_operation_details.operation_id").
      Joins("left join logistic_company on logistic_company.id = wms_operation.logistic_company_id").
      Where("wms_operation.source_number = ?", req.Number)
   if req.IsInput {
      search.Where("wms_operation.base_operation_type = ?", constvar.BaseOperationTypeIncoming)
   }
   if req.IsOutput {
      search.Where("wms_operation.base_operation_type = ?", constvar.BaseOperationTypeOutgoing)
   }
   err := search.Find(&details).Error
      Where("wms_operation.source_number = ?", req.Number).Find(&details).Error
   if err != nil {
      return nil, err
   }
   if len(details) == 0 {
      return resp, nil
   }
   var locationIds []int
   var locationId int
   for _, detail := range details {
      productIds = append(productIds, detail.ProductId)
      if req.IsInput { //只查入库
         locationIds = append(locationIds, detail.ToLocationId)
      } else if req.IsOutput { //只查出库
         locationIds = append(locationIds, detail.FromLocationId)
      }
      locationId = detail.FromLocationId
      locationId = detail.LocationId
   }
   //查询产品信息
   materials, err := models.NewMaterialSearch().SetIDs(productIds).FindNotTotal()
   if err != nil {
      return nil, err
   }
   locationHouseMap, houseLocations, houseMap, err := service.GetWarehouseByLocationIds(locationIds)
   //查询位置信息
   location, err := models.NewLocationSearch().SetID(locationId).First()
   if err != nil {
      return nil, err
   }
   warehouse := locationHouseMap[locationId]
   amounts, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).SetLocationIds(locationIds).SetPreload(true).Find()
   //根据仓库缩写查询仓库
   code := strings.Split(location.JointName, "/")[0]
   warehouse, err := models.NewWarehouseSearch().SetCode(code).First()
   if err != nil {
      return nil, err
   }
   //统计仓库下所有位置的产品在库数量
   locations, err := models.NewLocationSearch().SetJointName(code).FindNotTotal()
   if err != nil {
      return nil, err
   }
   var locationIds []int
   for _, l := range locations {
      locationIds = append(locationIds, l.Id)
   }
   amounts, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).SetLocationIds(locationIds).Find()
   if err != nil {
      return nil, err
   }
@@ -135,60 +136,6 @@
      products = append(products, &p)
   }
   resp.ProductList = products
   if req.GroupByWarehouse {
      canUseMap := make(map[int]map[string]decimal.Decimal) //map[locationID]map[productID]decimal
      for _, v := range canUse {
         if canUseMap[v.LocationId] == nil {
            canUseMap[v.LocationId] = make(map[string]decimal.Decimal)
         }
         canUseMap[v.LocationId][v.ProductId] = canUseMap[v.LocationId][v.ProductId].Add(v.Amount)
      }
      locationProductAmounts := make(map[int][]*models.LocationProductAmount)
      for _, v := range amounts {
         if locationProductAmounts[v.LocationId] == nil {
            locationProductAmounts[v.LocationId] = make([]*models.LocationProductAmount, 0)
         }
         locationProductAmounts[v.LocationId] = append(locationProductAmounts[v.LocationId], v)
      }
      materialMap := service.MaterialMap(materials)
      var warehouseProductsList []*WarehouseProducts
      for houseID, locationIDs := range houseLocations {
         house := houseMap[houseID]
         productAmountMap := make(map[string]decimal.Decimal, 0)
         productAvailableNumberMap := make(map[string]decimal.Decimal, 0)
         productInfoList := make([]*ProductInfo, 0)
         houseProductAmounts := make([]*models.LocationProductAmount, 0)
         for _, lid := range locationIDs {
            houseProductAmounts = append(houseProductAmounts, locationProductAmounts[lid]...)
         }
         for _, v := range houseProductAmounts {
            productAmountMap[v.ProductId] = productAmountMap[v.ProductId].Add(v.Amount)
            productAvailableNumberMap[v.ProductId] = productAvailableNumberMap[v.ProductId].Add(canUseMap[v.LocationId][v.ProductId])
         }
         for productID, amount := range productAvailableNumberMap {
            productInfoList = append(productInfoList, &ProductInfo{
               Number:          productID,
               Name:            materialMap[productID].Name,
               Unit:            materialMap[productID].Unit,
               Amount:          productAmountMap[productID].String(),
               AvailableNumber: amount.String(),
            })
         }
         warehouseProducts := &WarehouseProducts{
            WarehouseID:   house.Code,
            WarehouseName: house.Name,
            ProductList:   productInfoList,
         }
         warehouseProductsList = append(warehouseProductsList, warehouseProducts)
      }
      resp.WarehouseProductsList = warehouseProductsList
   }
   return resp, nil
}
@@ -256,3 +203,109 @@
   resp := new(CreateOperationResponse)
   return resp, err
}
type InputAndOutputDetails struct {
   ProductId         string                     `json:"productId"`
   Amount            decimal.Decimal            `json:"amount"`
   FromLocationId    int                        `json:"fromLocationId"`
   ToLocationId      int                        `json:"toLocationId"`
   Number            string                     `json:"number"`
   WaybillNumber     string                     `json:"waybillNumber"`
   Name              string                     `json:"name"`
   BaseOperationType constvar.BaseOperationType `json:"baseOperationType"`
   Status            constvar.OperationStatus   `json:"status"`
   CreatedAt         time.Time
}
func (s *Server) GetOrderInputAndOutputInfo(ctx context.Context, req *GetOrderInputAndOutputInfoRequest) (*GetOrderInputAndOutputInfoResponse, error) {
   if req.Number == "" {
      return nil, errors.New("参数不能为空")
   }
   var details []InputAndOutputDetails
   var productIds []string
   resp := new(GetOrderInputAndOutputInfoResponse)
   search := models.NewOperationDetailsSearch().Orm.Model(&models.OperationDetails{}).
      Select("wms_operation_details.product_id,wms_operation_details.amount,wms_operation_details.from_location_id,wms_operation_details.to_location_id,"+
         "wms_operation.number,wms_operation.waybill_number, logistic_company.name, wms_operation.base_operation_type, wms_operation.status, wms_operation.created_at").
      Joins("left join wms_operation on wms_operation.id = wms_operation_details.operation_id").
      Joins("left join logistic_company on logistic_company.id = wms_operation.logistic_company_id").
      Where("wms_operation.source_number = ?", req.Number).
      Where("wms_operation.base_operation_type in ?", []constvar.BaseOperationType{
         constvar.BaseOperationTypeIncoming, constvar.BaseOperationTypeOutgoing}).
      Where("wms_operation.status in ?", []constvar.OperationStatus{constvar.OperationStatus_Ready, constvar.OperationStatus_Finish})
   err := search.Find(&details).Error
   if err != nil {
      return nil, err
   }
   if len(details) == 0 {
      return resp, nil
   }
   var locationIds []int
   productInputMap := make(map[string]decimal.Decimal)
   productOutputMap := make(map[string]decimal.Decimal)
   for _, detail := range details {
      productIds = append(productIds, detail.ProductId)
      if detail.BaseOperationType == constvar.BaseOperationTypeIncoming {
         productInputMap[detail.ProductId] = productInputMap[detail.ProductId].Add(detail.Amount)
         locationIds = append(locationIds, detail.ToLocationId) //入库位置
      }
      if detail.BaseOperationType == constvar.BaseOperationTypeOutgoing {
         productOutputMap[detail.ProductId] = productOutputMap[detail.ProductId].Add(detail.Amount)
      }
   }
   //查询产品信息
   materials, err := models.NewMaterialSearch().SetIDs(productIds).FindNotTotal()
   if err != nil {
      return nil, err
   }
   locationHouseMap, _, _, err := service.GetWarehouseByLocationIds(locationIds)
   if err != nil {
      return nil, err
   }
   materialsMap := service.MaterialMap(materials)
   inputList := make([]*InputAndOutputInfo, 0)
   outputList := make([]*InputAndOutputInfo, 0)
   for _, detail := range details {
      if materialsMap[detail.ProductId] == nil {
         continue
      }
      material := materialsMap[detail.ProductId]
      var info InputAndOutputInfo
      info.Number = material.ID
      info.Name = material.Name
      info.OrderAmount = detail.Amount.String()
      info.Valorem = detail.Amount.Mul(material.SalePrice).String()
      info.Invoice = detail.Number
      info.Carrier = detail.Name
      info.Waybill = detail.WaybillNumber
      info.Unit = material.Unit
      info.SalePrice = material.SalePrice.String()
      info.Amount = detail.Amount.String()
      info.CreateTime = detail.CreatedAt.Format("2006-01-02 15:04")
      if detail.Status == constvar.OperationStatus_Finish { //是否完成
         info.Status = FinishStatus_Finish
      } else {
         info.Status = FinishStatus_Ready
      }
      if detail.BaseOperationType == constvar.BaseOperationTypeIncoming && detail.Status == constvar.OperationStatus_Finish {
         if locationHouseMap[detail.ToLocationId] != nil {
            info.Warehouse = locationHouseMap[detail.ToLocationId].Name //入库仓库名
         }
         inputList = append(inputList, &info)
      } else if detail.BaseOperationType == constvar.BaseOperationTypeOutgoing {
         if locationHouseMap[detail.FromLocationId] != nil {
            info.Warehouse = locationHouseMap[detail.FromLocationId].Name //发货仓库名
         }
         outputList = append(outputList, &info)
      }
   }
   resp.InputList = inputList
   resp.OutputList = outputList
   return resp, nil
}