当月的统计报表(未至库存结算时间点)支持实时查询入库数量出库数量期末数量
4个文件已修改
297 ■■■■■ 已修改文件
controllers/report_forms_controller.go 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/month_forms.go 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
task/month_stats.go 140 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/util.go 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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))
}
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
}
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,108 +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))
            if !amount.IsZero() {
                moreValueArr = service.CreateMoreUnit(amount, product.MoreUnitList)
            }
            if !inputMap[productId].IsZero() {
                inputMoreValueArr = service.CreateMoreUnit(inputMap[productId], product.MoreUnitList)
            }
            if !outputMap[productId].IsZero() {
                outputMoreValueArr = service.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.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))
                }
            }
@@ -157,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
}
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
}