feat: complete phase2 baseline cdr quality rbac

This commit is contained in:
hectorzhao
2026-06-24 18:40:21 +08:00
parent 7057fd3c42
commit a86de6545f
63 changed files with 7853 additions and 3678 deletions
+27 -1
View File
@@ -6,12 +6,20 @@ const schema = readFileSync(join(process.cwd(), 'prisma/schema.prisma'), 'utf8')
const migration = readFileSync(join(process.cwd(), 'prisma/migrations/20260621090000_init_v2_schema/migration.sql'), 'utf8');
const authMigration = readFileSync(join(process.cwd(), 'prisma/migrations/20260621093000_auth_sessions/migration.sql'), 'utf8');
const numberLibraryMigration = readFileSync(join(process.cwd(), 'prisma/migrations/20260624095000_number_library/migration.sql'), 'utf8');
const businessPrefixMigration = readFileSync(
join(process.cwd(), 'prisma/migrations/20260624121000_business_prefix_gateway_rewrite/migration.sql'),
'utf8'
);
describe('Prisma schema contract', () => {
it('defines every V2 core business table', () => {
const tables = [
'customers',
'customer_gateways',
'customer_gateway_ips',
'business_prefixes',
'customer_gateway_business_prefixes',
'customer_gateway_caller_prefixes',
'customer_gateway_policies',
'customer_recharges',
'vendors',
@@ -21,6 +29,7 @@ describe('Prisma schema contract', () => {
'vendor_gateway_forbidden_periods',
'vendor_gateway_codecs',
'vendor_gateway_prefix_rules',
'vendor_gateway_caller_rewrite_pool',
'landing_line_groups',
'landing_line_group_items',
'geo_cities',
@@ -45,7 +54,9 @@ describe('Prisma schema contract', () => {
for (const table of tables) {
expect(schema).toContain(`@@map("${table}")`);
expect(`${migration}\n${authMigration}\n${numberLibraryMigration}`).toContain(`CREATE TABLE \`${table}\``);
expect(`${migration}\n${authMigration}\n${numberLibraryMigration}\n${businessPrefixMigration}`).toContain(
`CREATE TABLE \`${table}\``
);
}
});
@@ -68,6 +79,21 @@ describe('Prisma schema contract', () => {
expect(numberLibraryMigration).toContain('CREATE INDEX `raw_cdrs_callee_operator_started_at_idx`');
});
it('models phase-2 business prefix gateway matching and landing rewrites', () => {
expect(schema).toContain('model BusinessPrefix');
expect(schema).toContain('model CustomerGatewayIp');
expect(schema).toContain('model CustomerGatewayBusinessPrefix');
expect(schema).toContain('model CustomerGatewayCallerPrefix');
expect(schema).toContain('model VendorGatewayCallerRewrite');
expect(schema).toContain('enum CustomerGatewayCallerMatchMode');
expect(schema).toContain('enum CustomerGatewayCalleeMatchMode');
expect(businessPrefixMigration).toContain('`billing_cycle_sec` INTEGER NOT NULL DEFAULT 60');
expect(businessPrefixMigration).toContain('`landing_callee_prefix` VARCHAR(64) NULL');
expect(businessPrefixMigration).toContain('`raw_callee` VARCHAR(64) NULL');
expect(businessPrefixMigration).toContain('`landing_caller` VARCHAR(64) NULL');
expect(businessPrefixMigration).toContain('CREATE INDEX `raw_cdrs_business_prefix_id_started_at_idx`');
});
it('models audit columns and outbox publishing state', () => {
expect(schema).toContain('createdAt');
expect(schema).toContain('updatedAt');
+19
View File
@@ -142,6 +142,12 @@ function sampleEvent(overrides: Partial<CdrStreamPublishInput> = {}): CdrStreamP
sourceIp: '100.93.185.30',
caller: 's21-ip-1001',
callee: '13800138000',
rawCallee: '67113800138000',
businessPrefixId: 'bp_1',
businessPrefix: '671',
landingCaller: '02160010001',
landingCallee: '8613800138000',
normalizedCallee: '13800138000',
calleeCityCode: '340100',
calleeCityName: '合肥市',
calleeProvinceName: '安徽省',
@@ -167,6 +173,13 @@ 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).toBe('13800138000');
expect(parsed.raw_callee).toBe('67113800138000');
expect(parsed.business_prefix_id).toBe('bp_1');
expect(parsed.business_prefix).toBe('671');
expect(parsed.landing_caller).toBe('02160010001');
expect(parsed.landing_callee).toBe('8613800138000');
expect(parsed.normalized_callee).toBe('13800138000');
expect(parsed.callee_city_code).toBe('340100');
expect(parsed.callee_city_name).toBe('合肥市');
expect(parsed.callee_operator).toBe('MOBILE');
@@ -202,6 +215,12 @@ describe('CDR Redis Stream contract', () => {
]);
expect(parsed.callee_city_code).toBe('');
expect(parsed.raw_callee).toBe('');
expect(parsed.business_prefix_id).toBe('');
expect(parsed.business_prefix).toBe('');
expect(parsed.landing_caller).toBe('');
expect(parsed.landing_callee).toBe('');
expect(parsed.normalized_callee).toBe('');
expect(parsed.callee_operator).toBe('UNKNOWN');
expect(parsed.callee_number_type).toBe('UNKNOWN');
});
+24
View File
@@ -36,6 +36,12 @@ export interface CdrStreamEvent {
source_ip: string;
caller: string;
callee: string;
raw_callee: string;
business_prefix_id: string;
business_prefix: string;
landing_caller: string;
landing_callee: string;
normalized_callee: string;
callee_city_code: string;
callee_city_name: string;
callee_province_name: string;
@@ -74,6 +80,12 @@ export interface CdrStreamPublishInput {
sourceIp: string;
caller?: string;
callee?: string;
rawCallee?: string;
businessPrefixId?: string;
businessPrefix?: string;
landingCaller?: string;
landingCallee?: string;
normalizedCallee?: string;
calleeCityCode?: string;
calleeCityName?: string;
calleeProvinceName?: string;
@@ -164,6 +176,12 @@ export function buildCdrStreamEvent(input: CdrStreamPublishInput): CdrStreamEven
source_ip: input.sourceIp,
caller: input.caller ?? '',
callee: input.callee ?? '',
raw_callee: input.rawCallee ?? input.callee ?? '',
business_prefix_id: input.businessPrefixId ?? '',
business_prefix: input.businessPrefix ?? '',
landing_caller: input.landingCaller ?? input.caller ?? '',
landing_callee: input.landingCallee ?? input.callee ?? '',
normalized_callee: input.normalizedCallee ?? input.callee ?? '',
callee_city_code: input.calleeCityCode ?? '',
callee_city_name: input.calleeCityName ?? '',
callee_province_name: input.calleeProvinceName ?? '',
@@ -235,6 +253,12 @@ export function parseCdrStreamEvent(fields: string[]): ParsedCdrStreamEvent {
source_ip: parsed.source_ip,
caller: parsed.caller ?? '',
callee: parsed.callee ?? '',
raw_callee: parsed.raw_callee ?? '',
business_prefix_id: parsed.business_prefix_id ?? '',
business_prefix: parsed.business_prefix ?? '',
landing_caller: parsed.landing_caller ?? '',
landing_callee: parsed.landing_callee ?? '',
normalized_callee: parsed.normalized_callee ?? '',
callee_city_code: parsed.callee_city_code ?? '',
callee_city_name: parsed.callee_city_name ?? '',
callee_province_name: parsed.callee_province_name ?? '',