feat: add number library routing and cdr location support

This commit is contained in:
hectorzhao
2026-06-24 11:39:32 +08:00
parent 5fa1bd35e9
commit 7057fd3c42
63 changed files with 6361 additions and 566 deletions
+41
View File
@@ -142,6 +142,11 @@ function sampleEvent(overrides: Partial<CdrStreamPublishInput> = {}): CdrStreamP
sourceIp: '100.93.185.30',
caller: 's21-ip-1001',
callee: '13800138000',
calleeCityCode: '340100',
calleeCityName: '合肥市',
calleeProvinceName: '安徽省',
calleeOperator: 'MOBILE',
calleeNumberType: 'MOBILE',
sipCode: 503,
hangupReason: 'CONFIG_MISSING',
configVersion: '0',
@@ -162,9 +167,45 @@ describe('CDR Redis Stream contract', () => {
expect(parsed.node_id).toBe('a1');
expect(parsed.opensips_instance).toBe('opensips-a1');
expect(parsed.rtpengine_node).toBe('a1');
expect(parsed.callee_city_code).toBe('340100');
expect(parsed.callee_city_name).toBe('合肥市');
expect(parsed.callee_operator).toBe('MOBILE');
expect(parsed.sipCode).toBe(503);
});
it('keeps old stream entries compatible when number snapshot fields are absent', () => {
const parsed = parseCdrStreamEvent([
'schema_version',
'1',
'event_id',
'evt-old',
'idempotency_key',
'call-old:1',
'call_id',
'call-old',
'node_id',
'a1',
'opensips_instance',
'opensips-a1',
'ingress_a_ip',
'100.90.90.90',
'rtpengine_node',
'a1',
'source_ip',
'100.93.185.30',
'sip_code',
'503',
'hangup_reason',
'CONFIG_MISSING',
'created_at',
'2026-06-21T07:30:00.000Z'
]);
expect(parsed.callee_city_code).toBe('');
expect(parsed.callee_operator).toBe('UNKNOWN');
expect(parsed.callee_number_type).toBe('UNKNOWN');
});
it('creates the consumer group idempotently', async () => {
const redis = new FakeRedis();
+20
View File
@@ -36,6 +36,11 @@ export interface CdrStreamEvent {
source_ip: string;
caller: string;
callee: string;
callee_city_code: string;
callee_city_name: string;
callee_province_name: string;
callee_operator: string;
callee_number_type: string;
vendor_id: string;
vendor_gateway_id: string;
line_group_id: string;
@@ -69,6 +74,11 @@ export interface CdrStreamPublishInput {
sourceIp: string;
caller?: string;
callee?: string;
calleeCityCode?: string;
calleeCityName?: string;
calleeProvinceName?: string;
calleeOperator?: string;
calleeNumberType?: string;
vendorId?: string;
vendorGatewayId?: string;
lineGroupId?: string;
@@ -154,6 +164,11 @@ export function buildCdrStreamEvent(input: CdrStreamPublishInput): CdrStreamEven
source_ip: input.sourceIp,
caller: input.caller ?? '',
callee: input.callee ?? '',
callee_city_code: input.calleeCityCode ?? '',
callee_city_name: input.calleeCityName ?? '',
callee_province_name: input.calleeProvinceName ?? '',
callee_operator: input.calleeOperator ?? 'UNKNOWN',
callee_number_type: input.calleeNumberType ?? 'UNKNOWN',
vendor_id: input.vendorId ?? '',
vendor_gateway_id: input.vendorGatewayId ?? '',
line_group_id: input.lineGroupId ?? '',
@@ -220,6 +235,11 @@ export function parseCdrStreamEvent(fields: string[]): ParsedCdrStreamEvent {
source_ip: parsed.source_ip,
caller: parsed.caller ?? '',
callee: parsed.callee ?? '',
callee_city_code: parsed.callee_city_code ?? '',
callee_city_name: parsed.callee_city_name ?? '',
callee_province_name: parsed.callee_province_name ?? '',
callee_operator: parsed.callee_operator ?? 'UNKNOWN',
callee_number_type: parsed.callee_number_type ?? 'UNKNOWN',
vendor_id: parsed.vendor_id ?? '',
vendor_gateway_id: parsed.vendor_gateway_id ?? '',
line_group_id: parsed.line_group_id ?? '',