17个文件已修改
403 ■■■■ 已修改文件
controllers/location_product_amount.go 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/product_controller.go 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/docs.go 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.json 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.yaml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/location_product_amount.go 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/material.go 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/operation.go 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/operation_details.go 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
request/operation.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
router/router.go 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/history_forms.go 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/inventory_report_forms.go 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/location_forms.go 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/month_forms.go 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/more_units.go 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/operation.go 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/location_product_amount.go
@@ -371,6 +371,7 @@
}
// Finish
// deprecated
//
//    @Tags    库存盘点
//    @Summary    应用、验证
controllers/product_controller.go
@@ -803,6 +803,7 @@
                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)
            listDetails[k].Product.StockMoreUnitList = service.SubMoreUnit(listDetails[k].Product.StockMoreUnitList, v.MoreUnitList)
            if err := tx.Save(&listDetails[k].Product).Error; err != nil {
                return err
            }
@@ -1028,6 +1029,16 @@
        v.Sort = i + 1
    }
    //校验重复
    m := make(map[string]struct{})
    for _, v := range params {
        if _, ok := m[v.Name]; ok {
            util.ResponseFormat(c, code.RequestParamError, "单位重复:"+v.Name)
            return
        }
        m[v.Name] = struct{}{}
    }
    err := models.WithTransaction(func(tx *gorm.DB) error {
        err := models.NewUnitDictSearch().SetOrm(tx).Delete()
        if err != nil {
@@ -1041,7 +1052,7 @@
        return nil
    })
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, "删除失败")
        util.ResponseFormat(c, code.RequestParamError, "保存失败")
        return
    }
docs/docs.go
@@ -5636,6 +5636,12 @@
                    "description": "是否调拨产生的出库",
                    "type": "boolean"
                },
                "moreUnitList": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/models.UnitItems"
                    }
                },
                "operationId": {
                    "description": "操作记录id",
                    "type": "integer"
@@ -6947,6 +6953,12 @@
                    "description": "Unit        string          ` + "`" + `json:\"unit\"` + "`" + `                    //单位\nProduct models.Material ` + "`" + `json:\"product\" ` + "`" + ` // 产品",
                    "type": "integer"
                },
                "moreUnitList": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/models.UnitItems"
                    }
                },
                "productId": {
                    "description": "产品id",
                    "type": "string"
docs/swagger.json
@@ -5625,6 +5625,12 @@
                    "description": "是否调拨产生的出库",
                    "type": "boolean"
                },
                "moreUnitList": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/models.UnitItems"
                    }
                },
                "operationId": {
                    "description": "操作记录id",
                    "type": "integer"
@@ -6936,6 +6942,12 @@
                    "description": "Unit        string          `json:\"unit\"`                    //单位\nProduct models.Material `json:\"product\" ` // 产品",
                    "type": "integer"
                },
                "moreUnitList": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/models.UnitItems"
                    }
                },
                "productId": {
                    "description": "产品id",
                    "type": "string"
docs/swagger.yaml
@@ -1118,6 +1118,10 @@
      isInternalOutput:
        description: 是否调拨产生的出库
        type: boolean
      moreUnitList:
        items:
          $ref: '#/definitions/models.UnitItems'
        type: array
      operationId:
        description: 操作记录id
        type: integer
@@ -2023,6 +2027,10 @@
          Unit        string          `json:"unit"`                    //单位
          Product models.Material `json:"product" ` // 产品
        type: integer
      moreUnitList:
        items:
          $ref: '#/definitions/models.UnitItems'
        type: array
      productId:
        description: 产品id
        type: string
models/location_product_amount.go
@@ -1,6 +1,7 @@
package models
import (
    "encoding/json"
    "fmt"
    "github.com/shopspring/decimal"
    "gorm.io/gorm"
@@ -21,7 +22,9 @@
        ProductId         string          `json:"productId" gorm:"type:varchar(191);not null;comment:产品id"` //产品id
        Product           Material        `json:"product" gorm:"foreignKey:ProductId;references:ID"`
        Amount            decimal.Decimal `json:"amount" gorm:"type:decimal(20,2);not null;comment:库存数量"` //库存数量
        CreateDate        string          `json:"createDate" gorm:"type:varchar(63);comment:日期"`          //日期
        MoreUnitList      []UnitItems     `json:"amountMoreUnits" gorm:"-"`                               //在库数量多单位
        MoreUnitValue     string          `json:"-" gorm:"type:varchar(255);comment:多单位值"`
        CreateDate        string          `json:"createDate" gorm:"type:varchar(63);comment:日期"` //日期
    }
    LocationProductAmountSearch struct {
@@ -64,6 +67,37 @@
    return "wms_location_product_amount"
}
func (slf *LocationProductAmount) AfterFind(tx *gorm.DB) (err error) {
    if slf.MoreUnitValue != "" {
        var arr []UnitItems
        err := json.Unmarshal([]byte(slf.MoreUnitValue), &arr)
        if err != nil {
            return err
        }
        slf.MoreUnitList = arr
    }
    return
}
func (slf *LocationProductAmount) BeforeCreate(tx *gorm.DB) (err error) {
    if len(slf.MoreUnitList) != 0 {
        items := make([]UnitItems, 0)
        for k, item := range slf.MoreUnitList {
            if item.Unit != "" && !item.Amount.IsZero() {
                items = append(items, slf.MoreUnitList[k])
            }
        }
        str, err := json.Marshal(items)
        if err != nil {
            return err
        }
        slf.MoreUnitValue = string(str)
    }
    return
}
func NewLocationProductAmountSearch() *LocationProductAmountSearch {
    return &LocationProductAmountSearch{Orm: mysqlx.GetDB()}
}
models/material.go
@@ -80,7 +80,9 @@
        ReorderRuleNum          int64           `json:"reorderRuleNum"`
        MoreUnit                *bool           `json:"moreUnit" gorm:"type:tinyint(1);default:false;comment:启动多单位"`
        MoreUnitList            []UnitItems     `json:"moreUnitList" gorm:"-"`
        MoreUnitValue           string          `json:"-" gorm:"type:varchar(255);comment:多单位值"`
        MoreUnitValue           string          `json:"-" gorm:"type:varchar(255);comment:多单位值"` //多单位换算比例
        StockMoreUnitList       []UnitItems     `json:"-" gorm:"-"`                              //多单位存储的值
        StockMoreUnitValue      string          `json:"-" gorm:"type:varchar(512);comment:多单位值"` //多单位存储的值
        GrossWeight             decimal.Decimal `json:"grossWeight" gorm:"type:decimal(20,3);comment:毛重"`
        NetWeight               decimal.Decimal `json:"netWeight" gorm:"type:decimal(20,3);comment:净重"`
        GrossUnit               string          `json:"grossUnit" gorm:"type:varchar(255);comment:毛重单位"`
@@ -120,7 +122,7 @@
    }
    UnitItems struct {
        Amount   decimal.Decimal `json:"amount"`
        Amount   decimal.Decimal `json:"amount"` //在物料中为换算率(1辅单位=换算率*主单位),在明细或库存中为具体值
        Unit     string          `json:"unit"`
        Floating bool            `json:"floating"` //是否浮动利率
    }
