liujiandao
2023-11-10 98961b50ca71608110e0156e7dfb30c8e1c46a27
注释修改
4个文件已修改
795 ■■■■ 已修改文件
controllers/operation.go 754 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/docs.go 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.json 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.yaml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/operation.go
@@ -1,11 +1,15 @@
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"
@@ -14,6 +18,7 @@
    "wms/extend/code"
    "wms/extend/util"
    "wms/models"
    "wms/opa"
    "wms/pkg/logx"
    "wms/pkg/structx"
    "wms/proto/product_inventory"
@@ -307,381 +312,380 @@
//    @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
    //}
    //if operation.SourceNumber != "" {
    //    go UpdateSalesDetailStatus(c, operation.SourceNumber)
    //}
    UpdateSalesDetailStatus(c, c.Param("id"))
    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)
    }
    util.ResponseFormat(c, code.Success, "操作成功")
}
docs/docs.go
@@ -3996,6 +3996,13 @@
                "id": {
                    "type": "integer"
                },
                "logisticCompanyId": {
                    "type": "string"
                },
                "logisticWeight": {
                    "description": "物流重量",
                    "type": "number"
                },
                "number": {
                    "description": "单号",
                    "type": "string"
@@ -4027,6 +4034,14 @@
                "toLocationId": {
                    "description": "目标位置id",
                    "type": "integer"
                },
                "waybillNumber": {
                    "description": "运单号",
                    "type": "string"
                },
                "weight": {
                    "description": "重量",
                    "type": "number"
                }
            }
        },
docs/swagger.json
@@ -3984,6 +3984,13 @@
                "id": {
                    "type": "integer"
                },
                "logisticCompanyId": {
                    "type": "string"
                },
                "logisticWeight": {
                    "description": "物流重量",
                    "type": "number"
                },
                "number": {
                    "description": "单号",
                    "type": "string"
@@ -4015,6 +4022,14 @@
                "toLocationId": {
                    "description": "目标位置id",
                    "type": "integer"
                },
                "waybillNumber": {
                    "description": "运单号",
                    "type": "string"
                },
                "weight": {
                    "description": "重量",
                    "type": "number"
                }
            }
        },
docs/swagger.yaml
@@ -1267,6 +1267,11 @@
        type: integer
      id:
        type: integer
      logisticCompanyId:
        type: string
      logisticWeight:
        description: 物流重量
        type: number
      number:
        description: 单号
        type: string
@@ -1289,6 +1294,12 @@
      toLocationId:
        description: 目标位置id
        type: integer
      waybillNumber:
        description: 运单号
        type: string
      weight:
        description: 重量
        type: number
    type: object
  request.UpdateOperationType:
    properties: