336 lines
9.7 KiB
Go
336 lines
9.7 KiB
Go
package service
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"strconv"
|
||
"time"
|
||
|
||
"be.ems/src/framework/i18n"
|
||
"be.ems/src/framework/logger"
|
||
"be.ems/src/framework/utils/date"
|
||
"be.ems/src/framework/utils/file"
|
||
"be.ems/src/framework/utils/parse"
|
||
"be.ems/src/modules/network_data/model"
|
||
"be.ems/src/modules/network_data/repository"
|
||
sysService "be.ems/src/modules/system/service"
|
||
)
|
||
|
||
// 实例化数据层 CDREventIMS 结构体
|
||
var NewCDREventIMS = &CDREventIMS{
|
||
cdrEventIMSRepository: repository.NewCDREventIMS,
|
||
}
|
||
|
||
// CDREventImpl CDR会话事件IMS 服务层处理
|
||
type CDREventIMS struct {
|
||
cdrEventIMSRepository *repository.CDREventIMS // CDR会话事件数据信息
|
||
}
|
||
|
||
// SelectPage 根据条件分页查询
|
||
func (r *CDREventIMS) SelectPageMT(querys model.CDREventIMSQuery) map[string]any {
|
||
return r.cdrEventIMSRepository.SelectPage(querys)
|
||
}
|
||
|
||
// SelectPage 根据条件分页查询
|
||
func (r *CDREventIMS) SelectPage(querys model.CDREventIMSQuery) ([]model.CDREventIMS, int64) {
|
||
return r.cdrEventIMSRepository.SelectByPage(querys)
|
||
}
|
||
|
||
// DeleteByIds 批量删除信息
|
||
func (r *CDREventIMS) DeleteByIds(cdrIds []string) (int64, error) {
|
||
// 检查是否存在
|
||
ids := r.cdrEventIMSRepository.SelectByIds(cdrIds)
|
||
if len(ids) <= 0 {
|
||
return 0, fmt.Errorf("not data")
|
||
}
|
||
|
||
if len(ids) == len(cdrIds) {
|
||
rows := r.cdrEventIMSRepository.DeleteByIds(cdrIds)
|
||
return rows, nil
|
||
}
|
||
// 删除信息失败!
|
||
return 0, fmt.Errorf("delete fail")
|
||
}
|
||
|
||
// ExportXlsx 导出数据到 xlsx 文件
|
||
func (r CDREventIMS) ExportXlsx(rows []model.CDREventIMS, fileName, language string) (string, error) {
|
||
// 第一行表头标题
|
||
headerCells := map[string]string{
|
||
"A1": "ID",
|
||
"B1": "Record Behavior",
|
||
"C1": "Type",
|
||
"D1": "Caller",
|
||
"E1": "Called",
|
||
"F1": "Duration",
|
||
"G1": "Result Code",
|
||
"H1": "Result Cause",
|
||
"I1": "MOS Average",
|
||
"J1": "Call Connection Time",
|
||
"K1": "Call Start Time",
|
||
"L1": "Hangup Time",
|
||
}
|
||
// 读取字典数据 CDR SIP响应代码类别类型
|
||
dictCDRSipCode := sysService.NewSysDictData.SelectDictDataByType("cdr_sip_code")
|
||
dictCDRSipCodeCause := sysService.NewSysDictData.SelectDictDataByType("cdr_sip_code_cause")
|
||
// 读取字典数据 CDR 呼叫类型
|
||
dictCDRCallType := sysService.NewSysDictData.SelectDictDataByType("cdr_call_type")
|
||
// 从第二行开始的数据
|
||
dataCells := make([]map[string]any, 0)
|
||
for i, row := range rows {
|
||
idx := strconv.Itoa(i + 2)
|
||
// 解析 JSON 字符串为 map
|
||
var cdrJSON map[string]interface{}
|
||
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
|
||
if err != nil {
|
||
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
|
||
continue
|
||
}
|
||
// 记录类型
|
||
recordType := ""
|
||
if v, ok := cdrJSON["recordType"]; ok && v != nil {
|
||
recordType = v.(string)
|
||
}
|
||
// 呼叫类型
|
||
callType := "sms"
|
||
callTypeLable := "SMS"
|
||
if v, ok := cdrJSON["callType"]; ok && v != nil {
|
||
callType = v.(string)
|
||
for _, v := range dictCDRCallType {
|
||
if callType == v.DictValue {
|
||
callTypeLable = i18n.TKey(language, v.DictLabel)
|
||
break
|
||
}
|
||
}
|
||
}
|
||
// 被叫
|
||
called := ""
|
||
if v, ok := cdrJSON["calledParty"]; ok && v != nil {
|
||
called = v.(string)
|
||
}
|
||
// 主叫
|
||
caller := ""
|
||
if v, ok := cdrJSON["callerParty"]; ok && v != nil {
|
||
caller = v.(string)
|
||
}
|
||
// 时长
|
||
duration := "-"
|
||
if v, ok := cdrJSON["callDuration"]; ok && v != nil && callType != "sms" {
|
||
duration = fmt.Sprintf("%ds", parse.Number(v))
|
||
}
|
||
// 呼叫结果 非短信都有code作为结果 sms短信都ok
|
||
// 呼叫结果 非短信都有code作为结果 sms短信都ok
|
||
callResult := "Other"
|
||
callCause := "Call failure for other reason"
|
||
if callType == "sms" {
|
||
callResult = "Success"
|
||
callCause = "Normal Send"
|
||
} else {
|
||
if v, ok := cdrJSON["cause"]; ok && v != nil {
|
||
cause := fmt.Sprint(v)
|
||
for _, v := range dictCDRSipCode {
|
||
if cause == v.DictValue {
|
||
callResult = i18n.TKey(language, v.DictLabel)
|
||
break
|
||
}
|
||
}
|
||
for _, v := range dictCDRSipCodeCause {
|
||
if cause == v.DictValue {
|
||
callCause = i18n.TKey(language, v.DictLabel)
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 呼叫时间
|
||
seizureTimeStr := ""
|
||
if v, ok := cdrJSON["seizureTime"]; ok && v != nil {
|
||
if seizureTime := parse.Number(v); seizureTime > 0 {
|
||
seizureTimeStr = date.ParseDateToStr(seizureTime, date.YYYY_MM_DD_HH_MM_SS_GMT_TZ)
|
||
} else {
|
||
seizureTimeStr = v.(string)
|
||
}
|
||
}
|
||
// 挂断时间
|
||
releaseTimeStr := ""
|
||
if v, ok := cdrJSON["releaseTime"]; ok && v != nil {
|
||
if releaseTime := parse.Number(v); releaseTime > 0 {
|
||
releaseTimeStr = date.ParseDateToStr(releaseTime, date.YYYY_MM_DD_HH_MM_SS_GMT_TZ)
|
||
} else {
|
||
releaseTimeStr = v.(string)
|
||
}
|
||
}
|
||
// 通话质量
|
||
var mosAverage int64 = 0
|
||
if v, ok := cdrJSON["mosAverage"]; ok && v != nil && callType != "sms" {
|
||
mosAverage = parse.Number(v)
|
||
}
|
||
// 通话连接时间
|
||
callConnectionTime := "-"
|
||
if v, ok := cdrJSON["callConnectionTime"]; ok && v != nil && callType != "sms" {
|
||
callConnectionTime = fmt.Sprintf("%ds", parse.Number(v))
|
||
}
|
||
|
||
dataCells = append(dataCells, map[string]any{
|
||
"A" + idx: row.ID,
|
||
"B" + idx: recordType,
|
||
"C" + idx: callTypeLable,
|
||
"D" + idx: caller,
|
||
"E" + idx: called,
|
||
"F" + idx: duration,
|
||
"G" + idx: callResult,
|
||
"H" + idx: callCause,
|
||
"I" + idx: mosAverage,
|
||
"J" + idx: callConnectionTime,
|
||
"K" + idx: seizureTimeStr,
|
||
"L" + idx: releaseTimeStr,
|
||
})
|
||
}
|
||
|
||
// 导出数据表格
|
||
return file.WriteSheet(headerCells, dataCells, fileName, "")
|
||
}
|
||
|
||
// CDRMOSHour CDR MOS 统计
|
||
func (r CDREventIMS) CDRMOSHour(rmUID string, timestamp int64) []map[string]any {
|
||
t := time.UnixMilli(timestamp)
|
||
beginTime := t
|
||
endTime := t
|
||
// 检查时分秒是否都为零
|
||
if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 {
|
||
// 获取当天起始时间(00:00:00)
|
||
beginTime = t.Truncate(time.Hour)
|
||
// 计算当天结束时间(23:59:59)
|
||
endTime = beginTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
|
||
} else {
|
||
// 起始时间:当前小时的 00 分 00 秒
|
||
beginTime = t.Truncate(time.Hour)
|
||
// 结束时间:当前小时的 59 分 59 秒 999 毫秒
|
||
endTime = beginTime.Add(time.Hour - time.Millisecond)
|
||
}
|
||
|
||
querys := model.CDREventIMSQuery{
|
||
RmUID: rmUID,
|
||
RecordType: "MOC",
|
||
StartTime: beginTime.Unix(),
|
||
EndTime: endTime.Unix(),
|
||
}
|
||
rows := r.cdrEventIMSRepository.Select(querys)
|
||
// 创建一个map来存储按时间段合并后的数据
|
||
timeGroup := make(map[int64]map[string]float64)
|
||
// 遍历每个数据项
|
||
for _, row := range rows {
|
||
// 将毫秒时间戳转换为小时级时间戳(保留到小时的起始毫秒)
|
||
timeHour := row.Timestamp / 3600 * 3600 // 1小时 = 3600000毫秒
|
||
|
||
// 解析 JSON 字符串为 map
|
||
var cdrJSON map[string]interface{}
|
||
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
|
||
if err != nil {
|
||
logger.Warnf("Unmarshal JSON: %s", err.Error())
|
||
continue
|
||
}
|
||
|
||
// 记录类型
|
||
var mosAverage float64 = 0
|
||
if v, ok := cdrJSON["mosAverage"]; ok && v != nil {
|
||
mosAverage = v.(float64)
|
||
} else {
|
||
continue
|
||
}
|
||
|
||
// 合并到对应的小时段
|
||
if _, exists := timeGroup[timeHour]; !exists {
|
||
timeGroup[timeHour] = map[string]float64{
|
||
"total": 0,
|
||
"mosSum": 0,
|
||
}
|
||
}
|
||
timeGroup[timeHour]["total"] += 1
|
||
timeGroup[timeHour]["mosSum"] += mosAverage
|
||
}
|
||
|
||
// 时间组合输出
|
||
data := make([]map[string]any, 0, len(timeGroup))
|
||
for hour, sums := range timeGroup {
|
||
data = append(data, map[string]any{
|
||
"timeGroup": fmt.Sprintf("%d", hour),
|
||
"total": sums["total"],
|
||
"mosSum": float64(int(sums["mosSum"]*100)) / 100,
|
||
"mosAvg": float64(int(sums["mosSum"]/sums["total"]*100)) / 100,
|
||
})
|
||
}
|
||
return data
|
||
}
|
||
|
||
// CDRCCTHour CDR CCT 统计
|
||
func (r CDREventIMS) CDRCCTHour(rmUID string, timestamp int64) []map[string]any {
|
||
t := time.UnixMilli(timestamp)
|
||
beginTime := t
|
||
endTime := t
|
||
// 检查时分秒是否都为零
|
||
if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 {
|
||
// 获取当天起始时间(00:00:00)
|
||
beginTime = t.Truncate(time.Hour)
|
||
// 计算当天结束时间(23:59:59)
|
||
endTime = beginTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
|
||
} else {
|
||
// 起始时间:当前小时的 00 分 00 秒
|
||
beginTime = t.Truncate(time.Hour)
|
||
// 结束时间:当前小时的 59 分 59 秒 999 毫秒
|
||
endTime = beginTime.Add(time.Hour - time.Millisecond)
|
||
}
|
||
|
||
querys := model.CDREventIMSQuery{
|
||
RmUID: rmUID,
|
||
RecordType: "MOC",
|
||
StartTime: beginTime.Unix(),
|
||
EndTime: endTime.Unix(),
|
||
}
|
||
rows := r.cdrEventIMSRepository.Select(querys)
|
||
// 创建一个map来存储按时间段合并后的数据
|
||
timeGroup := make(map[int64]map[string]float64)
|
||
// 遍历每个数据项
|
||
for _, row := range rows {
|
||
// 将毫秒时间戳转换为小时级时间戳(保留到小时的起始毫秒)
|
||
timeHour := row.Timestamp / 3600 * 3600 // 1小时 = 3600000毫秒
|
||
|
||
// 解析 JSON 字符串为 map
|
||
var cdrJSON map[string]interface{}
|
||
err := json.Unmarshal([]byte(row.CDRJSONStr), &cdrJSON)
|
||
if err != nil {
|
||
logger.Warnf("Unmarshal JSON: %s", err.Error())
|
||
continue
|
||
}
|
||
|
||
// 记录类型
|
||
var callConnectionTime float64 = 0
|
||
if v, ok := cdrJSON["callConnectionTime"]; ok && v != nil {
|
||
callConnectionTime = v.(float64)
|
||
} else {
|
||
continue
|
||
}
|
||
|
||
// 合并到对应的小时段
|
||
if _, exists := timeGroup[timeHour]; !exists {
|
||
timeGroup[timeHour] = map[string]float64{
|
||
"total": 0,
|
||
"cctSum": 0,
|
||
}
|
||
}
|
||
timeGroup[timeHour]["total"] += 1
|
||
timeGroup[timeHour]["cctSum"] += callConnectionTime
|
||
}
|
||
|
||
// 时间组合输出
|
||
data := make([]map[string]any, 0, len(timeGroup))
|
||
for hour, sums := range timeGroup {
|
||
data = append(data, map[string]any{
|
||
"timeGroup": fmt.Sprintf("%d", hour),
|
||
"total": sums["total"],
|
||
"cctSum": float64(int(sums["cctSum"]*100)) / 100,
|
||
"cctAvg": float64(int(sums["cctSum"]/sums["total"]*100)) / 100,
|
||
})
|
||
}
|
||
return data
|
||
}
|