@@ -177,6 +179,20 @@
        }
        slf.MoreUnitValue = string(str)
    }
    if len(slf.StockMoreUnitList) != 0 {
        items := make([]UnitItems, 0)
        for k, item := range slf.StockMoreUnitList {
            if item.Unit != "" && !item.Amount.IsZero() {
                items = append(items, slf.StockMoreUnitList[k])
            }
        }
        str, err := json.Marshal(items)
        if err != nil {
            return err
        }
        slf.StockMoreUnitValue = string(str)
    }
    return
}
models/operation.go
@@ -93,11 +93,12 @@
    return &OperationSearch{Orm: mysqlx.GetDB()}
}
func (slf *OperationSearch) BeforeCreate(tx *gorm.DB) {
func (slf *OperationSearch) BeforeCreate(tx *gorm.DB) error {
    for k := range slf.Details {
        slf.Details[k].BaseOperationType = slf.BaseOperationType
        slf.Details[k].DealerType = slf.DealerType
    }
    return nil
}
func (slf *OperationSearch) SetOrm(tx *gorm.DB) *OperationSearch {
models/operation_details.go
@@ -1,6 +1,7 @@
package models
import (
    "encoding/json"
    "fmt"
    "github.com/shopspring/decimal"
    "gorm.io/gorm"
@@ -39,6 +40,9 @@
        // 嘉联仓储添加 SilkMarket、SilkMarketClose
        SilkMarket      string `json:"silkMarket" gorm:"type:varchar(255);comment:庄口"`       // 庄口
        SilkMarketClose string `json:"silkMarketClose" gorm:"type:varchar(10);comment:庄口关闭"` // 庄口关闭
        MoreUnitList  []UnitItems `json:"moreUnitList" gorm:"-"`
        MoreUnitValue string      `json:"-" gorm:"type:varchar(255);comment:多单位值"`
    }
    OperationDetailsSearch struct {
@@ -62,6 +66,37 @@
    return &OperationDetailsSearch{Orm: mysqlx.GetDB()}
}
func (slf *OperationDetails) AfterFind(tx *gorm.DB) (err error) {
    if slf.MoreUnitValue != "" {
        var arr []UnitItems
        err := json.Unmarshal([]byte(slf.MoreUnitValue), &arr)
        if err != nil {
            return err
        }
        slf.MoreUnitList = arr
    }
    return
}
func (slf *OperationDetails) BeforeCreate(tx *gorm.DB) (err error) {
    if len(slf.MoreUnitList) != 0 {
        items := make([]UnitItems, 0)
        for k, item := range slf.MoreUnitList {
            if item.Unit != "" && !item.Amount.IsZero() {
                items = append(items, slf.MoreUnitList[k])
            }
        }
        str, err := json.Marshal(items)
        if err != nil {
            return err
        }
        slf.MoreUnitValue = string(str)
    }
    return
}
func (slf *OperationDetailsSearch) SetOrm(tx *gorm.DB) *OperationDetailsSearch {
    slf.Orm = tx
    return slf
request/operation.go
@@ -3,6 +3,7 @@
import (
    "github.com/shopspring/decimal"
    "wms/constvar"
    "wms/models"
)
type AddOperation struct {
@@ -62,6 +63,9 @@
    SalePrice       decimal.Decimal `json:"salePrice"`       //销售单价
    SilkMarket      string          `json:"silkMarket"`      // 庄口
    SilkMarketClose string          `json:"silkMarketClose"` // 庄口关闭
    MoreUnitList  []models.UnitItems `json:"moreUnitList" gorm:"-"`
    MoreUnitValue string             `json:"-" gorm:"type:varchar(255);comment:多单位值"`
}
type OperationList struct {
router/router.go
@@ -158,11 +158,11 @@
    locationProductAmountController := new(controllers.LocationProductAmountController)
    locationProductAmountAPI := r.Group(urlPrefix + "/locationProductAmount")
    {
        locationProductAmountAPI.POST("add", locationProductAmountController.Add)                                           //添加库存盘点信息
        locationProductAmountAPI.POST("list", locationProductAmountController.List)                                         //查看库存盘点列表
        locationProductAmountAPI.POST("locationProductList", locationProductAmountController.LocationProductList)           //查看产品库存列表
        locationProductAmountAPI.POST("update", locationProductAmountController.Update)                                     //修改库存盘点信息
        locationProductAmountAPI.POST("finish", locationProductAmountController.Finish)                                     //应用、验证库存盘点信息
        locationProductAmountAPI.POST("add", locationProductAmountController.Add)                                 //添加库存盘点信息
        locationProductAmountAPI.POST("list", locationProductAmountController.List)                               //查看库存盘点列表
        locationProductAmountAPI.POST("locationProductList", locationProductAmountController.LocationProductList) //查看产品库存列表
        locationProductAmountAPI.POST("update", locationProductAmountController.Update)                           //修改库存盘点信息
        //locationProductAmountAPI.POST("finish", locationProductAmountController.Finish)                                     //应用、验证库存盘点信息
        locationProductAmountAPI.POST("getRuleList", locationProductAmountController.GetRuleList)                           //获取上架规则
        locationProductAmountAPI.POST("getLocationProductAmount", locationProductAmountController.GetLocationProductAmount) //获取位置产品信息
    }
service/history_forms.go
@@ -137,8 +137,10 @@
    var fileName string
    f := excelize.NewFile()
    unitData, unitIndexMap := GetAllUnits()
    // 自定义表头
    headers := []interface{}{"日期", "单号", "产品", "产品编码", "业务类型", "从", "至", map[string][]string{"数量": {"件", "匹", "米", "重量"}}, "单位", "重量"}
    headers := []interface{}{"日期", "单号", "产品", "产品编码", "业务类型", "从", "至", map[string][]string{"数量": unitData}, "单位", "重量"}
    // 设置表头
    if err := SetExcelHeader(headers, f); err != nil {
@@ -166,7 +168,7 @@
        f.SetCellValue("Sheet1", "F"+column, v.FromLocation)
        f.SetCellValue("Sheet1", "G"+column, v.ToLocation)
        f.SetCellValue("Sheet1", "H"+column, v.Amount)
        FillMoreUnitToExcel(v.Amount, v.AmountMoreUnits, 7, i+3, f)
        FillMoreUnitToExcel(v.AmountMoreUnits, 7, i+3, unitIndexMap, f)
        f.SetCellValue("Sheet1", "L"+column, v.Unit)
        f.SetCellValue("Sheet1", "M"+column, v.Weight)
    }
service/inventory_report_forms.go
@@ -213,6 +213,7 @@
    var fileName string
    f := excelize.NewFile()
    unitData, unitIndexMap := GetAllUnits()
    // 自定义表头
    headers := []string{"产品", "产品类别", "单位成本", "总价值", "在库", "可用库存", "入库", "出库"}
    // 设置表头
@@ -221,12 +222,12 @@
        f.SetCellValue("Sheet1", cell, header)
    }
    f.SetCellValue("Sheet1", getColumnAlphabet(0)+"1", "产品")
    f.SetCellValue("Sheet1", getColumnAlphabet(1)+"1", "产品类别")
    f.SetCellValue("Sheet1", getColumnAlphabet(2)+"1", "单位成本")
    f.SetCellValue("Sheet1", getColumnAlphabet(3)+"1", "总价值")
    f.SetCellValue("Sheet1", getColumnAlphabet(4)+"1", "在库")
    f.MergeCell("Sheet1", getColumnAlphabet(4)+"1", getColumnAlphabet(7)+"1") // 合并单元格
    f.SetCellValue("Sheet1", getColumnAlphabet(1)+"1", "产品")
    f.SetCellValue("Sheet1", getColumnAlphabet(2)+"1", "产品类别")
    f.SetCellValue("Sheet1", getColumnAlphabet(3)+"1", "单位成本")
    f.SetCellValue("Sheet1", getColumnAlphabet(4)+"1", "总价值")
    f.SetCellValue("Sheet1", getColumnAlphabet(5)+"1", "在库")
    f.MergeCell("Sheet1", getColumnAlphabet(5)+"1", getColumnAlphabet(7)+"1") // 合并单元格
    f.SetCellValue("Sheet1", getColumnAlphabet(8)+"1", "可用库存")
    f.MergeCell("Sheet1", getColumnAlphabet(8)+"1", getColumnAlphabet(11)+"1") // 合并单元格
    f.SetCellValue("Sheet1", getColumnAlphabet(12)+"1", "入库")
@@ -234,7 +235,6 @@
    f.SetCellValue("Sheet1", getColumnAlphabet(16)+"1", "出库")
    f.MergeCell("Sheet1", getColumnAlphabet(16)+"1", getColumnAlphabet(19)+"1") // 合并单元格
    unitData := []string{"件", "匹", "米", "重量"}
    for i, header := range unitData {
        f.SetCellValue("Sheet1", getColumnAlphabet(i+4)+"2", header)
        f.SetCellValue("Sheet1", getColumnAlphabet(i+8)+"2", header)
@@ -276,16 +276,20 @@
        f.SetCellValue("Sheet1", getColumnAlphabet(3)+column, v.Value)
        f.SetCellValue("Sheet1", getColumnAlphabet(4)+column, v.Amount)
        FillMoreUnitToExcel(v.Amount, v.AmountMoreUnits, 5, i+3, f)
        v.AmountMoreUnits = append(v.AmountMoreUnits, models.UnitItems{Amount: v.Amount, Unit: v.Unit})
        FillMoreUnitToExcel(v.AmountMoreUnits, 5, i+3, unitIndexMap, f)
        f.SetCellValue("Sheet1", getColumnAlphabet(8)+column, v.AvailableNumber)
        FillMoreUnitToExcel(v.AvailableNumber, v.AvailableNumberMoreUnits, 9, i+3, f)
        v.AvailableNumberMoreUnits = append(v.AvailableNumberMoreUnits, models.UnitItems{Amount: v.AvailableNumber, Unit: v.Unit})
        FillMoreUnitToExcel(v.AvailableNumberMoreUnits, 9, i+3, unitIndexMap, f)
        f.SetCellValue("Sheet1", getColumnAlphabet(12)+column, v.In)
        FillMoreUnitToExcel(v.In, v.AmountMoreUnits, 13, i+3, f)
        v.InMoreUnits = append(v.InMoreUnits, models.UnitItems{Amount: v.In, Unit: v.Unit})
        FillMoreUnitToExcel(v.InMoreUnits, 13, i+3, unitIndexMap, f)
        f.SetCellValue("Sheet1", getColumnAlphabet(16)+column, v.Out)
        FillMoreUnitToExcel(v.Out, v.AmountMoreUnits, 17, i+3, f)
        v.OutMoreUnits = append(v.OutMoreUnits, models.UnitItems{Amount: v.Out, Unit: v.Unit})
        FillMoreUnitToExcel(v.OutMoreUnits, 17, i+3, unitIndexMap, f)
    }
    fileName = fmt.Sprintf("库存报表%s.xlsx", time.Now().Format("2006-01-02-1504"))
@@ -300,7 +304,9 @@
func getColumnAlphabet(index int) string {
    const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    if index <= 26 {
        return string(alphabet[index])
        return string(alphabet[index-1])
    }
    return getColumnAlphabet((index)/26) + getColumnAlphabet((index)%26+1)
    quotient := (index - 1) / 26
    remainder := (index - 1) % 26
    return getColumnAlphabet(quotient) + getColumnAlphabet(remainder+1)
}
service/location_forms.go
@@ -36,7 +36,7 @@
        moreUnit := amount.Product.MoreUnit
        if moreUnit != nil && *moreUnit {
            resp.AmountMoreUnits = CreateMoreUnit(resp.Amount, amount.Product.MoreUnitList)
            resp.AmountMoreUnits = amount.MoreUnitList
        }
        result = append(result, resp)
@@ -101,11 +101,12 @@
    var fileName string
    f := excelize.NewFile()
    unitData, unitIndexMap := GetAllUnits()
    // 自定义表头
    headers := []interface{}{"位置", "产品", "产品类别", map[string][]string{"在库数量": {"件", "匹", "米", "重量"}}, "价值"}
    headers := []interface{}{"位置", "产品", "产品类别", map[string][]string{"在库数量": unitData}, "价值"}
    // 设置表头
    var i int
    i := 1
    for _, h := range headers {
        if v, ok := h.(string); ok {
            f.SetCellValue("Sheet1", getColumnAlphabet(i)+"1", v)
@@ -146,16 +147,15 @@
    f.SetCellStyle("Sheet1", "A1", lastColumn+"2", titleStyle)
    // 设置列宽
    f.SetColWidth("Sheet1", "A", "C", 30)
    f.SetColWidth("Sheet1", "D", lastColumn, 15)
    for i, v := range dataList {
        column := strconv.Itoa(i + 3)
        f.SetCellValue("Sheet1", "A"+column, v.LocationName)
        f.SetCellValue("Sheet1", "B"+column, v.ProductName)
        f.SetCellValue("Sheet1", "C"+column, v.ProductTypeName)
        f.SetCellValue("Sheet1", "D"+column, v.Amount)
        FillMoreUnitToExcel(v.Amount, v.AmountMoreUnits, 4, i+2, f)
        f.SetCellValue("Sheet1", "H"+column, v.Value)
        row := strconv.Itoa(i + 3)
        f.SetCellValue("Sheet1", "A"+row, v.LocationName)
        f.SetCellValue("Sheet1", "B"+row, v.ProductName)
        f.SetCellValue("Sheet1", "C"+row, v.ProductTypeName)
        v.AmountMoreUnits = append(v.AmountMoreUnits, models.UnitItems{Amount: v.Amount, Unit: v.Unit})
        FillMoreUnitToExcel(v.AmountMoreUnits, 4, i+3, unitIndexMap, f)
        f.SetCellValue("Sheet1", getColumnAlphabet(4+len(unitData))+row, v.Value)
    }
    fileName = fmt.Sprintf("位置报表%s.xlsx", time.Now().Format("2006-01-02-1504"))
service/month_forms.go
@@ -67,36 +67,29 @@
        return "", err
    }
    unitData, unitIndexMap := GetAllUnits()
    unitLen := len(unitData)
    // 设置表头
    f.SetCellValue("Sheet1", "A1", "产品编码")
    f.MergeCell("Sheet1", "A1", "A2") // 合并单元格
    f.SetCellValue("Sheet1", "B1", "产品名称")
    f.SetCellValue("Sheet1", "C1", "期初库存")
    f.MergeCell("Sheet1", "C1", "F1") // 合并单元格
    f.SetCellValue("Sheet1", "G1", "本月入库")
    f.MergeCell("Sheet1", "G1", "J1") // 合并单元格
    f.SetCellValue("Sheet1", "K1", "本月出库")
    f.MergeCell("Sheet1", "K1", "N1") // 合并单元格
    f.SetCellValue("Sheet1", "O1", "期末库存")
    f.MergeCell("Sheet1", "O1", "R1") // 合并单元格
    f.MergeCell("Sheet1", "B1", "B2") // 合并单元格
    f.SetCellValue("Sheet1", getColumnAlphabet(3)+"1", "期初库存")
    f.MergeCell("Sheet1", getColumnAlphabet(3)+"1", getColumnAlphabet(2+unitLen)+"1") // 合并单元格
    f.SetCellValue("Sheet1", getColumnAlphabet(3+unitLen)+"1", "本月入库")
    f.MergeCell("Sheet1", getColumnAlphabet(3+unitLen)+"1", getColumnAlphabet(2+unitLen*2)+"1") // 合并单元格
    f.SetCellValue("Sheet1", getColumnAlphabet(3+unitLen*2)+"1", "本月出库")
    f.MergeCell("Sheet1", getColumnAlphabet(3+unitLen*2)+"1", getColumnAlphabet(2+unitLen*3)+"1") // 合并单元格
    f.SetCellValue("Sheet1", getColumnAlphabet(3+unitLen*3)+"1", "期末库存")
    f.MergeCell("Sheet1", getColumnAlphabet(3+unitLen*3)+"1", getColumnAlphabet(2+unitLen*4)+"1") // 合并单元格
    unitData := []string{"件", "匹", "米", "重量"}
    for i, header := range unitData {
        cell := getColumnAlphabet(i+3) + "2"
        f.SetCellValue("Sheet1", cell, header)
    for j := 0; j < 4; j++ { //给期初库存, 本月入库, 本月出库, 期末库存赋值多单位表头
        for i, header := range unitData {
            cell := getColumnAlphabet(i+3+unitLen*j) + "2"
            f.SetCellValue("Sheet1", cell, header)
        }
    }
    for i, header := range unitData {
        cell := getColumnAlphabet(i+7) + "2"
        f.SetCellValue("Sheet1", cell, header)
    }
    for i, header := range unitData {
        cell := getColumnAlphabet(i+11) + "2"
        f.SetCellValue("Sheet1", cell, header)
    }
    for i, header := range unitData {
        cell := getColumnAlphabet(i+15) + "2"
        f.SetCellValue("Sheet1", cell, header)
    }
    // 设置表头样式
    style := &excelize.Style{
        Border: nil,
@@ -116,61 +109,34 @@
    if err != nil {
        return
    }
    f.SetCellStyle("Sheet1", "A1", "R2", titleStyle)
    f.SetCellStyle("Sheet1", "A1", getColumnAlphabet(2+unitLen*4)+"2", titleStyle)
    // 设置列宽
    f.SetColWidth("Sheet1", "A", "B", 30)
    f.SetColWidth("Sheet1", "C", "R", 15)
    f.SetColWidth("Sheet1", "C", getColumnAlphabet(2+unitLen*4), 15)
    for i, v := range dataList {
        column := strconv.Itoa(i + 3)
        f.SetCellValue("Sheet1", "A"+column, v.ProductId)
        f.SetCellValue("Sheet1", "B"+column, v.ProductName)
        f.SetCellValue("Sheet1", "C"+column, v.BeginAmount)
        row := strconv.Itoa(i + 3)
        f.SetCellValue("Sheet1", "A"+row, v.ProductId)
        f.SetCellValue("Sheet1", "B"+row, v.ProductName)
        v.BeginMoreUnitsArr = append(v.BeginMoreUnitsArr, models.UnitItems{Amount: v.BeginAmount, Unit: v.Unit})
        for _, v := range v.BeginMoreUnitsArr {
            switch v.Unit {
            case "件":
                f.SetCellValue("Sheet1", "D"+column, v.Amount)
            case "匹":
                f.SetCellValue("Sheet1", "E"+column, v.Amount)
            case "米":
                f.SetCellValue("Sheet1", "F"+column, v.Amount)
            }
            f.SetCellValue("Sheet1", getColumnAlphabet(3+unitIndexMap[v.Unit])+row, v.Amount)
        }
        f.SetCellValue("Sheet1", "G"+column, v.InputAmount)
        v.InputMoreUnitsArr = append(v.InputMoreUnitsArr, models.UnitItems{Amount: v.InputAmount, Unit: v.Unit})
        for _, v := range v.InputMoreUnitsArr {
            switch v.Unit {
            case "件":
                f.SetCellValue("Sheet1", "H"+column, v.Amount)
            case "匹":
                f.SetCellValue("Sheet1", "I"+column, v.Amount)
            case "米":
                f.SetCellValue("Sheet1", "J"+column, v.Amount)
            }
            f.SetCellValue("Sheet1", getColumnAlphabet(3+unitLen*1+unitIndexMap[v.Unit])+row, v.Amount)
        }
        f.SetCellValue("Sheet1", "K"+column, v.OutputAmount)
        v.OutputMoreUnitsArr = append(v.OutputMoreUnitsArr, models.UnitItems{Amount: v.OutputAmount, Unit: v.Unit})
        for _, v := range v.OutputMoreUnitsArr {
            switch v.Unit {
            case "件":
                f.SetCellValue("Sheet1", "L"+column, v.Amount)
            case "匹":
                f.SetCellValue("Sheet1", "M"+column, v.Amount)
            case "米":
                f.SetCellValue("Sheet1", "N"+column, v.Amount)
            }
            f.SetCellValue("Sheet1", getColumnAlphabet(3+unitLen*2+unitIndexMap[v.Unit])+row, v.Amount)
        }
        f.SetCellValue("Sheet1", "O"+column, v.EndAmount)
        v.EndMoreUnitsArr = append(v.EndMoreUnitsArr, models.UnitItems{Amount: v.EndAmount, Unit: v.Unit})
        for _, v := range v.EndMoreUnitsArr {
            switch v.Unit {
            case "件":
                f.SetCellValue("Sheet1", "P"+column, v.Amount)
            case "匹":
                f.SetCellValue("Sheet1", "Q"+column, v.Amount)
            case "米":
                f.SetCellValue("Sheet1", "R"+column, v.Amount)
            }
            f.SetCellValue("Sheet1", getColumnAlphabet(3+unitLen*3+unitIndexMap[v.Unit])+row, v.Amount)
        }
    }
service/more_units.go
@@ -23,17 +23,54 @@
    return moreValueArr
}
func FillMoreUnitToExcel(amount decimal.Decimal, units []models.UnitItems, startIndex int, column int, f *excelize.File) {
    columnStr := strconv.Itoa(column)
    for _, v := range units {
        switch v.Unit {
        case "匹":
            f.SetCellValue("Sheet1", getColumnAlphabet(startIndex)+columnStr, v.Amount.Mul(amount))
        case "米":
            f.SetCellValue("Sheet1", getColumnAlphabet(startIndex+1)+columnStr, v.Amount.Mul(amount))
        case "重量":
            f.SetCellValue("Sheet1", getColumnAlphabet(startIndex+2)+columnStr, v.Amount.Mul(amount))
func AddMoreUnit(units []models.UnitItems, units2 []models.UnitItems) []models.UnitItems {
    moreValueArr := make([]models.UnitItems, 0, len(units))
    for _, unitItem1 := range units {
        for _, unitItem2 := range units2 {
            if unitItem1.Unit == unitItem2.Unit {
                moreValueArr = append(moreValueArr, models.UnitItems{
                    Amount:   unitItem1.Amount.Add(unitItem2.Amount),
                    Unit:     unitItem1.Unit,
                    Floating: unitItem1.Floating,
                })
            }
        }
    }
    return moreValueArr
}
// MoreUnitIsEnough 多单位库存是否足够
func MoreUnitIsEnough(units []models.UnitItems, units2 []models.UnitItems) bool {
    for _, unitItem1 := range units {
        for _, unitItem2 := range units2 {
            if unitItem1.Amount.LessThan(unitItem2.Amount) {
                return false
            }
        }
    }
    return true
}
func SubMoreUnit(units []models.UnitItems, units2 []models.UnitItems) []models.UnitItems {
    moreValueArr := make([]models.UnitItems, 0, len(units))
    for _, unitItem1 := range units {
        for _, unitItem2 := range units2 {
            if unitItem1.Unit == unitItem2.Unit {
                moreValueArr = append(moreValueArr, models.UnitItems{
                    Amount:   unitItem1.Amount.Sub(unitItem2.Amount),
                    Unit:     unitItem1.Unit,
                    Floating: unitItem1.Floating,
                })
            }
        }
    }
    return moreValueArr
}
func FillMoreUnitToExcel(units []models.UnitItems, startIndex int, row int, unitIndexMap map[string]int, f *excelize.File) {
    rowStr := strconv.Itoa(row)
    for _, v := range units {
        f.SetCellValue("Sheet1", getColumnAlphabet(startIndex+unitIndexMap[v.Unit])+rowStr, v.Amount)
    }
    return
}
@@ -88,3 +125,18 @@
    }
    return f.NewStyle(style)
}
func GetAllUnits() (allUnits []string, unitIndexMap map[string]int) {
    units, err := models.NewUnitDictSearch().FindNotTotal()
    allUnits = make([]string, 0, len(units))
    unitIndexMap = make(map[string]int)
    if err != nil {
        return
    }
    for k, v := range units {
        allUnits = append(allUnits, v.Name)
        unitIndexMap[v.Name] = k
    }
    return
}
service/operation.go
@@ -125,6 +125,7 @@
    var details []*models.OperationDetails
    for k, v := range listDetails {
        listDetails[k].Product.Amount = listDetails[k].Product.Amount.Add(v.Amount)
        listDetails[k].Product.StockMoreUnitList = AddMoreUnit(listDetails[k].Product.StockMoreUnitList, v.MoreUnitList)
        if err := tx.Save(&listDetails[k].Product).Error; err != nil {
            return err
        }
@@ -133,6 +134,7 @@
            detail := &models.OperationDetails{
                ProductId:      v.ProductId,
                Amount:         v.Amount,
                MoreUnitList:   v.MoreUnitList,
                FromLocationID: roleProduct.AreaId,
                ToLocationID:   roleProduct.LocationId,
            }
@@ -140,6 +142,7 @@
            if locAmount, aok := mapLocAmount[strconv.Itoa(roleProduct.LocationId)+v.ProductId]; aok {
                locAmount.Amount = locAmount.Amount.Add(v.Amount)
                locAmount.MoreUnitList = AddMoreUnit(locAmount.MoreUnitList, v.MoreUnitList)
                if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
                    return err
                }
@@ -149,6 +152,7 @@
                    ProductCategoryID: v.Product.CategoryId,
                    ProductId:         v.ProductId,
                    Amount:            v.Amount,
                    MoreUnitList:      v.MoreUnitList,
                    CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
                    WarehouseId:       operation.WarehouseId,
                }); err != nil {
@@ -160,6 +164,7 @@
                detail := &models.OperationDetails{
                    ProductId:      v.ProductId,
                    Amount:         v.Amount,
                    MoreUnitList:   v.MoreUnitList,
                    FromLocationID: roleCategory.AreaId,
                    ToLocationID:   roleCategory.LocationId,
                }
@@ -167,6 +172,7 @@
                if locAmount, aok := mapLocAmount[strconv.Itoa(roleCategory.LocationId)+v.ProductId]; aok {
                    locAmount.Amount = locAmount.Amount.Add(v.Amount)
                    locAmount.MoreUnitList = AddMoreUnit(locAmount.MoreUnitList, v.MoreUnitList)
                    if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
                        return err
                    }
@@ -176,6 +182,7 @@
                        ProductCategoryID: v.Product.CategoryId,
                        ProductId:         v.ProductId,
                        Amount:            v.Amount,
                        MoreUnitList:      v.MoreUnitList,
                        CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
                        WarehouseId:       operation.WarehouseId,
                    }); err != nil {
@@ -185,6 +192,7 @@
            } else {
                if locAmount, aok := mapLocAmount[strconv.Itoa(v.ToLocationID)+v.ProductId]; aok {
                    locAmount.Amount = locAmount.Amount.Add(v.Amount)
                    locAmount.MoreUnitList = AddMoreUnit(locAmount.MoreUnitList, v.MoreUnitList)
                    locAmount.ID = uint(locAmount.Id)
                    if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(int(locAmount.ID)).Save(locAmount); err != nil {
                        return err
@@ -195,6 +203,7 @@
                        ProductCategoryID: v.Product.CategoryId,
                        ProductId:         v.ProductId,
                        Amount:            v.Amount,
                        MoreUnitList:      v.MoreUnitList,
                        CreateDate:        time.Now().Format("2006-01-02 15:04:05"),
                        WarehouseId:       operation.WarehouseId,
                    }); err != nil {
@@ -236,7 +245,11 @@
        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()))
        }
        if !MoreUnitIsEnough(v.Product.MoreUnitList, v.MoreUnitList) {
            return errors.New(fmt.Sprintf("产品:%v, 多单位数量不够,无法完成出库操作", v.Product.Name))
        }
        listDetails[k].Product.Amount = listDetails[k].Product.Amount.Sub(v.Amount)
        listDetails[k].Product.StockMoreUnitList = SubMoreUnit(listDetails[k].Product.StockMoreUnitList, v.MoreUnitList)
        if err := models.NewMaterialSearch().SetOrm(tx).Save(&listDetails[k].Product); err != nil {
            return err
        }
@@ -245,7 +258,11 @@
            if locAmount.Amount.LessThan(v.Amount) {
                return errors.New(fmt.Sprintf("产品:%v,库存:%v,出库:%v,数量不够,无法完成出库操作", v.Product.Name, locAmount.Amount.String(), v.Amount.String()))
            }
            if !MoreUnitIsEnough(locAmount.MoreUnitList, v.MoreUnitList) {
                return errors.New(fmt.Sprintf("产品:%v, 多单位数量不够,无法完成出库操作", v.Product.Name))
            }
            locAmount.Amount = locAmount.Amount.Sub(v.Amount)
            locAmount.MoreUnitList = SubMoreUnit(locAmount.MoreUnitList, v.MoreUnitList)
            if err := models.NewLocationProductAmountSearch().SetOrm(tx).SetID(locAmount.Id).Save(locAmount); err != nil {
                return err
            }
@@ -293,6 +310,8 @@
        outputDetails = append(outputDetails, &models.OperationDetails{
            ProductId:        v.ProductId,
            Amount:           v.Amount,
            MoreUnitList:     v.MoreUnitList,
            DealerType:       v.DealerType,
            FromLocationID:   v.FromLocationID,
            ToLocationID:     v.ToLocationID,
            TotalGrossWeight: v.TotalGrossWeight,