package product_inventory
|
|
import (
|
"context"
|
"errors"
|
"github.com/shopspring/decimal"
|
"strconv"
|
"strings"
|
"time"
|
"wms/constvar"
|
"wms/models"
|
"wms/pkg/timex"
|
)
|
|
type Server struct {
|
UnimplementedProductInventoryServiceServer
|
}
|
|
type ProductAndLocationInfo struct {
|
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) {
|
if req.Number == "" {
|
return nil, errors.New("参数不能为空")
|
}
|
//查询产品id
|
var details []ProductAndLocationInfo
|
var productIds []string
|
resp := new(GetInventoryProductInfoResponse)
|
err := models.NewOperationDetailsSearch().Orm.Model(&models.OperationDetails{}).
|
Select("wms_operation_details.product_id,wms_operation_details.amount,wms_operation.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).Find(&details).Error
|
if err != nil {
|
return nil, err
|
}
|
if len(details) == 0 {
|
return resp, nil
|
}
|
var locationId int
|
for _, detail := range details {
|
productIds = append(productIds, detail.ProductId)
|
locationId = detail.LocationId
|
}
|
//查询产品信息
|
materials, err := models.NewMaterialSearch().SetIDs(productIds).FindNotTotal()
|
if err != nil {
|
return nil, err
|
}
|
//查询位置信息
|
location, err := models.NewLocationSearch().SetID(locationId).First()
|
if err != nil {
|
return nil, err
|
}
|
//根据仓库缩写查询仓库
|
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
|
}
|
var inventory []ProductAndLocationInfo
|
for _, productAmount := range amounts {
|
var in ProductAndLocationInfo
|
in.ProductId = productAmount.ProductId
|
in.Amount = productAmount.Amount
|
inventory = append(inventory, in)
|
}
|
//统计可用数量
|
var canUse []ProductAndLocationInfo
|
err = models.NewOperationDetailsSearch().Orm.Model(&models.OperationDetails{}).
|
Select("wms_operation_details.product_id, wms_operation_details.amount").
|
Joins("left join wms_operation on wms_operation_details.operation_id = wms_operation.id").
|
Where("wms_operation_details.product_id in (?)", productIds).
|
Where("wms_operation.from_location_id in (?)", locationIds).Where("wms_operation.status = ?", constvar.OperationStatus_Ready).
|
Where("wms_operation.base_operation_type in (?)", []constvar.BaseOperationType{constvar.BaseOperationTypeOutgoing, constvar.BaseOperationTypeInternal, constvar.BaseOperationTypeDisuse}).
|
Find(&canUse).Error
|
if err != nil {
|
return nil, err
|
}
|
products := make([]*ProductInfo, 0)
|
for _, material := range materials {
|
var p ProductInfo
|
p.Id = material.ID
|
p.Name = material.Name
|
for _, detail := range details {
|
if material.ID == detail.ProductId {
|
p.OrderAmount = detail.Amount.String()
|
p.Valorem = detail.Amount.Mul(material.SalePrice).String()
|
p.Invoice = detail.Number
|
p.Carrier = detail.Name
|
p.Waybill = detail.WaybillNumber
|
break
|
}
|
}
|
p.Unit = material.Unit
|
p.SalePrice = material.SalePrice.String()
|
p.Warehouse = warehouse.Name
|
at := decimal.NewFromInt(0)
|
for _, info := range inventory {
|
if material.ID == info.ProductId {
|
at = at.Add(info.Amount)
|
}
|
}
|
p.Amount = at.String()
|
cu := decimal.NewFromInt(0)
|
for _, info := range canUse {
|
if material.ID == info.ProductId {
|
cu = cu.Add(info.Amount)
|
}
|
}
|
cu = at.Sub(cu)
|
p.AvailableNumber = cu.String()
|
|
products = append(products, &p)
|
}
|
resp.ProductList = products
|
return resp, nil
|
}
|
|
func (s *Server) CreateOperation(ctx context.Context, req *CreateOperationRequest) (*CreateOperationResponse, error) {
|
var operations []*models.Operation
|
var operation models.Operation
|
var details []*models.OperationDetails
|
operation.SourceNumber = req.Number
|
operation.OperationDate = timex.TimeToString2(time.Now())
|
operation.Number = strconv.FormatInt(time.Now().Unix(), 10)
|
operation.Status = constvar.OperationStatus_Ready
|
warehouse, err := models.NewWarehouseSearch().First()
|
if err != nil {
|
return nil, err
|
}
|
operationType, err := models.NewOperationTypeSearch().SetWarehouseId(warehouse.Id).SetBaseOperationType(constvar.BaseOperationTypeOutgoing).First()
|
if err != nil {
|
return nil, err
|
}
|
operation.OperationTypeName = operationType.Name
|
operation.OperationTypeId = operationType.Id
|
location, err := models.NewLocationSearch().SetJointNames([]string{warehouse.Code}).First()
|
if err != nil {
|
return nil, err
|
}
|
operation.FromLocationID = location.Id
|
first, err := models.NewLocationSearch().SetType(int(constvar.LocationTypeCustomer)).First()
|
if err != nil {
|
return nil, err
|
}
|
operation.ToLocationID = first.Id
|
operation.BaseOperationType = constvar.BaseOperationTypeOutgoing
|
if req.DeliverType == 1 {
|
for _, product := range req.ProductList {
|
var detail models.OperationDetails
|
detail.ProductId = product.Id
|
amount, _ := decimal.NewFromString(product.Amount)
|
detail.Amount = amount
|
details = append(details, &detail)
|
}
|
operation.Details = details
|
operations = append(operations, &operation)
|
} else {
|
for _, product := range req.ProductList {
|
newOperation := operation
|
var detail models.OperationDetails
|
detail.ProductId = product.Id
|
amount, _ := decimal.NewFromString(product.Amount)
|
detail.Amount = amount
|
details = append(details, &detail)
|
newOperation.Details = append(newOperation.Details, &detail)
|
operations = append(operations, &newOperation)
|
}
|
}
|
err = models.NewOperationSearch().CreateBatch(operations)
|
resp := new(CreateOperationResponse)
|
return resp, err
|
}
|