liujiandao
2023-11-10 845f1b6da081aae73325e558356f9ab8a851462e
controllers/operation.go
@@ -1,23 +1,22 @@
package controllers
import (
   "encoding/json"
   "errors"
   "fmt"
   "github.com/gin-gonic/gin"
   "github.com/shopspring/decimal"
   "google.golang.org/grpc"
   "google.golang.org/grpc/credentials/insecure"
   "gorm.io/gorm"
   "os"
   "sort"
   "strconv"
   "time"
   "wms/conf"
   "wms/constvar"
   "wms/extend/code"
   "wms/extend/util"
   "wms/models"
   "wms/opa"
   "wms/pkg/logx"
   "wms/pkg/structx"
   "wms/proto/product_inventory"
   "wms/request"
)
@@ -308,380 +307,412 @@
//   @Success   200   {object}   util.Response   "成功"
//   @Router      /api-wms/v1/operation/finish/{id} [put]
func (slf OperationController) Finish(c *gin.Context) {
   id, err := strconv.Atoi(c.Param("id"))
   if err != nil {
      util.ResponseFormat(c, code.RequestParamError, "错误的id值")
      return
   }
   if id == 0 {
      util.ResponseFormat(c, code.RequestParamError, "id为0")
      return
   }
   operation, err := models.NewOperationSearch().SetPreload(true).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
   }
   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 {
         return err
      }
      var listProdtId []string
      var listProdt []*models.Material
      mapProdt := make(map[string]decimal.Decimal)
      listDetails, err := models.NewOperationDetailsSearch().SetOperationId(operation.Id).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
      }
      if operation.BaseOperationType == constvar.BaseOperationTypeIncoming {
         var operationInputs []*models.Operation
         for k, v := range listProdt {
            value, ok := mapProdt[v.ID]
            if !ok {
               return errors.New("产品种类异常")
            }
            listProdt[k].Amount = listProdt[k].Amount.Add(value)
            if err := tx.Save(listProdt[k]).Error; err != nil {
               return err
            }
            locationRule, err := models.NewLocationProductSearch().SetProductId(v.ID).SetAreaId(operation.ToLocationID).First()
            if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
               return err
            }
            if err == nil {
               operationTransfer := &models.Operation{
                  Number:            operation.Number,
                  SourceNumber:      operation.SourceNumber,
                  OperationTypeId:   0,
                  OperationTypeName: operation.OperationTypeName,
                  Status:            constvar.OperationStatus_Finish,
                  FromLocationID:    locationRule.AreaId,
                  ToLocationID:      locationRule.LocationId,
                  OperationDate:     operation.OperationDate,
                  ContacterID:       operation.ContacterID,
                  ContacterName:     operation.ContacterName,
                  CompanyID:         operation.CompanyID,
                  CompanyName:       operation.CompanyName,
                  Comment:           operation.Comment,
                  BaseOperationType: constvar.BaseOperationTypeInternal,
                  Details: []*models.OperationDetails{
                     {
                        ProductId: v.ID,
                        Amount:    value,
                     },
                  },
               }
               operationInputs = append(operationInputs, operationTransfer)
               //if err := tx.Create(&operationTransfer).Error; err != nil {
               //   return err
               //}
               //TODO:出入库的finish和报废的finish都要增加对location_product_amount表数量的更新,因为此表有ProductCategory字段,所以operation_details表中要增加ProductCategoryId字段
               locAmount, err := models.NewLocationProductAmountSearch().
                  SetProductId(v.ID).
                  SetLocationId(locationRule.LocationId).
                  First()
               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                  return err
               }
               locAmount.LocationId = locationRule.LocationId
               locAmount.ProductId = v.ID
               locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
               locAmount.Amount = locAmount.Amount.Add(value)
               if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
                  return res.Error
               }
            } else {
               locationRule, err = models.NewLocationProductSearch().SetProductCategoryId(v.CategoryId).SetAreaId(operation.ToLocationID).First()
               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                  return err
               }
               if err == nil {
                  operationTransfer := &models.Operation{
                     Number:            operation.Number,
                     SourceNumber:      operation.SourceNumber,
                     OperationTypeId:   0,
                     OperationTypeName: operation.OperationTypeName,
                     Status:            constvar.OperationStatus_Finish,
                     FromLocationID:    locationRule.AreaId,
                     ToLocationID:      locationRule.LocationId,
                     OperationDate:     operation.OperationDate,
                     ContacterID:       operation.ContacterID,
                     ContacterName:     operation.ContacterName,
                     CompanyID:         operation.CompanyID,
                     CompanyName:       operation.CompanyName,
                     Comment:           operation.Comment,
                     BaseOperationType: constvar.BaseOperationTypeInternal,
                     Details: []*models.OperationDetails{
                        {
                           ProductId: v.ID,
                           Amount:    value,
                        },
                     },
                  }
                  operationInputs = append(operationInputs, operationTransfer)
                  //if err := tx.Create(&operationTransfer).Error; err != nil {
                  //   return err
                  //}
                  //TODO:出入库的finish和报废的finish都要增加对location_product_amount表数量的更新,因为此表有ProductCategory字段,所以operation_details表中要增加ProductCategoryId字段
                  locAmount, err := models.NewLocationProductAmountSearch().
                     SetProductId(v.ID).
                     SetLocationId(locationRule.LocationId).
                     First()
                  if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                     return err
                  }
                  locAmount.LocationId = locationRule.LocationId
                  locAmount.ProductId = v.ID
                  locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
                  locAmount.Amount = locAmount.Amount.Add(value)
                  if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
                     return res.Error
                  }
               } else {
                  //TODO:出入库的finish和报废的finish都要增加对location_product_amount表数量的更新,因为此表有ProductCategory字段,所以operation_details表中要增加ProductCategoryId字段
                  locAmount, err := models.NewLocationProductAmountSearch().
                     SetProductId(v.ID).
                     SetLocationId(operation.ToLocationID).
                     First()
                  if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                     return err
                  }
                  locAmount.LocationId = operation.ToLocationID
                  locAmount.ProductId = v.ID
                  locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
                  locAmount.Amount = locAmount.Amount.Add(value)
                  if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
                     return res.Error
                  }
               }
            }
         }
         if len(operationInputs) > 0 {
            if err := tx.Create(&operationInputs).Error; err != nil {
               return err
            }
         }
      }
      if operation.BaseOperationType == constvar.BaseOperationTypeOutgoing {
         for k, v := range listProdt {
            value, ok := mapProdt[v.ID]
            if !ok {
               return errors.New("产品种类异常")
            }
            //todo 演示测试数据
            data, err := os.ReadFile("conf/input.json")
            if err != nil {
               return errors.New("文件读取失败")
            }
            m := make(map[string]interface{})
            err = json.Unmarshal(data, &m)
            if err != nil {
               return errors.New("格式转换失败")
            }
            if opa.OpaCheck(c, m, "operation") {
               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
            }
            locAmount, res := models.NewLocationProductAmountSearch().
               SetProductId(v.ID).
               SetLocationId(operation.ToLocationID).
               FirstRes()
            if res.Error != 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
            }
         }
      }
      if operation.BaseOperationType == constvar.BaseOperationTypeInternal {
         var operationInputs []*models.Operation
         for _, v := range listProdt {
            value, ok := mapProdt[v.ID]
            if !ok {
               return errors.New("产品种类异常")
            }
            //listProdt[k].Amount = listProdt[k].Amount.Add(value)
            //if err := tx.Save(listProdt[k]).Error; err != nil {
            //   return err
            //}
            fromLocAmount, res := models.NewLocationProductAmountSearch().
               SetProductId(v.ID).
               SetLocationId(operation.FromLocationID).
               FirstRes()
            if res.Error != nil {
               return err
            }
            if fromLocAmount.Amount.LessThan(value) {
               return errors.New(fmt.Sprintf("产品:%v,库存:%v,调拨:%v,数量不够,无法完成调拨操作", v.Name, v.Amount.String(), value.String()))
            }
            fromLocAmount.Amount = fromLocAmount.Amount.Sub(value)
            if err := models.NewLocationProductAmountSearch().SetID(fromLocAmount.Id).Update(fromLocAmount); err != nil {
               return err
            }
            locationRule, err := models.NewLocationProductSearch().SetProductId(v.ID).SetAreaId(operation.ToLocationID).First()
            if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
               return err
            }
            if err == nil {
               operationTransfer := &models.Operation{
                  Number:            operation.Number,
                  SourceNumber:      operation.SourceNumber,
                  OperationTypeId:   0,
                  OperationTypeName: operation.OperationTypeName,
                  Status:            constvar.OperationStatus_Finish,
                  FromLocationID:    locationRule.AreaId,
                  ToLocationID:      locationRule.LocationId,
                  OperationDate:     operation.OperationDate,
                  ContacterID:       operation.ContacterID,
                  ContacterName:     operation.ContacterName,
                  CompanyID:         operation.CompanyID,
                  CompanyName:       operation.CompanyName,
                  Comment:           operation.Comment,
                  BaseOperationType: constvar.BaseOperationTypeInternal,
                  Details: []*models.OperationDetails{
                     {
                        ProductId: v.ID,
                        Amount:    value,
                     },
                  },
               }
               operationInputs = append(operationInputs, operationTransfer)
               //if err := tx.Create(&operationTransfer).Error; err != nil {
               //   return err
               //}
               locAmount, err := models.NewLocationProductAmountSearch().
                  SetProductId(v.ID).
                  SetLocationId(locationRule.LocationId).
                  First()
               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                  return err
               }
               locAmount.LocationId = locationRule.LocationId
               locAmount.ProductId = v.ID
               locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
               locAmount.Amount = locAmount.Amount.Add(value)
               if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
                  return res.Error
               }
            } else {
               locationRule, err = models.NewLocationProductSearch().SetProductCategoryId(v.CategoryId).SetAreaId(operation.ToLocationID).First()
               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                  return err
               }
               if err == nil {
                  operationTransfer := &models.Operation{
                     Number:            operation.Number,
                     SourceNumber:      operation.SourceNumber,
                     OperationTypeId:   0,
                     OperationTypeName: operation.OperationTypeName,
                     Status:            constvar.OperationStatus_Finish,
                     FromLocationID:    locationRule.AreaId,
                     ToLocationID:      locationRule.LocationId,
                     OperationDate:     operation.OperationDate,
                     ContacterID:       operation.ContacterID,
                     ContacterName:     operation.ContacterName,
                     CompanyID:         operation.CompanyID,
                     CompanyName:       operation.CompanyName,
                     Comment:           operation.Comment,
                     BaseOperationType: constvar.BaseOperationTypeInternal,
                     Details: []*models.OperationDetails{
                        {
                           ProductId: v.ID,
                           Amount:    value,
                        },
                     },
                  }
                  operationInputs = append(operationInputs, operationTransfer)
                  //if err := tx.Create(&operationTransfer).Error; err != nil {
                  //   return err
                  //}
                  locAmount, err := models.NewLocationProductAmountSearch().
                     SetProductId(v.ID).
                     SetLocationId(locationRule.LocationId).
                     First()
                  if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                     return err
                  }
                  locAmount.LocationId = locationRule.LocationId
                  locAmount.ProductId = v.ID
                  locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
                  locAmount.Amount = locAmount.Amount.Add(value)
                  if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
                     return res.Error
                  }
               } else {
                  locAmount, err := models.NewLocationProductAmountSearch().
                     SetProductId(v.ID).
                     SetLocationId(operation.ToLocationID).
                     First()
                  if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
                     return err
                  }
                  locAmount.LocationId = operation.ToLocationID
                  locAmount.ProductId = v.ID
                  locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
                  locAmount.Amount = locAmount.Amount.Add(value)
                  if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
                     return res.Error
                  }
               }
            }
         }
         if len(operationInputs) > 0 {
            if err := tx.Create(&operationInputs).Error; err != nil {
               return err
            }
         }
      }
      return nil
   }); err != nil {
      util.ResponseFormat(c, code.RequestError, err.Error())
      return
   }
   //id, err := strconv.Atoi(c.Param("id"))
   //if err != nil {
   //   util.ResponseFormat(c, code.RequestParamError, "错误的id值")
   //   return
   //}
   //if id == 0 {
   //   util.ResponseFormat(c, code.RequestParamError, "id为0")
   //   return
   //}
   //operation, err := models.NewOperationSearch().SetPreload(true).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
   //}
   //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 {
   //      return err
   //   }
   //
   //   var listProdtId []string
   //   var listProdt []*models.Material
   //   mapProdt := make(map[string]decimal.Decimal)
   //   listDetails, err := models.NewOperationDetailsSearch().SetOperationId(operation.Id).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
   //   }
   //
   //   if operation.BaseOperationType == constvar.BaseOperationTypeIncoming {
   //      var operationInputs []*models.Operation
   //      for k, v := range listProdt {
   //         value, ok := mapProdt[v.ID]
   //         if !ok {
   //            return errors.New("产品种类异常")
   //         }
   //
   //         listProdt[k].Amount = listProdt[k].Amount.Add(value)
   //         if err := tx.Save(listProdt[k]).Error; err != nil {
   //            return err
   //         }
   //
   //         locationRule, err := models.NewLocationProductSearch().SetProductId(v.ID).SetAreaId(operation.ToLocationID).First()
   //         if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //            return err
   //         }
   //
   //         if err == nil {
   //            operationTransfer := &models.Operation{
   //               Number:            operation.Number,
   //               SourceNumber:      operation.SourceNumber,
   //               OperationTypeId:   0,
   //               OperationTypeName: operation.OperationTypeName,
   //               Status:            constvar.OperationStatus_Finish,
   //               FromLocationID:    locationRule.AreaId,
   //               ToLocationID:      locationRule.LocationId,
   //               OperationDate:     operation.OperationDate,
   //               ContacterID:       operation.ContacterID,
   //               ContacterName:     operation.ContacterName,
   //               CompanyID:         operation.CompanyID,
   //               CompanyName:       operation.CompanyName,
   //               Comment:           operation.Comment,
   //               BaseOperationType: constvar.BaseOperationTypeInternal,
   //               Details: []*models.OperationDetails{
   //                  {
   //                     ProductId: v.ID,
   //                     Amount:    value,
   //                  },
   //               },
   //            }
   //            operationInputs = append(operationInputs, operationTransfer)
   //
   //            //if err := tx.Create(&operationTransfer).Error; err != nil {
   //            //   return err
   //            //}
   //
   //            //TODO:出入库的finish和报废的finish都要增加对location_product_amount表数量的更新,因为此表有ProductCategory字段,所以operation_details表中要增加ProductCategoryId字段
   //            locAmount, err := models.NewLocationProductAmountSearch().
   //               SetProductId(v.ID).
   //               SetLocationId(locationRule.LocationId).
   //               First()
   //            if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //               return err
   //            }
   //            locAmount.LocationId = locationRule.LocationId
   //            locAmount.ProductId = v.ID
   //            locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
   //            locAmount.Amount = locAmount.Amount.Add(value)
   //            if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
   //               return res.Error
   //            }
   //         } else {
   //            locationRule, err = models.NewLocationProductSearch().SetProductCategoryId(v.CategoryId).SetAreaId(operation.ToLocationID).First()
   //            if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //               return err
   //            }
   //            if err == nil {
   //               operationTransfer := &models.Operation{
   //                  Number:            operation.Number,
   //                  SourceNumber:      operation.SourceNumber,
   //                  OperationTypeId:   0,
   //                  OperationTypeName: operation.OperationTypeName,
   //                  Status:            constvar.OperationStatus_Finish,
   //                  FromLocationID:    locationRule.AreaId,
   //                  ToLocationID:      locationRule.LocationId,
   //                  OperationDate:     operation.OperationDate,
   //                  ContacterID:       operation.ContacterID,
   //                  ContacterName:     operation.ContacterName,
   //                  CompanyID:         operation.CompanyID,
   //                  CompanyName:       operation.CompanyName,
   //                  Comment:           operation.Comment,
   //                  BaseOperationType: constvar.BaseOperationTypeInternal,
   //                  Details: []*models.OperationDetails{
   //                     {
   //                        ProductId: v.ID,
   //                        Amount:    value,
   //                     },
   //                  },
   //               }
   //               operationInputs = append(operationInputs, operationTransfer)
   //
   //               //if err := tx.Create(&operationTransfer).Error; err != nil {
   //               //   return err
   //               //}
   //
   //               //TODO:出入库的finish和报废的finish都要增加对location_product_amount表数量的更新,因为此表有ProductCategory字段,所以operation_details表中要增加ProductCategoryId字段
   //               locAmount, err := models.NewLocationProductAmountSearch().
   //                  SetProductId(v.ID).
   //                  SetLocationId(locationRule.LocationId).
   //                  First()
   //               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //                  return err
   //               }
   //               locAmount.LocationId = locationRule.LocationId
   //               locAmount.ProductId = v.ID
   //               locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
   //               locAmount.Amount = locAmount.Amount.Add(value)
   //               if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
   //                  return res.Error
   //               }
   //            } else {
   //               //TODO:出入库的finish和报废的finish都要增加对location_product_amount表数量的更新,因为此表有ProductCategory字段,所以operation_details表中要增加ProductCategoryId字段
   //               locAmount, err := models.NewLocationProductAmountSearch().
   //                  SetProductId(v.ID).
   //                  SetLocationId(operation.ToLocationID).
   //                  First()
   //               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //                  return err
   //               }
   //               locAmount.LocationId = operation.ToLocationID
   //               locAmount.ProductId = v.ID
   //               locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
   //               locAmount.Amount = locAmount.Amount.Add(value)
   //               if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
   //                  return res.Error
   //               }
   //            }
   //         }
   //      }
   //      if len(operationInputs) > 0 {
   //         if err := tx.Create(&operationInputs).Error; err != nil {
   //            return err
   //         }
   //      }
   //
   //   }
   //
   //   if operation.BaseOperationType == constvar.BaseOperationTypeOutgoing {
   //      for k, v := range listProdt {
   //         value, ok := mapProdt[v.ID]
   //         if !ok {
   //            return errors.New("产品种类异常")
   //         }
   //         //todo 演示测试数据
   //         data, err := os.ReadFile("conf/input.json")
   //         if err != nil {
   //            return errors.New("文件读取失败")
   //         }
   //         m := make(map[string]interface{})
   //         err = json.Unmarshal(data, &m)
   //         if err != nil {
   //            return errors.New("格式转换失败")
   //         }
   //         if opa.OpaCheck(c, m, "operation") {
   //            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
   //         }
   //         locAmount, res := models.NewLocationProductAmountSearch().
   //            SetProductId(v.ID).
   //            SetLocationId(operation.ToLocationID).
   //            FirstRes()
   //         if res.Error != 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
   //         }
   //      }
   //   }
   //
   //   if operation.BaseOperationType == constvar.BaseOperationTypeInternal {
   //      var operationInputs []*models.Operation
   //      for _, v := range listProdt {
   //         value, ok := mapProdt[v.ID]
   //         if !ok {
   //            return errors.New("产品种类异常")
   //         }
   //         //listProdt[k].Amount = listProdt[k].Amount.Add(value)
   //         //if err := tx.Save(listProdt[k]).Error; err != nil {
   //         //   return err
   //         //}
   //         fromLocAmount, res := models.NewLocationProductAmountSearch().
   //            SetProductId(v.ID).
   //            SetLocationId(operation.FromLocationID).
   //            FirstRes()
   //         if res.Error != nil {
   //            return err
   //         }
   //         if fromLocAmount.Amount.LessThan(value) {
   //            return errors.New(fmt.Sprintf("产品:%v,库存:%v,调拨:%v,数量不够,无法完成调拨操作", v.Name, v.Amount.String(), value.String()))
   //         }
   //         fromLocAmount.Amount = fromLocAmount.Amount.Sub(value)
   //         if err := models.NewLocationProductAmountSearch().SetID(fromLocAmount.Id).Update(fromLocAmount); err != nil {
   //            return err
   //         }
   //
   //         locationRule, err := models.NewLocationProductSearch().SetProductId(v.ID).SetAreaId(operation.ToLocationID).First()
   //         if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //            return err
   //         }
   //
   //         if err == nil {
   //            operationTransfer := &models.Operation{
   //               Number:            operation.Number,
   //               SourceNumber:      operation.SourceNumber,
   //               OperationTypeId:   0,
   //               OperationTypeName: operation.OperationTypeName,
   //               Status:            constvar.OperationStatus_Finish,
   //               FromLocationID:    locationRule.AreaId,
   //               ToLocationID:      locationRule.LocationId,
   //               OperationDate:     operation.OperationDate,
   //               ContacterID:       operation.ContacterID,
   //               ContacterName:     operation.ContacterName,
   //               CompanyID:         operation.CompanyID,
   //               CompanyName:       operation.CompanyName,
   //               Comment:           operation.Comment,
   //               BaseOperationType: constvar.BaseOperationTypeInternal,
   //               Details: []*models.OperationDetails{
   //                  {
   //                     ProductId: v.ID,
   //                     Amount:    value,
   //                  },
   //               },
   //            }
   //            operationInputs = append(operationInputs, operationTransfer)
   //
   //            //if err := tx.Create(&operationTransfer).Error; err != nil {
   //            //   return err
   //            //}
   //
   //            locAmount, err := models.NewLocationProductAmountSearch().
   //               SetProductId(v.ID).
   //               SetLocationId(locationRule.LocationId).
   //               First()
   //            if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //               return err
   //            }
   //            locAmount.LocationId = locationRule.LocationId
   //            locAmount.ProductId = v.ID
   //            locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
   //            locAmount.Amount = locAmount.Amount.Add(value)
   //            if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
   //               return res.Error
   //            }
   //         } else {
   //            locationRule, err = models.NewLocationProductSearch().SetProductCategoryId(v.CategoryId).SetAreaId(operation.ToLocationID).First()
   //            if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //               return err
   //            }
   //            if err == nil {
   //               operationTransfer := &models.Operation{
   //                  Number:            operation.Number,
   //                  SourceNumber:      operation.SourceNumber,
   //                  OperationTypeId:   0,
   //                  OperationTypeName: operation.OperationTypeName,
   //                  Status:            constvar.OperationStatus_Finish,
   //                  FromLocationID:    locationRule.AreaId,
   //                  ToLocationID:      locationRule.LocationId,
   //                  OperationDate:     operation.OperationDate,
   //                  ContacterID:       operation.ContacterID,
   //                  ContacterName:     operation.ContacterName,
   //                  CompanyID:         operation.CompanyID,
   //                  CompanyName:       operation.CompanyName,
   //                  Comment:           operation.Comment,
   //                  BaseOperationType: constvar.BaseOperationTypeInternal,
   //                  Details: []*models.OperationDetails{
   //                     {
   //                        ProductId: v.ID,
   //                        Amount:    value,
   //                     },
   //                  },
   //               }
   //               operationInputs = append(operationInputs, operationTransfer)
   //
   //               //if err := tx.Create(&operationTransfer).Error; err != nil {
   //               //   return err
   //               //}
   //
   //               locAmount, err := models.NewLocationProductAmountSearch().
   //                  SetProductId(v.ID).
   //                  SetLocationId(locationRule.LocationId).
   //                  First()
   //               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //                  return err
   //               }
   //               locAmount.LocationId = locationRule.LocationId
   //               locAmount.ProductId = v.ID
   //               locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
   //               locAmount.Amount = locAmount.Amount.Add(value)
   //               if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
   //                  return res.Error
   //               }
   //            } else {
   //               locAmount, err := models.NewLocationProductAmountSearch().
   //                  SetProductId(v.ID).
   //                  SetLocationId(operation.ToLocationID).
   //                  First()
   //               if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
   //                  return err
   //               }
   //               locAmount.LocationId = operation.ToLocationID
   //               locAmount.ProductId = v.ID
   //               locAmount.CreateDate = time.Now().Format("2006-01-02 15:04:05")
   //               locAmount.Amount = locAmount.Amount.Add(value)
   //               if res := models.NewLocationProductAmountSearch().Orm.Where("id=?", locAmount.ID).Save(locAmount); res.Error != nil {
   //                  return res.Error
   //               }
   //            }
   //         }
   //      }
   //      if len(operationInputs) > 0 {
   //         if err := tx.Create(&operationInputs).Error; err != nil {
   //            return err
   //         }
   //      }
   //   }
   //   return nil
   //}); err != nil {
   //   util.ResponseFormat(c, code.RequestError, err.Error())
   //   return
   //}
   //if operation.SourceNumber != "" {
   //   go UpdateSalesDetailStatus(c, operation.SourceNumber)
   //}
   UpdateSalesDetailStatus(c, c.Param("id"))
   util.ResponseFormat(c, code.Success, "操作成功")
}
var ProductInventoryServiceConn *grpc.ClientConn
func InitProductInventoryServiceConn() {
   var err error
   ProductInventoryServiceConn, err = grpc.Dial(conf.GrpcServerConf.CrmAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
   if err != nil {
      logx.Errorf("grpc dial product service error: %v", err.Error())
      return
   }
}
func CloseProductInventoryServiceConn() {
   if ProductInventoryServiceConn != nil {
      ProductInventoryServiceConn.Close()
   }
}
func UpdateSalesDetailStatus(ctx *gin.Context, number string) {
   client := product_inventory.NewProductInventoryServiceClient(ProductInventoryServiceConn)
   _, err := client.UpdateSalesDetailStatus(ctx, &product_inventory.UpdateSalesDetailStatusRequest{
      Number:            number,
      SalesDetailStatus: "已出库",
   })
   if err != nil {
      logx.Errorf("grpc dial UpdateSalesDetailStatus service error: %v", err)
   }
}
// ListTransfer
// @Tags      入库/出库
// @Summary   库存调拨列表