yinbentan
2024-06-28 9b60ddba27ef778419da5089e3b30ebe173afd7d
Merge remote-tracking branch 'origin/jialian' into jialian
20个文件已修改
4个文件已添加
1个文件已删除
1991 ■■■■ 已修改文件
conf/config.yaml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
constvar/const.go 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/location_product_amount.go 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/operation.go 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/product_controller.go 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/report_forms_controller.go 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/system_config.go 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/docs.go 353 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.json 350 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.yaml 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
example.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
main.go 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/db.go 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/material.go 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/operation.go 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/system_config.go 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
request/config_type.go 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
request/operation.go 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
router/router.go 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/month_forms.go 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/more_units.go 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/system_config.go 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
task/month_stats.go 158 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
task/tasklist.go 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/util.go 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
conf/config.yaml
@@ -27,8 +27,8 @@
  storePath: uploads/file
grpcServer:
  apsAddr: 127.0.0.1:9091
  crmAddr: 192.168.20.119:9092
  srmAddr: 192.168.20.119:9093
  crmAddr: 127.0.0.1:9092
  srmAddr: 127.0.0.1:9093
dingTalk:
  alarmKey: SEC31ccce95daf26763ab54575bd4cac156f22ed0a42f3e27d3edd06edb77b3d221
  alarmUrl: https://oapi.dingtalk.com/robot/send?access_token=c6023d2c55058b86d59290ad205eff86a8c681a7807f76c569f91434663081fa
constvar/const.go
@@ -316,3 +316,9 @@
)
const DoMonthStatsToken = "Eoh2ZAUJjtbmu0TBkc3dq7MPCpL4riw5NVxOfgXYlKvHF6sR"
type SystemConfigType int
const (
    SystemConfigTypeInventoryCutOffPoint SystemConfigType = 1 //库存结算时间点
)
controllers/location_product_amount.go
@@ -11,6 +11,7 @@
    "wms/constvar"
    "wms/extend/code"
    "wms/extend/util"
    "wms/middleware"
    "wms/models"
    "wms/pkg/mysqlx"
    "wms/request"
@@ -155,8 +156,8 @@
        util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
        return
    }
    if err := AddLocationProductAmount(reqParams); err != nil {
    userInfo := middleware.GetUserInfo(c)
    if err := AddLocationProductAmount(reqParams, userInfo); err != nil {
        util.ResponseFormat(c, code.RequestError, err)
        return
    }
@@ -164,7 +165,7 @@
    util.ResponseFormat(c, code.Success, "添加成功")
}
func AddLocationProductAmount(reqParams request.UpdateLocationProductAmount) error {
func AddLocationProductAmount(reqParams request.UpdateLocationProductAmount, userInfo *request.CustomClaims) error {
    if reqParams.LocationId == 0 {
        return errors.New("参数异常,位置id信息不存在")
    }
@@ -219,6 +220,7 @@
        Details:           []*models.OperationDetails{detail},
        LocationID:        location.Id,
        OperationTypeName: "库存调整",
        CreatedBy:         userInfo.Username,
    }
    if err := models.WithTransaction(func(tx *gorm.DB) error {
@@ -278,8 +280,9 @@
        util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
        return
    }
    userInfo := middleware.GetUserInfo(c)
    if reqParams.OperationId == 0 {
        if err := AddLocationProductAmount(reqParams); err != nil {
        if err := AddLocationProductAmount(reqParams, userInfo); err != nil {
            util.ResponseFormat(c, code.RequestError, err.Error())
            return
        }
@@ -349,8 +352,11 @@
        return
    }
    adjustAmount := operation.Details[0].Amount.Sub(locProductAmount.Amount)
    userInfo := middleware.GetUserInfo(c)
    if err := models.WithTransaction(func(tx *gorm.DB) error {
        if err := models.NewOperationSearch().SetOrm(tx).SetID(reqParams.OperationId).Update(&models.Operation{Status: constvar.OperationStatus_Finish}); err != nil {
        if err := models.NewOperationSearch().SetOrm(tx).SetID(reqParams.OperationId).Update(&models.Operation{
            Status: constvar.OperationStatus_Finish, CheckedBy: userInfo.Username,
            AuditDate: time.Now().Format("2006-01-02 15:04:05")}); err != nil {
            return err
        }
        if err := models.NewMaterialSearch().SetOrm(tx).SetID(reqParams.ProductId).Update(&models.Material{Amount: material.Amount.Add(adjustAmount)}); err != nil {
controllers/operation.go
@@ -72,17 +72,28 @@
        util.ResponseFormat(c, code.RequestParamError, "明细中不能存在重复的产品")
        return
    }
    operationType, err := models.NewOperationTypeSearch().SetID(uint(params.OperationTypeId)).First()
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, err.Error())
        return
    var operationType *models.OperationType
    var err error
    if params.OperationTypeId == 0 {
        operationType, err = models.NewOperationTypeSearch().SetWarehouseId(params.WarehouseId).SetBaseOperationType(params.BaseOperationType).First()
        if err != nil || params.WarehouseId != operationType.WarehouseId {
            util.ResponseFormat(c, code.RequestParamError, "参数缺失")
            return
        }
    } else {
        operationType, err = models.NewOperationTypeSearch().SetID(uint(params.OperationTypeId)).First()
        if err != nil {
            util.ResponseFormat(c, code.RequestParamError, err.Error())
            return
        }
    }
    userInfo := middleware.GetUserInfo(c)
    params.CreatedBy = userInfo.Username
    params.Status = constvar.OperationStatus_Ready
    //params.Number = strconv.FormatInt(time.Now().Unix(), 10)
    params.BaseOperationType = operationType.BaseOperationType
    params.WarehouseId = operationType.WarehouseId
    var numberNum int64
    if err := mysqlx.GetDB().Model(&models.Operation{}).Where("number=?", params.Number).Count(&numberNum).Error; err != nil {
@@ -191,7 +202,13 @@
    }
    if params.OperationTypeId == 0 && int(params.BaseOperationType) == 0 {
        return errors.New("未识别该记录类型")
        return errors.New("未识别该记录类型1")
    }
    if params.BaseOperationType != 0 {
        if params.WarehouseId == 0 {
            return errors.New("未识别该记录类型2")
        }
    }
    if params.OperationDate == "" {
@@ -282,7 +299,9 @@
        costMap[material.ID] = material.Cost
        salePriceMap[material.ID] = material.SalePrice
    }
    list, total, err := search.SetOperationTypeId(params.OperationTypeId).SetPreload(true).SetOrder("created_at desc").Find()
    list, total, err := search.SetOperationTypeId(params.OperationTypeId).
        SetBaseOperationType(params.BaseOperationType).
        SetPreload(true).SetOrder("created_at desc").Find()
    if err != nil {
        util.ResponseFormat(c, code.RequestError, "查找失败:"+err.Error())
        return
@@ -303,8 +322,8 @@
    if !params.PageInfo.Check() {
        return errors.New("数据分页信息错误")
    }
    if params.OperationTypeId == 0 {
        return errors.New("operationTypeId为0")
    if params.OperationTypeId == 0 && params.BaseOperationType == 0 {
        return errors.New("operationTypeId和baseOperationType不能同时为0")
    }
    return nil
}
@@ -1002,8 +1021,8 @@
    sheet := "Sheet1"
    f.SetCellValue(sheet, "A2", "单位(部门):"+operation.CompanyName) // 单位部门
    f.SetCellValue(sheet, "H2", operation.OperationDate)         // 时间
    f.SetCellValue(sheet, "O2", operation.Number)                // 编号
    f.SetCellValue(sheet, "J2", operation.OperationDate)         // 时间
    f.SetCellValue(sheet, "Q2", operation.Number)                // 编号
    totalAmount := decimal.NewFromInt(0) // 总金额
    totalPrice := decimal.NewFromInt(0)  // 总价
@@ -1013,14 +1032,19 @@
        if i > 9 {
            break
        }
        f.SetCellValue(sheet, "A"+strconv.Itoa(rowIndex), v.Product.Name)               // 产品名称
        f.SetCellValue(sheet, "B"+strconv.Itoa(rowIndex), v.Product.Specs)              //规格
        f.SetCellValue(sheet, "C"+strconv.Itoa(rowIndex), v.TotalGrossWeight.String())  //重量
        f.SetCellValue(sheet, "D"+strconv.Itoa(rowIndex), v.Amount.String())            //数量
        f.SetCellValue(sheet, "E"+strconv.Itoa(rowIndex), v.AuxiliaryAmount.String())   //辅助数量
        f.SetCellValue(sheet, "F"+strconv.Itoa(rowIndex), v.AuxiliaryUnit)              //辅助单位
        f.SetCellValue(sheet, "A"+strconv.Itoa(rowIndex), v.Product.Name)    // 品名
        f.SetCellValue(sheet, "B"+strconv.Itoa(rowIndex), v.Product.Type)    // 型号
        f.SetCellValue(sheet, "C"+strconv.Itoa(rowIndex), v.Product.Unit)    // 单位
        f.SetCellValue(sheet, "D"+strconv.Itoa(rowIndex), v.Amount.String()) // 数量
        unit := service.CreateMoreUnit(v.Amount, v.Product.MoreUnitList)
        for _, v1 := range unit {
            if !v1.Amount.IsZero() {
                f.SetCellValue(sheet, "E"+strconv.Itoa(rowIndex), v1.Amount) // 辅数量
                f.SetCellValue(sheet, "F"+strconv.Itoa(rowIndex), v1.Unit)   // 辅单位
                break
            }
        }
        f.SetCellValue(sheet, "G"+strconv.Itoa(rowIndex), v.Product.SalePrice.String()) // 单价
        // 金额
        if !v.Product.SalePrice.IsZero() {
            ap := v.Amount.Mul(v.Product.SalePrice)
controllers/product_controller.go
@@ -54,6 +54,13 @@
        util.ResponseFormat(c, code.RequestParamError, "单位不能为空")
        return
    }
    if params.BarCode != "" {
        m, err := models.NewMaterialSearch().SetBarCode(params.BarCode).First()
        if err == nil && m.ID != "" { //查出物料表是物料已存在
            util.ResponseFormat(c, code.RequestParamError, "条形码已经被使用")
            return
        }
    }
    //params.ID = utils.GetUUID()
    err := models.WithTransaction(func(tx *gorm.DB) error {
@@ -218,7 +225,7 @@
// GetProductDetails
// @Tags      产品
// @Summary   获取产品详情
// @Summary   通过产品/商品/物料 ID获取产品详情
// @Produce   application/json
// @Param     Authorization    header string true "token"
// @Param        id    path        string            true    "id"  "查询参数"
@@ -231,6 +238,62 @@
        return
    }
    material, err := models.NewMaterialSearch().SetID(id).SetPreload(true).First()
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, "查找失败")
        return
    }
    attributeValues, err := models.NewAttributeValueSearch().SetEntityID(material.ID).FindNotTotal()
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, "查找失败")
        return
    }
    aids := make([]uint, 0)
    for _, v := range attributeValues {
        aids = append(aids, v.AttributeID)
    }
    attributes, err := models.NewAttributeSearch().SetIDs(aids).FindNotTotal()
    attributesMap := make(map[uint]*models.Attribute, len(attributes))
    for _, v := range attributes {
        attributesMap[v.ID] = v
    }
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, "未知动态属性")
    }
    for _, v1 := range attributeValues {
        attribute := attributesMap[v1.AttributeID]
        if attribute == nil {
            continue
        }
        //product.Attributes = append(product.Attributes,v1)
        material.Attributes = append(material.Attributes, models.Attribute{
            Model:        gorm.Model{ID: v1.ID, CreatedAt: v1.CreatedAt, UpdatedAt: v1.UpdatedAt, DeletedAt: v1.DeletedAt},
            Name:         attribute.Name,
            DataType:     attribute.DataType,
            EntityType:   attribute.EntityType,
            SelectValues: attribute.SelectValues,
            SelectValue:  attribute.SelectValue,
            //Value:        v1.Value,
            Value: v1.Value,
        })
    }
    util.ResponseFormat(c, code.Success, material)
}
// GetProductDetailsByBarCode
// @Tags      产品
// @Summary   通过产品/商品/物料 条形码 获取产品详情
// @Produce   application/json
// @Param     Authorization    header string true "token"
// @Param        barCode    path        string            true    "barCode"  "查询参数"
// @Success   200 {object} util.Response{data=models.Material}    "成功"
// @Router    /api-wms/v1/product/getProductDetailsByBarCode/{barCode} [get]
func (slf ProductController) GetProductDetailsByBarCode(c *gin.Context) {
    barCode := c.Param("barCode")
    if barCode == "" {
        util.ResponseFormat(c, code.RequestParamError, "无效条形码")
        return
    }
    material, err := models.NewMaterialSearch().SetBarCode(barCode).SetPreload(true).First()
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, "查找失败")
        return
