当月的统计报表(未至库存结算时间点)支持实时查询入库数量出库数量期末数量
| | |
| | | "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" |
| | |
| | | util.ResponseFormat(c, code.InternalError, "查询总数失败") |
| | | return |
| | | } |
| | | |
| | | result, err := monthFormsService.Query(params) |
| | | if err != nil { |
| | | logx.Errorf("MonthStats query err:%v", err) |
| | |
| | | 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)) |
| | | } |
| | | |
| | |
| | | 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{} |
| | |
| | | |
| | | 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 |
| | | } |
| | |
| | | package task |
| | | |
| | | import ( |
| | | "encoding/json" |
| | | "fmt" |
| | | "github.com/shopspring/decimal" |
| | | "gorm.io/gorm" |
| | | "time" |
| | | "wms/constvar" |
| | | "wms/models" |
| | | "wms/pkg/logx" |
| | | "wms/service" |
| | |
| | | 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)) |
| | | } |
| | | } |
| | |
| | | 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 |
| | | } |
| | |
| | | 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 |
| | | } |