From 73b6baf6af3d88cdcb0e2df7932a9bd96b0b85c5 Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期一, 01 七月 2024 22:32:34 +0800
Subject: [PATCH] 月度统计出入库按类型汇总报表定时任务和手动跑任务接口

---
 controllers/product_controller.go |  601 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 526 insertions(+), 75 deletions(-)

diff --git a/controllers/product_controller.go b/controllers/product_controller.go
index b5d494d..0a0bc3f 100644
--- a/controllers/product_controller.go
+++ b/controllers/product_controller.go
@@ -12,10 +12,14 @@
 	"wms/constvar"
 	"wms/extend/code"
 	"wms/extend/util"
+	"wms/middleware"
 	"wms/models"
 	"wms/pkg/logx"
+	"wms/pkg/mysqlx"
+	"wms/pkg/structx"
 	"wms/request"
-	"wms/utils"
+	"wms/response"
+	"wms/service"
 )
 
 type ProductController struct {
@@ -34,12 +38,12 @@
 		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
 		return
 	}
-	if params.Name == "" {
-		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍚嶇О涓嶈兘涓虹┖")
+	if params.ID == "" {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧缂栫爜涓嶈兘涓虹┖")
 		return
 	}
-	if params.SalePrice.IntPart() <= 0 {
-		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍞环涓嶈兘灏忎簬绛変簬闆�")
+	if params.Name == "" {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍚嶇О涓嶈兘涓虹┖")
 		return
 	}
 	if params.Model == "" {
@@ -50,12 +54,50 @@
 		util.ResponseFormat(c, code.RequestParamError, "鍗曚綅涓嶈兘涓虹┖")
 		return
 	}
-	params.ID = utils.GetUUID()
-	err := models.NewMaterialSearch().Create(&params)
+	if params.BarCode != "" {
+		m, err := models.NewMaterialSearch().SetBarCode(params.BarCode).First()
+		if err == nil && m.ID != "" { //鏌ュ嚭鐗╂枡琛ㄦ槸鐗╂枡宸插瓨鍦�
+			util.ResponseFormat(c, code.RequestParamError, "鏉″舰鐮佸凡缁忚浣跨敤")
+			return
+		}
+	}
+	//params.ID = utils.GetUUID()
+
+	err := models.WithTransaction(func(tx *gorm.DB) error {
+		if err := models.NewMaterialSearch().SetOrm(tx).Create(&params); err != nil {
+			return err
+		}
+		materialAttachmentList := []*models.MaterialAttachment{}
+		for _, v := range params.AttachmentIDs {
+			ma := &models.MaterialAttachment{MaterialID: params.ID, AttachmentID: v}
+			materialAttachmentList = append(materialAttachmentList, ma)
+		}
+		if len(materialAttachmentList) > 0 {
+			if err := models.NewMaterialAttachmentSearch().SetOrm(tx).CreateBatch(materialAttachmentList); err != nil {
+				return err
+			}
+		}
+		avs := make([]*models.AttributeValue, 0)
+		for _, v := range params.Attributes {
+			av := models.AttributeValue{
+				Model:       gorm.Model{},
+				EntityID:    params.ID,
+				AttributeID: v.ID,
+				Value:       v.Value,
+			}
+			avs = append(avs, &av)
+
+		}
+		if err := models.NewAttributeValueSearch().SetOrm(tx).CreateBatch(avs); err != nil {
+			return err
+		}
+		return nil
+	})
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "浜у搧淇℃伅淇濆瓨澶辫触")
 		return
 	}
+
 	util.ResponseFormat(c, code.Success, "淇濆瓨鎴愬姛")
 }
 
@@ -76,7 +118,7 @@
 	if params.PageInfo.Check() {
 		search.SetPage(params.Page, params.PageSize)
 	}
-	products, total, err := search.SetKeyword(params.KeyWord).SetCategoryId(params.CategoryId).SetOrder("created_at desc").Find()
+	products, total, err := search.SetPreload(true).SetKeyword(params.KeyWord).SetCategoryId(params.CategoryId).SetOrder("created_at desc").Find()
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
 		return
@@ -97,14 +139,95 @@
 				product.CategoryName = category.Name
 			}
 		}