@@ -296,6 +359,13 @@
    if params.Unit == "" {
        util.ResponseFormat(c, code.RequestParamError, "单位不能为空")
        return
    }
    if params.BarCode != "" {
        m, err := models.NewMaterialSearch().SetBarCode(params.BarCode).First()
        if err == nil && m.ID != params.ID { //查出物料且ID不一样,
            util.ResponseFormat(c, code.RequestParamError, "条形码已经被使用")
            return
        }
    }
    err := models.NewMaterialSearch().SetID(params.ID).Save(&params)
    if err != nil {
@@ -365,7 +435,7 @@
// DeleteProduct
// @Tags      产品
// @Summary   删除产品
// @Summary   通过产品/商品/物料 ID删除产品
// @Produce   application/json
// @Param        id    path        string            true    "id"  "查询参数"
// @Success   200 {object} util.Response "成功"
@@ -384,6 +454,27 @@
    util.ResponseFormat(c, code.Success, "删除成功")
}
// DeleteProductByBarCode
// @Tags      产品
// @Summary    通过产品/商品/物料 条形码删除产品
// @Produce   application/json
// @Param        barCode    path        string            true    "barCode"  "查询参数"
// @Success   200 {object} util.Response "成功"
// @Router    /api-wms/v1/product/deleteProductByBarCode/{barCode} [delete]
func (slf ProductController) DeleteProductByBarCode(c *gin.Context) {
    barCode := c.Param("barCode")
    if barCode == "" {
        util.ResponseFormat(c, code.RequestParamError, "无效id")
        return
    }
    err := models.NewMaterialSearch().SetBarCode(barCode).Delete()
    if err != nil {
        util.ResponseFormat(c, code.RequestParamError, "删除失败")
        return
    }
    util.ResponseFormat(c, code.Success, "删除成功")
}
// AddProductCategory
// @Tags      产品类型
// @Summary   添加产品类型
controllers/report_forms_controller.go
@@ -5,9 +5,11 @@
    "github.com/shopspring/decimal"
    "net/url"
    "os"
    "time"
    "wms/constvar"
    "wms/extend/code"
    "wms/extend/util"
    "wms/models"
    "wms/pkg/logx"
    "wms/request"
    "wms/service"
