package services import ( "eta/eta_forum_hub/models" "eta/eta_forum_hub/models/mgodb" "eta/eta_forum_hub/utils" "fmt" "github.com/shopspring/decimal" "strconv" "time" ) func BatchAddOrUpdateEdbData(req []*models.AddEdbDataReq) (err error) { for _, reqData := range req { if reqData.EdbType == 1 { err = AddOrUpdateEdbData(reqData.EdbCode, reqData.DataList) if err != nil { return } } else { err = AddOrUpdateEdbDataCalculate(reqData.EdbCode, reqData.DataList) if err != nil { return } } } return } func AddOrUpdateEdbData(edbCode string, dataList []*models.EdbDataBase) (err error) { addList := make([]interface{}, 0) existList, err := mgodb.GetEdbDataBaseByEdbCode(edbCode) if err != nil { err = fmt.Errorf("查询指标数据出错 error, %v", err) return } existMap := make(map[string]*mgodb.EdbDataBase, len(existList)) deleteMap := make(map[string]struct{}, len(existList)) for _, exist := range existList { tmp := exist.DataTime.Format(utils.FormatDate) existMap[tmp] = exist deleteMap[tmp] = struct{}{} } for _, v := range dataList { dataTime, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local) if e != nil { err = fmt.Errorf("时间格式化出错 error, %v", e) return } val, e := strconv.ParseFloat(v.Value, 64) if e != nil { err = fmt.Errorf("指标数据格式化出错 error, %v", e) return } if oldObj, ok := existMap[v.DataTime]; !ok { tmp := &mgodb.EdbDataBase{ EdbInfoId: 0, EdbCode: v.EdbCode, DataTime: dataTime, Value: val, Status: v.Status, CreateTime: time.Now(), ModifyTime: time.Now(), DataTimestamp: v.DataTimestamp, } addList = append(addList, tmp) if len(addList) >= 500 { err = mgodb.InsertEdbDataBatch(addList) if err != nil { err = fmt.Errorf("批量新增指标数据失败 error, %v", e) return } addList = make([]interface{}, 0) } } else { delete(deleteMap, v.DataTime) if val != oldObj.Value { err = mgodb.ModifyValueEdbDataValue(oldObj.EdbDataId, val) if err != nil { err = fmt.Errorf("更新指标数据出错 error, %v", err) return } } } } //遍历deletemap,找出需要删除的日期 { removeDateList := make([]time.Time, 0) for dateTime := range deleteMap { dateT, e := time.ParseInLocation(utils.FormatDate, dateTime, time.Local) if e != nil { err = fmt.Errorf("日期格式错误 error, %v", e) return } removeDateList = append(removeDateList, dateT) } removeNum := len(removeDateList) if removeNum > 0 { err = mgodb.DeleteEdbInfoDataByEdbInfoIdAndDate(edbCode, removeDateList) if err != nil { err = fmt.Errorf("删除多余日期失败,error, %v", err) return } } } if len(addList) > 0 { err = mgodb.InsertEdbDataBatch(addList) } return } func AddOrUpdateEdbDataCalculate(edbCode string, dataList []*models.EdbDataBase) (err error) { addList := make([]interface{}, 0) existList, err := mgodb.GetEdbDataCalculateByEdbCode(edbCode) if err != nil { err = fmt.Errorf("查询指标数据出错 error, %v", err) return } existMap := make(map[string]*mgodb.EdbDataBase, len(existList)) deleteMap := make(map[string]struct{}, len(existList)) for _, exist := range existList { tmp := exist.DataTime.Format(utils.FormatDate) existMap[tmp] = exist deleteMap[tmp] = struct{}{} } for _, v := range dataList { dataTime, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local) if e != nil { err = fmt.Errorf("时间格式化出错 error, %v", e) return } val, e := strconv.ParseFloat(v.Value, 64) if e != nil { err = fmt.Errorf("指标数据格式化出错 error, %v", e) return } if oldObj, ok := existMap[v.DataTime]; !ok { tmp := &mgodb.EdbDataBase{ EdbInfoId: 0, EdbCode: v.EdbCode, DataTime: dataTime, Value: val, Status: v.Status, CreateTime: time.Now(), ModifyTime: time.Now(), DataTimestamp: v.DataTimestamp, } addList = append(addList, tmp) if len(addList) >= 500 { err = mgodb.InsertEdbCalculateDataBatch(addList) if err != nil { err = fmt.Errorf("批量新增指标数据失败 error, %v", e) return } addList = make([]interface{}, 0) } } else { delete(deleteMap, v.DataTime) if val != oldObj.Value { err = mgodb.ModifyValueEdbCalculateDataValue(oldObj.EdbDataId, val) if err != nil { err = fmt.Errorf("更新指标数据出错 error, %v", err) return } } } } //遍历deleteMap,找出需要删除的日期 { removeDateList := make([]time.Time, 0) for dateTime := range deleteMap { dateT, e := time.ParseInLocation(utils.FormatDate, dateTime, time.Local) if e != nil { err = fmt.Errorf("日期格式错误 error, %v", e) return } removeDateList = append(removeDateList, dateT) } removeNum := len(removeDateList) if removeNum > 0 { err = mgodb.DeleteEdbCalculateDataByEdbInfoIdAndDate(edbCode, removeDateList) if err != nil { err = fmt.Errorf("删除多余日期失败,error, %v", err) return } } } if len(addList) > 0 { err = mgodb.InsertEdbCalculateDataBatch(addList) } return } // GetEdbDataList 获取指标的数据(日期正序返回) func GetEdbDataList(endInfoId, edbType int, startDate, endDate string) (list []*models.EdbDataList, err error) { dataList := make([]*mgodb.EdbDataBase, 0) var startDateT, endDateT time.Time if startDate != "" { startDateT, err = time.ParseInLocation(utils.FormatDate, startDate, time.Local) if err != nil { err = fmt.Errorf("日期格式错误 error, %v", err) return } } if endDate != "" { endDateT, err = time.ParseInLocation(utils.FormatDate, endDate, time.Local) if err != nil { err = fmt.Errorf("日期格式错误 error, %v", err) return } } if edbType == 1 { dataList, err = mgodb.GetEdbDataList(endInfoId, startDateT, endDateT) if err != nil { err = fmt.Errorf("查询指标数据出错 error, %v", err) return } } else { dataList, err = mgodb.GetEdbCalculateDataList(endInfoId, startDateT, endDateT) if err != nil { err = fmt.Errorf("查询指标数据出错 error, %v", err) return } } list = make([]*models.EdbDataList, 0) for _, v := range dataList { // 字符串转成浮点数 list = append(list, &models.EdbDataList{ EdbInfoId: v.EdbInfoId, DataTime: v.DataTime.Format(utils.FormatDate), DataTimestamp: v.DataTimestamp, Value: v.Value, }, ) } return } // TbzDiv 同比值计算 func TbzDiv(a, b float64) float64 { var valFloat float64 if b != 0 { af := decimal.NewFromFloat(a) bf := decimal.NewFromFloat(b) val, _ := af.Div(bf).Float64() val = val - 1 valFloat, _ = decimal.NewFromFloat(val).RoundCeil(4).Float64() } else { valFloat = 0 } return valFloat } // GetEdbDataTbzForSeason 获取指标的同比值数据 func GetEdbDataTbzForSeason(frequency string, tmpDataList []*models.EdbDataList, startDateTime time.Time) (dataList []*models.EdbDataList, minValue, maxValue float64, err error) { dataList = make([]*models.EdbDataList, 0) // 数据处理 var dateArr []string dataMap := make(map[string]*models.EdbDataList) for _, v := range tmpDataList { dateArr = append(dateArr, v.DataTime) dataMap[v.DataTime] = v } for _, av := range dateArr { currentItem, ok := dataMap[av] // 如果找不到当前日期的数据,那么终止当前循环,进入下一循环 if !ok { continue } tmpItem := *currentItem var isOk bool //是否计算出来结果 //当前日期 currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local) if tmpErr != nil { err = tmpErr return } // 如果存在开始日期,同时,当前日期早于开始日期,那么终止当前循环,进入下一循环 if !startDateTime.IsZero() && currentDate.Before(startDateTime) { continue } //上一年的日期 preDate := currentDate.AddDate(-1, 0, 0) preDateStr := preDate.Format(utils.FormatDate) if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到 tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value) isOk = true } else { if frequency == "月度" { //向上和向下,各找一个月 for i := 0; i <= 35; i++ { nextDateDay := preDate.AddDate(0, 0, i) nextDateDayStr := nextDateDay.Format(utils.FormatDate) if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到 tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value) isOk = true break } else { preDateDay := preDate.AddDate(0, 0, -i) preDateDayStr := preDateDay.Format(utils.FormatDate) if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到 tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value) isOk = true break } } } } else if frequency == "季度" || frequency == "年度" { if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到 tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value) isOk = true break } } else { nextDateDay := preDate.AddDate(0, 0, 1) nextDateDayStr := nextDateDay.Format(utils.FormatDate) preDateDay := preDate.AddDate(0, 0, -1) preDateDayStr := preDateDay.Format(utils.FormatDate) for i := 0; i < 35; i++ { if i >= 1 { nextDateDay = nextDateDay.AddDate(0, 0, i) nextDateDayStr = nextDateDay.Format(utils.FormatDate) } if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到 tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value) isOk = true break } else { if i >= 1 { preDateDay = preDate.AddDate(0, 0, -i) preDateDayStr = nextDateDay.Format(utils.FormatDate) } if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到 tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value) isOk = true break } } } } } if isOk { if tmpItem.Value > maxValue { maxValue = tmpItem.Value } if tmpItem.Value < minValue { minValue = tmpItem.Value } dataList = append(dataList, &tmpItem) } } return }