+		var reorderAmount request.ProductStatisticsAmount
+		if err := models.NewOperationSearch().Orm.
+			Table("wms_operation_details").
+			InnerJoins("INNER JOIN wms_operation on wms_operation_details.operation_id=wms_operation.id").
+			Select("wms_operation_details.product_id,SUM(wms_operation_details.amount) as total_count").
+			Where("wms_operation_details.product_id=? and wms_operation.`status`=? and wms_operation.base_operation_type in (?)", product.ID, constvar.OperationStatus_Ready, []constvar.BaseOperationType{constvar.BaseOperationTypeIncoming, constvar.BaseOperationTypeOutgoing, constvar.BaseOperationTypeDisuse}).
+			Group("wms_operation_details.product_id").
+			//Order("wms_operation_details.product_id").
+			First(&reorderAmount).Error; err != nil {
+			if !errors.Is(err, gorm.ErrRecordNotFound) {
+				util.ResponseFormat(c, code.RequestParamError, "浜у搧鏁版嵁缁熻澶辫触")
+				return
+			} else {
+				reorderAmount.TotalAmount = decimal.NewFromInt(0)
+			}
+		}
+		product.PredictionAmount = product.Amount.Add(reorderAmount.TotalAmount)
+
+		var statisticsList []*request.ProductStatistics
+		if err := models.NewOperationSearch().Orm.Table("wms_operation").
+			InnerJoins("INNER JOIN wms_operation_details on wms_operation_details.operation_id=wms_operation.id").
+			Select("SUM(wms_operation_details.amount) as total_amount,wms_operation.base_operation_type").
+			Where("wms_operation_details.product_id=? and wms_operation.`status`=? and wms_operation.base_operation_type in (?)", product.ID, constvar.OperationStatus_Finish, []constvar.BaseOperationType{constvar.BaseOperationTypeIncoming, constvar.BaseOperationTypeOutgoing, constvar.BaseOperationTypeDisuse}).
+			Group("wms_operation.base_operation_type").
+			Find(&statisticsList).Error; err != nil {
+			util.ResponseFormat(c, code.RequestParamError, "浜у搧鏁版嵁缁熻澶辫触")
+			return
+		}
+		for _, v := range statisticsList {
+			if v.BaseOperationType == constvar.BaseOperationTypeIncoming {
+				product.InputAmount = v.TotalAmount
+			}
+			if v.BaseOperationType == constvar.BaseOperationTypeOutgoing {
+				product.OutputAmount = product.OutputAmount.Add(v.TotalAmount)
+			}
+			if v.BaseOperationType == constvar.BaseOperationTypeAdjust {
+				product.OutputAmount = product.OutputAmount.Add(v.TotalAmount)
+			}
+		}
+		reorderRules, rulesTotal, err := models.NewReorderRuleSearch().SetProductId(product.ID).Find()
+		if err != nil {
+			util.ResponseFormat(c, code.RequestParamError, "閲嶈璐ц鍒欑粺璁″け璐�")
+			return
+		}
+		if rulesTotal == 1 {
+			product.MinInventoryRule = reorderRules[0].MinInventory
+			product.MaxInventoryRule = reorderRules[0].MaxInventory
+		}
+		product.ReorderRuleNum = rulesTotal
+		attributeValues, err := models.NewAttributeValueSearch().SetEntityID(product.ID).FindNotTotal()
+		aids := make([]uint, 0)
+		for _, v := range attributeValues {
+			aids = append(aids, v.AttributeID)
+		}
+		attributes, err := models.NewAttributeSearch().SetIDs(aids).FindNotTotal()
+		attributesMap := make(map[uint]*models.Attribute, len(attributes))
+		for _, v := range attributes {
+			attributesMap[v.ID] = v
+		}
+		if err != nil {
+			util.ResponseFormat(c, code.RequestParamError, "鏈煡鍔ㄦ�佸睘鎬�")
+		}
+		for _, v1 := range attributeValues {
+			attribute := attributesMap[v1.AttributeID]
+			if attribute == nil {
+				continue
+			}
+			//product.Attributes = append(product.Attributes,v1)
+			product.Attributes = append(product.Attributes, models.Attribute{
+				Model:        gorm.Model{ID: v1.ID, CreatedAt: v1.CreatedAt, UpdatedAt: v1.UpdatedAt, DeletedAt: v1.DeletedAt},
+				Name:         attribute.Name,
+				DataType:     attribute.DataType,
+				EntityType:   attribute.EntityType,
+				SelectValues: attribute.SelectValues,
+				SelectValue:  attribute.SelectValue,
+				//Value:        v1.Value,
+				Value: v1.Value,
+			})
+		}
+
 	}
 	util.ResponseFormatList(c, code.Success, products, int(total))
 }
 
 // GetProductDetails
 // @Tags      浜у搧
