797 lines
22 KiB
Go
797 lines
22 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"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"
|
|
)
|
|
|
|
// 实例化数据层 CDREvent 结构体
|
|
var NewCDREvent = &CDREvent{
|
|
cdrEventRepository: repository.NewCDREvent,
|
|
}
|
|
|
|
// CDREvent CDR会话事件 服务层处理
|
|
type CDREvent struct {
|
|
cdrEventRepository *repository.CDREvent // CDR会话事件数据信息
|
|
}
|
|
|
|
// FindByPage 根据条件分页查询
|
|
func (r CDREvent) FindByPage(neType string, query map[string]string) ([]model.CDREvent, int64) {
|
|
return r.cdrEventRepository.SelectByPage(neType, query)
|
|
}
|
|
|
|
// DeleteByIds 批量删除信息
|
|
func (r CDREvent) DeleteByIds(neType string, ids []int64) (int64, error) {
|
|
// 检查是否存在
|
|
rows := r.cdrEventRepository.SelectByIds(neType, ids)
|
|
if len(rows) <= 0 {
|
|
return 0, fmt.Errorf("not data")
|
|
}
|
|
|
|
if len(rows) == len(ids) {
|
|
rows := r.cdrEventRepository.DeleteByIds(neType, ids)
|
|
return rows, nil
|
|
}
|
|
// 删除信息失败!
|
|
return 0, fmt.Errorf("delete fail")
|
|
}
|
|
|
|
// Insert 新增信息
|
|
func (s CDREvent) Insert(param model.CDREvent) int64 {
|
|
return s.cdrEventRepository.Insert(param)
|
|
}
|
|
|
|
// ExportSMSC 导出数据到 xlsx 文件
|
|
func (r CDREvent) ExportSMSC(rows []model.CDREvent, fileName, language string) (string, error) {
|
|
// 第一行表头标题
|
|
headerCells := map[string]string{
|
|
"A1": "ID",
|
|
"B1": "NE Name",
|
|
"C1": "Record Behavior",
|
|
"D1": "Service Type",
|
|
"E1": "Caller",
|
|
"F1": "Called",
|
|
"G1": "Result",
|
|
"H1": "Time",
|
|
}
|
|
// 读取字典数据 CDR 原因码
|
|
dictCDRCauseCode := sysService.NewSysDictData.FindByType("cdr_cause_code")
|
|
// 从第二行开始的数据
|
|
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.CdrJson), &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)
|
|
}
|
|
// 服务类型
|
|
serviceType := ""
|
|
if v, ok := cdrJSON["serviceType"]; ok && v != nil {
|
|
serviceType = v.(string)
|
|
}
|
|
// 被叫
|
|
called := ""
|
|
if v, ok := cdrJSON["calledParty"]; ok && v != nil {
|
|
called = v.(string)
|
|
}
|
|
// 主叫
|
|
caller := ""
|
|
if v, ok := cdrJSON["callerParty"]; ok && v != nil {
|
|
caller = v.(string)
|
|
}
|
|
// 呼叫结果 0失败,1成功
|
|
callResult := "Fail"
|
|
if v, ok := cdrJSON["result"]; ok && v != nil {
|
|
resultVal := parse.Number(v)
|
|
if resultVal == 1 {
|
|
callResult = "Success"
|
|
}
|
|
}
|
|
// 结果原因
|
|
if v, ok := cdrJSON["cause"]; ok && v != nil && callResult == "Fail" {
|
|
cause := fmt.Sprint(v)
|
|
for _, v := range dictCDRCauseCode {
|
|
if cause == v.DataValue {
|
|
callResult = fmt.Sprintf("%s, %s", callResult, i18n.TKey(language, v.DataLabel))
|
|
break
|
|
}
|
|
}
|
|
}
|
|
// 取时间
|
|
timeStr := ""
|
|
if v, ok := cdrJSON["updateTime"]; ok && v != nil {
|
|
if releaseTime := parse.Number(v); releaseTime > 0 {
|
|
timeStr = date.ParseDateToStr(releaseTime, date.YYYY_MM_DDTHH_MM_SSZ)
|
|
} else {
|
|
timeStr = v.(string)
|
|
}
|
|
}
|
|
|
|
dataCells = append(dataCells, map[string]any{
|
|
"A" + idx: row.ID,
|
|
"B" + idx: row.NeName,
|
|
"C" + idx: recordType,
|
|
"D" + idx: serviceType,
|
|
"E" + idx: caller,
|
|
"F" + idx: called,
|
|
"G" + idx: callResult,
|
|
"H" + idx: timeStr,
|
|
})
|
|
}
|
|
|
|
// 导出数据表格
|
|
return file.WriteSheet(headerCells, dataCells, fileName, "")
|
|
}
|
|
|
|
// ExportSMF 导出数据到 xlsx 文件
|
|
func (r CDREvent) ExportSMF(rows []model.CDREvent, fileName string) (string, error) {
|
|
// 第一行表头标题
|
|
headerCells := map[string]string{
|
|
"A1": "ID",
|
|
"B1": "Charging ID",
|
|
"C1": "NE Name",
|
|
"D1": "Resource Unique ID",
|
|
"E1": "Subscriber ID Data",
|
|
"F1": "Subscriber ID Type",
|
|
"G1": "Data Volume Uplink",
|
|
"H1": "Data Volume Downlink",
|
|
"I1": "Data Total Volume",
|
|
"J1": "Duration",
|
|
"K1": "Invocation Time",
|
|
"L1": "User Identifier",
|
|
"M1": "SSC Mode",
|
|
"N1": "DNN ID",
|
|
"O1": "PDU Type",
|
|
"P1": "RAT Type",
|
|
"Q1": "PDU IPv4 Address",
|
|
"R1": "Network Function IPv4",
|
|
"S1": "PDU IPv6 Address Swith Prefix",
|
|
"T1": "Record Network Function ID",
|
|
"U1": "Record Type",
|
|
"V1": "Record Opening Time",
|
|
}
|
|
// 从第二行开始的数据
|
|
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.CdrJson), &cdrJSON)
|
|
if err != nil {
|
|
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
|
|
continue
|
|
}
|
|
// 计费ID
|
|
chargingID := ""
|
|
if v, ok := cdrJSON["chargingID"]; ok && v != nil {
|
|
chargingID = fmt.Sprint(parse.Number(v))
|
|
}
|
|
// 订阅 ID 类型
|
|
subscriptionIDType := "-"
|
|
// 订阅 ID 数据
|
|
subscriptionIDData := "-"
|
|
if v, ok := cdrJSON["subscriberIdentifier"]; ok && v != nil {
|
|
if sub, subOk := v.(map[string]any); subOk && sub != nil {
|
|
subscriptionIDType = sub["subscriptionIDType"].(string)
|
|
subscriptionIDData = sub["subscriptionIDData"].(string)
|
|
}
|
|
}
|
|
|
|
// 网络功能 IPv4 地址
|
|
networkFunctionIPv4Address := ""
|
|
if v, ok := cdrJSON["nFunctionConsumerInformation"]; ok && v != nil {
|
|
if conInfo, conInfoOk := v.(map[string]any); conInfoOk && conInfo != nil {
|
|
networkFunctionIPv4Address = conInfo["networkFunctionIPv4Address"].(string)
|
|
}
|
|
}
|
|
|
|
// 数据量上行链路
|
|
var dataVolumeUplink int64 = 0
|
|
// 数据量下行链路
|
|
var dataVolumeDownlink int64 = 0
|
|
// 数据总量
|
|
var dataTotalVolume int64 = 0
|
|
if v, ok := cdrJSON["listOfMultipleUnitUsage"]; ok && v != nil {
|
|
usageList := v.([]any)
|
|
if len(usageList) > 0 {
|
|
for _, used := range usageList {
|
|
usedUnit := used.(map[string]any)
|
|
usedUnitList := usedUnit["usedUnitContainer"].([]any)
|
|
if len(usedUnitList) > 0 {
|
|
for _, data := range usedUnitList {
|
|
udata := data.(map[string]any)
|
|
if dup, dupOk := udata["dataVolumeUplink"]; dupOk {
|
|
dataVolumeUplink += parse.Number(dup)
|
|
}
|
|
if ddown, ddownOk := udata["dataVolumeDownlink"]; ddownOk {
|
|
dataVolumeDownlink += parse.Number(ddown)
|
|
}
|
|
if dt, dtOk := udata["dataTotalVolume"]; dtOk {
|
|
dataTotalVolume += parse.Number(dt)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 时长
|
|
duration := "-"
|
|
if v, ok := cdrJSON["duration"]; ok && v != nil {
|
|
duration = fmt.Sprint(parse.Number(v))
|
|
}
|
|
// 调用时间
|
|
invocationTimestamp := ""
|
|
if v, ok := cdrJSON["invocationTimestamp"]; ok && v != nil {
|
|
invocationTimestamp = v.(string)
|
|
}
|
|
// 记录打开时间
|
|
User_Identifier := ""
|
|
SSC_Mode := ""
|
|
RAT_Type := ""
|
|
DNN_ID := ""
|
|
PDU_Type := ""
|
|
PDU_IPv4 := ""
|
|
PDU_IPv6 := ""
|
|
if v, ok := cdrJSON["pDUSessionChargingInformation"]; ok && v != nil {
|
|
pduInfo := v.(map[string]any)
|
|
|
|
if v, ok := pduInfo["userIdentifier"]; ok && v != nil {
|
|
User_Identifier = v.(string)
|
|
}
|
|
if v, ok := pduInfo["sSCMode"]; ok && v != nil {
|
|
SSC_Mode = v.(string)
|
|
}
|
|
if v, ok := pduInfo["rATType"]; ok && v != nil {
|
|
RAT_Type = v.(string)
|
|
}
|
|
if v, ok := pduInfo["dNNID"]; ok && v != nil {
|
|
DNN_ID = v.(string)
|
|
}
|
|
if v, ok := pduInfo["pDUType"]; ok && v != nil {
|
|
PDU_Type = v.(string)
|
|
}
|
|
if v, ok := pduInfo["pDUAddress"]; ok && v != nil {
|
|
pDUAddress := v.(map[string]any)
|
|
if addr, ok := pDUAddress["pDUIPv4Address"]; ok && addr != nil {
|
|
PDU_IPv4 = addr.(string)
|
|
}
|
|
if addr, ok := pDUAddress["pDUIPv6AddresswithPrefix"]; ok && addr != nil {
|
|
PDU_IPv6 = addr.(string)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 记录网络参数ID
|
|
recordNFID := ""
|
|
if v, ok := cdrJSON["recordingNetworkFunctionID"]; ok && v != nil {
|
|
recordNFID = v.(string)
|
|
}
|
|
|
|
//记录开始时间
|
|
recordOpeningTime := ""
|
|
if v, ok := cdrJSON["recordOpeningTime"]; ok && v != nil {
|
|
recordOpeningTime = v.(string)
|
|
}
|
|
|
|
//记录类型
|
|
recordType := ""
|
|
if v, ok := cdrJSON["recordType"]; ok && v != nil {
|
|
recordType = v.(string)
|
|
}
|
|
|
|
dataCells = append(dataCells, map[string]any{
|
|
"A" + idx: row.ID,
|
|
"B" + idx: chargingID,
|
|
"C" + idx: row.NeName,
|
|
"D" + idx: row.RmUid,
|
|
"E" + idx: subscriptionIDData,
|
|
"F" + idx: subscriptionIDType,
|
|
"G" + idx: dataVolumeUplink,
|
|
"H" + idx: dataVolumeDownlink,
|
|
"I" + idx: dataTotalVolume,
|
|
"J" + idx: duration,
|
|
"K" + idx: invocationTimestamp,
|
|
"L" + idx: User_Identifier,
|
|
"M" + idx: SSC_Mode,
|
|
"N" + idx: DNN_ID,
|
|
"O" + idx: PDU_Type,
|
|
"P" + idx: RAT_Type,
|
|
"Q" + idx: PDU_IPv4,
|
|
"R" + idx: networkFunctionIPv4Address,
|
|
"S" + idx: PDU_IPv6,
|
|
"T" + idx: recordNFID,
|
|
"U" + idx: recordType,
|
|
"V" + idx: recordOpeningTime,
|
|
})
|
|
}
|
|
|
|
// 导出数据表格
|
|
return file.WriteSheet(headerCells, dataCells, fileName, "")
|
|
}
|
|
|
|
// ExportSGWC 导出数据到 xlsx 文件
|
|
func (r CDREvent) ExportSGWC(rows []model.CDREvent, fileName string) (string, error) {
|
|
// 第一行表头标题
|
|
headerCells := map[string]string{
|
|
"A1": "ID",
|
|
"B1": "NE Name",
|
|
"C1": "Resource Unique ID",
|
|
"D1": "Charging ID",
|
|
"E1": "IMSI",
|
|
"F1": "MSISDN",
|
|
"G1": "GPRS Uplink",
|
|
"H1": "GPRS Downlink",
|
|
"I1": "Duration",
|
|
"J1": "Invocation Time",
|
|
"K1": "PGW Address",
|
|
"L1": "SGW Address",
|
|
"M1": "RAT Type",
|
|
"N1": "PDPPDN Type",
|
|
"O1": "PDPPDN Address",
|
|
"P1": "Node Address",
|
|
"Q1": "Node Type",
|
|
"R1": "Record Access Point Name NI",
|
|
"S1": "Record Cause For Rec Closing",
|
|
"T1": "Record Sequence Number",
|
|
"U1": "Local Record Sequence Number",
|
|
"V1": "Record Type",
|
|
"W1": "Record Opening Time",
|
|
}
|
|
// 从第二行开始的数据
|
|
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.CdrJson), &cdrJSON)
|
|
if err != nil {
|
|
logger.Warnf("CDRExport Error parsing JSON: %s", err.Error())
|
|
continue
|
|
}
|
|
// 计费ID
|
|
chargingID := ""
|
|
if v, ok := cdrJSON["chargingID"]; ok && v != nil {
|
|
chargingID = fmt.Sprint(parse.Number(v))
|
|
}
|
|
// IMSI
|
|
servedIMSI := ""
|
|
if v, ok := cdrJSON["servedIMSI"]; ok && v != nil {
|
|
servedIMSI = fmt.Sprint(v)
|
|
}
|
|
// MSISDN
|
|
servedMSISDN := ""
|
|
if v, ok := cdrJSON["servedMSISDN"]; ok && v != nil {
|
|
servedMSISDN = fmt.Sprint(v)
|
|
}
|
|
// pGWAddressUsed
|
|
pGWAddressUsed := ""
|
|
if v, ok := cdrJSON["pGWAddressUsed"]; ok && v != nil {
|
|
pGWAddressUsed = fmt.Sprint(v)
|
|
headerCells["K1"] = "PGW Address"
|
|
}
|
|
if v, ok := cdrJSON["GGSNAddress"]; ok && v != nil {
|
|
pGWAddressUsed = fmt.Sprint(v)
|
|
headerCells["K1"] = "GGSN Address"
|
|
}
|
|
// sGWAddress
|
|
sGWAddress := ""
|
|
if v, ok := cdrJSON["sGWAddress"]; ok && v != nil {
|
|
sGWAddress = fmt.Sprint(v)
|
|
headerCells["L1"] = "SGW Address"
|
|
}
|
|
if v, ok := cdrJSON["SGSNAddress"]; ok && v != nil {
|
|
sGWAddress = fmt.Sprint(v)
|
|
headerCells["L1"] = "SGSN Address"
|
|
}
|
|
// recordType
|
|
recordType := ""
|
|
if v, ok := cdrJSON["recordType"]; ok && v != nil {
|
|
recordType = fmt.Sprint(v)
|
|
}
|
|
// rATType
|
|
rATType := ""
|
|
if v, ok := cdrJSON["rATType"]; ok && v != nil {
|
|
rATType = fmt.Sprint(v)
|
|
}
|
|
// pdpPDNType
|
|
pdpPDNType := ""
|
|
if v, ok := cdrJSON["pdpPDNType"]; ok && v != nil {
|
|
pdpPDNType = fmt.Sprint(v)
|
|
}
|
|
// servedPDPPDNAddress
|
|
servedPDPPDNAddress := ""
|
|
if v, ok := cdrJSON["servedPDPPDNAddress"]; ok && v != nil {
|
|
servedPDPPDNAddress = fmt.Sprint(v)
|
|
}
|
|
// servedPDPPDNAddress
|
|
servingNodeAddress := []string{}
|
|
if v, ok := cdrJSON["servingNodeAddress"]; ok && v != nil {
|
|
for _, v := range v.([]any) {
|
|
servingNodeAddress = append(servingNodeAddress, fmt.Sprint(v))
|
|
}
|
|
}
|
|
// servingNodeType
|
|
servingNodeType := []string{}
|
|
if v, ok := cdrJSON["servingNodeType"]; ok && v != nil {
|
|
for _, v := range v.([]any) {
|
|
if v, ok := v.(map[string]any)["servingNodeType"]; ok && v != nil {
|
|
servingNodeType = append(servingNodeType, fmt.Sprint(v))
|
|
}
|
|
}
|
|
}
|
|
// accessPointNameNI
|
|
accessPointNameNI := ""
|
|
if v, ok := cdrJSON["accessPointNameNI"]; ok && v != nil {
|
|
accessPointNameNI = fmt.Sprint(v)
|
|
}
|
|
// causeForRecClosing
|
|
causeForRecClosing := ""
|
|
if v, ok := cdrJSON["causeForRecClosing"]; ok && v != nil {
|
|
causeForRecClosing = fmt.Sprint(v)
|
|
}
|
|
// recordSequenceNumber
|
|
recordSequenceNumber := ""
|
|
if v, ok := cdrJSON["recordSequenceNumber"]; ok && v != nil {
|
|
recordSequenceNumber = fmt.Sprint(v)
|
|
}
|
|
// localRecordSequenceNumber
|
|
localRecordSequenceNumber := ""
|
|
if v, ok := cdrJSON["localRecordSequenceNumber"]; ok && v != nil {
|
|
localRecordSequenceNumber = fmt.Sprint(v)
|
|
}
|
|
// 数据量上行链路
|
|
var dataVolumeGPRSUplink int64 = 0
|
|
// 数据量下行链路
|
|
var dataVolumeGPRSDownlink int64 = 0
|
|
if v, ok := cdrJSON["listOfTrafficVolumes"]; ok && v != nil {
|
|
usageList := v.([]any)
|
|
if len(usageList) > 0 {
|
|
for _, used := range usageList {
|
|
usedUnit := used.(map[string]any)
|
|
if dup, dupOk := usedUnit["dataVolumeGPRSUplink"]; dupOk {
|
|
dataVolumeGPRSUplink = parse.Number(dup)
|
|
}
|
|
if ddown, ddownOk := usedUnit["dataVolumeGPRSDownlink"]; ddownOk {
|
|
dataVolumeGPRSDownlink = parse.Number(ddown)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 时长
|
|
duration := "-"
|
|
if v, ok := cdrJSON["duration"]; ok && v != nil {
|
|
duration = fmt.Sprint(parse.Number(v))
|
|
}
|
|
// 调用时间
|
|
invocationTimestamp := ""
|
|
if v, ok := cdrJSON["recordOpeningTime"]; ok && v != nil {
|
|
invocationTimestamp = v.(string)
|
|
}
|
|
|
|
dataCells = append(dataCells, map[string]any{
|
|
"A" + idx: row.ID,
|
|
"B" + idx: row.NeName,
|
|
"C" + idx: row.RmUid,
|
|
"D" + idx: chargingID,
|
|
"E" + idx: servedIMSI,
|
|
"F" + idx: servedMSISDN,
|
|
"G" + idx: dataVolumeGPRSUplink,
|
|
"H" + idx: dataVolumeGPRSDownlink,
|
|
"I" + idx: duration,
|
|
"J" + idx: invocationTimestamp,
|
|
"K" + idx: pGWAddressUsed,
|
|
"L" + idx: sGWAddress,
|
|
"M" + idx: rATType,
|
|
"N" + idx: pdpPDNType,
|
|
"O" + idx: servedPDPPDNAddress,
|
|
"P" + idx: strings.Join(servingNodeAddress, ","),
|
|
"Q" + idx: strings.Join(servingNodeType, ","),
|
|
"R" + idx: accessPointNameNI,
|
|
"S" + idx: causeForRecClosing,
|
|
"T" + idx: recordSequenceNumber,
|
|
"U" + idx: localRecordSequenceNumber,
|
|
"V" + idx: recordType,
|
|
"W" + idx: invocationTimestamp,
|
|
})
|
|
}
|
|
|
|
// 导出数据表格
|
|
return file.WriteSheet(headerCells, dataCells, fileName, "")
|
|
}
|
|
|
|
// ExportIMS 导出数据到 xlsx 文件
|
|
func (r CDREvent) ExportIMS(rows []model.CDREvent, fileName, language string) (string, error) {
|
|
// 第一行表头标题
|
|
headerCells := map[string]string{
|
|
"A1": "ID",
|
|
"B1": "NE Name",
|
|
"C1": "Record Behavior",
|
|
"D1": "Type",
|
|
"E1": "Caller",
|
|
"F1": "Called",
|
|
"G1": "Duration",
|
|
"H1": "Result Code",
|
|
"I1": "Result Cause",
|
|
"J1": "Call Start Time",
|
|
"K1": "Hangup Time",
|
|
}
|
|
// 读取字典数据 CDR SIP响应代码类别类型
|
|
dictCDRSipCode := sysService.NewSysDictData.FindByType("cdr_sip_code")
|
|
// 读取字典数据 CDR SIP响应代码类别类型原因
|
|
dictCDRSipCodeCause := sysService.NewSysDictData.FindByType("cdr_sip_code_cause")
|
|
// 读取字典数据 CDR 呼叫类型
|
|
dictCDRCallType := sysService.NewSysDictData.FindByType("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]any
|
|
err := json.Unmarshal([]byte(row.CdrJson), &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.DataValue {
|
|
callTypeLable = i18n.TKey(language, v.DataLabel)
|
|
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
|
|
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.DataValue {
|
|
callResult = i18n.TKey(language, v.DataLabel)
|
|
break
|
|
}
|
|
}
|
|
for _, v := range dictCDRSipCodeCause {
|
|
if cause == v.DataValue {
|
|
callCause = i18n.TKey(language, v.DataLabel)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 呼叫时间
|
|
seizureTimeStr := ""
|
|
if v, ok := cdrJSON["seizureTime"]; ok && v != nil {
|
|
if seizureTime := parse.Number(v); seizureTime > 0 {
|
|
seizureTimeStr = date.ParseDateToStr(seizureTime, date.YYYY_MM_DDTHH_MM_SSZ)
|
|
} 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_DDTHH_MM_SSZ)
|
|
} else {
|
|
releaseTimeStr = v.(string)
|
|
}
|
|
}
|
|
|
|
dataCells = append(dataCells, map[string]any{
|
|
"A" + idx: row.ID,
|
|
"B" + idx: row.NeName,
|
|
"C" + idx: recordType,
|
|
"D" + idx: callTypeLable,
|
|
"E" + idx: caller,
|
|
"F" + idx: called,
|
|
"G" + idx: duration,
|
|
"H" + idx: callResult,
|
|
"I" + idx: callCause,
|
|
"J" + idx: seizureTimeStr,
|
|
"K" + idx: releaseTimeStr,
|
|
})
|
|
}
|
|
|
|
// 导出数据表格
|
|
return file.WriteSheet(headerCells, dataCells, fileName, "")
|
|
}
|
|
|
|
// IMSCDRMOSHour CDR MOS 统计
|
|
func (r CDREvent) IMSCDRMOSHour(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)
|
|
}
|
|
|
|
query := map[string]string{
|
|
"rmUID": rmUID,
|
|
"recordType": "MOC",
|
|
"beginTime": fmt.Sprintf("%d", beginTime.Unix()),
|
|
"endTime": fmt.Sprintf("%d", endTime.Unix()),
|
|
}
|
|
rows, total := r.cdrEventRepository.SelectByPage("IMS", query)
|
|
if total == 0 {
|
|
return []map[string]any{}
|
|
}
|
|
// 创建一个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.CdrJson), &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
|
|
}
|
|
|
|
// IMSCDRCCTHour CDR CCT 统计
|
|
func (r CDREvent) IMSCDRCCTHour(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)
|
|
}
|
|
|
|
query := map[string]string{
|
|
"rmUID": rmUID,
|
|
"recordType": "MOC",
|
|
"beginTime": fmt.Sprintf("%d", beginTime.Unix()),
|
|
"endTime": fmt.Sprintf("%d", endTime.Unix()),
|
|
}
|
|
rows, total := r.cdrEventRepository.SelectByPage("IMS", query)
|
|
if total == 0 {
|
|
return []map[string]any{}
|
|
}
|
|
// 创建一个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.CdrJson), &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
|
|
}
|