| | |
| | | "errors" |
| | | "github.com/shopspring/decimal" |
| | | "strconv" |
| | | "strings" |
| | | "time" |
| | | "wms/constvar" |
| | | "wms/models" |
| | |
| | | } |
| | | |
| | | type ProductAndLocationInfo struct { |
| | | 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"` |
| | | ProductId string `json:"productId"` |
| | | Amount decimal.Decimal `json:"amount"` |
| | | LocationId int `json:"locationId"` |
| | | Number string `json:"number"` |
| | | WaybillNumber string `json:"waybillNumber"` |
| | | Name string `json:"name"` |
| | | } |
| | | |
| | | func (s *Server) GetInventoryProductInfo(ctx context.Context, req *GetInventoryProductInfoRequest) (*GetInventoryProductInfoResponse, error) { |
| | |
| | | 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 |
| | | } |
| | |
| | | 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 |
| | | } |
| | | |
| | |
| | | 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 |
| | | } |