-// @Summary   鑾峰彇浜у搧璇︽儏
+// @Summary   閫氳繃浜у搧/鍟嗗搧/鐗╂枡 ID鑾峰彇浜у搧璇︽儏
 // @Produce   application/json
+// @Param     Authorization	header string true "token"
 // @Param		id	path		string			true	"id"  "鏌ヨ鍙傛暟"
 // @Success   200 {object} util.Response{data=models.Material}	"鎴愬姛"
 // @Router    /api-wms/v1/product/getProductDetails/{id} [get]
@@ -114,10 +237,100 @@
 		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥id")
 		return
 	}
-	material, err := models.NewMaterialSearch().SetID(id).First()
+	material, err := models.NewMaterialSearch().SetID(id).SetPreload(true).First()
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
 		return
+	}
+	attributeValues, err := models.NewAttributeValueSearch().SetEntityID(material.ID).FindNotTotal()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
+		return
+	}
+	aids := make([]uint, 0)
+	for _, v := range attributeValues {
+		aids = append(aids, v.AttributeID)
+	}
+	attributes, err := models.NewAttributeSearch().SetIDs(aids).FindNotTotal()
+	attributesMap := make(map[uint]*models.Attribute, len(attributes))
+	for _, v := range attributes {
+		attributesMap[v.ID] = v
+	}
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏈煡鍔ㄦ�佸睘鎬�")
+	}
+	for _, v1 := range attributeValues {
+		attribute := attributesMap[v1.AttributeID]
+		if attribute == nil {
+			continue
+		}
+		//product.Attributes = append(product.Attributes,v1)
+		material.Attributes = append(material.Attributes, models.Attribute{
+			Model:        gorm.Model{ID: v1.ID, CreatedAt: v1.CreatedAt, UpdatedAt: v1.UpdatedAt, DeletedAt: v1.DeletedAt},
+			Name:         attribute.Name,
+			DataType:     attribute.DataType,
+			EntityType:   attribute.EntityType,
+			SelectValues: attribute.SelectValues,
+			SelectValue:  attribute.SelectValue,
+			//Value:        v1.Value,
+			Value: v1.Value,
+		})
+	}
+	util.ResponseFormat(c, code.Success, material)
+}
+
+// GetProductDetailsByBarCode
+// @Tags      浜у搧
+// @Summary   閫氳繃浜у搧/鍟嗗搧/鐗╂枡 鏉″舰鐮� 鑾峰彇浜у搧璇︽儏
+// @Produce   application/json
+// @Param     Authorization	header string true "token"
+// @Param		barCode	path		string			true	"barCode"  "鏌ヨ鍙傛暟"
+// @Success   200 {object} util.Response{data=models.Material}	"鎴愬姛"
+// @Router    /api-wms/v1/product/getProductDetailsByBarCode/{barCode} [get]
+func (slf ProductController) GetProductDetailsByBarCode(c *gin.Context) {
+	barCode := c.Param("barCode")
+	if barCode == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥鏉″舰鐮�")
+		return
+	}
+	material, err := models.NewMaterialSearch().SetBarCode(barCode).SetPreload(true).First()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
+		return
+	}
+	attributeValues, err := models.NewAttributeValueSearch().SetEntityID(material.ID).FindNotTotal()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
+		return
+	}
+	aids := make([]uint, 0)
+	for _, v := range attributeValues {
+		aids = append(aids, v.AttributeID)
+	}
+	attributes, err := models.NewAttributeSearch().SetIDs(aids).FindNotTotal()
+	attributesMap := make(map[uint]*models.Attribute, len(attributes))
+	for _, v := range attributes {
+		attributesMap[v.ID] = v
+	}
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏈煡鍔ㄦ�佸睘鎬�")
+	}
+	for _, v1 := range attributeValues {
+		attribute := attributesMap[v1.AttributeID]
+		if attribute == nil {
+			continue
+		}
+		//product.Attributes = append(product.Attributes,v1)
+		material.Attributes = append(material.Attributes, models.Attribute{
+			Model:        gorm.Model{ID: v1.ID, CreatedAt: v1.CreatedAt, UpdatedAt: v1.UpdatedAt, DeletedAt: v1.DeletedAt},
+			Name:         attribute.Name,
+			DataType:     attribute.DataType,
+			EntityType:   attribute.EntityType,
+			SelectValues: attribute.SelectValues,
+			SelectValue:  attribute.SelectValue,
+			//Value:        v1.Value,
+			Value: v1.Value,
+		})
 	}
 	util.ResponseFormat(c, code.Success, material)
 }
