From 221108b0e0416968ca8417513ebf65c8b5109662 Mon Sep 17 00:00:00 2001
From: lishihai <dslsh@dscom>
Date: 星期三, 26 六月 2024 11:40:47 +0800
Subject: [PATCH] 库存盘点应用按钮记录创建人,创建时间,应用时间、应用人员等信息;根据条形码查询产品详情;新增编辑产品增加条形码字段->添加条形码被使用验证
---
service/operation.go | 390 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 363 insertions(+), 27 deletions(-)
diff --git a/service/operation.go b/service/operation.go
index 6ec8332..3b9c43b 100644
--- a/service/operation.go
+++ b/service/operation.go
@@ -1,18 +1,26 @@
package service
import (
+ "errors"
+ "fmt"
+ "github.com/gin-gonic/gin"
+ "github.com/mitchellh/mapstructure"
"github.com/shopspring/decimal"
+ "gorm.io/gorm"
+ "strconv"
"time"
"wms/constvar"
+ "wms/middleware"
"wms/models"
)
type OutputInfo struct {
- LocationID int
- WarehouseID int
- Products []*ProductInfo
- OperationID int
- SourceNumber string
+ LocationID int
+ WarehouseID int
+ Products []*ProductInfo
+ OperationID int
+ SourceNumber string
+ SaleDetailsNumber string
}
type ProductInfo struct {
@@ -60,28 +68,29 @@
continue
}
operation := &models.Operation{
- Id: 0,
- Number: autoCode,
- SourceNumber: output.SourceNumber,
- OperationTypeId: opTypeMap[output.WarehouseID].Id,
- OperationTypeName: opTypeMap[output.WarehouseID].Name,
- Status: constvar.OperationStatus_Ready,
- OperationDate: time.Now().Format("2006-01-02 15:04:05"),
- ContacterID: 0,
- ContacterName: "",
- CompanyID: 0,
- CompanyName: "",
- Comment: "crm鍙戣揣鐢宠",
- LogisticCompanyId: "",
- LogisticCompany: models.LogisticCompany{},
- WaybillNumber: "",
- Weight: decimal.Decimal{},
- LogisticWeight: decimal.Decimal{},
- Source: "crm",
- Details: details,
- BaseOperationType: constvar.BaseOperationTypeOutgoing,
- LocationID: output.LocationID,
- OperationSource: constvar.OperationSourceSaleDelivery,
+ Id: 0,
+ Number: autoCode,
+ SourceNumber: output.SourceNumber,
+ OperationTypeId: opTypeMap[output.WarehouseID].Id,
+ OperationTypeName: opTypeMap[output.WarehouseID].Name,
+ Status: constvar.OperationStatus_Ready,
+ OperationDate: time.Now().Format("2006-01-02 15:04:05"),
+ ContacterID: 0,
+ ContacterName: "",
+ CompanyID: "",
+ CompanyName: "",
+ Comment: "crm鍙戣揣鐢宠",
+ LogisticCompanyId: "",
+ LogisticCompany: models.LogisticCompany{},
+ WaybillNumber: "",
+ Weight: decimal.Decimal{},
+ LogisticWeight: decimal.Decimal{},
+ Source: "crm",
+ Details: details,
+ BaseOperationType: constvar.BaseOperationTypeOutgoing,
+ LocationID: output.LocationID,
+ OperationSource: constvar.OperationSourceSaleDelivery,
+ SalesDetailsNumber: output.SaleDetailsNumber,
}
operations = append(operations, operation)
autoCode = models.GetAutoCode(maxAutoIncr, codeStandard)
@@ -90,3 +99,330 @@
return models.NewOperationSearch().CreateBatch(operations)
}
+
+// FinishOperationInput 瀹屾垚鍏ュ簱
+func FinishOperationInput(c *gin.Context, tx *gorm.DB, operation *models.Operation, listDetails []*models.OperationDetails, mapLocAmount map[string]*models.LocationProductAmount) (err error) {
+ userInfo := middleware.GetUserInfo(c)
+ locationRoleList, err := models.NewLocationProductSearch().Find()
+ if err != nil {
+ return errors.New("鑾峰彇涓婃灦瑙勫垯淇℃伅澶辫触")
+ }
+ var mapLocationRoleProduct, mapLocationRoleCategory map[string]*models.LocationProduct
+ if len(locationRoleList) > 0 {
+ mapLocationRoleProduct = make(map[string]*models.LocationProduct)
+ mapLocationRoleCategory = make(map[string]*models.LocationProduct)
+ for _, v := range locationRoleList {
+ if v.RuleType == constvar.RuleType_Product {
+ mapLocationRoleProduct[strconv.Itoa(v.AreaId)+v.ProductId] = v
+ }
+ if v.RuleType == constvar.RuleType_ProductCategory {
+ mapLocationRoleCategory[strconv.Itoa(v.AreaId)+strconv.Itoa(v.ProductCategoryID)] = v
+ }
+ }
+ }
+
+ var details []*models.OperationDetails
+ for k, v := range listDetails {
+ listDetails[k].Product.Amount = listDetails[k].Product.Amount.Add(v.Amount)
+ if err := tx.Save(&listDetails[k].Product).Error; err != nil {
+ return err
+ }
+
+ if roleProduct, ok := mapLocationRoleProduct[strconv.Itoa(operation.LocationID)+v.ProductId]; ok {
+ detail := &models.OperationDetails{
+ ProductId: v.ProductId,
+ Amount: v.Amount,
+ FromLocationID: roleProduct.AreaId,
+ ToLocationID: roleProduct.LocationId,
+ }
+ details = append(details, detail)
+
+ if locAmount, aok := mapLocAmount[strconv.Itoa(roleProduct.LocationId)+v.ProductId]; aok {
+ locAmount.Amount = locAmount.Amount.Add(v.Amount)
+ if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
+ return err
+ }
+ } else {
+ 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"),
+ }); err != nil {
+ return err
+ }
+ }
+ } else {
+ if roleCategory, cok := mapLocationRoleCategory[strconv.Itoa(operation.LocationID)+strconv.Itoa(v.Product.CategoryId)]; cok {
+ detail := &models.OperationDetails{
+ ProductId: v.ProductId,
+ Amount: v.Amount,
+ FromLocationID: roleCategory.AreaId,
+ ToLocationID: roleCategory.LocationId,
+ }
+ details = append(details, detail)
+
+ if locAmount, aok := mapLocAmount[strconv.Itoa(roleCategory.LocationId)+v.ProductId]; aok {
+ locAmount.Amount = locAmount.Amount.Add(v.Amount)
+ if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
+ return err
+ }
+ } else {
+ 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"),
+ }); err != nil {
+ return err
+ }
+ }
+ } else {
+ if locAmount, aok := mapLocAmount[strconv.Itoa(operation.LocationID)+v.ProductId]; aok {
+ locAmount.Amount = locAmount.Amount.Add(v.Amount)
+ if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
+ return err
+ }
+ } else {
+ if err := models.NewLocationProductAmountSearch().SetOrm(tx).Create(&models.LocationProductAmount{
+ LocationId: operation.LocationID,
+ 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(details) > 0 {
+ if err := tx.Create(&models.Operation{
+ Number: operation.Number,
+ SourceNumber: operation.SourceNumber,
+ OperationTypeId: 0,
+ OperationTypeName: operation.OperationTypeName,
+ Status: constvar.OperationStatus_Finish,
+ OperationDate: operation.OperationDate,
+ ContacterID: operation.ContacterID,
+ ContacterName: operation.ContacterName,
+ CompanyID: operation.CompanyID,
+ CompanyName: operation.CompanyName,
+ Comment: operation.Comment,
+ BaseOperationType: constvar.BaseOperationTypeInternal,
+ Details: details,
+ CheckedBy: userInfo.Username,
+ }).Error; err != nil {
+ return err
+ }
+ }
+ return nil
+
+}
+
+// FinishOperationOutput 瀹屾垚鍑哄簱鎴栨姤搴�
+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()))
+ }
+ listDetails[k].Product.Amount = listDetails[k].Product.Amount.Sub(v.Amount)
+ if err := models.NewMaterialSearch().SetOrm(tx).Save(&listDetails[k].Product); err != nil {
+ return err
+ }
+
+ if locAmount, aok := mapLocAmount[strconv.Itoa(v.FromLocationID)+v.ProductId]; aok {
+ if locAmount.Amount.LessThan(v.Amount) {
+ 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().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 := GetTargetOperationTypeIdByOperation(originOperation, 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: internalInputDetails[0].ToLocationID,
+ OperationTypeName: "搴撳瓨璋冩嫧鍏ュ簱",
+ }
+ if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
+ return err
+ }
+ }
+ return nil
+
+}
+
+// FinishOperationInternal 楠岃瘉鍐呴儴璋冩嫧鐢熸垚鍑哄簱鍗�
+func FinishOperationInternal(tx *gorm.DB, listDetails []*models.OperationDetails, originOperation *models.Operation) (err error) {
+ var outputDetails []*models.OperationDetails
+ for _, v := range listDetails {
+ 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
+ }
+ 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: "搴撳瓨璋冩嫧鍑哄簱",
+ IsInternalOutput: true,
+ }
+ if err := models.NewOperationSearch().SetOrm(tx).Create(operation); err != nil {
+ return err
+ }
+ }
+ return nil
+
+}
+
+// FinishOperationAdjust 瀹屾垚搴撳瓨璋冩暣
+// 楠岃瘉鍚庣敓鎴愬叆搴撳崟鎴栧嚭搴撳崟锛堝簱瀛樺噺灏戠敓鎴愬嚭搴撳崟锛屽簱瀛樺鍔犵敓鎴愬叆搴撳崟锛�
+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 {
+ if locAmount.Amount.Equal(v.Amount) {
+ continue
+ }
+ if v.Amount.GreaterThan(locAmount.Amount) {
+ inputDetails = append(inputDetails, &models.OperationDetails{
+ ProductId: v.ProductId,
+ Amount: v.Amount.Sub(locAmount.Amount),
+ FromLocationID: v.FromLocationID,
+ ToLocationID: v.ToLocationID,
+ 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,
+ TotalGrossWeight: v.TotalGrossWeight,
+ TotalNetWeight: v.TotalNetWeight,
+ AuxiliaryAmount: v.AuxiliaryAmount,
+ AuxiliaryUnit: v.AuxiliaryUnit,
+ Remark: v.Remark,
+ Cost: v.Cost,
+ SalePrice: v.SalePrice,
+ })
+ }
+ } else {
+ inputDetails = append(inputDetails, &models.OperationDetails{
+ ProductId: v.ProductId,
+ Amount: v.Amount,
+ FromLocationID: v.FromLocationID,
+ ToLocationID: v.ToLocationID,
+ Remark: v.Remark,
+ })
+ }
+ }
+ if len(inputDetails) > 0 {
+ opTypeId, err := GetTargetOperationTypeIdByOperation(originOperation, 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: inputDetails,
+ LocationID: inputDetails[0].FromLocationID,
+ OperationTypeName: "搴撳瓨璋冩暣鍏ュ簱",
+ }
+ 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: "搴撳瓨璋冩暣鍑哄簱",
+ }
+ 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) {
+ oT, err := models.NewOperationTypeSearch().SetID(uint(operation.OperationTypeId)).First()
+ if err != nil {
+ return 0, err
+ }
+ targetOT, err := models.NewOperationTypeSearch().SetBaseOperationType(baseOT).SetWarehouseId(oT.WarehouseId).First()
+ if err != nil {
+ return 0, err
+ }
+ return targetOT.Id, nil
+}
--
Gitblit v1.8.0