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 | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 314 insertions(+), 5 deletions(-)
diff --git a/proto/product_inventory/server.go b/proto/product_inventory/server.go
index b564f8d..41e54d1 100644
--- a/proto/product_inventory/server.go
+++ b/proto/product_inventory/server.go
@@ -3,13 +3,17 @@
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"
)
type Server struct {
@@ -34,7 +38,7 @@
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,"+
+ 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").
@@ -92,7 +96,7 @@
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_details.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 {
@@ -160,18 +164,19 @@
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.LocationID = location.Id
operation.BaseOperationType = constvar.BaseOperationTypeOutgoing
operation.ReceiverName = req.Addressee
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 {
@@ -179,6 +184,8 @@
detail.ProductId = product.Id
amount, _ := decimal.NewFromString(product.Amount)
detail.Amount = amount
+ detail.FromLocationID = location.Id
+ detail.ToLocationID = first.Id
details = append(details, &detail)
}
operation.Details = details
@@ -190,6 +197,8 @@
detail.ProductId = product.Id
amount, _ := decimal.NewFromString(product.Amount)
detail.Amount = amount
+ detail.FromLocationID = location.Id
+ detail.ToLocationID = first.Id
newOperation.Details = append(newOperation.Details, &detail)
operations = append(operations, &newOperation)
}
@@ -198,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