@@ -139,10 +352,6 @@
 		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍚嶇О涓嶈兘涓虹┖")
 		return
 	}
-	if params.SalePrice.IntPart() <= 0 {
-		util.ResponseFormat(c, code.RequestParamError, "浜у搧鍞环涓嶈兘灏忎簬绛変簬闆�")
-		return
-	}
 	if params.Model == "" {
 		util.ResponseFormat(c, code.RequestParamError, "鐗╂枡绫诲瀷涓嶈兘涓虹┖")
 		return
@@ -151,17 +360,82 @@
 		util.ResponseFormat(c, code.RequestParamError, "鍗曚綅涓嶈兘涓虹┖")
 		return
 	}
+	if params.BarCode != "" {
+		m, err := models.NewMaterialSearch().SetBarCode(params.BarCode).First()
+		if err == nil && m.ID != params.ID { //鏌ュ嚭鐗╂枡涓擨D涓嶄竴鏍�,
+			util.ResponseFormat(c, code.RequestParamError, "鏉″舰鐮佸凡缁忚浣跨敤")
+			return
+		}
+	}
 	err := models.NewMaterialSearch().SetID(params.ID).Save(&params)
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "浜у搧淇℃伅鏇存柊澶辫触")
 		return
 	}
+	err = models.WithTransaction(func(tx *gorm.DB) error {
+		//鏇存柊鍦ㄥ簱鐨勪骇鍝佺被鍨�
+		if params.CategoryId > 0 {
+			find, _ := models.NewLocationProductAmountSearch().SetProductId(params.ID).Find()
+			if len(find) > 0 {
+				var ids []int
+				for _, f := range find {
+					if f.ProductCategoryID != params.CategoryId {
+						ids = append(ids, f.Id)
+					}
+				}
+				m := make(map[string]interface{})
+				m["productCategoryId"] = params.CategoryId
+				_ = models.NewLocationProductAmountSearch().SetOrm(tx).SetIds(ids).UpdateByMap(m)
+			}
+		}
+		materialAttachmentList := []*models.MaterialAttachment{}
+		for _, v := range params.AttachmentIDs {
+			ma := &models.MaterialAttachment{MaterialID: params.ID, AttachmentID: v}
+			materialAttachmentList = append(materialAttachmentList, ma)
+		}
+		if err := models.NewMaterialAttachmentSearch().SetOrm(tx).SetMaterialID(params.ID).Delete(); err != nil {
+			util.ResponseFormat(c, code.RequestParamError, "浜у搧闄勪欢娓呴櫎澶辫触")
+			return err
+		}
+		if len(materialAttachmentList) > 0 {
+			if err := models.NewMaterialAttachmentSearch().SetOrm(tx).CreateBatch(materialAttachmentList); err != nil {
+				util.ResponseFormat(c, code.RequestParamError, "浜у搧淇℃伅鏇存柊澶辫触")
+				return err
+			}
+		}
+
+		/*attributeValueSearch := models.NewAttributeValueSearch()
+		//鍒犻櫎浠庢柊鎻掑叆
+		if err := attributeValueSearch.SetOrm(tx).SetEntityID(params.ID).Delete(); err != nil {
+			return err
+		}*/
+		//avs := make([]*models.AttributeValue, 0)
+		for _, v := range params.Attributes {
+			av := models.AttributeValue{
+				Model:       gorm.Model{ID: v.ID},
+				EntityID:    params.ID,
+				AttributeID: v.ID,
+				Value:       v.Value,
+			}
+			//avs = append(avs, &av)
+			if err := models.NewAttributeValueSearch().SetOrm(tx).Save(&av); err != nil {
+				return err
+			}
+		}
+
+		return nil
+	})
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "浜у搧淇℃伅鏇存柊澶辫触")
+		return
+	}
+
 	util.ResponseFormat(c, code.Success, "鏇存柊鎴愬姛")
 }
 
 // DeleteProduct
 // @Tags      浜у搧
-// @Summary   鍒犻櫎浜у搧
+// @Summary   閫氳繃浜у搧/鍟嗗搧/鐗╂枡 ID鍒犻櫎浜у搧
 // @Produce   application/json
 // @Param		id	path		string			true	"id"  "鏌ヨ鍙傛暟"
 // @Success   200 {object} util.Response "鎴愬姛"
@@ -173,6 +447,27 @@
 		return
 	}
 	err := models.NewMaterialSearch().SetID(id).Delete()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍒犻櫎澶辫触")
