fix web ui smoke and brand assets
This commit is contained in:
@@ -0,0 +1,844 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { hashPasswordArgon2id } from '../packages/auth/src/index';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const ACTOR_ID = 'usr_test_admin';
|
||||
const TEST_PASSWORD = 'Test@123456';
|
||||
|
||||
const permissions = [
|
||||
'dashboard.view',
|
||||
'active_calls.view',
|
||||
'active_calls.manage',
|
||||
'customers.view',
|
||||
'customers.manage',
|
||||
'customer_gateways.view',
|
||||
'customer_gateways.manage',
|
||||
'vendors.view',
|
||||
'vendors.manage',
|
||||
'vendor_gateways.view',
|
||||
'vendor_gateways.manage',
|
||||
'line_groups.view',
|
||||
'line_groups.manage',
|
||||
'number_library.view',
|
||||
'number_library.manage',
|
||||
'recharges.view',
|
||||
'recharges.manage',
|
||||
'cdr.view',
|
||||
'recordings.play',
|
||||
'quality.view',
|
||||
'quality.manage',
|
||||
'users.view',
|
||||
'users.manage',
|
||||
'roles.view',
|
||||
'roles.manage',
|
||||
'audit.view',
|
||||
] as const;
|
||||
|
||||
const roles = [
|
||||
{ id: 'ROLE_TEST_ADMIN', name: '测试管理员', permissionIds: [...permissions] },
|
||||
{
|
||||
id: 'ROLE_TEST_VIEWER',
|
||||
name: '测试只读员',
|
||||
permissionIds: permissions.filter((permission) => permission.endsWith('.view') || permission === 'cdr.view'),
|
||||
},
|
||||
{ id: 'ROLE_TEST_FINANCE', name: '测试财务员', permissionIds: ['customers.view', 'recharges.view', 'recharges.manage'] },
|
||||
{ id: 'ROLE_TEST_QUALITY', name: '测试质检员', permissionIds: ['quality.view', 'quality.manage', 'recordings.play', 'cdr.view'] },
|
||||
{
|
||||
id: 'ROLE_TEST_GATEWAY',
|
||||
name: '测试客户网关员',
|
||||
permissionIds: ['customers.view', 'customer_gateways.view', 'customer_gateways.manage', 'line_groups.view'],
|
||||
},
|
||||
{
|
||||
id: 'ROLE_TEST_VENDOR',
|
||||
name: '测试供应商线路员',
|
||||
permissionIds: ['vendors.view', 'vendors.manage', 'vendor_gateways.view', 'vendor_gateways.manage', 'line_groups.view', 'line_groups.manage'],
|
||||
},
|
||||
{ id: 'ROLE_TEST_ACTIVE', name: '测试话务员', permissionIds: ['active_calls.view', 'active_calls.manage'] },
|
||||
{ id: 'ROLE_TEST_AUDIT', name: '测试审计员', permissionIds: ['audit.view'] },
|
||||
] as const;
|
||||
|
||||
const users = [
|
||||
{ id: ACTOR_ID, username: 'test.admin', displayName: '测试管理员', roleId: 'ROLE_TEST_ADMIN' },
|
||||
{ id: 'usr_test_viewer', username: 'test.viewer', displayName: '测试只读员', roleId: 'ROLE_TEST_VIEWER' },
|
||||
{ id: 'usr_test_fin', username: 'test.finance', displayName: '测试财务员', roleId: 'ROLE_TEST_FINANCE' },
|
||||
{ id: 'usr_test_quality', username: 'test.quality', displayName: '测试质检员', roleId: 'ROLE_TEST_QUALITY' },
|
||||
{ id: 'usr_test_gateway', username: 'test.gateway', displayName: '测试客户网关员', roleId: 'ROLE_TEST_GATEWAY' },
|
||||
{ id: 'usr_test_vendor', username: 'test.vendor', displayName: '测试供应商线路员', roleId: 'ROLE_TEST_VENDOR' },
|
||||
{ id: 'usr_test_active', username: 'test.active', displayName: '测试话务员', roleId: 'ROLE_TEST_ACTIVE' },
|
||||
{ id: 'usr_test_audit', username: 'test.audit', displayName: '测试审计员', roleId: 'ROLE_TEST_AUDIT' },
|
||||
] as const;
|
||||
|
||||
function sipHa1(username: string, domain: string, password: string): string {
|
||||
return createHash('md5').update(`${username}:${domain}:${password}`).digest('hex');
|
||||
}
|
||||
|
||||
async function seedAuth() {
|
||||
for (const id of permissions) {
|
||||
const [module, action] = id.split('.');
|
||||
await prisma.permission.upsert({
|
||||
where: { id },
|
||||
update: {},
|
||||
create: {
|
||||
id,
|
||||
module,
|
||||
action,
|
||||
description: `测试权限 ${id}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
for (const role of roles) {
|
||||
await prisma.role.upsert({
|
||||
where: { id: role.id },
|
||||
update: {
|
||||
name: role.name,
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: role.id,
|
||||
name: role.name,
|
||||
description: '自动化测试角色',
|
||||
builtIn: false,
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
for (const permissionId of role.permissionIds) {
|
||||
await prisma.rolePermission.upsert({
|
||||
where: { roleId_permissionId: { roleId: role.id, permissionId } },
|
||||
update: {},
|
||||
create: { roleId: role.id, permissionId, createdBy: ACTOR_ID },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const passwordHash = await hashPasswordArgon2id(TEST_PASSWORD, { memoryKiB: 1024, passes: 1 });
|
||||
for (const user of users) {
|
||||
await prisma.user.upsert({
|
||||
where: { id: user.id },
|
||||
update: {
|
||||
username: user.username,
|
||||
displayName: user.displayName,
|
||||
passwordHash,
|
||||
passwordAlgo: 'argon2id',
|
||||
status: 'ENABLED',
|
||||
failedLoginCount: 0,
|
||||
lockedUntil: null,
|
||||
requirePasswordChange: false,
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
displayName: user.displayName,
|
||||
email: `${user.username}@example.test`,
|
||||
passwordHash,
|
||||
passwordAlgo: 'argon2id',
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.userRole.upsert({
|
||||
where: { userId_roleId: { userId: user.id, roleId: user.roleId } },
|
||||
update: {},
|
||||
create: { userId: user.id, roleId: user.roleId, createdBy: ACTOR_ID },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function seedNumberLibrary() {
|
||||
await prisma.geoCity.upsert({
|
||||
where: { code: 'geo_340100' },
|
||||
update: {
|
||||
provinceCode: '340000',
|
||||
provinceName: '安徽省',
|
||||
cityCode: '340100',
|
||||
cityName: '合肥市',
|
||||
cityLevel: '地级市',
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
code: 'geo_340100',
|
||||
provinceCode: '340000',
|
||||
provinceName: '安徽省',
|
||||
cityCode: '340100',
|
||||
cityName: '合肥市',
|
||||
cityLevel: '地级市',
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.phoneNumberSegment.upsert({
|
||||
where: { segment7: '1380013' },
|
||||
update: {
|
||||
cityCode: '340100',
|
||||
provinceName: '安徽省',
|
||||
cityName: '合肥市',
|
||||
carrier: 'MOBILE',
|
||||
source: 'test-seed',
|
||||
batchId: 'test-seed',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
segment7: '1380013',
|
||||
cityCode: '340100',
|
||||
provinceName: '安徽省',
|
||||
cityName: '合肥市',
|
||||
carrier: 'MOBILE',
|
||||
source: 'test-seed',
|
||||
batchId: 'test-seed',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.phoneAreaCode.upsert({
|
||||
where: { areaCode: '0551' },
|
||||
update: {
|
||||
cityCode: '340100',
|
||||
provinceName: '安徽省',
|
||||
cityName: '合肥市',
|
||||
source: 'test-seed',
|
||||
batchId: 'test-seed',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
areaCode: '0551',
|
||||
cityCode: '340100',
|
||||
provinceName: '安徽省',
|
||||
cityName: '合肥市',
|
||||
source: 'test-seed',
|
||||
batchId: 'test-seed',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.carrierPrefixRule.upsert({
|
||||
where: { prefix: '138' },
|
||||
update: {
|
||||
carrier: 'MOBILE',
|
||||
priority: 10,
|
||||
source: 'test-seed',
|
||||
batchId: 'test-seed',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
prefix: '138',
|
||||
carrier: 'MOBILE',
|
||||
priority: 10,
|
||||
source: 'test-seed',
|
||||
batchId: 'test-seed',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function seedBusinessData() {
|
||||
await prisma.customer.upsert({
|
||||
where: { id: 'cus_auto_001' },
|
||||
update: {
|
||||
name: '自动化测试客户A',
|
||||
contactName: '测试联系人',
|
||||
phone: '13800138000',
|
||||
email: 'customer-a@example.test',
|
||||
domain: 'customer-a.example.test',
|
||||
status: 'ENABLED',
|
||||
billingMode: 'PREPAID',
|
||||
balance: '1000.000000',
|
||||
creditLimit: '200.000000',
|
||||
minBalance: '10.000000',
|
||||
notes: '自动化测试固定客户,可用于充值、扣款、网关和话单测试',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'cus_auto_001',
|
||||
name: '自动化测试客户A',
|
||||
contactName: '测试联系人',
|
||||
phone: '13800138000',
|
||||
email: 'customer-a@example.test',
|
||||
domain: 'customer-a.example.test',
|
||||
status: 'ENABLED',
|
||||
billingMode: 'PREPAID',
|
||||
balance: '1000.000000',
|
||||
creditLimit: '200.000000',
|
||||
minBalance: '10.000000',
|
||||
notes: '自动化测试固定客户,可用于充值、扣款、网关和话单测试',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.customer.upsert({
|
||||
where: { id: 'cus_low_001' },
|
||||
update: {
|
||||
name: '自动化低余额客户',
|
||||
status: 'ENABLED',
|
||||
billingMode: 'PREPAID',
|
||||
balance: '3.000000',
|
||||
creditLimit: '0.000000',
|
||||
minBalance: '10.000000',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'cus_low_001',
|
||||
name: '自动化低余额客户',
|
||||
domain: 'customer-low.example.test',
|
||||
status: 'ENABLED',
|
||||
billingMode: 'PREPAID',
|
||||
balance: '3.000000',
|
||||
creditLimit: '0.000000',
|
||||
minBalance: '10.000000',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
const businessPrefixes = [
|
||||
{ id: 'bp_auto_671', prefix: '671', name: '自动化业务前缀671', priority: 10 },
|
||||
{ id: 'bp_auto_672', prefix: '672', name: '自动化业务前缀672', priority: 20 },
|
||||
] as const;
|
||||
for (const prefix of businessPrefixes) {
|
||||
await prisma.businessPrefix.upsert({
|
||||
where: { id: prefix.id },
|
||||
update: {
|
||||
prefix: prefix.prefix,
|
||||
name: prefix.name,
|
||||
description: '自动化测试业务前缀',
|
||||
priority: prefix.priority,
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: prefix.id,
|
||||
prefix: prefix.prefix,
|
||||
name: prefix.name,
|
||||
description: '自动化测试业务前缀',
|
||||
priority: prefix.priority,
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.vendor.upsert({
|
||||
where: { id: 'ven_auto_001' },
|
||||
update: {
|
||||
name: '自动化测试供应商A',
|
||||
contactName: '供应商联系人',
|
||||
phone: '13900139000',
|
||||
email: 'vendor-a@example.test',
|
||||
status: 'ENABLED',
|
||||
balance: '5000.000000',
|
||||
creditLimit: '500.000000',
|
||||
settlement: '月结',
|
||||
notes: '自动化测试固定供应商',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'ven_auto_001',
|
||||
name: '自动化测试供应商A',
|
||||
contactName: '供应商联系人',
|
||||
phone: '13900139000',
|
||||
email: 'vendor-a@example.test',
|
||||
status: 'ENABLED',
|
||||
balance: '5000.000000',
|
||||
creditLimit: '500.000000',
|
||||
settlement: '月结',
|
||||
notes: '自动化测试固定供应商',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
const vendorGateways = [
|
||||
{ id: 'vgw_auto_primary', name: '自动化主落地网关', host: '10.88.0.10', priority: 10, weight: 70 },
|
||||
{ id: 'vgw_auto_backup', name: '自动化备落地网关', host: '10.88.0.11', priority: 20, weight: 30 },
|
||||
] as const;
|
||||
for (const gateway of vendorGateways) {
|
||||
await prisma.vendorGateway.upsert({
|
||||
where: { id: gateway.id },
|
||||
update: {
|
||||
vendorId: 'ven_auto_001',
|
||||
name: gateway.name,
|
||||
authMode: 'IP',
|
||||
host: gateway.host,
|
||||
port: 5060,
|
||||
transport: 'udp',
|
||||
cpsLimit: 50,
|
||||
concurrencyLimit: 500,
|
||||
billingCycleSec: 60,
|
||||
cycleRate: gateway.id === 'vgw_auto_primary' ? '0.035000' : '0.040000',
|
||||
landingCalleePrefix: '86',
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: gateway.id,
|
||||
vendorId: 'ven_auto_001',
|
||||
name: gateway.name,
|
||||
authMode: 'IP',
|
||||
host: gateway.host,
|
||||
port: 5060,
|
||||
transport: 'udp',
|
||||
cpsLimit: 50,
|
||||
concurrencyLimit: 500,
|
||||
billingCycleSec: 60,
|
||||
cycleRate: gateway.id === 'vgw_auto_primary' ? '0.035000' : '0.040000',
|
||||
landingCalleePrefix: '86',
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.vendorGatewayCodec.upsert({
|
||||
where: { vendorGatewayId_codec: { vendorGatewayId: gateway.id, codec: 'PCMA' } },
|
||||
update: { priority: 10, updatedBy: ACTOR_ID },
|
||||
create: { id: `${gateway.id}_pcma`, vendorGatewayId: gateway.id, codec: 'PCMA', priority: 10, createdBy: ACTOR_ID, updatedBy: ACTOR_ID },
|
||||
});
|
||||
|
||||
await prisma.vendorGatewayPrefixRule.upsert({
|
||||
where: { vendorGatewayId_direction_priority: { vendorGatewayId: gateway.id, direction: 'CALLEE', priority: 10 } },
|
||||
update: { matchPrefix: '671', replacePrefix: '86', updatedBy: ACTOR_ID },
|
||||
create: {
|
||||
id: `${gateway.id}_callee`,
|
||||
vendorGatewayId: gateway.id,
|
||||
direction: 'CALLEE',
|
||||
matchPrefix: '671',
|
||||
replacePrefix: '86',
|
||||
priority: 10,
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.vendorGatewayForbiddenPeriod.upsert({
|
||||
where: { id: 'vgwfp_auto_001' },
|
||||
update: {
|
||||
vendorGatewayId: 'vgw_auto_backup',
|
||||
weekdayMask: 127,
|
||||
startTime: '00:00:00',
|
||||
endTime: '00:10:00',
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
create: {
|
||||
id: 'vgwfp_auto_001',
|
||||
vendorGatewayId: 'vgw_auto_backup',
|
||||
weekdayMask: 127,
|
||||
startTime: '00:00:00',
|
||||
endTime: '00:10:00',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.vendorGatewayCallerRewrite.upsert({
|
||||
where: { id: 'vgwcr_auto_001' },
|
||||
update: {
|
||||
vendorGatewayId: 'vgw_auto_primary',
|
||||
caller: '05510000001',
|
||||
weight: 100,
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'vgwcr_auto_001',
|
||||
vendorGatewayId: 'vgw_auto_primary',
|
||||
caller: '05510000001',
|
||||
weight: 100,
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.landingLineGroup.upsert({
|
||||
where: { id: 'llg_auto_001' },
|
||||
update: {
|
||||
name: '自动化测试线路组',
|
||||
status: 'ENABLED',
|
||||
notes: '主备落地网关测试线路组',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'llg_auto_001',
|
||||
name: '自动化测试线路组',
|
||||
status: 'ENABLED',
|
||||
notes: '主备落地网关测试线路组',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
for (const gateway of vendorGateways) {
|
||||
await prisma.landingLineGroupItem.upsert({
|
||||
where: { lineGroupId_vendorGatewayId: { lineGroupId: 'llg_auto_001', vendorGatewayId: gateway.id } },
|
||||
update: {
|
||||
priority: gateway.priority,
|
||||
weight: gateway.weight,
|
||||
concurrencyCap: gateway.id === 'vgw_auto_primary' ? 300 : 100,
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
create: {
|
||||
id: gateway.id === 'vgw_auto_primary' ? 'llgi_auto_primary' : 'llgi_auto_backup',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
vendorGatewayId: gateway.id,
|
||||
priority: gateway.priority,
|
||||
weight: gateway.weight,
|
||||
concurrencyCap: gateway.id === 'vgw_auto_primary' ? 300 : 100,
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.customerGateway.upsert({
|
||||
where: { id: 'cgw_auto_ip' },
|
||||
update: {
|
||||
customerId: 'cus_auto_001',
|
||||
name: '自动化IP认证客户网关',
|
||||
authMode: 'IP',
|
||||
sourceIp: '10.66.0.10',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
billingCycleSec: 60,
|
||||
cycleRate: '0.080000',
|
||||
callerMatchMode: 'PREFIXES',
|
||||
calleeMatchMode: 'BUSINESS_PREFIXES',
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'cgw_auto_ip',
|
||||
customerId: 'cus_auto_001',
|
||||
name: '自动化IP认证客户网关',
|
||||
authMode: 'IP',
|
||||
sourceIp: '10.66.0.10',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
billingCycleSec: 60,
|
||||
cycleRate: '0.080000',
|
||||
callerMatchMode: 'PREFIXES',
|
||||
calleeMatchMode: 'BUSINESS_PREFIXES',
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.customerGateway.upsert({
|
||||
where: { id: 'cgw_auto_sip' },
|
||||
update: {
|
||||
customerId: 'cus_auto_001',
|
||||
name: '自动化SIP认证客户网关',
|
||||
authMode: 'SIP_DIGEST',
|
||||
sipUsername: 'auto_sip_user',
|
||||
sipDomain: 'customer-a.example.test',
|
||||
sipHa1: sipHa1('auto_sip_user', 'customer-a.example.test', TEST_PASSWORD),
|
||||
lineGroupId: 'llg_auto_001',
|
||||
billingCycleSec: 60,
|
||||
cycleRate: '0.090000',
|
||||
callerMatchMode: 'ANY',
|
||||
calleeMatchMode: 'BUSINESS_PREFIXES',
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'cgw_auto_sip',
|
||||
customerId: 'cus_auto_001',
|
||||
name: '自动化SIP认证客户网关',
|
||||
authMode: 'SIP_DIGEST',
|
||||
sipUsername: 'auto_sip_user',
|
||||
sipDomain: 'customer-a.example.test',
|
||||
sipHa1: sipHa1('auto_sip_user', 'customer-a.example.test', TEST_PASSWORD),
|
||||
lineGroupId: 'llg_auto_001',
|
||||
billingCycleSec: 60,
|
||||
cycleRate: '0.090000',
|
||||
callerMatchMode: 'ANY',
|
||||
calleeMatchMode: 'BUSINESS_PREFIXES',
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.customerGatewayIp.upsert({
|
||||
where: { gatewayId_sourceIp: { gatewayId: 'cgw_auto_ip', sourceIp: '10.66.0.10' } },
|
||||
update: { status: 'ENABLED', updatedBy: ACTOR_ID, deletedAt: null },
|
||||
create: { id: 'cgip_auto_001', gatewayId: 'cgw_auto_ip', sourceIp: '10.66.0.10', status: 'ENABLED', createdBy: ACTOR_ID, updatedBy: ACTOR_ID },
|
||||
});
|
||||
|
||||
await prisma.customerGatewayBusinessPrefix.upsert({
|
||||
where: { gatewayId_businessPrefixId: { gatewayId: 'cgw_auto_ip', businessPrefixId: 'bp_auto_671' } },
|
||||
update: {},
|
||||
create: { id: 'cgbp_auto_ip_671', gatewayId: 'cgw_auto_ip', businessPrefixId: 'bp_auto_671', createdBy: ACTOR_ID },
|
||||
});
|
||||
|
||||
await prisma.customerGatewayBusinessPrefix.upsert({
|
||||
where: { gatewayId_businessPrefixId: { gatewayId: 'cgw_auto_sip', businessPrefixId: 'bp_auto_671' } },
|
||||
update: {},
|
||||
create: { id: 'cgbp_auto_sip_671', gatewayId: 'cgw_auto_sip', businessPrefixId: 'bp_auto_671', createdBy: ACTOR_ID },
|
||||
});
|
||||
|
||||
await prisma.customerGatewayCallerPrefix.upsert({
|
||||
where: { gatewayId_prefix: { gatewayId: 'cgw_auto_ip', prefix: '0551' } },
|
||||
update: { priority: 10 },
|
||||
create: { id: 'cgcp_auto_0551', gatewayId: 'cgw_auto_ip', prefix: '0551', priority: 10, createdBy: ACTOR_ID },
|
||||
});
|
||||
|
||||
await prisma.customerGatewayPolicy.upsert({
|
||||
where: { id: 'cgp_auto_001' },
|
||||
update: {
|
||||
customerId: 'cus_auto_001',
|
||||
gatewayId: 'cgw_auto_ip',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
name: '自动化客户网关策略',
|
||||
priority: 10,
|
||||
callerMode: 'PREFIX',
|
||||
callerValue: '0551',
|
||||
calleeMode: 'PREFIX',
|
||||
calleeValue: '671',
|
||||
status: 'ENABLED',
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'cgp_auto_001',
|
||||
customerId: 'cus_auto_001',
|
||||
gatewayId: 'cgw_auto_ip',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
name: '自动化客户网关策略',
|
||||
priority: 10,
|
||||
callerMode: 'PREFIX',
|
||||
callerValue: '0551',
|
||||
calleeMode: 'PREFIX',
|
||||
calleeValue: '671',
|
||||
status: 'ENABLED',
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function seedCdrAndQuality() {
|
||||
const startedAt = new Date('2026-01-01T10:00:00.000Z');
|
||||
const answeredAt = new Date('2026-01-01T10:00:06.000Z');
|
||||
const endedAt = new Date('2026-01-01T10:01:06.000Z');
|
||||
|
||||
await prisma.rawCdr.upsert({
|
||||
where: { id: 'raw_auto_001' },
|
||||
update: {
|
||||
eventId: 'evt_auto_001',
|
||||
callId: 'call_auto_001',
|
||||
customerId: 'cus_auto_001',
|
||||
customerGatewayId: 'cgw_auto_ip',
|
||||
customerGatewayPolicyId: 'cgp_auto_001',
|
||||
sourceIp: '10.66.0.10',
|
||||
caller: '05510000001',
|
||||
callee: '67113800138000',
|
||||
rawCallee: '67113800138000',
|
||||
businessPrefixId: 'bp_auto_671',
|
||||
businessPrefix: '671',
|
||||
calleeCityCode: '340100',
|
||||
calleeCityName: '合肥市',
|
||||
calleeProvinceName: '安徽省',
|
||||
calleeOperator: 'MOBILE',
|
||||
calleeNumberType: 'MOBILE',
|
||||
vendorId: 'ven_auto_001',
|
||||
vendorGatewayId: 'vgw_auto_primary',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
landingCaller: '05510000001',
|
||||
landingCallee: '8613800138000',
|
||||
startedAt,
|
||||
answeredAt,
|
||||
endedAt,
|
||||
durationSec: 66,
|
||||
sipCode: 200,
|
||||
hangupReason: 'NORMAL_CLEARING',
|
||||
recordingKey: 'seed/call_auto_001.wav',
|
||||
configVersion: 1,
|
||||
ratingStatus: 'RATED',
|
||||
payload: { source: 'test-seed' },
|
||||
},
|
||||
create: {
|
||||
id: 'raw_auto_001',
|
||||
eventId: 'evt_auto_001',
|
||||
callId: 'call_auto_001',
|
||||
customerId: 'cus_auto_001',
|
||||
customerGatewayId: 'cgw_auto_ip',
|
||||
customerGatewayPolicyId: 'cgp_auto_001',
|
||||
sourceIp: '10.66.0.10',
|
||||
caller: '05510000001',
|
||||
callee: '67113800138000',
|
||||
rawCallee: '67113800138000',
|
||||
businessPrefixId: 'bp_auto_671',
|
||||
businessPrefix: '671',
|
||||
calleeCityCode: '340100',
|
||||
calleeCityName: '合肥市',
|
||||
calleeProvinceName: '安徽省',
|
||||
calleeOperator: 'MOBILE',
|
||||
calleeNumberType: 'MOBILE',
|
||||
vendorId: 'ven_auto_001',
|
||||
vendorGatewayId: 'vgw_auto_primary',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
landingCaller: '05510000001',
|
||||
landingCallee: '8613800138000',
|
||||
startedAt,
|
||||
answeredAt,
|
||||
endedAt,
|
||||
durationSec: 66,
|
||||
sipCode: 200,
|
||||
hangupReason: 'NORMAL_CLEARING',
|
||||
recordingKey: 'seed/call_auto_001.wav',
|
||||
configVersion: 1,
|
||||
ratingStatus: 'RATED',
|
||||
payload: { source: 'test-seed' },
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.ratedCdr.upsert({
|
||||
where: { rawCdrId: 'raw_auto_001' },
|
||||
update: {
|
||||
billSec: 60,
|
||||
customerFee: '0.080000',
|
||||
vendorCost: '0.035000',
|
||||
grossProfit: '0.045000',
|
||||
customerRate: { cycleSec: 60, cycleRate: '0.080000' },
|
||||
vendorRate: { cycleSec: 60, cycleRate: '0.035000' },
|
||||
},
|
||||
create: {
|
||||
id: 'rated_auto_001',
|
||||
rawCdrId: 'raw_auto_001',
|
||||
billSec: 60,
|
||||
customerFee: '0.080000',
|
||||
vendorCost: '0.035000',
|
||||
grossProfit: '0.045000',
|
||||
customerRate: { cycleSec: 60, cycleRate: '0.080000' },
|
||||
vendorRate: { cycleSec: 60, cycleRate: '0.035000' },
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.recording.upsert({
|
||||
where: { id: 'rec_auto_001' },
|
||||
update: {
|
||||
rawCdrId: 'raw_auto_001',
|
||||
storageKey: 'seed/call_auto_001.wav',
|
||||
storagePath: '/recordings/seed/call_auto_001.wav',
|
||||
sha256: 'a'.repeat(64),
|
||||
bytes: BigInt(55758),
|
||||
durationSec: 66,
|
||||
status: 'READY',
|
||||
movedAt: endedAt,
|
||||
},
|
||||
create: {
|
||||
id: 'rec_auto_001',
|
||||
rawCdrId: 'raw_auto_001',
|
||||
storageKey: 'seed/call_auto_001.wav',
|
||||
storagePath: '/recordings/seed/call_auto_001.wav',
|
||||
sha256: 'a'.repeat(64),
|
||||
bytes: BigInt(55758),
|
||||
durationSec: 66,
|
||||
status: 'READY',
|
||||
movedAt: endedAt,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.qualitySamplingRule.upsert({
|
||||
where: { id: 'qsr_auto_001' },
|
||||
update: {
|
||||
name: '自动化抽检规则',
|
||||
customerId: 'cus_auto_001',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
ratio: '10.00',
|
||||
status: 'ENABLED',
|
||||
effectiveAt: startedAt,
|
||||
expiresAt: null,
|
||||
updatedBy: ACTOR_ID,
|
||||
deletedAt: null,
|
||||
},
|
||||
create: {
|
||||
id: 'qsr_auto_001',
|
||||
name: '自动化抽检规则',
|
||||
customerId: 'cus_auto_001',
|
||||
lineGroupId: 'llg_auto_001',
|
||||
ratio: '10.00',
|
||||
status: 'ENABLED',
|
||||
effectiveAt: startedAt,
|
||||
createdBy: ACTOR_ID,
|
||||
updatedBy: ACTOR_ID,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.qualityReview.upsert({
|
||||
where: { id: 'qr_auto_001' },
|
||||
update: {
|
||||
recordingId: 'rec_auto_001',
|
||||
reviewerId: 'usr_test_quality',
|
||||
score: 88,
|
||||
result: 'PASS',
|
||||
issueTags: [],
|
||||
notes: '自动化测试质检样本',
|
||||
reviewedAt: endedAt,
|
||||
},
|
||||
create: {
|
||||
id: 'qr_auto_001',
|
||||
recordingId: 'rec_auto_001',
|
||||
reviewerId: 'usr_test_quality',
|
||||
score: 88,
|
||||
result: 'PASS',
|
||||
issueTags: [],
|
||||
notes: '自动化测试质检样本',
|
||||
reviewedAt: endedAt,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await seedAuth();
|
||||
await seedNumberLibrary();
|
||||
await seedBusinessData();
|
||||
await seedCdrAndQuality();
|
||||
|
||||
console.log('Test seed completed.');
|
||||
console.log(`Login users: ${users.map((user) => user.username).join(', ')}`);
|
||||
console.log(`Default password: ${TEST_PASSWORD}`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error('Test seed failed.', error);
|
||||
process.exitCode = 1;
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user