@@ -335,6 +337,7 @@
        util.ResponseFormat(c, code.InternalError, "查询总数失败")
        return
    }
    result, err := monthFormsService.Query(params)
    if err != nil {
        logx.Errorf("MonthStats query err:%v", err)
@@ -342,6 +345,37 @@
        return
    }
    now := time.Now().Local()
    today := now.Day()
    nowMonth := now.Format("2006-01")
    day, dateStr, err := service.NewSystemConfigService().GetInventoryCutOffPoint()
    if nowMonth == params.Date && today < day || today == day && now.Format("15:04") < dateStr { //本月未至结算时间点
        productIds := make([]string, 0, len(result))
        for _, item := range result {
            productIds = append(productIds, item.ProductId)
        }
        statsRecords, err := service.GetCurrentStats(params.Date, productIds)
        if err != nil {
            util.ResponseFormat(c, code.InternalError, "内部错误")
            return
        }
        statsMap := models.MonthStatsMap(statsRecords)
        for k, v := range result {
            if statsMap[v.ProductId] == nil {
                continue
            }
            result[k].OutputAmount = statsMap[v.ProductId].OutputAmount
            result[k].OutputMoreUnits = statsMap[v.ProductId].OutputMoreUnits
            result[k].EndAmount = statsMap[v.ProductId].EndAmount
            result[k].EndMoreUnits = statsMap[v.ProductId].EndMoreUnits
            result[k].InputAmount = statsMap[v.ProductId].InputAmount
            result[k].InputMoreUnits = statsMap[v.ProductId].InputMoreUnits
        }
    }
    util.ResponseFormatList(c, code.Success, result, int(total))
}
controllers/system_config.go
New file
@@ -0,0 +1,89 @@
package controllers
import (
    "github.com/gin-gonic/gin"
    "wms/extend/code"
    "wms/extend/util"
    "wms/models"
    "wms/pkg/logx"
    "wms/pkg/structx"
    "wms/request"
    "wms/service"
    "wms/task"
)
type SystemConfigController struct{}
// SaveConfig
// @Tags      系统设置
// @Summary   保存系统设置
// @Produce   application/json
// @Param     object  body  request.SystemConfig true  "系统设置信息"'
// @Param     Authorization    header string true "token"
// @Success   200 {object} util.Response "成功"
// @Router    /api-wms/v1/systemConfig/save [post]
func (slf SystemConfigController) SaveConfig(c *gin.Context) {
    var reqParams request.SystemConfig
    var params models.SystemConfig
    if err := c.BindJSON(&reqParams); err != nil {
        util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
        return
    }
    if err := structx.AssignTo(reqParams, &params); err != nil {
        util.ResponseFormat(c, code.RequestParamError, "数据转换错误")
        return
    }
    srv := service.NewSystemConfigService()
    if err := srv.ParamsCheck(params); err != nil {
        util.ResponseFormat(c, code.RequestParamError, err.Error())
        return
    }
    if params.Id == 0 {
        if err := models.NewSystemConfigSearch().Create(&params); err != nil {
            logx.Errorf("SystemConfig create err: %v", err)
            util.ResponseFormat(c, code.SaveFail, "插入失败")
            return
        }
    } else {
        if err := models.NewSystemConfigSearch().SetID(params.ID).Update(&params); err != nil {
            logx.Errorf("SystemConfig update err: %v", err)
            util.ResponseFormat(c, code.SaveFail, "插入失败")
            return
        }
    }
    if err := task.RestartDynamicTask(); err != nil {
        util.ResponseFormat(c, code.SaveFail, "重启定时任务失败")
        return
    }
    util.ResponseFormat(c, code.Success, "保存成功")
}
// GetSystemConfig
// @Tags      系统设置
// @Summary   根据设置类型查询系统设置
// @Produce   application/json
// @Param     object  query    request.GetSystemConfig true  "查询参数"
// @Param     Authorization    header string true "token"
// @Success   200   {object}  util.Response{data=models.SystemConfig}  "成功"
// @Router    /api-wms/v1/systemConfig/get [get]
func (slf SystemConfigController) GetSystemConfig(c *gin.Context) {
    var params request.GetSystemConfig
    if err := c.ShouldBindQuery(&params); err != nil {
        util.ResponseFormat(c, code.RequestParamError, err.Error())
        return
    }
    if params.ConfigType == 0 {
        util.ResponseFormat(c, code.RequestParamError, "配置类型缺失")
        return
    }
    config, _ := models.NewSystemConfigSearch().SetConfigType(params.ConfigType).First()
    util.ResponseFormat(c, code.Success, config)
}
docs/docs.go
@@ -1,5 +1,4 @@
// Code generated by swaggo/swag. DO NOT EDIT.
// Package docs Code generated by swaggo/swag. DO NOT EDIT
package docs
import "github.com/swaggo/swag"
@@ -167,7 +166,7 @@
            }
        },
        "/api-wms/v1/attribute/attribute": {
            "post": {
            "get": {
                "produces": [
                    "application/json"
                ],
@@ -184,6 +183,41 @@
                        "schema": {
                            "$ref": "#/definitions/request.AttributeList"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "$ref": "#/definitions/util.Response"
                        }
                    }
                }
            },
            "post": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "属性"
                ],
                "summary": "添加属性",
                "parameters": [
                    {
                        "description": "属性信息",
                        "name": "object",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/request.AddAttribute"
                        }
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
@@ -2356,12 +2390,40 @@
                "tags": [
                    "产品"
                ],
                "summary": "删除产品",
                "summary": "通过产品/商品/物料 ID删除产品",
                "parameters": [
                    {
                        "type": "string",
                        "description": "id",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "$ref": "#/definitions/util.Response"
                        }
                    }
                }
            }
        },
        "/api-wms/v1/product/deleteProductByBarCode/{barCode}": {
            "delete": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "产品"
                ],
                "summary": "通过产品/商品/物料 条形码删除产品",
                "parameters": [
                    {
                        "type": "string",
                        "description": "barCode",
                        "name": "barCode",
                        "in": "path",
                        "required": true
                    }
@@ -2525,12 +2587,66 @@
                "tags": [
                    "产品"
                ],
                "summary": "获取产品详情",
                "summary": "通过产品/商品/物料 ID获取产品详情",
                "parameters": [
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "id",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/util.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/models.Material"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api-wms/v1/product/getProductDetailsByBarCode/{barCode}": {
            "get": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "产品"
                ],
                "summary": "通过产品/商品/物料 条形码 获取产品详情",
                "parameters": [
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "barCode",
                        "name": "barCode",
                        "in": "path",
                        "required": true
                    }
@@ -2670,6 +2786,9 @@
        },
        "/api-wms/v1/product/inputProduct": {
            "post": {
                "consumes": [
                    "multipart/form-data"
                ],
                "produces": [
                    "application/xlsx"
                ],
@@ -2677,6 +2796,22 @@
                    "物料管理"
                ],
                "summary": "导入物料",
                "parameters": [
                    {
                        "type": "file",
                        "description": "file",
                        "name": "file",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
@@ -3138,6 +3273,99 @@
                }
            }
        },
        "/api-wms/v1/systemConfig/get": {
            "get": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "系统设置"
                ],
                "summary": "根据设置类型查询系统设置",
                "parameters": [
                    {
                        "enum": [
                            1
                        ],
                        "type": "integer",
                        "x-enum-comments": {
                            "SystemConfigTypeInventoryCutOffPoint": "库存结算时间点"
                        },
                        "x-enum-varnames": [
                            "SystemConfigTypeInventoryCutOffPoint"
                        ],
                        "description": "1 每月库存结算时间点",
                        "name": "configType",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/util.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/models.SystemConfig"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api-wms/v1/systemConfig/save": {
            "post": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "系统设置"
                ],
                "summary": "保存系统设置",
                "parameters": [
                    {
                        "description": "系统设置信息",
                        "name": "object",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/request.SystemConfig"
                        }
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "$ref": "#/definitions/util.Response"
                        }
                    }
                }
            }
        },
        "/api-wms/v1/warehouse/getWarehouseDetails/{id}": {
            "get": {
                "produces": [
@@ -3424,6 +3652,21 @@
                "CostingMethodAverageCost"
            ]
        },
        "constvar.FileTemplateCategory": {
            "type": "integer",
            "enum": [
                1,
                2
            ],
            "x-enum-comments": {
                "FileTemplateCategory_Output": "出库",
                "FileTemplateCategory_Selfmade": "入库-自制"
            },
            "x-enum-varnames": [
                "FileTemplateCategory_Selfmade",
                "FileTemplateCategory_Output"
            ]
        },
        "constvar.FileType": {
            "type": "string",
            "enum": [
@@ -3696,6 +3939,18 @@
            "x-enum-varnames": [
                "RuleType_Product",
                "RuleType_ProductCategory"
            ]
        },
        "constvar.SystemConfigType": {
            "type": "integer",
            "enum": [
                1
            ],
            "x-enum-comments": {
                "SystemConfigTypeInventoryCutOffPoint": "库存结算时间点"
            },
            "x-enum-varnames": [
                "SystemConfigTypeInventoryCutOffPoint"
            ]
        },
        "constvar.WhetherType": {
@@ -4047,7 +4302,7 @@
                "autoIncr": {
                    "type": "integer"
                },
                "barcode": {
                "barCode": {
                    "description": "条码",
                    "type": "string"
                },
@@ -4587,6 +4842,9 @@
                "receiverPhone": {
                    "type": "string"
                },
                "remark": {
                    "type": "string"
                },
                "salesDetailsNumber": {
                    "type": "string"
                },
@@ -4619,6 +4877,9 @@
                },
                "updateTime": {
                    "type": "string"
                },
                "warehouseId": {
                    "type": "integer"
                },
                "waybillNumber": {
                    "description": "运单号",
@@ -4829,6 +5090,36 @@
                }
            }
        },
        "models.SystemConfig": {
            "type": "object",
            "properties": {
                "configType": {
                    "description": "每月库存结算时间点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.SystemConfigType"
                        }
                    ]
                },
                "createTime": {
                    "type": "string"
                },
                "id": {
                    "type": "integer"
                },
                "name": {
                    "description": "设置名称",
                    "type": "string"
                },
                "updateTime": {
                    "type": "string"
                },
                "val": {
                    "description": "设置值",
                    "type": "string"
                }
            }
        },
        "models.UnitDict": {
            "type": "object",
            "properties": {
@@ -4889,6 +5180,12 @@
                },
                "createTime": {
                    "type": "string"
                },
                "fileTemplateCategoryIn": {
                    "$ref": "#/definitions/constvar.FileTemplateCategory"
                },
                "fileTemplateCategoryOut": {
                    "$ref": "#/definitions/constvar.FileTemplateCategory"
                },
                "id": {
                    "type": "integer"
@@ -5066,6 +5363,14 @@
                "accountantId": {
                    "type": "string"
                },
                "baseOperationType": {
                    "description": "基础作业类型 5库存盘点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.BaseOperationType"
                        }
                    ]
                },
                "comment": {
                    "description": "备注",
                    "type": "string"
@@ -5157,6 +5462,10 @@
                },
                "toLocationId": {
                    "description": "目标位置id",
                    "type": "integer"
                },
                "warehouseId": {
                    "description": "仓库id",
                    "type": "integer"
                },
                "waybillNumber": {
@@ -5669,6 +5978,14 @@
        "request.OperationList": {
            "type": "object",
            "properties": {
                "baseOperationType": {
                    "description": "1 入库 2 出库 3 内部调拨 4 报废 5 库存盘点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.BaseOperationType"
                        }
                    ]
                },
                "number": {
                    "type": "string"
                },
@@ -5763,6 +6080,30 @@
                }
            }
        },
        "request.SystemConfig": {
            "type": "object",
            "properties": {
                "ID": {
                    "type": "integer"
                },
                "configType": {
                    "description": "1 每月库存结算时间点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.SystemConfigType"
                        }
                    ]
                },
                "name": {
                    "description": "设置名称",
                    "type": "string"
                },
                "val": {
                    "description": "设置值",
                    "type": "string"
                }
            }
        },
        "request.UnitDict": {
            "type": "object",
            "properties": {
docs/swagger.json
@@ -155,7 +155,7 @@
            }
        },
        "/api-wms/v1/attribute/attribute": {
            "post": {
            "get": {
                "produces": [
                    "application/json"
                ],
@@ -172,6 +172,41 @@
                        "schema": {
                            "$ref": "#/definitions/request.AttributeList"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "$ref": "#/definitions/util.Response"
                        }
                    }
                }
            },
            "post": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "属性"
                ],
                "summary": "添加属性",
                "parameters": [
                    {
                        "description": "属性信息",
                        "name": "object",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/request.AddAttribute"
                        }
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
@@ -2344,12 +2379,40 @@
                "tags": [
                    "产品"
                ],
                "summary": "删除产品",
                "summary": "通过产品/商品/物料 ID删除产品",
                "parameters": [
                    {
                        "type": "string",
                        "description": "id",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "$ref": "#/definitions/util.Response"
                        }
                    }
                }
            }
        },
        "/api-wms/v1/product/deleteProductByBarCode/{barCode}": {
            "delete": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "产品"
                ],
                "summary": "通过产品/商品/物料 条形码删除产品",
                "parameters": [
                    {
                        "type": "string",
                        "description": "barCode",
                        "name": "barCode",
                        "in": "path",
                        "required": true
                    }
@@ -2513,12 +2576,66 @@
                "tags": [
                    "产品"
                ],
                "summary": "获取产品详情",
                "summary": "通过产品/商品/物料 ID获取产品详情",
                "parameters": [
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "id",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/util.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/models.Material"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api-wms/v1/product/getProductDetailsByBarCode/{barCode}": {
            "get": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "产品"
                ],
                "summary": "通过产品/商品/物料 条形码 获取产品详情",
                "parameters": [
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "barCode",
                        "name": "barCode",
                        "in": "path",
                        "required": true
                    }
@@ -2658,6 +2775,9 @@
        },
        "/api-wms/v1/product/inputProduct": {
            "post": {
                "consumes": [
                    "multipart/form-data"
                ],
                "produces": [
                    "application/xlsx"
                ],
@@ -2665,6 +2785,22 @@
                    "物料管理"
                ],
                "summary": "导入物料",
                "parameters": [
                    {
                        "type": "file",
                        "description": "file",
                        "name": "file",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
@@ -3126,6 +3262,99 @@
                }
            }
        },
        "/api-wms/v1/systemConfig/get": {
            "get": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "系统设置"
                ],
                "summary": "根据设置类型查询系统设置",
                "parameters": [
                    {
                        "enum": [
                            1
                        ],
                        "type": "integer",
                        "x-enum-comments": {
                            "SystemConfigTypeInventoryCutOffPoint": "库存结算时间点"
                        },
                        "x-enum-varnames": [
                            "SystemConfigTypeInventoryCutOffPoint"
                        ],
                        "description": "1 每月库存结算时间点",
                        "name": "configType",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/util.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/models.SystemConfig"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api-wms/v1/systemConfig/save": {
            "post": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "系统设置"
                ],
                "summary": "保存系统设置",
                "parameters": [
                    {
                        "description": "系统设置信息",
                        "name": "object",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/request.SystemConfig"
                        }
                    },
                    {
                        "type": "string",
                        "description": "token",
                        "name": "Authorization",
                        "in": "header",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "成功",
                        "schema": {
                            "$ref": "#/definitions/util.Response"
                        }
                    }
                }
            }
        },
        "/api-wms/v1/warehouse/getWarehouseDetails/{id}": {
            "get": {
                "produces": [
@@ -3412,6 +3641,21 @@
                "CostingMethodAverageCost"
            ]
        },
        "constvar.FileTemplateCategory": {
            "type": "integer",
            "enum": [
                1,
                2
            ],
            "x-enum-comments": {
                "FileTemplateCategory_Output": "出库",
                "FileTemplateCategory_Selfmade": "入库-自制"
            },
            "x-enum-varnames": [
                "FileTemplateCategory_Selfmade",
                "FileTemplateCategory_Output"
            ]
        },
        "constvar.FileType": {
            "type": "string",
            "enum": [
@@ -3684,6 +3928,18 @@
            "x-enum-varnames": [
                "RuleType_Product",
                "RuleType_ProductCategory"
            ]
        },
        "constvar.SystemConfigType": {
            "type": "integer",
            "enum": [
                1
            ],
            "x-enum-comments": {
                "SystemConfigTypeInventoryCutOffPoint": "库存结算时间点"
            },
            "x-enum-varnames": [
                "SystemConfigTypeInventoryCutOffPoint"
            ]
        },
        "constvar.WhetherType": {
@@ -4035,7 +4291,7 @@
                "autoIncr": {
                    "type": "integer"
                },
                "barcode": {
                "barCode": {
                    "description": "条码",
                    "type": "string"
                },
@@ -4575,6 +4831,9 @@
                "receiverPhone": {
                    "type": "string"
                },
                "remark": {
                    "type": "string"
                },
                "salesDetailsNumber": {
                    "type": "string"
                },
@@ -4607,6 +4866,9 @@
                },
                "updateTime": {
                    "type": "string"
                },
                "warehouseId": {
                    "type": "integer"
                },
                "waybillNumber": {
                    "description": "运单号",
@@ -4817,6 +5079,36 @@
                }
            }
        },
        "models.SystemConfig": {
            "type": "object",
            "properties": {
                "configType": {
                    "description": "每月库存结算时间点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.SystemConfigType"
                        }
                    ]
                },
                "createTime": {
                    "type": "string"
                },
                "id": {
                    "type": "integer"
                },
                "name": {
                    "description": "设置名称",
                    "type": "string"
                },
                "updateTime": {
                    "type": "string"
                },
                "val": {
                    "description": "设置值",
                    "type": "string"
                }
            }
        },
        "models.UnitDict": {
            "type": "object",
            "properties": {
@@ -4877,6 +5169,12 @@
                },
                "createTime": {
                    "type": "string"
                },
                "fileTemplateCategoryIn": {
                    "$ref": "#/definitions/constvar.FileTemplateCategory"
                },
                "fileTemplateCategoryOut": {
                    "$ref": "#/definitions/constvar.FileTemplateCategory"
                },
                "id": {
                    "type": "integer"
@@ -5054,6 +5352,14 @@
                "accountantId": {
                    "type": "string"
                },
                "baseOperationType": {
                    "description": "基础作业类型 5库存盘点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.BaseOperationType"
                        }
                    ]
                },
                "comment": {
                    "description": "备注",
                    "type": "string"
@@ -5145,6 +5451,10 @@
                },
                "toLocationId": {
                    "description": "目标位置id",
                    "type": "integer"
                },
                "warehouseId": {
                    "description": "仓库id",
                    "type": "integer"
                },
                "waybillNumber": {
@@ -5657,6 +5967,14 @@
        "request.OperationList": {
            "type": "object",
            "properties": {
                "baseOperationType": {
                    "description": "1 入库 2 出库 3 内部调拨 4 报废 5 库存盘点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.BaseOperationType"
                        }
                    ]
                },
                "number": {
                    "type": "string"
                },
@@ -5751,6 +6069,30 @@
                }
            }
        },
        "request.SystemConfig": {
            "type": "object",
            "properties": {
                "ID": {
                    "type": "integer"
                },
                "configType": {
                    "description": "1 每月库存结算时间点",
                    "allOf": [
                        {
                            "$ref": "#/definitions/constvar.SystemConfigType"
                        }
                    ]
                },
                "name": {
                    "description": "设置名称",
                    "type": "string"
                },
                "val": {
                    "description": "设置值",
                    "type": "string"
                }
            }
        },
        "request.UnitDict": {
            "type": "object",
            "properties": {
docs/swagger.yaml
@@ -74,6 +74,17 @@
    - CostingMethodStandardPrice
    - CostingMethodFIFO
    - CostingMethodAverageCost
  constvar.FileTemplateCategory:
    enum:
    - 1
    - 2
    type: integer
    x-enum-comments:
      FileTemplateCategory_Output: 出库
      FileTemplateCategory_Selfmade: 入库-自制
    x-enum-varnames:
    - FileTemplateCategory_Selfmade
    - FileTemplateCategory_Output
  constvar.FileType:
    enum:
    - file
@@ -297,6 +308,14 @@
    x-enum-varnames:
    - RuleType_Product
    - RuleType_ProductCategory
  constvar.SystemConfigType:
    enum:
    - 1
    type: integer
    x-enum-comments:
      SystemConfigTypeInventoryCutOffPoint: 库存结算时间点
    x-enum-varnames:
    - SystemConfigTypeInventoryCutOffPoint
  constvar.WhetherType:
    enum:
    - 1
@@ -540,7 +559,7 @@
        type: array
      autoIncr:
        type: integer
      barcode:
      barCode:
        description: 条码
        type: string
      buyExplain:
@@ -926,6 +945,8 @@
        type: string
      receiverPhone:
        type: string
      remark:
        type: string
      salesDetailsNumber:
        type: string
      source:
@@ -946,6 +967,8 @@
        type: integer
      updateTime:
        type: string
      warehouseId:
        type: integer
      waybillNumber:
        description: 运单号
        type: string
@@ -1085,6 +1108,25 @@
      updateTime:
        type: string
    type: object
  models.SystemConfig:
    properties:
      configType:
        allOf:
        - $ref: '#/definitions/constvar.SystemConfigType'
        description: 每月库存结算时间点
      createTime:
        type: string
      id:
        type: integer
      name:
        description: 设置名称
        type: string
      updateTime:
        type: string
      val:
        description: 设置值
        type: string
    type: object
  models.UnitDict:
    properties:
      id:
@@ -1127,6 +1169,10 @@
        type: string
      createTime:
        type: string
      fileTemplateCategoryIn:
        $ref: '#/definitions/constvar.FileTemplateCategory'
      fileTemplateCategoryOut:
        $ref: '#/definitions/constvar.FileTemplateCategory'
      id:
        type: integer
      inboundTransportation:
@@ -1248,6 +1294,10 @@
        type: string
      accountantId:
        type: string
      baseOperationType:
        allOf:
        - $ref: '#/definitions/constvar.BaseOperationType'
        description: 基础作业类型 5库存盘点
      comment:
        description: 备注
        type: string
@@ -1314,6 +1364,9 @@
        description: 状态
      toLocationId:
        description: 目标位置id
        type: integer
      warehouseId:
        description: 仓库id
        type: integer
      waybillNumber:
        description: 运单号
@@ -1672,6 +1725,10 @@
    type: object
  request.OperationList:
    properties:
      baseOperationType:
        allOf:
        - $ref: '#/definitions/constvar.BaseOperationType'
        description: 1 入库 2 出库 3 内部调拨 4 报废 5 库存盘点
      number:
        type: string
      operationTypeId:
@@ -1735,6 +1792,21 @@
        items:
          $ref: '#/definitions/request.UnitDict'
        type: array
    type: object
  request.SystemConfig:
    properties:
      ID:
        type: integer
      configType:
        allOf:
        - $ref: '#/definitions/constvar.SystemConfigType'
        description: 1 每月库存结算时间点
      name:
        description: 设置名称
        type: string
      val:
        description: 设置值
        type: string
    type: object
  request.UnitDict:
    properties:
@@ -2217,7 +2289,7 @@
      tags:
      - 附件管理
  /api-wms/v1/attribute/attribute:
    post:
    get:
      parameters:
      - description: 属性值和对象信息
        in: body
@@ -2235,6 +2307,29 @@
      summary: 添加属性值和对象
      tags:
      - 属性值和对象
    post:
      parameters:
      - description: 属性信息
        in: body
        name: object
        required: true
        schema:
          $ref: '#/definitions/request.AddAttribute'
      - description: token
        in: header
        name: Authorization
        required: true
        type: string
      produces:
      - application/json
      responses:
        "200":
          description: 成功
          schema:
            $ref: '#/definitions/util.Response'
      summary: 添加属性
      tags:
      - 属性
  /api-wms/v1/attribute/delete/{id}:
    delete:
      parameters:
@@ -3577,7 +3672,25 @@
          description: 成功
          schema:
            $ref: '#/definitions/util.Response'
      summary: 删除产品
      summary: 通过产品/商品/物料 ID删除产品
      tags:
      - 产品
  /api-wms/v1/product/deleteProductByBarCode/{barCode}:
    delete:
      parameters:
      - description: barCode
        in: path
        name: barCode
        required: true
        type: string
      produces:
      - application/json
      responses:
        "200":
          description: 成功
          schema:
            $ref: '#/definitions/util.Response'
      summary: 通过产品/商品/物料 条形码删除产品
      tags:
      - 产品
  /api-wms/v1/product/deleteProductCategory/{id}:
@@ -3668,6 +3781,11 @@
  /api-wms/v1/product/getProductDetails/{id}:
    get:
      parameters:
      - description: token
        in: header
        name: Authorization
        required: true
        type: string
      - description: id
        in: path
        name: id
@@ -3685,7 +3803,35 @@
                data:
                  $ref: '#/definitions/models.Material'
              type: object
      summary: 获取产品详情
      summary: 通过产品/商品/物料 ID获取产品详情
      tags:
      - 产品
  /api-wms/v1/product/getProductDetailsByBarCode/{barCode}:
    get:
      parameters:
      - description: token
        in: header
        name: Authorization
        required: true
        type: string
      - description: barCode
        in: path
        name: barCode
        required: true
        type: string
      produces:
      - application/json
      responses:
        "200":
          description: 成功
          schema:
            allOf:
            - $ref: '#/definitions/util.Response'
            - properties:
                data:
                  $ref: '#/definitions/models.Material'
              type: object
      summary: 通过产品/商品/物料 条形码 获取产品详情
      tags:
      - 产品
  /api-wms/v1/product/getProductList:
@@ -3753,6 +3899,19 @@
      - 产品
  /api-wms/v1/product/inputProduct:
    post:
      consumes:
      - multipart/form-data
      parameters:
      - description: file
        in: formData
        name: file
        required: true
        type: file
      - description: token
        in: header
        name: Authorization
        required: true
        type: string
      produces:
      - application/xlsx
      responses:
@@ -4039,6 +4198,64 @@
      summary: 更新重订货规则
      tags:
      - 重订货规则
  /api-wms/v1/systemConfig/get:
    get:
      parameters:
      - description: 1 每月库存结算时间点
        enum:
        - 1
        in: query
        name: configType
        required: true
        type: integer
        x-enum-comments:
          SystemConfigTypeInventoryCutOffPoint: 库存结算时间点
        x-enum-varnames:
        - SystemConfigTypeInventoryCutOffPoint
      - description: token
        in: header
        name: Authorization
        required: true
        type: string
      produces:
      - application/json
      responses:
        "200":
          description: 成功
          schema:
            allOf:
            - $ref: '#/definitions/util.Response'
            - properties:
                data:
                  $ref: '#/definitions/models.SystemConfig'
              type: object
      summary: 根据设置类型查询系统设置
      tags:
      - 系统设置
  /api-wms/v1/systemConfig/save:
    post:
      parameters:
      - description: 系统设置信息
        in: body
        name: object
        required: true
        schema:
          $ref: '#/definitions/request.SystemConfig'
      - description: token
        in: header
        name: Authorization
        required: true
        type: string
      produces:
      - application/json
      responses:
        "200":
          description: 成功
          schema:
            $ref: '#/definitions/util.Response'
      summary: 保存系统设置
      tags:
      - 系统设置
  /api-wms/v1/warehouse/getWarehouseDetails/{id}:
    get:
      parameters:
example.xlsx
Binary files differ
main.go
@@ -78,7 +78,10 @@
    go service.InitHistoryReportData()
    //定时任务初始化
    task.Init()
    if err := task.Init(); err != nil {
        logx.Errorf("task init error: %v", err.Error())
        return
    }
    //钉钉机器人初始化
    dingtalkrobot.Init(conf.DingTalkConf.AlarmKey, conf.DingTalkConf.AlarmUrl)
models/db.go
@@ -122,6 +122,7 @@
        MonthStats{},
        Attribute{},
        AttributeValue{},
        SystemConfig{},
    )
    return err
}
models/material.go
@@ -51,7 +51,6 @@
        CategoryId          int                        `gorm:"type:int(11);comment:产品类别id" json:"categoryId"`                //产品类别id
        CategoryName        string                     `gorm:"type:varchar(255);comment:产品类别名称" json:"categoryName"`         //产品类别名称
        InternalReference   string                     `gorm:"type:varchar(255);comment:内部参考" json:"internalReference"`      //内部参考
        Barcode             string                     `gorm:"type:varchar(255);comment:条码" json:"barcode"`                  //条码
        ProductTagId        int                        `gorm:"type:int(11);comment:产品标签id" json:"productTagId"`              //产品标签id
        ProductTagName      string                     `gorm:"type:varchar(255);comment:产品标签名称" json:"productTagName"`       //产品标签名称
        CompanyId           int                        `gorm:"type:int(11);comment:公司id" json:"companyId"`                   //公司id
