From 7d1b46b246613585acda03a2148db76ebea79de1 Mon Sep 17 00:00:00 2001
From: liujiandao <274878379@qq.com>
Date: 星期四, 18 四月 2024 18:16:17 +0800
Subject: [PATCH] 物料字段类型修改
---
proto/product_inventory/server.go | 417 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 334 insertions(+), 83 deletions(-)
diff --git a/proto/product_inventory/server.go b/proto/product_inventory/server.go
index 14fa029..41e54d1 100644
--- a/proto/product_inventory/server.go
+++ b/proto/product_inventory/server.go
@@ -3,11 +3,15 @@
import (
"context"
"errors"
+ "fmt"
"github.com/shopspring/decimal"
+ "gorm.io/gorm"
"strconv"
+ "strings"
"time"
"wms/constvar"
"wms/models"
+ "wms/pkg/logx"
"wms/pkg/timex"
"wms/service"
)
@@ -17,14 +21,12 @@
}
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) {
@@ -35,47 +37,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 +139,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
}
@@ -225,7 +175,8 @@
operation.ReceiverPhone = req.Phone
operation.ReceiverAddr = req.Address
operation.Source = req.Source
- operation.CompanyID = int(req.ClientId)
+ operation.OperationSource = constvar.OperationSource(req.OperationSource)
+ operation.CompanyID = strconv.FormatInt(req.ClientId, 10)
operation.CompanyName = req.ClientName
if req.DeliverType == 1 {
for _, product := range req.ProductList {
@@ -256,3 +207,303 @@
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.sales_details_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 //鍏ュ簱浠撳簱鍚�
+ info.LocationID = int64(detail.ToLocationId)
+ info.WareHouseID = int64(locationHouseMap[detail.ToLocationId].Id)
+ }
+ inputList = append(inputList, &info)
+ } else if detail.BaseOperationType == constvar.BaseOperationTypeOutgoing {
+ if locationHouseMap[detail.FromLocationId] != nil {
+ info.Warehouse = locationHouseMap[detail.FromLocationId].Name //鍙戣揣浠撳簱鍚�
+ info.LocationID = int64(detail.FromLocationId)
+ info.WareHouseID = int64(locationHouseMap[detail.FromLocationId].Id)
+ }
+ outputList = append(outputList, &info)
+ }
+ }
+ resp.InputList = inputList
+ resp.OutputList = outputList
+
+ return resp, nil
+}
+
+type StoreInfo struct {
+ Name string `json:"name"` //浜у搧鍚嶇О
+ Number string `json:"number"` //浜у搧缂栧彿
+ StoreAmount decimal.Decimal `json:"storeAmount"` //璁㈠崟鍏ュ簱鏁伴噺
+ AvailableAmount decimal.Decimal `json:"availableAmount"` //鍓╀綑鍙敤鏁伴噺
+}
+
+type OutputSimpleInfo struct {
+ Number string `json:"number"` //浜у搧缂栧彿
+ Amount decimal.Decimal `json:"amount"` //鍦ㄥ簱鏁伴噺
+ Status int `json:"status"` //0灏辩华 1瀹屾垚
+}
+
+func (s *Server) OrderProductOutput(ctx context.Context, req *OrderProductOutputRequest) (resp *OrderProductOutputResponse, err error) {
+ resp = new(OrderProductOutputResponse)
+ if req.OrderNumber == "" || len(req.Products) == 0 {
+ return nil, errors.New("鍙傛暟缂哄け")
+ }
+ orderInputAndOutputInfoResponse, err := s.GetOrderInputAndOutputInfo(ctx, &GetOrderInputAndOutputInfoRequest{
+ Number: req.OrderNumber,
+ })
+ if err != nil {
+ logx.Errorf("OrderProductOutput GetOrderInputAndOutputInfo err:%v, req:%v", err, req)
+ return nil, errors.New("鑾峰彇鍑哄叆搴撲俊鎭け璐�")
+ }
+
+ outputList := orderInputAndOutputInfoResponse.OutputList
+ inputList := orderInputAndOutputInfoResponse.InputList
+ inputProductMap := make(map[string]*StoreInfo)
+ outputProductMap := make(map[string]*OutputSimpleInfo)
+ inputLocationAmountMap := make(map[int64]map[string]decimal.Decimal)
+ outputLocationAmountMap := make(map[int64]map[string]decimal.Decimal)
+ for _, v := range outputList {
+ if req.WarehouseId != 0 && v.WareHouseID != req.WarehouseId {
+ continue
+ }
+ if outputProductMap[v.Number] == nil {
+ simpleInfo := &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 inputList {
+ if req.WarehouseId != 0 && v.WareHouseID != req.WarehouseId {
+ continue
+ }
+ if inputProductMap[v.Number] == nil {
+ storeInfo := &StoreInfo{
+ Number: v.Number,
+ Name: v.Name,
+ }
+ storeAmount, _ := decimal.NewFromString(v.Amount)
+ storeInfo.StoreAmount = storeAmount
+ storeInfo.AvailableAmount = storeAmount
+ inputProductMap[v.Number] = storeInfo
+ } else {
+ storeAmount, _ := decimal.NewFromString(v.Amount)
+ inputProductMap[v.Number].StoreAmount = inputProductMap[v.Number].StoreAmount.Add(storeAmount)
+ inputProductMap[v.Number].AvailableAmount = inputProductMap[v.Number].StoreAmount
+ }
+ }
+
+ for number, inputInfo := range inputProductMap {
+ outputInfo := outputProductMap[inputInfo.Number]
+ if outputInfo != nil {
+ inputProductMap[number].AvailableAmount = inputProductMap[number].AvailableAmount.Sub(outputInfo.Amount) //鍙敤鏁伴噺 = 鍏ュ簱瀹屾垚鏁伴噺 - 宸插彂璐ф暟閲�
+ }
+ }
+
+ //鏍¢獙鍙敤鏁伴噺鏄惁瓒冲
+ productNeedSendAmount := make(map[string]decimal.Decimal)
+ for _, product := range req.Products {
+ sendAmount, _ := decimal.NewFromString(product.Amount)
+ productNeedSendAmount[product.Number] = sendAmount
+ if inputProductMap[product.Number] == nil {
+ return nil, fmt.Errorf("鑾峰彇鍏ュ簱淇℃伅澶辫触锛屼骇鍝佺紪鍙凤細%v", product.Number)
+ }
+ if sendAmount.GreaterThan(inputProductMap[product.Number].AvailableAmount) {
+ return nil, fmt.Errorf("浜у搧鍙敤鏁伴噺涓嶈冻浠ュ彂璐э紝浜у搧缂栧彿锛�%v", product.Number)
+ }
+ }
+
+ LocationIDWarehouseIDMap := make(map[int64]int64)
+ for _, output := range outputList {
+ if req.WarehouseId != 0 && output.WareHouseID != req.WarehouseId {
+ continue
+ }
+ if outputLocationAmountMap[output.LocationID] == nil {
+ outputLocationAmountMap[output.LocationID] = make(map[string]decimal.Decimal)
+ }
+ outputAmount, _ := decimal.NewFromString(output.Amount)
+ outputLocationAmountMap[output.LocationID][output.Number] = outputAmount
+ }
+ for _, input := range inputList {
+ if req.WarehouseId != 0 && input.WareHouseID != req.WarehouseId {
+ continue
+ }
+ LocationIDWarehouseIDMap[input.LocationID] = input.WareHouseID
+
+ if inputLocationAmountMap[input.LocationID] == nil {
+ inputLocationAmountMap[input.LocationID] = make(map[string]decimal.Decimal)
+ }
+ storeAmount, _ := decimal.NewFromString(input.Amount)
+ if outputLocationAmountMap[input.LocationID] != nil {
+ storeAmount = storeAmount.Sub(outputLocationAmountMap[input.LocationID][input.Number])
+ }
+ inputLocationAmountMap[input.LocationID][input.Number] = storeAmount
+ }
+
+ productHasSendAmount := make(map[string]decimal.Decimal) //鏈宸插彂璐ф暟閲�
+
+ //find location ID
+ outputInfoList := make([]*service.OutputInfo, 0)
+ for locationID, locationProductAmounts := range inputLocationAmountMap {
+ productInfoList := make([]*service.ProductInfo, 0)
+ for productNumber, productAmount := range locationProductAmounts {
+ remainAmount := productNeedSendAmount[productNumber].Sub(productHasSendAmount[productNumber])
+ if remainAmount.LessThanOrEqual(decimal.Zero) {
+ continue
+ }
+ var locationSendAmount decimal.Decimal
+ if productAmount.GreaterThanOrEqual(remainAmount) {
+ locationSendAmount = remainAmount
+ } else {
+ locationSendAmount = productAmount
+ }
+ if locationSendAmount.LessThanOrEqual(decimal.Zero) {
+ continue
+ }
+ productInfoList = append(productInfoList, &service.ProductInfo{
+ ProductID: productNumber,
+ Amount: locationSendAmount,
+ })
+ productHasSendAmount[productNumber] = productHasSendAmount[productNumber].Add(locationSendAmount)
+ }
+ outputInfoList = append(outputInfoList, &service.OutputInfo{
+ LocationID: int(locationID),
+ WarehouseID: int(LocationIDWarehouseIDMap[locationID]),
+ Products: productInfoList,
+ OperationID: 0,
+ SourceNumber: req.OrderNumber,
+ SaleDetailsNumber: req.OrderNumber,
+ })
+ }
+
+ err = service.AddOutputOperations(outputInfoList)
+
+ if err != nil {
+ logx.Errorf("OrderProductOutput AddOutputOperations err:%v", err)
+ return nil, err
+ }
+ resp.Code = 1
+ resp.Msg = "success"
+ return resp, nil
+}
+
+func (s *Server) GetOutputOperationInfo(ctx context.Context, req *GetOutputOperationInfoRequest) (*GetOutputOperationInfoResponse, error) {
+ if req.Number == "" {
+ return nil, errors.New("鍙傛暟涓嶈兘涓虹┖")
+ }
+ result := new(GetOutputOperationInfoResponse)
+ first, err := models.NewOperationSearch().SetSourceNumber(req.Number).SetBaseOperationType(constvar.BaseOperationTypeOutgoing).SetStatus(constvar.OperationStatus_Finish).First()
+ if err != nil {
+ if err == gorm.ErrRecordNotFound {
+ return result, nil
+ }
+ return nil, err
+ }
+ details, err := models.NewOperationDetailsSearch().SetOperationId(first.Id).FindNotTotal()
+ if err != nil {
+ return nil, err
+ }
+ list := make([]*OutputProduct, 0)
+ for _, detail := range details {
+ var op OutputProduct
+ op.Number = detail.ProductId
+ op.Amount = detail.Amount.String()
+ list = append(list, &op)
+ }
+ result.Products = list
+
+ return result, nil
+}
--
Gitblit v1.8.0