feat: add number library routing and cdr location support
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
import { Inject, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { Prisma } from '@lisglosips/database';
|
||||
import { PrismaService } from '../database/prisma.service.js';
|
||||
|
||||
export type CdrCarrier = 'MOBILE' | 'UNICOM' | 'TELECOM' | 'BROADCAST' | 'MVNO' | 'UNKNOWN';
|
||||
|
||||
export interface CdrQuery {
|
||||
caller?: string;
|
||||
callee?: string;
|
||||
customerGatewayId?: string;
|
||||
vendorGatewayId?: string;
|
||||
cityCode?: string;
|
||||
carrier?: CdrCarrier;
|
||||
take: number;
|
||||
skip: number;
|
||||
}
|
||||
|
||||
export interface CdrListItem {
|
||||
id: string;
|
||||
eventId: string;
|
||||
callId: string;
|
||||
sourceIp: string | null;
|
||||
caller: string;
|
||||
callee: string;
|
||||
calleeCityCode: string | null;
|
||||
calleeCityName: string | null;
|
||||
calleeProvinceName: string | null;
|
||||
calleeOperator: CdrCarrier;
|
||||
calleeNumberType: string;
|
||||
customerId: string | null;
|
||||
customerName: string | null;
|
||||
customerGatewayId: string | null;
|
||||
customerGatewayName: string | null;
|
||||
vendorId: string | null;
|
||||
vendorName: string | null;
|
||||
vendorGatewayId: string | null;
|
||||
vendorGatewayName: string | null;
|
||||
vendorGatewayHost: string | null;
|
||||
vendorGatewayPort: number | null;
|
||||
lineGroupId: string | null;
|
||||
lineGroupName: string | null;
|
||||
startedAt: Date;
|
||||
answeredAt: Date | null;
|
||||
endedAt: Date;
|
||||
durationSec: number;
|
||||
sipCode: number;
|
||||
hangupReason: string | null;
|
||||
recordingKey: string | null;
|
||||
configVersion: number | null;
|
||||
ratingStatus: string;
|
||||
customerFee: string | null;
|
||||
vendorCost: string | null;
|
||||
grossProfit: string | null;
|
||||
billSec: number | null;
|
||||
}
|
||||
|
||||
export interface CdrsRepository {
|
||||
list(query: CdrQuery): Promise<{ items: CdrListItem[]; total: number }>;
|
||||
get(id: string): Promise<CdrListItem>;
|
||||
}
|
||||
|
||||
export const CDRS_REPOSITORY = Symbol('CDRS_REPOSITORY');
|
||||
|
||||
type RawCdrRecord = Prisma.RawCdrGetPayload<{
|
||||
include: {
|
||||
customer: { select: { name: true } };
|
||||
customerGateway: { select: { name: true } };
|
||||
vendor: { select: { name: true } };
|
||||
vendorGateway: { select: { name: true; host: true; port: true } };
|
||||
lineGroup: { select: { name: true } };
|
||||
ratedCdr: { select: { customerFee: true; vendorCost: true; grossProfit: true; billSec: true } };
|
||||
};
|
||||
}>;
|
||||
|
||||
@Injectable()
|
||||
export class PrismaCdrsRepository implements CdrsRepository {
|
||||
constructor(@Inject(PrismaService) private readonly prisma: PrismaService) {}
|
||||
|
||||
async list(query: CdrQuery): Promise<{ items: CdrListItem[]; total: number }> {
|
||||
const where = this.where(query);
|
||||
const [items, total] = await this.prisma.$transaction([
|
||||
this.prisma.rawCdr.findMany({
|
||||
where,
|
||||
orderBy: [{ startedAt: 'desc' }],
|
||||
take: query.take,
|
||||
skip: query.skip,
|
||||
include: this.includeCdr()
|
||||
}),
|
||||
this.prisma.rawCdr.count({ where })
|
||||
]);
|
||||
return { items: items.map((item) => this.toItem(item)), total };
|
||||
}
|
||||
|
||||
async get(id: string): Promise<CdrListItem> {
|
||||
const item = await this.prisma.rawCdr.findUnique({
|
||||
where: { id },
|
||||
include: this.includeCdr()
|
||||
});
|
||||
if (!item) {
|
||||
throw new NotFoundException({ code: 'CDR_NOT_FOUND', message: 'CDR not found.' });
|
||||
}
|
||||
return this.toItem(item);
|
||||
}
|
||||
|
||||
private where(query: CdrQuery): Prisma.RawCdrWhereInput {
|
||||
return {
|
||||
caller: query.caller ? { contains: query.caller } : undefined,
|
||||
callee: query.callee ? { contains: query.callee } : undefined,
|
||||
customerGatewayId: query.customerGatewayId,
|
||||
vendorGatewayId: query.vendorGatewayId,
|
||||
calleeCityCode: query.cityCode,
|
||||
calleeOperator: query.carrier
|
||||
};
|
||||
}
|
||||
|
||||
private includeCdr() {
|
||||
return {
|
||||
customer: { select: { name: true } },
|
||||
customerGateway: { select: { name: true } },
|
||||
vendor: { select: { name: true } },
|
||||
vendorGateway: { select: { name: true, host: true, port: true } },
|
||||
lineGroup: { select: { name: true } },
|
||||
ratedCdr: { select: { customerFee: true, vendorCost: true, grossProfit: true, billSec: true } }
|
||||
} satisfies Prisma.RawCdrInclude;
|
||||
}
|
||||
|
||||
private toItem(item: RawCdrRecord): CdrListItem {
|
||||
return {
|
||||
id: item.id,
|
||||
eventId: item.eventId,
|
||||
callId: item.callId,
|
||||
sourceIp: item.sourceIp,
|
||||
caller: item.caller,
|
||||
callee: item.callee,
|
||||
calleeCityCode: item.calleeCityCode,
|
||||
calleeCityName: item.calleeCityName,
|
||||
calleeProvinceName: item.calleeProvinceName,
|
||||
calleeOperator: item.calleeOperator,
|
||||
calleeNumberType: item.calleeNumberType,
|
||||
customerId: item.customerId,
|
||||
customerName: item.customer?.name ?? null,
|
||||
customerGatewayId: item.customerGatewayId,
|
||||
customerGatewayName: item.customerGateway?.name ?? null,
|
||||
vendorId: item.vendorId,
|
||||
vendorName: item.vendor?.name ?? null,
|
||||
vendorGatewayId: item.vendorGatewayId,
|
||||
vendorGatewayName: item.vendorGateway?.name ?? null,
|
||||
vendorGatewayHost: item.vendorGateway?.host ?? null,
|
||||
vendorGatewayPort: item.vendorGateway?.port ?? null,
|
||||
lineGroupId: item.lineGroupId,
|
||||
lineGroupName: item.lineGroup?.name ?? null,
|
||||
startedAt: item.startedAt,
|
||||
answeredAt: item.answeredAt,
|
||||
endedAt: item.endedAt,
|
||||
durationSec: item.durationSec,
|
||||
sipCode: item.sipCode,
|
||||
hangupReason: item.hangupReason,
|
||||
recordingKey: item.recordingKey,
|
||||
configVersion: item.configVersion,
|
||||
ratingStatus: item.ratingStatus,
|
||||
customerFee: item.ratedCdr?.customerFee.toFixed(6) ?? null,
|
||||
vendorCost: item.ratedCdr?.vendorCost.toFixed(6) ?? null,
|
||||
grossProfit: item.ratedCdr?.grossProfit.toFixed(6) ?? null,
|
||||
billSec: item.ratedCdr?.billSec ?? null
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user