+		return
+	}
+	util.ResponseFormat(c, code.Success, "鍒犻櫎鎴愬姛")
+}
+
+// DeleteProductByBarCode
+// @Tags      浜у搧
+// @Summary    閫氳繃浜у搧/鍟嗗搧/鐗╂枡 鏉″舰鐮佸垹闄や骇鍝�
+// @Produce   application/json
+// @Param		barCode	path		string			true	"barCode"  "鏌ヨ鍙傛暟"
+// @Success   200 {object} util.Response "鎴愬姛"
+// @Router    /api-wms/v1/product/deleteProductByBarCode/{barCode} [delete]
+func (slf ProductController) DeleteProductByBarCode(c *gin.Context) {
+	barCode := c.Param("barCode")
+	if barCode == "" {
+		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥id")
+		return
+	}
+	err := models.NewMaterialSearch().SetBarCode(barCode).Delete()
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "鍒犻櫎澶辫触")
 		return
@@ -245,7 +540,7 @@
 		return
 	}
 
-	first, err := models.NewProductCategorySearch().SetID(cast.ToUint(id)).First()
+	first, err := models.NewProductCategorySearch().SetID(cast.ToInt(id)).First()
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "鏌ユ壘澶辫触")
 		return
@@ -270,7 +565,7 @@
 		util.ResponseFormat(c, code.RequestParamError, "浜у搧绫诲瀷鍚嶇О涓嶈兘涓虹┖")
 		return
 	}
-	err := models.NewProductCategorySearch().SetID(params.ID).Save(&params)
+	err := models.NewProductCategorySearch().SetID(params.Id).Save(&params)
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "浜у搧绫诲瀷淇℃伅鏇存柊澶辫触")
 		return
@@ -291,7 +586,7 @@
 		util.ResponseFormat(c, code.RequestParamError, "鏃犳晥id")
 		return
 	}
-	err := models.NewProductCategorySearch().SetID(cast.ToUint(id)).Delete()
+	err := models.NewProductCategorySearch().SetID(cast.ToInt(id)).Delete()
 	if err != nil {
 		util.ResponseFormat(c, code.RequestParamError, "鍒犻櫎澶辫触")
 		return
@@ -358,20 +653,37 @@
 		util.ResponseFormat(c, code.RequestParamError, "璇疯緭鍏ユ簮鍗曟嵁")
 		return
 	}
+	if params.Number == "" {
+		util.ResponseFormat(c, code.RequestParamError, "璇疯緭鍏ュ崟鍙�")
+		return
+	}
+
+	var numberNum int64
+	if err := mysqlx.GetDB().Model(&models.Operation{}).Where("number=?", params.Number).Count(&numberNum).Error; err != nil {
+		util.ResponseFormat(c, code.RequestParamError, err.Error())
+		return
+	}
+	if numberNum > 0 {
+		util.ResponseFormat(c, code.RequestParamError, "鍗曞彿宸插瓨鍦�")
+		return
+	}
+
 	detail := &models.OperationDetails{
-		ProductId: params.ProductId,
-		Amount:    params.Amount,
+		ProductId:      params.ProductId,
+		Amount:         params.Amount,
+		FromLocationID: params.FromLocationId,
+		ToLocationID:   params.ToLocationId,
 	}
 	operation := models.Operation{
-		Number:            strconv.FormatInt(time.Now().Unix(), 10),
+		//Number:            strconv.FormatInt(time.Now().Unix(), 10),
+		Number:            params.Number,
 		SourceNumber:      params.SourceNumber,
 		OperationTypeId:   0,
 		Status:            constvar.OperationStatus_Ready,
-		FromLocationID:    params.FromLocationId,
-		ToLocationID:      params.ToLocationId,
 		OperationDate:     time.Now().Format("2006-01-02 15:04:05"),
 		Details:           []*models.OperationDetails{detail},
 		BaseOperationType: constvar.BaseOperationTypeDisuse,
+		OperationTypeName: "搴撳瓨鎶ュ簾",
 	}
 	if err := models.NewOperationSearch().Create(&operation); err != nil {
 		logx.Errorf("Operation create err: %v", err)
@@ -399,9 +711,15 @@
 		return
 	}
 