@@ -96,7 +95,8 @@
        MinInventoryRule decimal.Decimal `json:"minInventoryRule" gorm:"-"` //最小库存
        MaxInventoryRule decimal.Decimal `json:"maxInventoryRule" gorm:"-"` //最大库存
        CreateBy string `gorm:"type:varchar(255);comment:导入人、创建人" json:"createBy"` //创建人
        CreateBy string `gorm:"type:varchar(255);comment:导入人、创建人" json:"createBy"`       //创建人
        BarCode  string `gorm:"type:varchar(255);comment:(商品/产品/物料的)条形码" json:"barCode"` //条码
    }
    MaterialSearch struct {
@@ -164,7 +164,14 @@
        }
    }
    if len(slf.MoreUnitList) != 0 {
        str, err := json.Marshal(slf.MoreUnitList)
        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
        }
@@ -198,6 +205,11 @@
func (slf *MaterialSearch) SetID(id string) *MaterialSearch {
    slf.ID = id
    return slf
}
func (slf *MaterialSearch) SetBarCode(barCode string) *MaterialSearch {
    slf.BarCode = barCode
    return slf
}
@@ -272,6 +284,9 @@
    if slf.ID != "" {
        db = db.Where("id = ?", slf.ID)
    }
    if slf.BarCode != "" {
        db = db.Where("bar_code = ?", slf.BarCode)
    }
    if slf.Name != "" {
        db = db.Where("name = ?", slf.Name)
models/operation.go
@@ -61,6 +61,7 @@
        CheckedBy    string `json:"checkedBy" gorm:"type:varchar(255);comment:验证者UserId"`
        Remark       string `json:"remark"`
        WarehouseId      int  `json:"warehouseId" gorm:"type:int;not null;comment:仓库id"`
        IsInternalOutput bool `json:"isInternalOutput"` //是否调拨产生的出库
    }
