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
|
||
}
|