-	//db := models.NewOperationSearch().Orm.Table("wms_operation").Select("wms_operation.id,wms_operation.number,wms_operation.source_number,wms_operation.status,wms_operation.from_location_id,wms_operation.to_location_id,wms_operation.operation_date,wms_operation.contacter_id,wms_operation.contacter_name,wms_operation.company_id,wms_operation.company_name,wms_operation.comment,wms_operation_details.product_id,wms_operation_details.product_name,wms_operation_details.unit,wms_operation_details.amount").InnerJoins("inner join wms_operation_details on wms_operation_details.operation_id=wms_operation.id")
-
-	db := models.NewOperationSearch().Orm.Table("wms_operation").Select("wms_operation.id,wms_operation.number,wms_operation.source_number,wms_operation.status,wms_operation.from_location_id,wms_operation.to_location_id,wms_operation.operation_date,wms_operation.contacter_id,wms_operation.contacter_name,wms_operation.company_id,wms_operation.company_name,wms_operation.comment,wms_operation_details.product_id,material.name as product_name,material.unit,wms_operation_details.amount").InnerJoins("inner join wms_operation_details on wms_operation_details.operation_id=wms_operation.id").InnerJoins("inner join material on material.id=wms_operation_details.product_id")
+	db := models.NewOperationSearch().Orm.
+		Table("wms_operation").
+		Select("wms_operation.id,wms_operation.number,wms_operation.source_number,wms_operation.status,wms_operation_details.from_location_id,"+
+			"wms_operation_details.to_location_id,wms_operation.operation_date,wms_operation.contacter_id,wms_operation.contacter_name,"+
+			"wms_operation.company_id,wms_operation.company_name,wms_operation.comment,wms_operation_details.product_id,"+
+			"material.name as product_name,material.unit,wms_operation_details.amount,wms_operation.base_operation_type").
+		InnerJoins("inner join wms_operation_details on wms_operation_details.operation_id=wms_operation.id").
+		InnerJoins("inner join material on material.id=wms_operation_details.product_id").
+		Where("wms_operation.base_operation_type=?", constvar.BaseOperationTypeDisuse)
 
 	if params.Number != "" {
 		db = db.Where("wms_operation.number like ? or wms_operation.source_number like ? or material.name like ?", fmt.Sprintf("%%%v%%", params.Number), fmt.Sprintf("%%%v%%", params.Number), fmt.Sprintf("%%%v%%", params.Number))
@@ -457,49 +775,37 @@
 		return
 	}
 	if err := models.WithTransaction(func(tx *gorm.DB) error {
-		if err := models.NewOperationSearch().SetOrm(tx).SetID(id).Update(&models.Operation{Status: constvar.OperationStatus_Finish}); err != nil {
+		if err := models.NewOperationSearch().SetOrm(tx).SetID(id).Update(&models.Operation{Status: constvar.OperationStatus_Finish, AuditDate: time.Now().Format("2006-01-02 15:04:05")}); err != nil {
 			return err
 		}
-		var listProdtId []string
-		var listProdt []*models.Material
-		mapProdt := make(map[string]decimal.Decimal)
-		listDetails, err := models.NewOperationDetailsSearch().SetOperationId(operation.Id).FindAll()
+
+		listDetails, err := models.NewOperationDetailsSearch().SetOperationId(operation.Id).SetPreload(true).FindAll()
 		if err != nil {
 			return err
 		}
-		for _, v := range listDetails {
-			listProdtId = append(listProdtId, v.ProductId)
-			mapProdt[v.ProductId] = v.Amount
-		}
-		if err := models.NewMaterialSearch().Orm.Where("id IN ?", listProdtId).Find(&listProdt).Error; err != nil {
-			return err
-		}
-		for k, v := range listProdt {
-			if value, ok := mapProdt[v.ID]; !ok {
-				return errors.New("浜у搧绉嶇被寮傚父")
-			} else {
-				if v.Amount.LessThan(value) {
-					return errors.New(fmt.Sprintf("浜у搧锛�%v,搴撳瓨锛�%v,鎶ュ簾锛�%v,鏁伴噺涓嶅锛屾棤娉曞畬鎴愭姤搴熸搷浣�", v.Name, v.Amount.String(), value.String()))
-				}
-				listProdt[k].Amount = listProdt[k].Amount.Sub(value)
-				if err := tx.Save(listProdt[k]).Error; err != nil {
-					return err
-				}
-				var locAmount models.LocationProductAmount
-				if err := models.NewLocationProductAmountSearch().Orm.
-					Table("wms_location_product_amount").
-					Joins("inner join wms_location_product on wms_location_product.id=wms_location_product_amount.location_product_id").
-					Where("wms_location_product.product_id=? and wms_location_product.location_id=?", v.ID, operation.FromLocationID).
-					First(&locAmount).Error; err != nil {
-					return err
-				}
-				if locAmount.Amount.LessThan(value) {
-					return errors.New(fmt.Sprintf("浜у搧锛�%v,搴撳瓨锛�%v,鍑哄簱锛�%v,鏁伴噺涓嶅锛屾棤娉曞畬鎴愬嚭搴撴搷浣�", v.Name, v.Amount.String(), value.String()))
-				}
-				locAmount.Amount = locAmount.Amount.Sub(value)
-				if err := models.NewLocationProductAmountSearch().SetID(locAmount.Id).Update(&locAmount); err != nil {
-					return err
-				}
+
+		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 := tx.Save(&listDetails[k].Product).Error; err != nil {
+				return err
+			}
+
+			locAmount, res := models.NewLocationProductAmountSearch().
+				SetProductId(v.ProductId).
+				SetLocationId(v.FromLocationID).
+				FirstRes()
+			if res.Error != nil {
+				return err
+			}
+			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().SetID(locAmount.Id).Update(locAmount); err != nil {
+				return err
 			}
 		}
 		return nil
@@ -552,17 +858,18 @@
 		//ProductName: params.ProductName,
 		Amount: params.Amount,
 		//Unit:        params.Unit,
+		FromLocationID: params.FromLocationId,
+		ToLocationID:   params.ToLocationId,
 	}
 	operation := models.Operation{
-		Id:              params.Id,
-		Number:          params.Number,
-		SourceNumber:    params.SourceNumber,
-		OperationTypeId: 0,
-		Status:          params.Status,
-		FromLocationID:  params.FromLocationId,
-		ToLocationID:    params.ToLocationId,
-		OperationDate:   params.OperationDate,
-		Details:         []*models.OperationDetails{detail},
+		Id:                params.Id,
+		Number:            params.Number,
+		SourceNumber:      params.SourceNumber,
+		OperationTypeId:   0,
+		Status:            params.Status,
+		OperationDate:     params.OperationDate,
+		Details:           []*models.OperationDetails{detail},
+		BaseOperationType: params.BaseOperationType,
 	}
 	if err := models.WithTransaction(func(tx *gorm.DB) error {
 		if err := models.NewOperationDetailsSearch().SetOrm(tx).SetOperationId(params.Id).Delete(); err != nil {
@@ -602,9 +909,9 @@
 	}
 
 	search := models.NewOperationSearch().SetPage(params.Page, params.PageSize).SetPreload(true).SetOrder("created_at desc")
-	search.SetOrm(search.Orm.InnerJoins("inner join wms_operation_details on wms_operation_details.operation_id=wms_operation.id").Where("wms_operation_details.product_id=? and (wms_operation.from_location_id=? or wms_operation.to_location_id=?)", params.ProductId, params.LocationId, params.LocationId))
+	search.SetOrm(search.Orm.InnerJoins("inner join wms_operation_details on wms_operation_details.operation_id=wms_operation.id").Where("wms_operation_details.product_id=? and (wms_operation_details.from_location_id=? or wms_operation_details.to_location_id=?)", params.ProductId, params.LocationId, params.LocationId))
 
-	list, total, err := search.Find()
+	list, total, err := search.SetBaseOperationType(constvar.BaseOperationTypeAdjust).Find()
 	if err != nil {
 		util.ResponseFormat(c, code.RequestError, "鏌ユ壘澶辫触:"+err.Error())
 		return
@@ -612,3 +919,147 @@
 
 	util.ResponseFormatListWithPage(c, code.Success, list, int(total), params.Page, params.PageSize)
 }
+
+// CancelDisuse
+//
+//	@Tags		浜у搧
+//	@Summary	鍙栨秷鎶ュ簾
+//	@Produce	application/json
+//	@Param		id	path		int			true	"id"
+//	@Success	200	{object}	util.Response	"鎴愬姛"
+//	@Router		/api-wms/v1/product/cancelDisuse/{id} [put]
+func (slf ProductController) CancelDisuse(c *gin.Context) {
+	id, err := strconv.Atoi(c.Param("id"))
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "閿欒鐨刬d鍊�")
+		return
+	}
+	if id == 0 {
+		util.ResponseFormat(c, code.RequestParamError, "id涓�0")
+		return
+	}
+	operation, err := models.NewOperationSearch().SetID(id).First()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏈壘鍒扮浉鍏充俊鎭�:"+err.Error())
+		return
+	}
+	if operation.Status != constvar.OperationStatus_Ready {
+		util.ResponseFormat(c, code.RequestError, "璇ヤ俊鎭棤娉曞彇娑�")
+		return
+	}
+	operation.Status = constvar.OperationStatus_Cancel
+	operation.AuditDate = time.Now().Format("2006-01-02 15:04:05")
+	if err := models.NewOperationSearch().SetID(operation.Id).Save(operation); err != nil {
+		util.ResponseFormat(c, code.SaveFail, err.Error())
+		return
+	}
+	util.ResponseFormat(c, code.Success, "鎿嶄綔鎴愬姛")
+}
+
+// GetUserInfo
+//
+//	@Tags		浜у搧
+//	@Summary	鑾峰彇鐧诲綍鐢ㄦ埛淇℃伅
+//	@Produce	application/json
+//	@Success	200	{object}	util.ResponseList{data=map[string]interface{}}	"鎴愬姛"
+//	@Router		/api-wms/v1/product/getUserInfo [get]
+func (slf ProductController) GetUserInfo(c *gin.Context) {
+	userInfo := middleware.GetUserInfo(c)
+	m := make(map[string]interface{})
+	m["userName"] = userInfo.Username
+	util.ResponseFormat(c, code.Success, m)
+}
+
+// GetUnitInfo
+//
+//	@Tags		浜у搧
+//	@Summary	鑾峰彇鍗曚綅淇℃伅
+//	@Produce	application/json
+//	@Success	200	{object}	util.ResponseList{data=[]models.UnitDict}	"鎴愬姛"
+//	@Router		/api-wms/v1/product/getUnitInfo [get]
+func (slf ProductController) GetUnitInfo(c *gin.Context) {
+	dicts, total, err := models.NewUnitDictSearch().Find()
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏌ヨ鍑洪敊")
+		return
+	}
+	util.ResponseFormatList(c, code.Success, dicts, int(total))
+}
+
+// SaveUnitDict
+//
+//	@Tags		鏁版嵁瀛楀吀
+//	@Summary	鏇存柊璁¢噺鍗曚綅瀛楀吀
+//	@Produce	application/json
+//	@Param		object	body		request.SaveUnitDict	true	"鍙傛暟"
+//	@Success	200		{object}	util.Response			"鎴愬姛"
+//	@Router		/api-wms/v1/product/saveUnitDict [post]
+func (slf ProductController) SaveUnitDict(c *gin.Context) {
+	var reqParams request.SaveUnitDict
+	var params []*models.UnitDict
+	if err := c.BindJSON(&reqParams); err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
+		return
+	}
+	if err := structx.AssignTo(reqParams.Data, &params); err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鏁版嵁杞崲閿欒")
+		return
+	}
+
+	for i, v := range params {
+		if len(v.Name) == 0 {
+			util.ResponseFormat(c, code.RequestParamError, "鍚嶇О涓虹┖")
+			return
+		}
+		v.Sort = i + 1
+	}
+
+	err := models.WithTransaction(func(tx *gorm.DB) error {
+		err := models.NewUnitDictSearch().SetOrm(tx).Delete()
+		if err != nil {
+			return err
+		}
+
+		err = models.NewUnitDictSearch().SetOrm(tx).CreateBatch(params)
+		if err != nil {
+			return err
+		}
+		return nil
+	})
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, "鍒犻櫎澶辫触")
+		return
+	}
+
+	util.ResponseFormat(c, code.Success, "娣诲姞鎴愬姛")
+}
+
+// InputProduct
+//
+//	@Tags		鐗╂枡绠$悊
+//	@Summary	瀵煎叆鐗╂枡
+//
+// @Accept multipart/form-data
+// @Param file formData file true "file"
+// @Param     Authorization	header string true "token"
+//
+//	@Produce	application/xlsx
+//	@Success	200		{object}	util.Response 	"鎴愬姛"
+//	@Router		/api-wms/v1/product/inputProduct [post]
+func (slf ProductController) InputProduct(c *gin.Context) {
+	file, _, err := c.Request.FormFile("file")
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, err.Error())
+		return
+	}
+	defer file.Close()
+	resp := response.MaterialInputRes{InputCount: 0, ErrCount: 0, FileAddress: ""}
+	userInfo := middleware.GetUserInfo(c)
+	insertCount, err := service.InputMaterial(file, userInfo.Username)
+	if err != nil {
+		util.ResponseFormat(c, code.RequestParamError, err.Error())
+		return
+	}
+	resp.InputCount = insertCount
+	util.ResponseFormat(c, code.Success, resp)
+}

--
Gitblit v1.8.0