models/system_config.go
New file
@@ -0,0 +1,244 @@
package models
import (
    "fmt"
    "gorm.io/gorm"
    "wms/constvar"
    "wms/pkg/mysqlx"
)
type (
    // SystemConfig 系统设置
    SystemConfig struct {
        WmsModel
        Id         int                       `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
        ConfigType constvar.SystemConfigType `json:"configType" gorm:"type:int;not null"`                                 //每月库存结算时间点
        Name       string                    `json:"name" gorm:"index;type:varchar(255);not null;default:'';comment:设置名"` //设置名称
        Val        string                    `json:"val"  gorm:"index;type:varchar(255);not null;comment:设置值"`            //设置值
    }
    SystemConfigSearch struct {
        SystemConfig
        Order    string
        PageNum  int
        PageSize int
        Keyword  string
        Orm      *gorm.DB
    }
)
func (slf *SystemConfig) TableName() string {
    return "wms_system_config"
}
func NewSystemConfigSearch() *SystemConfigSearch {
    return &SystemConfigSearch{Orm: mysqlx.GetDB()}
}
func (slf *SystemConfigSearch) SetOrm(tx *gorm.DB) *SystemConfigSearch {
    slf.Orm = tx
    return slf
}
func (slf *SystemConfigSearch) SetPage(page, size int) *SystemConfigSearch {
    slf.PageNum, slf.PageSize = page, size
    return slf
}
func (slf *SystemConfigSearch) SetOrder(order string) *SystemConfigSearch {
    slf.Order = order
    return slf
}
func (slf *SystemConfigSearch) SetConfigType(configType constvar.SystemConfigType) *SystemConfigSearch {
    slf.ConfigType = configType
    return slf
}
func (slf *SystemConfigSearch) SetID(id uint) *SystemConfigSearch {
    slf.ID = id
    return slf
}
func (slf *SystemConfigSearch) SetValue(name string) *SystemConfigSearch {
    slf.Name = name
    return slf
}
func (slf *SystemConfigSearch) SetKeyword(keyword string) *SystemConfigSearch {
    slf.Keyword = keyword
    return slf
}
func (slf *SystemConfigSearch) build() *gorm.DB {
    var db = slf.Orm.Table(slf.TableName())
    if slf.ID != 0 {
        db = db.Where("id = ?", slf.ID)
    }
    if slf.Order != "" {
        db = db.Order(slf.Order)
    }
    if slf.Keyword != "" {
        db = db.Where("name like ?", fmt.Sprintf("%%%v%%", slf.Keyword))
    }
    if slf.Name != "" {
        db = db.Where("name = ?", slf.Name)
    }
    if slf.ConfigType != 0 {
        db = db.Where("config_type = ?", slf.ConfigType)
    }
    return db
}
// Create 单条插入
func (slf *SystemConfigSearch) Create(record *SystemConfig) error {
    var db = slf.build()
    if err := db.Create(record).Error; err != nil {
        return err
    }
    return nil
}
// CreateBatch 批量插入
func (slf *SystemConfigSearch) CreateBatch(records []*SystemConfig) error {
    var db = slf.build()
    if err := db.Create(&records).Error; err != nil {
        return fmt.Errorf("create batch err: %v, records: %+v", err, records)
    }
    return nil
}
func (slf *SystemConfigSearch) Update(record *SystemConfig) error {
    var db = slf.build()
    if err := db.Omit("CreatedAt").Updates(record).Error; err != nil {
        return fmt.Errorf("save err: %v, record: %+v", err, record)
    }
    return nil
}
func (slf *SystemConfigSearch) UpdateByMap(upMap map[string]interface{}) error {
    var (
        db = slf.build()
    )
    if err := db.Updates(upMap).Error; err != nil {
        return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
    }
    return nil
}
func (slf *SystemConfigSearch) UpdateByQuery(query string, args []interface{}, upMap map[string]interface{}) error {
    var (
        db = slf.Orm.Table(slf.TableName()).Where(query, args...)
    )
    if err := db.Updates(upMap).Error; err != nil {
        return fmt.Errorf("update by query err: %v, query: %s, args: %+v, upMap: %+v", err, query, args, upMap)
    }
    return nil
}
func (slf *SystemConfigSearch) Delete() error {
    var db = slf.build()
    return db.Delete(&SystemConfig{}).Error
}
func (slf *SystemConfigSearch) First() (*SystemConfig, error) {
    var (
        record = new(SystemConfig)
        db     = slf.build()
    )
    if err := db.First(record).Error; err != nil {
        return record, err
    }
    return record, nil
}
func (slf *SystemConfigSearch) Find() ([]*SystemConfig, int64, error) {
    var (
        records = make([]*SystemConfig, 0)
        total   int64
        db      = slf.build()
    )
    if err := db.Count(&total).Error; err != nil {
        return records, total, fmt.Errorf("find count err: %v", err)
    }
    if slf.PageNum*slf.PageSize > 0 {
        db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
    }
    if err := db.Find(&records).Error; err != nil {
        return records, total, fmt.Errorf("find records err: %v", err)
    }
    return records, total, nil
}
func (slf *SystemConfigSearch) FindNotTotal() ([]*SystemConfig, error) {
    var (
        records = make([]*SystemConfig, 0)
        db      = slf.build()
    )
    if slf.PageNum*slf.PageSize > 0 {
        db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
    }
    if err := db.Find(&records).Error; err != nil {
        return records, fmt.Errorf("find records err: %v", err)
    }
    return records, nil
}
// FindByQuery 指定条件查询.
func (slf *SystemConfigSearch) FindByQuery(query string, args []interface{}) ([]*SystemConfig, int64, error) {
    var (
        records = make([]*SystemConfig, 0)
        total   int64
        db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
    )
    if err := db.Count(&total).Error; err != nil {
        return records, total, fmt.Errorf("find by query count err: %v", err)
    }
    if slf.PageNum*slf.PageSize > 0 {
        db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
    }
    if err := db.Find(&records).Error; err != nil {
        return records, total, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
    }
    return records, total, nil
}
// FindByQueryNotTotal 指定条件查询&不查询总条数.
func (slf *SystemConfigSearch) FindByQueryNotTotal(query string, args []interface{}) ([]*SystemConfig, error) {
    var (
        records = make([]*SystemConfig, 0)
        db      = slf.Orm.Table(slf.TableName()).Where(query, args...)
    )
    if slf.PageNum*slf.PageSize > 0 {
        db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
    }
    if err := db.Find(&records).Error; err != nil {
        return records, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
    }
    return records, nil
}
request/config_type.go
New file
@@ -0,0 +1,14 @@
package request
import "wms/constvar"
type SystemConfig struct {
    ID         uint                      `json:"ID"`
    ConfigType constvar.SystemConfigType `json:"configType" gorm:"type:int;not null"`                                 //1 每月库存结算时间点
    Name       string                    `json:"name" gorm:"index;type:varchar(255);not null;default:'';comment:设置名"` //设置名称
    Val        string                    `json:"val"  gorm:"index;type:varchar(255);not null;comment:设置值"`            //设置值
}
type GetSystemConfig struct {
    ConfigType constvar.SystemConfigType `form:"configType" binding:"required"` //1 每月库存结算时间点
}
request/operation.go
@@ -14,28 +14,30 @@
    Status            constvar.OperationStatus `json:"status" gorm:"type:int(11);not null;comment:状态"`            //状态
    //FromLocationId    int                      `json:"fromLocationId"   gorm:"type:int;not null;comment:源位置id"`   //源位置id
    //ToLocationId      int                      `json:"toLocationId"    gorm:"type:int;not null;comment:目标位置id"`   //目标位置id
    OperationDate     string              `json:"operationDate" gorm:"type:varchar(31);comment:安排日期"` //安排日期
    Details           []*OperationDetails `json:"details"`
    ContacterID       int                 `json:"contacterID" gorm:"type:int;comment:联系人ID"`           //联系人ID-非必填
    ContacterName     string              `json:"contacterName" gorm:"type:varchar(63);comment:联系人姓名"` //联系人姓名-非必填
    CompanyID         string              `json:"companyID"`                                           //公司ID-客户
    CompanyName       string              `json:"companyName" gorm:"type:varchar(127);comment:公司名称"`   //公司名称-客户名称
    Comment           string              `json:"comment" gorm:"type:text;comment:备注"`                 //备注
    LogisticCompanyId string              `json:"logisticCompanyId"   gorm:"type:varchar(191);comment:物流公司id"`
    WaybillNumber     string              `json:"waybillNumber" gorm:"type:varchar(255);comment:运单号"`    //运单号
    Weight            decimal.Decimal     `gorm:"type:decimal(20,2);comment:重量" json:"weight"`           //重量
    LogisticWeight    decimal.Decimal     `gorm:"type:decimal(20,2);comment:物流重量" json:"logisticWeight"` //物流重量
    ReceiverName      string              `json:"receiverName" gorm:"type:varchar(31);comment:收货人姓名"`
    ReceiverPhone     string              `json:"receiverPhone" gorm:"type:varchar(31);comment:联系电话"`
    ReceiverAddr      string              `json:"receiverAddr" gorm:"type:varchar(255);comment:收货地址"`
    LocationId        int                 `json:"locationId"   gorm:"type:int;not null;comment:源位置id"`     //源位置id
    ToLocationId      int                 `json:"toLocationId"    gorm:"type:int;not null;comment:仓库位置id"` //目标位置id
    ManagerId         string              `json:"managerId" gorm:"type:varchar(255);comment:主管id"`
    Manager           string              `json:"manager" gorm:"type:varchar(255);comment:主管名称"`
    AccountantId      string              `json:"accountantId" gorm:"type:varchar(255);comment:会计id"`
    Accountant        string              `json:"accountant" gorm:"type:varchar(255);comment:会计名称"`
    CustodianId       string              `json:"custodianId" gorm:"type:varchar(255);comment:保管员id"`
    Custodian         string              `json:"custodian" gorm:"type:varchar(255);comment:保管员名称"`
    OperationDate     string                     `json:"operationDate" gorm:"type:varchar(31);comment:安排日期"` //安排日期
    Details           []*OperationDetails        `json:"details"`
    ContacterID       int                        `json:"contacterID" gorm:"type:int;comment:联系人ID"`           //联系人ID-非必填
    ContacterName     string                     `json:"contacterName" gorm:"type:varchar(63);comment:联系人姓名"` //联系人姓名-非必填
    CompanyID         string                     `json:"companyID"`                                           //公司ID-客户
    CompanyName       string                     `json:"companyName" gorm:"type:varchar(127);comment:公司名称"`   //公司名称-客户名称
    Comment           string                     `json:"comment" gorm:"type:text;comment:备注"`                 //备注
    LogisticCompanyId string                     `json:"logisticCompanyId"   gorm:"type:varchar(191);comment:物流公司id"`
    WaybillNumber     string                     `json:"waybillNumber" gorm:"type:varchar(255);comment:运单号"`    //运单号
    Weight            decimal.Decimal            `gorm:"type:decimal(20,2);comment:重量" json:"weight"`           //重量
    LogisticWeight    decimal.Decimal            `gorm:"type:decimal(20,2);comment:物流重量" json:"logisticWeight"` //物流重量
    ReceiverName      string                     `json:"receiverName" gorm:"type:varchar(31);comment:收货人姓名"`
    ReceiverPhone     string                     `json:"receiverPhone" gorm:"type:varchar(31);comment:联系电话"`
    ReceiverAddr      string                     `json:"receiverAddr" gorm:"type:varchar(255);comment:收货地址"`
    LocationId        int                        `json:"locationId"   gorm:"type:int;not null;comment:源位置id"`     //源位置id
    ToLocationId      int                        `json:"toLocationId"    gorm:"type:int;not null;comment:仓库位置id"` //目标位置id
    ManagerId         string                     `json:"managerId" gorm:"type:varchar(255);comment:主管id"`
    Manager           string                     `json:"manager" gorm:"type:varchar(255);comment:主管名称"`
    AccountantId      string                     `json:"accountantId" gorm:"type:varchar(255);comment:会计id"`
    Accountant        string                     `json:"accountant" gorm:"type:varchar(255);comment:会计名称"`
    CustodianId       string                     `json:"custodianId" gorm:"type:varchar(255);comment:保管员id"`
    Custodian         string                     `json:"custodian" gorm:"type:varchar(255);comment:保管员名称"`
    BaseOperationType constvar.BaseOperationType `json:"baseOperationType" gorm:"type:tinyint;not null;comment:基础作业类型"` //基础作业类型 5库存盘点
    WarehouseId       int                        `json:"warehouseId" gorm:"type:int;not null;comment:仓库id"`             //仓库id
}
type OperationDetails struct {
@@ -59,9 +61,10 @@
type OperationList struct {
    PageInfo
    OperationTypeId int                      `json:"operationTypeId" form:"operationTypeId"`
    Number          string                   `json:"number"`
    Status          constvar.OperationStatus `json:"status"`
    OperationTypeId   int                        `json:"operationTypeId" form:"operationTypeId"`
    BaseOperationType constvar.BaseOperationType `json:"baseOperationType"` // 1 入库 2 出库 3 内部调拨 4 报废 5 库存盘点
    Number            string                     `json:"number"`
    Status            constvar.OperationStatus   `json:"status"`
}
type UpdateOperation struct {
router/router.go
@@ -115,11 +115,13 @@
    productController := new(controllers.ProductController)
    productAPI := r.Group(urlPrefix + "/product")
    {
        productAPI.POST("addProduct", productController.AddProduct)                  // 新增产品
        productAPI.POST("getProductList", productController.GetProductList)          // 获取产品列表
        productAPI.GET("getProductDetails/:id", productController.GetProductDetails) // 获取产品详情
        productAPI.POST("updateProduct", productController.UpdateProduct)            // 修改产品详情
        productAPI.DELETE("deleteProduct/:id", productController.DeleteProduct)      // 删除产品
        productAPI.POST("addProduct", productController.AddProduct)                                         // 新增产品
        productAPI.POST("getProductList", productController.GetProductList)                                 // 获取产品列表
        productAPI.GET("getProductDetails/:id", productController.GetProductDetails)                        // 通过ID获取产品详情
        productAPI.GET("getProductDetailsByBarCode/:barCode", productController.GetProductDetailsByBarCode) // 通过条形码获取产品详情
        productAPI.POST("updateProduct", productController.UpdateProduct)                                   // 修改产品详情
        productAPI.DELETE("deleteProduct/:id", productController.DeleteProduct)                             // 通过ID获删除产品
        productAPI.DELETE("deleteProductByBarCode/:barCode", productController.DeleteProductByBarCode)      // 通过条形码删除产品
        productAPI.POST("addProductCategory", productController.AddProductCategory)                  //添加产品类型
        productAPI.POST("getProductCategoryList", productController.GetProductCategoryList)          //获取产品类型列表
@@ -212,5 +214,13 @@
        attributeValueAPI.GET("primary/:id", attributeValueController.PrimaryAttributeValue) //删除
    }
    //系统配置
    sysCfgCtl := new(controllers.SystemConfigController)
    sysCfgApi := r.Group(urlPrefix + "/systemConfig")
    {
        sysCfgApi.POST("save", sysCfgCtl.SaveConfig)    //保存系统设置
        sysCfgApi.GET("get", sysCfgCtl.GetSystemConfig) //获取系统配置
    }
    return r
}
service/month_forms.go
@@ -1,13 +1,17 @@
package service
import (
    "encoding/json"
    "fmt"
    "github.com/shopspring/decimal"
    "github.com/xuri/excelize/v2"
    "strconv"
    "time"
    "wms/constvar"
    "wms/models"
    "wms/pkg/logx"
    "wms/request"
    "wms/utils"
)
type MonthFormsService struct{}
@@ -178,3 +182,100 @@
    return fileName, nil
}
func GetCurrentStats(date string, productIds []string) (statRecords []*models.MonthStats, err error) {
    //本月期初数量/上月结余数量
    groupSumList, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).GroupSum("product_id", "amount")
    productIds = make([]string, 0, len(groupSumList))
    for _, groupSum := range groupSumList {
        productIds = append(productIds, groupSum.Class)
    }
    products, err := models.NewMaterialSearch().SetFields("id, name, unit, weight, more_unit, more_unit_value").SetIDs(productIds).FindNotTotal()
    if err != nil {
        logx.Errorf("MonthStats GetCurrentStats get products err:%v", err)
        return
    }
    productMap := models.MaterialMap(products)
    beginTime, endTime := utils.GetLastMonthPeriod()
    inputMap, err := GetStatsByOperationType(beginTime, endTime, constvar.BaseOperationTypeIncoming)
    if err != nil {
        logx.Errorf("MonthStats GetStatsByOperationType input err:%v", err)
        return
    }
    outputMap, err := GetStatsByOperationType(beginTime, endTime, constvar.BaseOperationTypeOutgoing)
    if err != nil {
        logx.Errorf("MonthStats GetStatsByOperationType output err:%v", err)
        return
    }
    for _, groupSum := range groupSumList {
        productId := groupSum.Class
        if productMap[productId] == nil {
            continue
        }
        product := productMap[productId]
        amount := groupSum.Sum
        record := models.MonthStats{
            ProductId:   productId,
            ProductName: product.Name,
            Unit:        product.Unit,
            Weight:      product.Weight.Mul(amount),
            Date:        date,
        }
        var (
            moreUnits       string
            inputMoreUnits  string
            outputMoreUnits string
        )
        if *product.MoreUnit {
            moreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList))
            inputMoreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList))
            outputMoreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList))
            if !amount.IsZero() {
                moreValueArr = CreateMoreUnit(amount, product.MoreUnitList)
            }
            if !inputMap[productId].IsZero() {
                inputMoreValueArr = CreateMoreUnit(inputMap[productId], product.MoreUnitList)
            }
            if !outputMap[productId].IsZero() {
                outputMoreValueArr = CreateMoreUnit(outputMap[productId], product.MoreUnitList)
            }
            bys, _ := json.Marshal(moreValueArr)
            moreUnits = string(bys)
            bys, _ = json.Marshal(inputMoreValueArr)
            inputMoreUnits = string(bys)
            bys, _ = json.Marshal(outputMoreValueArr)
            outputMoreUnits = string(bys)
        }
        record.InputAmount = inputMap[productId]
        record.InputMoreUnits = inputMoreUnits
        record.OutputAmount = outputMap[productId]
        record.OutputMoreUnits = outputMoreUnits
        record.EndAmount = amount
        record.EndMoreUnits = moreUnits
        statRecords = append(statRecords, &record)
    }
    return
}
func GetStatsByOperationType(beginTime, endTime time.Time, operationType constvar.BaseOperationType) (m map[string]decimal.Decimal, err error) {
    operationIds, err := models.NewOperationSearch().SetBaseOperationType(operationType).SetFields("id").SetTimeBetween(beginTime, endTime).FindIds()
    if err != nil {
        return
    }
    groupSumList, err := models.NewOperationDetailsSearch().SetOperationIds(operationIds).SetFields("product_id, amount").GroupSum("product_id", "amount")
    if err != nil {
        return
    }
    m = make(map[string]decimal.Decimal, len(groupSumList))
    for _, v := range groupSumList {
        m[v.Class] = v.Sum
    }
    return
}
service/more_units.go
@@ -11,8 +11,11 @@
func CreateMoreUnit(amount decimal.Decimal, units []models.UnitItems) []models.UnitItems {
    moreValueArr := make([]models.UnitItems, 0, len(units))
    for _, unitItem := range units {
        if unitItem.Amount.IsZero() {
            continue
        }
        moreValueArr = append(moreValueArr, models.UnitItems{
            Amount:   amount.Mul(unitItem.Amount),
            Amount:   amount.Div(unitItem.Amount),
            Unit:     unitItem.Unit,
            Floating: unitItem.Floating,
        })
service/system_config.go
New file
@@ -0,0 +1,73 @@
package service
import (
    "errors"
    "github.com/spf13/cast"
    "gorm.io/gorm"
    "strings"
    "time"
    "wms/constvar"
    "wms/models"
)
type SystemConfigService struct {
}
func NewSystemConfigService() *SystemConfigService {
    return &SystemConfigService{}
}
func (slf SystemConfigService) ParamsCheck(params models.SystemConfig) (err error) {
    var oldRecord *models.SystemConfig
    if params.Id != 0 {
        oldRecord, err = models.NewSystemConfigSearch().SetID(params.ID).First()
        if err == gorm.ErrRecordNotFound {
            return errors.New("配置不存在")
        }
    }
    if oldRecord == nil || params.ConfigType != oldRecord.ConfigType {
        _, err = models.NewSystemConfigSearch().SetConfigType(params.ConfigType).First()
        if err != gorm.ErrRecordNotFound {
            return errors.New("配置项重复")
        }
    }
    switch params.ConfigType {
    case constvar.SystemConfigTypeInventoryCutOffPoint:
        _, _, err = slf.CheckInventoryCutOffPoint(params.Val)
        if err != nil {
            return err
        }
    }
    return nil
}
func (slf SystemConfigService) CheckInventoryCutOffPoint(val string) (day int, timeStr string, err error) {
    if !strings.Contains(val, "-") {
        err = errors.New("库存结算时间点应该用分隔符'-'分隔日期和时间")
        return
    }
    arr := strings.Split(val, "-")
    if len(arr) != 2 {
        err = errors.New("库存结算时间点应该用分隔符'-'分隔日期和时间,且只能有一个分隔符")
        return
    }
    day = cast.ToInt(arr[0])
    if day < 0 || day > 28 {
        err = errors.New("库存结算时间点日期不正确,应在1~28之间")
        return
    }
    timeStr = arr[1]
    _, err = time.ParseInLocation("15:04", arr[1], time.Local)
    return
}
func (slf SystemConfigService) GetInventoryCutOffPoint() (day int, timeStr string, err error) {
    config, err := models.NewSystemConfigSearch().SetConfigType(constvar.SystemConfigTypeInventoryCutOffPoint).First()
    if err != nil {
        err = errors.New("库存结算时间点未配置")
        return
    }
    return slf.CheckInventoryCutOffPoint(config.Val)
}
task/month_stats.go
@@ -1,12 +1,9 @@
package task
import (
    "encoding/json"
    "fmt"
    "github.com/shopspring/decimal"
    "gorm.io/gorm"
    "time"
    "wms/constvar"
    "wms/models"
    "wms/pkg/logx"
    "wms/service"
@@ -45,126 +42,40 @@
    oldRecordsMap := models.MonthStatsMap(oldRecords)
    //本月期初数量/上月结余数量
    groupSumList, err := models.NewLocationProductAmountSearch().GroupSum("product_id", "amount")
    productIds := make([]string, 0, len(groupSumList))
    for _, groupSum := range groupSumList {
        productIds = append(productIds, groupSum.Class)
    }
    products, err := models.NewMaterialSearch().SetFields("id, name, unit, weight, more_unit, more_unit_value").SetIDs(productIds).FindNotTotal()
    statsRecords, err := service.GetCurrentStats(date, nil)
    if err != nil {
        logx.Errorf("MonthStats get products err:%v", err)
        return
        return err
    }
    productMap := models.MaterialMap(products)
    beginTime, endTime := GetLastMonthPeriod()
    inputMap, err := GetStatsByOperationType(beginTime, endTime, constvar.BaseOperationTypeIncoming)
    if err != nil {
        logx.Errorf("MonthStats GetStatsByOperationType input err:%v", err)
        return
    }
    outputMap, err := GetStatsByOperationType(beginTime, endTime, constvar.BaseOperationTypeOutgoing)
    if err != nil {
        logx.Errorf("MonthStats GetStatsByOperationType output err:%v", err)
        return
    }
    var record models.MonthStats
    err = models.NewMonthStatsSearch().SetDate(date).Delete()
    if err != nil {
        return
    }
    for _, groupSum := range groupSumList {
        productId := groupSum.Class
        if productMap[productId] == nil {
            continue
        }
        product := productMap[productId]
        amount := groupSum.Sum
        record = models.MonthStats{
            ProductId:   productId,
            ProductName: product.Name,
            BeginAmount: amount,
            Unit:        product.Unit,
            Weight:      product.Weight.Mul(amount),
            Date:        date,
        }
        var (
            moreUnits       string
            inputMoreUnits  string
            outputMoreUnits string
        )
        if *product.MoreUnit {
            moreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList))
            inputMoreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList))
            outputMoreValueArr := make([]models.UnitItems, 0, len(product.MoreUnitList))
            for _, unitItem := range product.MoreUnitList {
                if !amount.IsZero() {
                    moreValueArr = append(moreValueArr, models.UnitItems{
                        Amount:   amount.Mul(unitItem.Amount),
                        Unit:     unitItem.Unit,
                        Floating: unitItem.Floating,
                    })
                }
                if !inputMap[productId].IsZero() {
                    inputMoreValueArr = append(inputMoreValueArr, models.UnitItems{
                        Amount:   inputMap[productId].Mul(unitItem.Amount),
                        Unit:     unitItem.Unit,
                        Floating: unitItem.Floating,
                    })
                }
                if !outputMap[productId].IsZero() {
                    outputMoreValueArr = append(outputMoreValueArr, models.UnitItems{
                        Amount:   outputMap[productId].Mul(unitItem.Amount),
                        Unit:     unitItem.Unit,
                        Floating: unitItem.Floating,
                    })
                }
            }
            bys, _ := json.Marshal(moreValueArr)
            if len(moreValueArr) > 0 {
                fmt.Println(moreValueArr)
            }
            moreUnits = string(bys)
            bys, _ = json.Marshal(inputMoreValueArr)
            inputMoreUnits = string(bys)
            bys, _ = json.Marshal(outputMoreValueArr)
            outputMoreUnits = string(bys)
        }
        record.BeginMoreUnits = moreUnits
    for _, record := range statsRecords {
        record.BeginAmount = record.EndAmount
        record.BeginMoreUnits = record.EndMoreUnits
        err = models.WithTransaction(func(db *gorm.DB) error {
            err = models.NewMonthStatsSearch().SetOrm(db).Create(&record)
            err = models.NewMonthStatsSearch().SetOrm(db).Create(record)
            if err != nil {
                logx.Errorf("NewMonthStatsSearch Create err:%v, record: %+v", err, record)
                service.SendAlarm("月度统计创建本月失败", fmt.Sprintf("NewMonthStatsSearch Create err:%v, record: %+v", err, record))
            }
            if oldRecordsMap[productId] != nil {
            if oldRecordsMap[record.ProductId] != nil && oldRecordsMap[record.ProductId].Id != 0 {
                m := map[string]interface{}{
                    "end_more_units": moreUnits,
                    "end_amount":     amount,
                    "end_more_units": record.BeginMoreUnits,
                    "end_amount":     record.BeginAmount,
                }
                if !inputMap[productId].IsZero() || !outputMap[productId].IsZero() {
                    record.InputAmount = inputMap[productId]
                    record.InputMoreUnits = inputMoreUnits
                    record.OutputAmount = outputMap[productId]
                    record.OutputMoreUnits = outputMoreUnits
                    m["input_amount"] = inputMap[productId]
                    m["input_more_units"] = inputMoreUnits
                    m["output_amount"] = outputMap[productId]
                    m["output_more_units"] = outputMoreUnits
                if !record.InputAmount.IsZero() || !record.InputAmount.IsZero() {
                    m["input_amount"] = record.InputAmount
                    m["input_more_units"] = record.InputMoreUnits
                    m["output_amount"] = record.InputAmount
                    m["output_more_units"] = record.OutputMoreUnits
                }
                err = models.NewMonthStatsSearch().SetOrm(db).SetID(oldRecordsMap[productId].Id).UpdateByMap(m)
                err = models.NewMonthStatsSearch().SetOrm(db).SetID(oldRecordsMap[record.ProductId].Id).UpdateByMap(m)
                if err != nil {
                    logx.Errorf("NewMonthStatsSearch UpdateByMap err:%v, id:%v, m:%+v", err, oldRecordsMap[productId].ID, m)
                    logx.Errorf("NewMonthStatsSearch UpdateByMap err:%v, id:%v, m:%+v", err, oldRecordsMap[record.ProductId].Id, m)
                    service.SendAlarm("月度统计更改上月失败", fmt.Sprintf("NewMonthStatsSearch Create err:%v, record: %+v", err, record))
                }
            }
@@ -175,41 +86,4 @@
        service.SendAlarm("月度统计执行成功", "")
    }
    return
}
func GetStatsByOperationType(beginTime, endTime time.Time, operationType constvar.BaseOperationType) (m map[string]decimal.Decimal, err error) {
    operationIds, err := models.NewOperationSearch().SetBaseOperationType(operationType).SetFields("id").SetTimeBetween(beginTime, endTime).FindIds()
    if err != nil {
        return
    }
    groupSumList, err := models.NewOperationDetailsSearch().SetOperationIds(operationIds).SetFields("product_id, amount").GroupSum("product_id", "amount")
    if err != nil {
        return
    }
    m = make(map[string]decimal.Decimal, len(groupSumList))
    for _, v := range groupSumList {
        m[v.Class] = v.Sum
    }
    return
}
// GetLastMonthPeriod 返回上个月的月初时间和月末时间
func GetLastMonthPeriod() (time.Time, time.Time) {
    // 获取当前时间
    now := time.Now()
    // 计算上个月的年份和月份
    lastMonth := now.AddDate(0, -1, 0)
    lastYear, lastMonthNum, _ := lastMonth.Date()
    // 获取上个月的第一天的日期(即上个月月初)
    firstDayOfLastMonth := time.Date(lastYear, lastMonthNum, 1, 0, 0, 0, 0, now.Location())
    // 获取本月第一天的日期(即本月月初)
    firstDayOfThisMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
    // 上个月月末时间即为本月月初减去一秒
    lastDayOfLastMonth := firstDayOfThisMonth.Add(-time.Second)
    return firstDayOfLastMonth, lastDayOfLastMonth
}
task/tasklist.go
@@ -4,19 +4,42 @@
    "github.com/go-co-op/gocron"
    "time"
    "wms/pkg/logx"
    "wms/service"
)
var s *gocron.Scheduler
var dynamicScheduler *gocron.Scheduler
func init() {
    s = gocron.NewScheduler(time.UTC)
    dynamicScheduler = gocron.NewScheduler(time.Local)
}
func Init() {
    _, err := s.Every(1).Month(1).Do(MonthStats) //每月初执行一次
    if err != nil {
        logx.Errorf("init task err:%v", err)
        panic(err)
    }
func Init() error {
    return StartDynamicTask()
}
    s.StartAsync()
func StartDynamicTask() (err error) {
    sysCfgService := service.NewSystemConfigService()
    day, timeStr, err := sysCfgService.GetInventoryCutOffPoint()
    if err != nil {
        return
    }
    if day != 0 && timeStr != "" {
        _, err = dynamicScheduler.Every(1).Month(day).At(timeStr).Do(MonthStats) //每月初执行一次
        if err != nil {
            logx.Errorf("init task err:%v", err)
            return err
        }
    }
    if dynamicScheduler.Len() == 0 {
        return
    }
    dynamicScheduler.StartAsync()
    return nil
}
func RestartDynamicTask() error {
    if dynamicScheduler != nil {
        dynamicScheduler.Stop()
        dynamicScheduler.Clear()
    }
    return StartDynamicTask()
}
utils/util.go
@@ -3,9 +3,31 @@
import (
    "github.com/google/uuid"
    "strings"
    "time"
)
func GetUUID() string {
    s := uuid.New().String()
    return strings.ReplaceAll(s, "-", "")
}
// GetLastMonthPeriod 返回上个月的月初时间和月末时间
func GetLastMonthPeriod() (time.Time, time.Time) {
    // 获取当前时间
    now := time.Now()
    // 计算上个月的年份和月份
    lastMonth := now.AddDate(0, -1, 0)
    lastYear, lastMonthNum, _ := lastMonth.Date()
    // 获取上个月的第一天的日期(即上个月月初)
    firstDayOfLastMonth := time.Date(lastYear, lastMonthNum, 1, 0, 0, 0, 0, now.Location())
    // 获取本月第一天的日期(即本月月初)
    firstDayOfThisMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
    // 上个月月末时间即为本月月初减去一秒
    lastDayOfLastMonth := firstDayOfThisMonth.Add(-time.Second)
    return firstDayOfLastMonth, lastDayOfLastMonth
}