From 79aef24a785581d95343ccd99e9cb362b2bc9c97 Mon Sep 17 00:00:00 2001
From: yinbentan <yinbentan@live.com>
Date: 星期六, 06 七月 2024 21:31:59 +0800
Subject: [PATCH] 调整库存商品位置错误

---
 service/operation.go |  277 +++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 176 insertions(+), 101 deletions(-)

diff --git a/service/operation.go b/service/operation.go
index 59b3421..6c9fa72 100644
--- a/service/operation.go
+++ b/service/operation.go
@@ -4,6 +4,7 @@
 	"errors"
 	"fmt"
 	"github.com/gin-gonic/gin"
+	"github.com/mitchellh/mapstructure"
 	"github.com/shopspring/decimal"
 	"gorm.io/gorm"
 	"strconv"
@@ -90,6 +91,7 @@
 			LocationID:         output.LocationID,
 			OperationSource:    constvar.OperationSourceSaleDelivery,
 			SalesDetailsNumber: output.SaleDetailsNumber,
+			WarehouseId:        output.WarehouseID,
 		}
 		operations = append(operations, operation)
 		autoCode = models.GetAutoCode(maxAutoIncr, codeStandard)
@@ -127,7 +129,7 @@
 			return err
 		}
 
-		if roleProduct, ok := mapLocationRoleProduct[strconv.Itoa(operation.LocationID)+v.ProductId]; ok {
+		if roleProduct, ok := mapLocationRoleProduct[strconv.Itoa(v.ToLocationID)+v.ProductId]; ok {
 			detail := &models.OperationDetails{
 				ProductId:      v.ProductId,
 				Amount:         v.Amount,
@@ -138,22 +140,23 @@
 
 			if locAmount, aok := mapLocAmount[strconv.Itoa(roleProduct.LocationId)+v.ProductId]; aok {
 				locAmount.Amount = locAmount.Amount.Add(v.Amount)
-				if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
-					return res.Error
+				if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
+					return err
 				}
 			} else {
-				if err := models.NewLocationProductAmountSearch().Create(&models.LocationProductAmount{
+				if err := models.NewLocationProductAmountSearch().SetOrm(tx).Create(&models.LocationProductAmount{
 					LocationId:        roleProduct.LocationId,
 					ProductCategoryID: v.Product.CategoryId,
 					ProductId:         v.ProductId,
 					Amount:            v.Amount,
 					CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
+					WarehouseId:       operation.WarehouseId,
 				}); err != nil {
 					return err
 				}
 			}
 		} else {
-			if roleCategory, cok := mapLocationRoleCategory[strconv.Itoa(operation.LocationID)+strconv.Itoa(v.Product.CategoryId)]; cok {
+			if roleCategory, cok := mapLocationRoleCategory[strconv.Itoa(v.ToLocationID)+strconv.Itoa(v.Product.CategoryId)]; cok {
 				detail := &models.OperationDetails{
 					ProductId:      v.ProductId,
 					Amount:         v.Amount,
@@ -164,33 +167,36 @@
 
 				if locAmount, aok := mapLocAmount[strconv.Itoa(roleCategory.LocationId)+v.ProductId]; aok {
 					locAmount.Amount = locAmount.Amount.Add(v.Amount)
-					if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
-						return res.Error
+					if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
+						return err
 					}
 				} else {
-					if err := models.NewLocationProductAmountSearch().Create(&models.LocationProductAmount{
+					if err := models.NewLocationProductAmountSearch().SetOrm(tx).Create(&models.LocationProductAmount{
 						LocationId:        roleCategory.LocationId,
 						ProductCategoryID: v.Product.CategoryId,
 						ProductId:         v.ProductId,
 						Amount:            v.Amount,
 						CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
+						WarehouseId:       operation.WarehouseId,
 					}); err != nil {
 						return err
 					}
 				}
 			} else {
-				if locAmount, aok := mapLocAmount[strconv.Itoa(operation.LocationID)+v.ProductId]; aok {
+				if locAmount, aok := mapLocAmount[strconv.Itoa(v.ToLocationID)+v.ProductId]; aok {
 					locAmount.Amount = locAmount.Amount.Add(v.Amount)
-					if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
-						return res.Error
+					locAmount.ID = uint(locAmount.Id)
+					if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
+						return err
 					}
 				} else {
-					if err := models.NewLocationProductAmountSearch().Create(&models.LocationProductAmount{
-						LocationId:        operation.LocationID,
+					if err := models.NewLocationProductAmountSearch().SetOrm(tx).Create(&models.LocationProductAmount{
+						LocationId:        v.ToLocationID,
 						ProductCategoryID: v.Product.CategoryId,
 						ProductId:         v.ProductId,
 						Amount:            v.Amount,
 						CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
+						WarehouseId:       operation.WarehouseId,
 					}); err != nil {
 						return err
 					}
@@ -214,6 +220,7 @@
 			BaseOperationType: constvar.BaseOperationTypeInternal,
 			Details:           details,
 			CheckedBy:         userInfo.Username,
+			WarehouseId:       operation.WarehouseId,
 		}).Error; err != nil {
 			return err
 		}
@@ -223,7 +230,8 @@
 }
 
 // FinishOperationOutput 瀹屾垚鍑哄簱鎴栨姤搴�
-func FinishOperationOutput(tx *gorm.DB, listDetails []*models.OperationDetails, mapLocAmount map[string]*models.LocationProductAmount) (err error) {
+func FinishOperationOutput(tx *gorm.DB, listDetails []*models.OperationDetails, mapLocAmount map[string]*models.LocationProductAmount, originOperation *models.Operation) (err error) {
+	var internalInputDetails []*models.OperationDetails //鍐呴儴璋冩嫧浜х敓鐨勫嚭搴撻獙璇佸悗锛岀敓鎴愬叆搴撳崟
 	for k, v := range listDetails {
 		if v.Product.Amount.LessThan(v.Amount) {
 			return errors.New(fmt.Sprintf("浜у搧锛�%v,搴撳瓨锛�%v,鍑哄簱锛�%v,鏁伴噺涓嶅锛屾棤娉曞畬鎴愬嚭搴撴搷浣�", v.Product.Name, v.Product.Amount.String(), v.Amount.String()))
@@ -238,47 +246,86 @@
 				return errors.New(fmt.Sprintf("浜у搧锛�%v,搴撳瓨锛�%v,鍑哄簱锛�%v,鏁伴噺涓嶅锛屾棤娉曞畬鎴愬嚭搴撴搷浣�", v.Product.Name, locAmount.Amount.String(), v.Amount.String()))
 			}
 			locAmount.Amount = locAmount.Amount.Sub(v.Amount)
-			if err := models.NewLocationProductAmountSearch().SetID(locAmount.Id).Update(locAmount); err != nil {
+			if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(locAmount.Id).Save(locAmount); err != nil {
 				return err
 			}
 		} else {
 			return errors.New("褰撳墠浠撳簱娌℃湁璇ヤ骇鍝�,璇峰厛鍏ュ簱")
+		}
+		if v.IsInternalOutput {
+			var inputDetail models.OperationDetails
+			mapstructure.Decode(v, &inputDetail)
+			inputDetail.Id = 0
+			inputDetail.OperationID = 0
+			internalInputDetails = append(internalInputDetails, &inputDetail)
+		}
+	}
+	if len(internalInputDetails) > 0 {
+		opTypeId, err := GetTargetOperationTypeIdByWarehouseId(originOperation.ToLocation.WarehouseId, constvar.BaseOperationTypeIncoming)
+		if err != nil {
+			return err
+		}
+		operation := &models.Operation{
+			OperationTypeId:   opTypeId,
+			Number:            strconv.FormatInt(time.Now().Unix(), 10),
+			Status:            constvar.OperationStatus_Ready,
+			OperationDate:     time.Now().Format("2006-01-02 15:04:05"),
+			Comment:           "搴撳瓨璋冩嫧鍏ュ簱",
+			BaseOperationType: constvar.BaseOperationTypeIncoming,
+			Details:           internalInputDetails,
+			LocationID:        originOperation.LocationID,
+			ToLocationID:      originOperation.ToLocationID,
+			OperationTypeName: "搴撳瓨璋冩嫧鍏ュ簱",
+			WarehouseId:       originOperation.ToLocation.WarehouseId,
+		}
+		if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
+			return err
 		}
 	}
 	return nil
 
 }
 
-// FinishOperationInternal 瀹屾垚鍐呴儴璋冩嫧
-func FinishOperationInternal(tx *gorm.DB, listDetails []*models.OperationDetails, mapLocAmount map[string]*models.LocationProductAmount) (err error) {
+// FinishOperationInternal 楠岃瘉鍐呴儴璋冩嫧鐢熸垚鍑哄簱鍗�
+func FinishOperationInternal(tx *gorm.DB, listDetails []*models.OperationDetails, originOperation *models.Operation) (err error) {
+	var outputDetails []*models.OperationDetails
 	for _, v := range listDetails {
-		if fromLocAmount, aok := mapLocAmount[strconv.Itoa(v.FromLocationID)+v.ProductId]; aok {
-			if fromLocAmount.Amount.LessThan(v.Amount) {
-				return errors.New(fmt.Sprintf("浜у搧锛�%v,搴撳瓨锛�%v,鍑哄簱锛�%v,鏁伴噺涓嶅锛屾棤娉曞畬鎴愬嚭搴撴搷浣�", v.Product.Name, fromLocAmount.Amount.String(), v.Amount.String()))
-			}
-			fromLocAmount.Amount = fromLocAmount.Amount.Sub(v.Amount)
-			if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(fromLocAmount.Id).Update(fromLocAmount); err != nil {
-				return err
-			}
-		} else {
-			return errors.New("褰撳墠浠撳簱娌℃湁璇ヤ骇鍝�,璇峰厛鍏ュ簱")
+		outputDetails = append(outputDetails, &models.OperationDetails{
+			ProductId:        v.ProductId,
+			Amount:           v.Amount,
+			FromLocationID:   v.FromLocationID,
+			ToLocationID:     v.ToLocationID,
+			TotalGrossWeight: v.TotalGrossWeight,
+			TotalNetWeight:   v.TotalNetWeight,
+			AuxiliaryAmount:  v.AuxiliaryAmount,
+			AuxiliaryUnit:    v.AuxiliaryUnit,
+			Remark:           v.Remark,
+			IsInternalOutput: true,
+			Cost:             v.Cost,
+			SalePrice:        v.SalePrice,
+		})
+	}
+	if len(outputDetails) > 0 {
+		opTypeId, err := GetTargetOperationTypeIdByOperation(originOperation, constvar.BaseOperationTypeOutgoing)
+		if err != nil {
+			return err
 		}
-
-		if toLocAmount, aok := mapLocAmount[strconv.Itoa(v.ToLocationID)+v.ProductId]; aok {
-			toLocAmount.Amount = toLocAmount.Amount.Add(v.Amount)
-			if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(toLocAmount.Id).Update(toLocAmount); err != nil {
-				return err
-			}
-		} else {
-			if err := models.NewLocationProductAmountSearch().SetOrm(tx).Create(&models.LocationProductAmount{
-				LocationId:        v.ToLocationID,
-				ProductCategoryID: v.Product.CategoryId,
-				ProductId:         v.ProductId,
-				Amount:            v.Amount,
-				CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
-			}); err != nil {
-				return err
-			}
+		operation := &models.Operation{
+			OperationTypeId:   opTypeId,
+			Number:            strconv.FormatInt(time.Now().Unix(), 10),
+			Status:            constvar.OperationStatus_Ready,
+			OperationDate:     time.Now().Format("2006-01-02 15:04:05"),
+			Comment:           "搴撳瓨璋冩嫧鍑哄簱",
+			BaseOperationType: constvar.BaseOperationTypeOutgoing,
+			Details:           outputDetails,
+			LocationID:        originOperation.LocationID,
+			ToLocationID:      originOperation.ToLocationID,
+			OperationTypeName: "搴撳瓨璋冩嫧鍑哄簱",
+			IsInternalOutput:  true,
+			WarehouseId:       originOperation.WarehouseId,
+		}
+		if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
+			return err
 		}
 	}
 	return nil
@@ -287,28 +334,41 @@
 
 // FinishOperationAdjust 瀹屾垚搴撳瓨璋冩暣
 // 楠岃瘉鍚庣敓鎴愬叆搴撳崟鎴栧嚭搴撳崟锛堝簱瀛樺噺灏戠敓鎴愬嚭搴撳崟锛屽簱瀛樺鍔犵敓鎴愬叆搴撳崟锛�
-func FinishOperationAdjust(tx *gorm.DB, listDetails []*models.OperationDetails, mapLocAmount map[string]*models.LocationProductAmount) (err error) {
+func FinishOperationAdjust(tx *gorm.DB, listDetails []*models.OperationDetails, mapLocAmount map[string]*models.LocationProductAmount, originOperation *models.Operation) (err error) {
 	var inputDetails []*models.OperationDetails
 	var outputDetails []*models.OperationDetails
 	for _, v := range listDetails {
-		if locAmount, aok := mapLocAmount[strconv.Itoa(v.ToLocationID)+v.ProductId]; aok {
-			locAmount.Amount = v.Amount
-			if locAmount.Amount.Equal(v.Amount) {
+		if _, aok := mapLocAmount[strconv.Itoa(v.FromLocationID)+v.ProductId]; aok {
+			if v.StockAmount.Equal(v.Amount) { //鐩樼偣鏁伴噺鍜屽墿浣欐暟閲忎竴鑷�
 				continue
 			}
-			if v.Amount.GreaterThan(locAmount.Amount) {
+			if v.Amount.GreaterThan(v.StockAmount) {
 				inputDetails = append(inputDetails, &models.OperationDetails{
-					ProductId:      v.ProductId,
-					Amount:         v.Amount.Sub(locAmount.Amount),
-					FromLocationID: v.FromLocationID,
-					ToLocationID:   v.ToLocationID,
+					ProductId:        v.ProductId,
+					Amount:           v.Amount.Sub(v.StockAmount),
+					FromLocationID:   0,
+					ToLocationID:     v.FromLocationID,
+					TotalGrossWeight: v.TotalGrossWeight,
+					TotalNetWeight:   v.TotalNetWeight,
+					AuxiliaryAmount:  v.AuxiliaryAmount,
+					AuxiliaryUnit:    v.AuxiliaryUnit,
+					Remark:           v.Remark,
+					Cost:             v.Cost,
+					SalePrice:        v.SalePrice,
 				})
 			} else {
 				outputDetails = append(outputDetails, &models.OperationDetails{
-					ProductId:      v.ProductId,
-					Amount:         locAmount.Amount.Sub(v.Amount),
-					FromLocationID: v.ToLocationID,
-					ToLocationID:   v.FromLocationID,
+					ProductId:        v.ProductId,
+					Amount:           v.StockAmount.Sub(v.Amount),
+					FromLocationID:   v.FromLocationID,
+					ToLocationID:     0,
+					TotalGrossWeight: v.TotalGrossWeight,
+					TotalNetWeight:   v.TotalNetWeight,
+					AuxiliaryAmount:  v.AuxiliaryAmount,
+					AuxiliaryUnit:    v.AuxiliaryUnit,
+					Remark:           v.Remark,
+					Cost:             v.Cost,
+					SalePrice:        v.SalePrice,
 				})
 			}
 		} else {
@@ -317,56 +377,71 @@
 				Amount:         v.Amount,
 				FromLocationID: v.FromLocationID,
 				ToLocationID:   v.ToLocationID,
+				Remark:         v.Remark,
 			})
 		}
-		//if locAmount, aok := mapLocAmount[strconv.Itoa(v.ToLocationID)+v.ProductId]; aok {
-		//	locAmount.Amount = v.Amount
-		//	if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(locAmount.Id).Save(locAmount); err != nil {
-		//		return err
-		//	}
-		//} else {
-		//	if err := models.NewLocationProductAmountSearch().SetOrm(tx).Create(&models.LocationProductAmount{
-		//		LocationId:        v.ToLocationID,
-		//		ProductCategoryID: v.Product.CategoryId,
-		//		ProductId:         v.ProductId,
-		//		Amount:            v.Amount,
-		//		CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
-		//	}); err != nil {
-		//		return err
-		//	}
-		//}
-
-		if len(inputDetails) > 0 {
-			operation := &models.Operation{
-				Number:            strconv.FormatInt(time.Now().Unix(), 10),
-				Status:            constvar.OperationStatus_Ready,
-				OperationDate:     time.Now().Format("2006-01-02 15:04:05"),
-				Comment:           "搴撳瓨鐩樼偣",
-				BaseOperationType: constvar.BaseOperationTypeIncoming,
-				Details:           inputDetails,
-				LocationID:        inputDetails[0].FromLocationID,
-				OperationTypeName: "搴撳瓨璋冩暣",
-			}
-			if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
-				return err
-			}
+	}
+	if len(inputDetails) > 0 {
+		opTypeId, err := GetTargetOperationTypeIdByOperation(originOperation, constvar.BaseOperationTypeIncoming)
+		if err != nil {
+			return err
 		}
-		if len(outputDetails) > 0 {
-			operation := &models.Operation{
-				Number:            strconv.FormatInt(time.Now().Unix(), 10),
-				Status:            constvar.OperationStatus_Ready,
-				OperationDate:     time.Now().Format("2006-01-02 15:04:05"),
-				Comment:           "搴撳瓨鐩樼偣",
-				BaseOperationType: constvar.BaseOperationTypeOutgoing,
-				Details:           outputDetails,
-				LocationID:        outputDetails[0].FromLocationID,
-				OperationTypeName: "搴撳瓨璋冩暣",
-			}
-			if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
-				return err
-			}
+		operation := &models.Operation{
+			OperationTypeId:   opTypeId,
+			Number:            strconv.FormatInt(time.Now().Unix(), 10),
+			Status:            constvar.OperationStatus_Ready,
+			OperationDate:     time.Now().Format("2006-01-02 15:04:05"),
+			Comment:           "搴撳瓨璋冩暣鍏ュ簱",
+			BaseOperationType: constvar.BaseOperationTypeIncoming,
+			Details:           inputDetails,
+			LocationID:        inputDetails[0].FromLocationID,
+			OperationTypeName: "搴撳瓨璋冩暣鍏ュ簱",
+			WarehouseId:       originOperation.WarehouseId,
+		}
+		if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
+			return err
+		}
+	}
+	if len(outputDetails) > 0 {
+		opTypeId, err := GetTargetOperationTypeIdByOperation(originOperation, constvar.BaseOperationTypeOutgoing)
+		if err != nil {
+			return err
+		}
+		operation := &models.Operation{
+			OperationTypeId:   opTypeId,
+			Number:            strconv.FormatInt(time.Now().Unix(), 10),
+			Status:            constvar.OperationStatus_Ready,
+			OperationDate:     time.Now().Format("2006-01-02 15:04:05"),
+			Comment:           "搴撳瓨璋冩暣鍑哄簱",
+			BaseOperationType: constvar.BaseOperationTypeOutgoing,
+			Details:           outputDetails,
+			LocationID:        outputDetails[0].FromLocationID,
+			OperationTypeName: "搴撳瓨璋冩暣鍑哄簱",
+			WarehouseId:       originOperation.WarehouseId,
+		}
+		if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
+			return err
 		}
 	}
 	return nil
 
 }
+
+func GetTargetOperationTypeIdByOperation(operation *models.Operation, baseOT constvar.BaseOperationType) (operationTypeId int, err error) {
+	targetOT, err := models.NewOperationTypeSearch().SetBaseOperationType(baseOT).SetWarehouseId(operation.WarehouseId).First()
+	if err != nil {
+		return 0, err
+	}
+	return targetOT.Id, nil
+}
+
+func GetTargetOperationTypeIdByWarehouseId(warehouseId int, baseOT constvar.BaseOperationType) (operationTypeId int, err error) {
+	if warehouseId == 0 {
+		return 0, errors.New("warehouseId miss")
+	}
+	targetOT, err := models.NewOperationTypeSearch().SetBaseOperationType(baseOT).SetWarehouseId(warehouseId).First()
+	if err != nil {
+		return 0, err
+	}
+	return targetOT.Id, nil
+}

--
Gitblit v1.8.0