Initial LisgloSIPS V2 implementation
This commit is contained in:
@@ -0,0 +1,617 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE `customers` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`contact_name` VARCHAR(80) NULL,
|
||||
`phone` VARCHAR(32) NULL,
|
||||
`email` VARCHAR(160) NULL,
|
||||
`domain` VARCHAR(160) NULL,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`billing_mode` ENUM('PREPAID', 'POSTPAID') NOT NULL DEFAULT 'PREPAID',
|
||||
`balance` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`credit_limit` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`min_balance` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`notes` VARCHAR(500) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
UNIQUE INDEX `customers_name_key`(`name`),
|
||||
UNIQUE INDEX `customers_domain_key`(`domain`),
|
||||
INDEX `customers_status_idx`(`status`),
|
||||
INDEX `customers_deleted_at_idx`(`deleted_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `customer_gateways` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`customer_id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`auth_mode` ENUM('IP', 'SIP_DIGEST', 'MIXED') NOT NULL,
|
||||
`source_ip` VARCHAR(45) NULL,
|
||||
`sip_username` VARCHAR(120) NULL,
|
||||
`sip_domain` VARCHAR(160) NULL,
|
||||
`sip_ha1` VARCHAR(128) NULL,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
INDEX `customer_gateways_customer_id_status_idx`(`customer_id`, `status`),
|
||||
INDEX `customer_gateways_source_ip_idx`(`source_ip`),
|
||||
INDEX `customer_gateways_deleted_at_idx`(`deleted_at`),
|
||||
UNIQUE INDEX `customer_gateways_customer_id_name_key`(`customer_id`, `name`),
|
||||
UNIQUE INDEX `customer_gateways_sip_username_sip_domain_key`(`sip_username`, `sip_domain`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `customer_gateway_policies` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`customer_id` VARCHAR(32) NOT NULL,
|
||||
`gateway_id` VARCHAR(32) NOT NULL,
|
||||
`line_group_id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`priority` INTEGER NOT NULL,
|
||||
`caller_mode` ENUM('ANY', 'EQUALS', 'PREFIX') NOT NULL DEFAULT 'ANY',
|
||||
`caller_value` VARCHAR(64) NULL,
|
||||
`callee_mode` ENUM('ANY', 'EQUALS', 'PREFIX') NOT NULL DEFAULT 'ANY',
|
||||
`callee_value` VARCHAR(64) NULL,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
INDEX `customer_gateway_policies_customer_id_status_idx`(`customer_id`, `status`),
|
||||
INDEX `customer_gateway_policies_line_group_id_idx`(`line_group_id`),
|
||||
INDEX `customer_gateway_policies_deleted_at_idx`(`deleted_at`),
|
||||
UNIQUE INDEX `customer_gateway_policies_gateway_id_priority_key`(`gateway_id`, `priority`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `customer_recharges` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`customer_id` VARCHAR(32) NOT NULL,
|
||||
`amount` DECIMAL(20, 6) NOT NULL,
|
||||
`before_balance` DECIMAL(20, 6) NOT NULL,
|
||||
`after_balance` DECIMAL(20, 6) NOT NULL,
|
||||
`idempotency_key` VARCHAR(128) NOT NULL,
|
||||
`remark` VARCHAR(500) NULL,
|
||||
`status` ENUM('SUCCEEDED', 'FAILED', 'REVERSED') NOT NULL DEFAULT 'SUCCEEDED',
|
||||
`occurred_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
|
||||
UNIQUE INDEX `customer_recharges_idempotency_key_key`(`idempotency_key`),
|
||||
INDEX `customer_recharges_customer_id_occurred_at_idx`(`customer_id`, `occurred_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `vendors` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`contact_name` VARCHAR(80) NULL,
|
||||
`phone` VARCHAR(32) NULL,
|
||||
`email` VARCHAR(160) NULL,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`balance` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`credit_limit` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`settlement` VARCHAR(80) NULL,
|
||||
`notes` VARCHAR(500) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
UNIQUE INDEX `vendors_name_key`(`name`),
|
||||
INDEX `vendors_status_idx`(`status`),
|
||||
INDEX `vendors_deleted_at_idx`(`deleted_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `vendor_recharges` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`vendor_id` VARCHAR(32) NOT NULL,
|
||||
`amount` DECIMAL(20, 6) NOT NULL,
|
||||
`before_balance` DECIMAL(20, 6) NOT NULL,
|
||||
`after_balance` DECIMAL(20, 6) NOT NULL,
|
||||
`idempotency_key` VARCHAR(128) NOT NULL,
|
||||
`remark` VARCHAR(500) NULL,
|
||||
`status` ENUM('SUCCEEDED', 'FAILED', 'REVERSED') NOT NULL DEFAULT 'SUCCEEDED',
|
||||
`occurred_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
|
||||
UNIQUE INDEX `vendor_recharges_idempotency_key_key`(`idempotency_key`),
|
||||
INDEX `vendor_recharges_vendor_id_occurred_at_idx`(`vendor_id`, `occurred_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `vendor_gateways` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`vendor_id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`auth_mode` ENUM('IP', 'SIP_DIGEST', 'MIXED') NOT NULL,
|
||||
`host` VARCHAR(160) NOT NULL,
|
||||
`port` INTEGER NOT NULL DEFAULT 5060,
|
||||
`transport` VARCHAR(16) NOT NULL DEFAULT 'udp',
|
||||
`sip_username` VARCHAR(120) NULL,
|
||||
`sip_ha1` VARCHAR(128) NULL,
|
||||
`cps_limit` INTEGER NOT NULL DEFAULT 0,
|
||||
`concurrency_limit` INTEGER NOT NULL DEFAULT 0,
|
||||
`billing_cycle_sec` INTEGER NOT NULL DEFAULT 60,
|
||||
`cycle_rate` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
INDEX `vendor_gateways_vendor_id_status_idx`(`vendor_id`, `status`),
|
||||
INDEX `vendor_gateways_host_idx`(`host`),
|
||||
INDEX `vendor_gateways_deleted_at_idx`(`deleted_at`),
|
||||
UNIQUE INDEX `vendor_gateways_vendor_id_name_key`(`vendor_id`, `name`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `vendor_gateway_forbidden_periods` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`vendor_gateway_id` VARCHAR(32) NOT NULL,
|
||||
`weekday_mask` INTEGER NOT NULL,
|
||||
`start_time` VARCHAR(8) NOT NULL,
|
||||
`end_time` VARCHAR(8) NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
INDEX `vendor_gateway_forbidden_periods_vendor_gateway_id_idx`(`vendor_gateway_id`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `vendor_gateway_codecs` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`vendor_gateway_id` VARCHAR(32) NOT NULL,
|
||||
`codec` VARCHAR(32) NOT NULL,
|
||||
`priority` INTEGER NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
UNIQUE INDEX `vendor_gateway_codecs_vendor_gateway_id_codec_key`(`vendor_gateway_id`, `codec`),
|
||||
UNIQUE INDEX `vendor_gateway_codecs_vendor_gateway_id_priority_key`(`vendor_gateway_id`, `priority`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `vendor_gateway_prefix_rules` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`vendor_gateway_id` VARCHAR(32) NOT NULL,
|
||||
`direction` ENUM('CALLER', 'CALLEE') NOT NULL,
|
||||
`match_prefix` VARCHAR(32) NOT NULL,
|
||||
`replace_prefix` VARCHAR(32) NOT NULL,
|
||||
`priority` INTEGER NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
INDEX `vendor_gateway_prefix_rules_vendor_gateway_id_direction_idx`(`vendor_gateway_id`, `direction`),
|
||||
UNIQUE INDEX `vendor_gateway_prefix_rules_vendor_gateway_id_direction_prio_key`(`vendor_gateway_id`, `direction`, `priority`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `landing_line_groups` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`notes` VARCHAR(500) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
UNIQUE INDEX `landing_line_groups_name_key`(`name`),
|
||||
INDEX `landing_line_groups_status_idx`(`status`),
|
||||
INDEX `landing_line_groups_deleted_at_idx`(`deleted_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `landing_line_group_items` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`line_group_id` VARCHAR(32) NOT NULL,
|
||||
`vendor_gateway_id` VARCHAR(32) NOT NULL,
|
||||
`priority` INTEGER NOT NULL,
|
||||
`weight` INTEGER NOT NULL DEFAULT 1,
|
||||
`concurrency_cap` INTEGER NOT NULL DEFAULT 0,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
INDEX `landing_line_group_items_vendor_gateway_id_idx`(`vendor_gateway_id`),
|
||||
UNIQUE INDEX `landing_line_group_items_line_group_id_vendor_gateway_id_key`(`line_group_id`, `vendor_gateway_id`),
|
||||
UNIQUE INDEX `landing_line_group_items_line_group_id_priority_key`(`line_group_id`, `priority`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `raw_cdrs` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`event_id` VARCHAR(64) NOT NULL,
|
||||
`call_id` VARCHAR(255) NOT NULL,
|
||||
`customer_id` VARCHAR(32) NULL,
|
||||
`customer_gateway_id` VARCHAR(32) NULL,
|
||||
`customer_gateway_policy_id` VARCHAR(32) NULL,
|
||||
`source_ip` VARCHAR(45) NULL,
|
||||
`caller` VARCHAR(64) NOT NULL,
|
||||
`callee` VARCHAR(64) NOT NULL,
|
||||
`vendor_id` VARCHAR(32) NULL,
|
||||
`vendor_gateway_id` VARCHAR(32) NULL,
|
||||
`line_group_id` VARCHAR(32) NULL,
|
||||
`started_at` DATETIME(3) NOT NULL,
|
||||
`answered_at` DATETIME(3) NULL,
|
||||
`ended_at` DATETIME(3) NOT NULL,
|
||||
`duration_sec` INTEGER NOT NULL DEFAULT 0,
|
||||
`sip_code` INTEGER NOT NULL,
|
||||
`hangup_reason` VARCHAR(120) NULL,
|
||||
`recording_key` VARCHAR(255) NULL,
|
||||
`config_version` INTEGER NULL,
|
||||
`rating_status` ENUM('UNRATED', 'RATED', 'SKIPPED', 'FAILED') NOT NULL DEFAULT 'UNRATED',
|
||||
`payload` JSON NULL,
|
||||
`received_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
|
||||
UNIQUE INDEX `raw_cdrs_event_id_key`(`event_id`),
|
||||
INDEX `raw_cdrs_customer_id_started_at_idx`(`customer_id`, `started_at`),
|
||||
INDEX `raw_cdrs_vendor_id_started_at_idx`(`vendor_id`, `started_at`),
|
||||
INDEX `raw_cdrs_sip_code_idx`(`sip_code`),
|
||||
INDEX `raw_cdrs_rating_status_idx`(`rating_status`),
|
||||
UNIQUE INDEX `raw_cdrs_call_id_ended_at_key`(`call_id`, `ended_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `rated_cdrs` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`raw_cdr_id` VARCHAR(40) NOT NULL,
|
||||
`bill_sec` INTEGER NOT NULL,
|
||||
`customer_fee` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`vendor_cost` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`gross_profit` DECIMAL(20, 6) NOT NULL DEFAULT 0,
|
||||
`customer_rate` JSON NULL,
|
||||
`vendor_rate` JSON NULL,
|
||||
`rated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
|
||||
UNIQUE INDEX `rated_cdrs_raw_cdr_id_key`(`raw_cdr_id`),
|
||||
INDEX `rated_cdrs_rated_at_idx`(`rated_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `recordings` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`raw_cdr_id` VARCHAR(40) NULL,
|
||||
`storage_key` VARCHAR(255) NOT NULL,
|
||||
`storage_path` VARCHAR(500) NOT NULL,
|
||||
`sha256` CHAR(64) NULL,
|
||||
`bytes` BIGINT NOT NULL DEFAULT 0,
|
||||
`duration_sec` INTEGER NOT NULL DEFAULT 0,
|
||||
`status` ENUM('PENDING', 'READY', 'FAILED', 'DELETED') NOT NULL DEFAULT 'PENDING',
|
||||
`moved_at` DATETIME(3) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
|
||||
UNIQUE INDEX `recordings_raw_cdr_id_key`(`raw_cdr_id`),
|
||||
UNIQUE INDEX `recordings_storage_key_key`(`storage_key`),
|
||||
INDEX `recordings_status_created_at_idx`(`status`, `created_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `quality_sampling_rules` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(120) NOT NULL,
|
||||
`customer_id` VARCHAR(32) NULL,
|
||||
`line_group_id` VARCHAR(32) NULL,
|
||||
`ratio` DECIMAL(5, 2) NOT NULL,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`effective_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`expires_at` DATETIME(3) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
INDEX `quality_sampling_rules_customer_id_status_idx`(`customer_id`, `status`),
|
||||
INDEX `quality_sampling_rules_line_group_id_status_idx`(`line_group_id`, `status`),
|
||||
INDEX `quality_sampling_rules_deleted_at_idx`(`deleted_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `quality_reviews` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`recording_id` VARCHAR(40) NOT NULL,
|
||||
`reviewer_id` VARCHAR(32) NOT NULL,
|
||||
`score` INTEGER NULL,
|
||||
`result` ENUM('PASS', 'ISSUE', 'ESCALATED') NOT NULL,
|
||||
`issue_tags` JSON NULL,
|
||||
`notes` VARCHAR(1000) NULL,
|
||||
`reviewed_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
INDEX `quality_reviews_recording_id_idx`(`recording_id`),
|
||||
INDEX `quality_reviews_reviewer_id_reviewed_at_idx`(`reviewer_id`, `reviewed_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `users` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`username` VARCHAR(80) NOT NULL,
|
||||
`display_name` VARCHAR(80) NOT NULL,
|
||||
`phone` VARCHAR(32) NULL,
|
||||
`email` VARCHAR(160) NULL,
|
||||
`password_hash` VARCHAR(255) NULL,
|
||||
`password_algo` VARCHAR(32) NULL,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`failed_login_count` INTEGER NOT NULL DEFAULT 0,
|
||||
`locked_until` DATETIME(3) NULL,
|
||||
`require_password_change` BOOLEAN NOT NULL DEFAULT false,
|
||||
`last_login_at` DATETIME(3) NULL,
|
||||
`last_login_ip` VARCHAR(45) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
UNIQUE INDEX `users_username_key`(`username`),
|
||||
UNIQUE INDEX `users_email_key`(`email`),
|
||||
INDEX `users_status_idx`(`status`),
|
||||
INDEX `users_deleted_at_idx`(`deleted_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `roles` (
|
||||
`id` VARCHAR(32) NOT NULL,
|
||||
`name` VARCHAR(80) NOT NULL,
|
||||
`description` VARCHAR(300) NULL,
|
||||
`built_in` BOOLEAN NOT NULL DEFAULT false,
|
||||
`status` ENUM('ENABLED', 'DISABLED') NOT NULL DEFAULT 'ENABLED',
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
`updated_by` VARCHAR(32) NULL,
|
||||
`version` INTEGER NOT NULL DEFAULT 1,
|
||||
`deleted_at` DATETIME(3) NULL,
|
||||
|
||||
UNIQUE INDEX `roles_name_key`(`name`),
|
||||
INDEX `roles_status_idx`(`status`),
|
||||
INDEX `roles_deleted_at_idx`(`deleted_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `permissions` (
|
||||
`id` VARCHAR(80) NOT NULL,
|
||||
`module` VARCHAR(80) NOT NULL,
|
||||
`action` VARCHAR(80) NOT NULL,
|
||||
`description` VARCHAR(300) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
|
||||
UNIQUE INDEX `permissions_module_action_key`(`module`, `action`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `user_roles` (
|
||||
`user_id` VARCHAR(32) NOT NULL,
|
||||
`role_id` VARCHAR(32) NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
|
||||
INDEX `user_roles_role_id_idx`(`role_id`),
|
||||
PRIMARY KEY (`user_id`, `role_id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `role_permissions` (
|
||||
`role_id` VARCHAR(32) NOT NULL,
|
||||
`permission_id` VARCHAR(80) NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`created_by` VARCHAR(32) NULL,
|
||||
|
||||
INDEX `role_permissions_permission_id_idx`(`permission_id`),
|
||||
PRIMARY KEY (`role_id`, `permission_id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `audit_logs` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`request_id` VARCHAR(64) NOT NULL,
|
||||
`user_id` VARCHAR(32) NULL,
|
||||
`username` VARCHAR(80) NULL,
|
||||
`role_names` VARCHAR(300) NULL,
|
||||
`ip` VARCHAR(45) NULL,
|
||||
`user_agent` VARCHAR(500) NULL,
|
||||
`module` VARCHAR(80) NOT NULL,
|
||||
`action` VARCHAR(80) NOT NULL,
|
||||
`object_type` VARCHAR(80) NOT NULL,
|
||||
`object_id` VARCHAR(80) NULL,
|
||||
`before_summary` JSON NULL,
|
||||
`after_summary` JSON NULL,
|
||||
`result` ENUM('SUCCESS', 'FAILURE') NOT NULL,
|
||||
`error_code` VARCHAR(80) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
|
||||
INDEX `audit_logs_user_id_created_at_idx`(`user_id`, `created_at`),
|
||||
INDEX `audit_logs_module_action_created_at_idx`(`module`, `action`, `created_at`),
|
||||
INDEX `audit_logs_object_type_object_id_idx`(`object_type`, `object_id`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `outbox_events` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`aggregate_type` VARCHAR(80) NOT NULL,
|
||||
`aggregate_id` VARCHAR(80) NOT NULL,
|
||||
`event_type` VARCHAR(120) NOT NULL,
|
||||
`payload` JSON NOT NULL,
|
||||
`status` ENUM('PENDING', 'PROCESSING', 'PUBLISHED', 'FAILED') NOT NULL DEFAULT 'PENDING',
|
||||
`attempts` INTEGER NOT NULL DEFAULT 0,
|
||||
`available_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`locked_at` DATETIME(3) NULL,
|
||||
`processed_at` DATETIME(3) NULL,
|
||||
`last_error` VARCHAR(1000) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
|
||||
INDEX `outbox_events_status_available_at_idx`(`status`, `available_at`),
|
||||
INDEX `outbox_events_aggregate_type_aggregate_id_idx`(`aggregate_type`, `aggregate_id`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE `idempotency_keys` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`key` VARCHAR(128) NOT NULL,
|
||||
`scope` VARCHAR(80) NOT NULL,
|
||||
`request_hash` CHAR(64) NOT NULL,
|
||||
`response_status` INTEGER NULL,
|
||||
`response_body` JSON NULL,
|
||||
`status` ENUM('IN_PROGRESS', 'SUCCEEDED', 'FAILED', 'EXPIRED') NOT NULL DEFAULT 'IN_PROGRESS',
|
||||
`locked_until` DATETIME(3) NULL,
|
||||
`expires_at` DATETIME(3) NOT NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL,
|
||||
|
||||
UNIQUE INDEX `idempotency_keys_key_key`(`key`),
|
||||
INDEX `idempotency_keys_scope_status_idx`(`scope`, `status`),
|
||||
INDEX `idempotency_keys_expires_at_idx`(`expires_at`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `customer_gateways` ADD CONSTRAINT `customer_gateways_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `customer_gateway_policies` ADD CONSTRAINT `customer_gateway_policies_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `customer_gateway_policies` ADD CONSTRAINT `customer_gateway_policies_gateway_id_fkey` FOREIGN KEY (`gateway_id`) REFERENCES `customer_gateways`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `customer_gateway_policies` ADD CONSTRAINT `customer_gateway_policies_line_group_id_fkey` FOREIGN KEY (`line_group_id`) REFERENCES `landing_line_groups`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `customer_recharges` ADD CONSTRAINT `customer_recharges_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `vendor_recharges` ADD CONSTRAINT `vendor_recharges_vendor_id_fkey` FOREIGN KEY (`vendor_id`) REFERENCES `vendors`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `vendor_gateways` ADD CONSTRAINT `vendor_gateways_vendor_id_fkey` FOREIGN KEY (`vendor_id`) REFERENCES `vendors`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `vendor_gateway_forbidden_periods` ADD CONSTRAINT `vendor_gateway_forbidden_periods_vendor_gateway_id_fkey` FOREIGN KEY (`vendor_gateway_id`) REFERENCES `vendor_gateways`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `vendor_gateway_codecs` ADD CONSTRAINT `vendor_gateway_codecs_vendor_gateway_id_fkey` FOREIGN KEY (`vendor_gateway_id`) REFERENCES `vendor_gateways`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `vendor_gateway_prefix_rules` ADD CONSTRAINT `vendor_gateway_prefix_rules_vendor_gateway_id_fkey` FOREIGN KEY (`vendor_gateway_id`) REFERENCES `vendor_gateways`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `landing_line_group_items` ADD CONSTRAINT `landing_line_group_items_line_group_id_fkey` FOREIGN KEY (`line_group_id`) REFERENCES `landing_line_groups`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `landing_line_group_items` ADD CONSTRAINT `landing_line_group_items_vendor_gateway_id_fkey` FOREIGN KEY (`vendor_gateway_id`) REFERENCES `vendor_gateways`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `raw_cdrs` ADD CONSTRAINT `raw_cdrs_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `raw_cdrs` ADD CONSTRAINT `raw_cdrs_customer_gateway_id_fkey` FOREIGN KEY (`customer_gateway_id`) REFERENCES `customer_gateways`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `raw_cdrs` ADD CONSTRAINT `raw_cdrs_customer_gateway_policy_id_fkey` FOREIGN KEY (`customer_gateway_policy_id`) REFERENCES `customer_gateway_policies`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `raw_cdrs` ADD CONSTRAINT `raw_cdrs_vendor_id_fkey` FOREIGN KEY (`vendor_id`) REFERENCES `vendors`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `raw_cdrs` ADD CONSTRAINT `raw_cdrs_vendor_gateway_id_fkey` FOREIGN KEY (`vendor_gateway_id`) REFERENCES `vendor_gateways`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `raw_cdrs` ADD CONSTRAINT `raw_cdrs_line_group_id_fkey` FOREIGN KEY (`line_group_id`) REFERENCES `landing_line_groups`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `rated_cdrs` ADD CONSTRAINT `rated_cdrs_raw_cdr_id_fkey` FOREIGN KEY (`raw_cdr_id`) REFERENCES `raw_cdrs`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `recordings` ADD CONSTRAINT `recordings_raw_cdr_id_fkey` FOREIGN KEY (`raw_cdr_id`) REFERENCES `raw_cdrs`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `quality_sampling_rules` ADD CONSTRAINT `quality_sampling_rules_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `quality_sampling_rules` ADD CONSTRAINT `quality_sampling_rules_line_group_id_fkey` FOREIGN KEY (`line_group_id`) REFERENCES `landing_line_groups`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `quality_reviews` ADD CONSTRAINT `quality_reviews_recording_id_fkey` FOREIGN KEY (`recording_id`) REFERENCES `recordings`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `quality_reviews` ADD CONSTRAINT `quality_reviews_reviewer_id_fkey` FOREIGN KEY (`reviewer_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_role_id_fkey` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `role_permissions` ADD CONSTRAINT `role_permissions_role_id_fkey` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE `role_permissions` ADD CONSTRAINT `role_permissions_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
-- S09 login authentication session table.
|
||||
-- Forward-only additive migration: no existing table or column is modified.
|
||||
|
||||
CREATE TABLE `user_sessions` (
|
||||
`id` VARCHAR(40) NOT NULL,
|
||||
`user_id` VARCHAR(32) NOT NULL,
|
||||
`refresh_token_hash` CHAR(64) NOT NULL,
|
||||
`user_agent` VARCHAR(500) NULL,
|
||||
`ip` VARCHAR(45) NULL,
|
||||
`expires_at` DATETIME(3) NOT NULL,
|
||||
`revoked_at` DATETIME(3) NULL,
|
||||
`rotated_from_id` VARCHAR(40) NULL,
|
||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
`updated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `user_sessions_refresh_token_hash_key` (`refresh_token_hash`),
|
||||
INDEX `user_sessions_user_id_created_at_idx` (`user_id`, `created_at`),
|
||||
INDEX `user_sessions_expires_at_idx` (`expires_at`),
|
||||
INDEX `user_sessions_revoked_at_idx` (`revoked_at`),
|
||||
CONSTRAINT `user_sessions_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
@@ -0,0 +1,699 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "mysql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum EntityStatus {
|
||||
ENABLED
|
||||
DISABLED
|
||||
|
||||
@@map("entity_status")
|
||||
}
|
||||
|
||||
enum CustomerBillingMode {
|
||||
PREPAID
|
||||
POSTPAID
|
||||
|
||||
@@map("customer_billing_mode")
|
||||
}
|
||||
|
||||
enum GatewayAuthMode {
|
||||
IP
|
||||
SIP_DIGEST
|
||||
MIXED
|
||||
|
||||
@@map("gateway_auth_mode")
|
||||
}
|
||||
|
||||
enum MatchMode {
|
||||
ANY
|
||||
EQUALS
|
||||
PREFIX
|
||||
|
||||
@@map("match_mode")
|
||||
}
|
||||
|
||||
enum RechargeStatus {
|
||||
SUCCEEDED
|
||||
FAILED
|
||||
REVERSED
|
||||
|
||||
@@map("recharge_status")
|
||||
}
|
||||
|
||||
enum PrefixRuleDirection {
|
||||
CALLER
|
||||
CALLEE
|
||||
|
||||
@@map("prefix_rule_direction")
|
||||
}
|
||||
|
||||
enum CdrRatingStatus {
|
||||
UNRATED
|
||||
RATED
|
||||
SKIPPED
|
||||
FAILED
|
||||
|
||||
@@map("cdr_rating_status")
|
||||
}
|
||||
|
||||
enum RecordingStatus {
|
||||
PENDING
|
||||
READY
|
||||
FAILED
|
||||
DELETED
|
||||
|
||||
@@map("recording_status")
|
||||
}
|
||||
|
||||
enum QualityReviewResult {
|
||||
PASS
|
||||
ISSUE
|
||||
ESCALATED
|
||||
|
||||
@@map("quality_review_result")
|
||||
}
|
||||
|
||||
enum AuditResult {
|
||||
SUCCESS
|
||||
FAILURE
|
||||
|
||||
@@map("audit_result")
|
||||
}
|
||||
|
||||
enum OutboxStatus {
|
||||
PENDING
|
||||
PROCESSING
|
||||
PUBLISHED
|
||||
FAILED
|
||||
|
||||
@@map("outbox_status")
|
||||
}
|
||||
|
||||
enum IdempotencyStatus {
|
||||
IN_PROGRESS
|
||||
SUCCEEDED
|
||||
FAILED
|
||||
EXPIRED
|
||||
|
||||
@@map("idempotency_status")
|
||||
}
|
||||
|
||||
model Customer {
|
||||
id String @id @db.VarChar(32)
|
||||
name String @unique @db.VarChar(120)
|
||||
contactName String? @map("contact_name") @db.VarChar(80)
|
||||
phone String? @db.VarChar(32)
|
||||
email String? @db.VarChar(160)
|
||||
domain String? @unique @db.VarChar(160)
|
||||
status EntityStatus @default(ENABLED)
|
||||
billingMode CustomerBillingMode @default(PREPAID) @map("billing_mode")
|
||||
balance Decimal @default(0) @db.Decimal(20, 6)
|
||||
creditLimit Decimal @default(0) @map("credit_limit") @db.Decimal(20, 6)
|
||||
minBalance Decimal @default(0) @map("min_balance") @db.Decimal(20, 6)
|
||||
notes String? @db.VarChar(500)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
gateways CustomerGateway[]
|
||||
policies CustomerGatewayPolicy[]
|
||||
recharges CustomerRecharge[]
|
||||
rawCdrs RawCdr[]
|
||||
samplingRules QualitySamplingRule[]
|
||||
|
||||
@@index([status])
|
||||
@@index([deletedAt])
|
||||
@@map("customers")
|
||||
}
|
||||
|
||||
model CustomerGateway {
|
||||
id String @id @db.VarChar(32)
|
||||
customerId String @map("customer_id") @db.VarChar(32)
|
||||
name String @db.VarChar(120)
|
||||
authMode GatewayAuthMode @map("auth_mode")
|
||||
sourceIp String? @map("source_ip") @db.VarChar(45)
|
||||
sipUsername String? @map("sip_username") @db.VarChar(120)
|
||||
sipDomain String? @map("sip_domain") @db.VarChar(160)
|
||||
sipHa1 String? @map("sip_ha1") @db.VarChar(128)
|
||||
status EntityStatus @default(ENABLED)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
customer Customer @relation(fields: [customerId], references: [id], onDelete: Restrict)
|
||||
policies CustomerGatewayPolicy[]
|
||||
rawCdrs RawCdr[]
|
||||
|
||||
@@unique([customerId, name])
|
||||
@@unique([sipUsername, sipDomain])
|
||||
@@index([customerId, status])
|
||||
@@index([sourceIp])
|
||||
@@index([deletedAt])
|
||||
@@map("customer_gateways")
|
||||
}
|
||||
|
||||
model CustomerGatewayPolicy {
|
||||
id String @id @db.VarChar(32)
|
||||
customerId String @map("customer_id") @db.VarChar(32)
|
||||
gatewayId String @map("gateway_id") @db.VarChar(32)
|
||||
lineGroupId String @map("line_group_id") @db.VarChar(32)
|
||||
name String @db.VarChar(120)
|
||||
priority Int
|
||||
callerMode MatchMode @default(ANY) @map("caller_mode")
|
||||
callerValue String? @map("caller_value") @db.VarChar(64)
|
||||
calleeMode MatchMode @default(ANY) @map("callee_mode")
|
||||
calleeValue String? @map("callee_value") @db.VarChar(64)
|
||||
status EntityStatus @default(ENABLED)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
customer Customer @relation(fields: [customerId], references: [id], onDelete: Restrict)
|
||||
gateway CustomerGateway @relation(fields: [gatewayId], references: [id], onDelete: Restrict)
|
||||
lineGroup LandingLineGroup @relation(fields: [lineGroupId], references: [id], onDelete: Restrict)
|
||||
rawCdrs RawCdr[]
|
||||
|
||||
@@unique([gatewayId, priority])
|
||||
@@index([customerId, status])
|
||||
@@index([lineGroupId])
|
||||
@@index([deletedAt])
|
||||
@@map("customer_gateway_policies")
|
||||
}
|
||||
|
||||
model CustomerRecharge {
|
||||
id String @id @db.VarChar(40)
|
||||
customerId String @map("customer_id") @db.VarChar(32)
|
||||
amount Decimal @db.Decimal(20, 6)
|
||||
beforeBalance Decimal @map("before_balance") @db.Decimal(20, 6)
|
||||
afterBalance Decimal @map("after_balance") @db.Decimal(20, 6)
|
||||
idempotencyKey String @unique @map("idempotency_key") @db.VarChar(128)
|
||||
remark String? @db.VarChar(500)
|
||||
status RechargeStatus @default(SUCCEEDED)
|
||||
occurredAt DateTime @default(now()) @map("occurred_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
|
||||
customer Customer @relation(fields: [customerId], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([customerId, occurredAt])
|
||||
@@map("customer_recharges")
|
||||
}
|
||||
|
||||
model Vendor {
|
||||
id String @id @db.VarChar(32)
|
||||
name String @unique @db.VarChar(120)
|
||||
contactName String? @map("contact_name") @db.VarChar(80)
|
||||
phone String? @db.VarChar(32)
|
||||
email String? @db.VarChar(160)
|
||||
status EntityStatus @default(ENABLED)
|
||||
balance Decimal @default(0) @db.Decimal(20, 6)
|
||||
creditLimit Decimal @default(0) @map("credit_limit") @db.Decimal(20, 6)
|
||||
settlement String? @db.VarChar(80)
|
||||
notes String? @db.VarChar(500)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
gateways VendorGateway[]
|
||||
recharges VendorRecharge[]
|
||||
rawCdrs RawCdr[]
|
||||
|
||||
@@index([status])
|
||||
@@index([deletedAt])
|
||||
@@map("vendors")
|
||||
}
|
||||
|
||||
model VendorRecharge {
|
||||
id String @id @db.VarChar(40)
|
||||
vendorId String @map("vendor_id") @db.VarChar(32)
|
||||
amount Decimal @db.Decimal(20, 6)
|
||||
beforeBalance Decimal @map("before_balance") @db.Decimal(20, 6)
|
||||
afterBalance Decimal @map("after_balance") @db.Decimal(20, 6)
|
||||
idempotencyKey String @unique @map("idempotency_key") @db.VarChar(128)
|
||||
remark String? @db.VarChar(500)
|
||||
status RechargeStatus @default(SUCCEEDED)
|
||||
occurredAt DateTime @default(now()) @map("occurred_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
|
||||
vendor Vendor @relation(fields: [vendorId], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([vendorId, occurredAt])
|
||||
@@map("vendor_recharges")
|
||||
}
|
||||
|
||||
model VendorGateway {
|
||||
id String @id @db.VarChar(32)
|
||||
vendorId String @map("vendor_id") @db.VarChar(32)
|
||||
name String @db.VarChar(120)
|
||||
authMode GatewayAuthMode @map("auth_mode")
|
||||
host String @db.VarChar(160)
|
||||
port Int @default(5060)
|
||||
transport String @default("udp") @db.VarChar(16)
|
||||
sipUsername String? @map("sip_username") @db.VarChar(120)
|
||||
sipHa1 String? @map("sip_ha1") @db.VarChar(128)
|
||||
cpsLimit Int @default(0) @map("cps_limit")
|
||||
concurrencyLimit Int @default(0) @map("concurrency_limit")
|
||||
billingCycleSec Int @default(60) @map("billing_cycle_sec")
|
||||
cycleRate Decimal @default(0) @map("cycle_rate") @db.Decimal(20, 6)
|
||||
status EntityStatus @default(ENABLED)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
vendor Vendor @relation(fields: [vendorId], references: [id], onDelete: Restrict)
|
||||
forbiddenPeriods VendorGatewayForbiddenPeriod[]
|
||||
codecs VendorGatewayCodec[]
|
||||
prefixRules VendorGatewayPrefixRule[]
|
||||
lineGroupItems LandingLineGroupItem[]
|
||||
rawCdrs RawCdr[]
|
||||
|
||||
@@unique([vendorId, name])
|
||||
@@index([vendorId, status])
|
||||
@@index([host])
|
||||
@@index([deletedAt])
|
||||
@@map("vendor_gateways")
|
||||
}
|
||||
|
||||
model VendorGatewayForbiddenPeriod {
|
||||
id String @id @db.VarChar(32)
|
||||
vendorGatewayId String @map("vendor_gateway_id") @db.VarChar(32)
|
||||
weekdayMask Int @map("weekday_mask")
|
||||
startTime String @map("start_time") @db.VarChar(8)
|
||||
endTime String @map("end_time") @db.VarChar(8)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
|
||||
vendorGateway VendorGateway @relation(fields: [vendorGatewayId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([vendorGatewayId])
|
||||
@@map("vendor_gateway_forbidden_periods")
|
||||
}
|
||||
|
||||
model VendorGatewayCodec {
|
||||
id String @id @db.VarChar(32)
|
||||
vendorGatewayId String @map("vendor_gateway_id") @db.VarChar(32)
|
||||
codec String @db.VarChar(32)
|
||||
priority Int
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
|
||||
vendorGateway VendorGateway @relation(fields: [vendorGatewayId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([vendorGatewayId, codec])
|
||||
@@unique([vendorGatewayId, priority])
|
||||
@@map("vendor_gateway_codecs")
|
||||
}
|
||||
|
||||
model VendorGatewayPrefixRule {
|
||||
id String @id @db.VarChar(32)
|
||||
vendorGatewayId String @map("vendor_gateway_id") @db.VarChar(32)
|
||||
direction PrefixRuleDirection
|
||||
matchPrefix String @map("match_prefix") @db.VarChar(32)
|
||||
replacePrefix String @map("replace_prefix") @db.VarChar(32)
|
||||
priority Int
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
|
||||
vendorGateway VendorGateway @relation(fields: [vendorGatewayId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([vendorGatewayId, direction, priority])
|
||||
@@index([vendorGatewayId, direction])
|
||||
@@map("vendor_gateway_prefix_rules")
|
||||
}
|
||||
|
||||
model LandingLineGroup {
|
||||
id String @id @db.VarChar(32)
|
||||
name String @unique @db.VarChar(120)
|
||||
status EntityStatus @default(ENABLED)
|
||||
notes String? @db.VarChar(500)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
items LandingLineGroupItem[]
|
||||
policies CustomerGatewayPolicy[]
|
||||
rawCdrs RawCdr[]
|
||||
rules QualitySamplingRule[]
|
||||
|
||||
@@index([status])
|
||||
@@index([deletedAt])
|
||||
@@map("landing_line_groups")
|
||||
}
|
||||
|
||||
model LandingLineGroupItem {
|
||||
id String @id @db.VarChar(32)
|
||||
lineGroupId String @map("line_group_id") @db.VarChar(32)
|
||||
vendorGatewayId String @map("vendor_gateway_id") @db.VarChar(32)
|
||||
priority Int
|
||||
weight Int @default(1)
|
||||
concurrencyCap Int @default(0) @map("concurrency_cap")
|
||||
status EntityStatus @default(ENABLED)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
|
||||
lineGroup LandingLineGroup @relation(fields: [lineGroupId], references: [id], onDelete: Cascade)
|
||||
vendorGateway VendorGateway @relation(fields: [vendorGatewayId], references: [id], onDelete: Restrict)
|
||||
|
||||
@@unique([lineGroupId, vendorGatewayId])
|
||||
@@unique([lineGroupId, priority])
|
||||
@@index([vendorGatewayId])
|
||||
@@map("landing_line_group_items")
|
||||
}
|
||||
|
||||
model RawCdr {
|
||||
id String @id @db.VarChar(40)
|
||||
eventId String @unique @map("event_id") @db.VarChar(64)
|
||||
callId String @map("call_id") @db.VarChar(255)
|
||||
customerId String? @map("customer_id") @db.VarChar(32)
|
||||
customerGatewayId String? @map("customer_gateway_id") @db.VarChar(32)
|
||||
customerGatewayPolicyId String? @map("customer_gateway_policy_id") @db.VarChar(32)
|
||||
sourceIp String? @map("source_ip") @db.VarChar(45)
|
||||
caller String @db.VarChar(64)
|
||||
callee String @db.VarChar(64)
|
||||
vendorId String? @map("vendor_id") @db.VarChar(32)
|
||||
vendorGatewayId String? @map("vendor_gateway_id") @db.VarChar(32)
|
||||
lineGroupId String? @map("line_group_id") @db.VarChar(32)
|
||||
startedAt DateTime @map("started_at") @db.DateTime(3)
|
||||
answeredAt DateTime? @map("answered_at") @db.DateTime(3)
|
||||
endedAt DateTime @map("ended_at") @db.DateTime(3)
|
||||
durationSec Int @default(0) @map("duration_sec")
|
||||
sipCode Int @map("sip_code")
|
||||
hangupReason String? @map("hangup_reason") @db.VarChar(120)
|
||||
recordingKey String? @map("recording_key") @db.VarChar(255)
|
||||
configVersion Int? @map("config_version")
|
||||
ratingStatus CdrRatingStatus @default(UNRATED) @map("rating_status")
|
||||
payload Json?
|
||||
receivedAt DateTime @default(now()) @map("received_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
|
||||
customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull)
|
||||
customerGateway CustomerGateway? @relation(fields: [customerGatewayId], references: [id], onDelete: SetNull)
|
||||
customerGatewayPolicy CustomerGatewayPolicy? @relation(fields: [customerGatewayPolicyId], references: [id], onDelete: SetNull)
|
||||
vendor Vendor? @relation(fields: [vendorId], references: [id], onDelete: SetNull)
|
||||
vendorGateway VendorGateway? @relation(fields: [vendorGatewayId], references: [id], onDelete: SetNull)
|
||||
lineGroup LandingLineGroup? @relation(fields: [lineGroupId], references: [id], onDelete: SetNull)
|
||||
ratedCdr RatedCdr?
|
||||
recording Recording?
|
||||
|
||||
@@unique([callId, endedAt])
|
||||
@@index([customerId, startedAt])
|
||||
@@index([vendorId, startedAt])
|
||||
@@index([sipCode])
|
||||
@@index([ratingStatus])
|
||||
@@map("raw_cdrs")
|
||||
}
|
||||
|
||||
model RatedCdr {
|
||||
id String @id @db.VarChar(40)
|
||||
rawCdrId String @unique @map("raw_cdr_id") @db.VarChar(40)
|
||||
billSec Int @map("bill_sec")
|
||||
customerFee Decimal @default(0) @map("customer_fee") @db.Decimal(20, 6)
|
||||
vendorCost Decimal @default(0) @map("vendor_cost") @db.Decimal(20, 6)
|
||||
grossProfit Decimal @default(0) @map("gross_profit") @db.Decimal(20, 6)
|
||||
customerRate Json? @map("customer_rate")
|
||||
vendorRate Json? @map("vendor_rate")
|
||||
ratedAt DateTime @default(now()) @map("rated_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
|
||||
rawCdr RawCdr @relation(fields: [rawCdrId], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([ratedAt])
|
||||
@@map("rated_cdrs")
|
||||
}
|
||||
|
||||
model Recording {
|
||||
id String @id @db.VarChar(40)
|
||||
rawCdrId String? @unique @map("raw_cdr_id") @db.VarChar(40)
|
||||
storageKey String @unique @map("storage_key") @db.VarChar(255)
|
||||
storagePath String @map("storage_path") @db.VarChar(500)
|
||||
sha256 String? @db.Char(64)
|
||||
bytes BigInt @default(0)
|
||||
durationSec Int @default(0) @map("duration_sec")
|
||||
status RecordingStatus @default(PENDING)
|
||||
movedAt DateTime? @map("moved_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
|
||||
rawCdr RawCdr? @relation(fields: [rawCdrId], references: [id], onDelete: SetNull)
|
||||
reviews QualityReview[]
|
||||
|
||||
@@index([status, createdAt])
|
||||
@@map("recordings")
|
||||
}
|
||||
|
||||
model QualitySamplingRule {
|
||||
id String @id @db.VarChar(32)
|
||||
name String @db.VarChar(120)
|
||||
customerId String? @map("customer_id") @db.VarChar(32)
|
||||
lineGroupId String? @map("line_group_id") @db.VarChar(32)
|
||||
ratio Decimal @db.Decimal(5, 2)
|
||||
status EntityStatus @default(ENABLED)
|
||||
effectiveAt DateTime @default(now()) @map("effective_at") @db.DateTime(3)
|
||||
expiresAt DateTime? @map("expires_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull)
|
||||
lineGroup LandingLineGroup? @relation(fields: [lineGroupId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([customerId, status])
|
||||
@@index([lineGroupId, status])
|
||||
@@index([deletedAt])
|
||||
@@map("quality_sampling_rules")
|
||||
}
|
||||
|
||||
model QualityReview {
|
||||
id String @id @db.VarChar(40)
|
||||
recordingId String @map("recording_id") @db.VarChar(40)
|
||||
reviewerId String @map("reviewer_id") @db.VarChar(32)
|
||||
score Int?
|
||||
result QualityReviewResult
|
||||
issueTags Json? @map("issue_tags")
|
||||
notes String? @db.VarChar(1000)
|
||||
reviewedAt DateTime @default(now()) @map("reviewed_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
version Int @default(1)
|
||||
|
||||
recording Recording @relation(fields: [recordingId], references: [id], onDelete: Restrict)
|
||||
reviewer User @relation(fields: [reviewerId], references: [id], onDelete: Restrict)
|
||||
|
||||
@@index([recordingId])
|
||||
@@index([reviewerId, reviewedAt])
|
||||
@@map("quality_reviews")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @db.VarChar(32)
|
||||
username String @unique @db.VarChar(80)
|
||||
displayName String @map("display_name") @db.VarChar(80)
|
||||
phone String? @db.VarChar(32)
|
||||
email String? @unique @db.VarChar(160)
|
||||
passwordHash String? @map("password_hash") @db.VarChar(255)
|
||||
passwordAlgo String? @map("password_algo") @db.VarChar(32)
|
||||
status EntityStatus @default(ENABLED)
|
||||
failedLoginCount Int @default(0) @map("failed_login_count")
|
||||
lockedUntil DateTime? @map("locked_until") @db.DateTime(3)
|
||||
requirePasswordChange Boolean @default(false) @map("require_password_change")
|
||||
lastLoginAt DateTime? @map("last_login_at") @db.DateTime(3)
|
||||
lastLoginIp String? @map("last_login_ip") @db.VarChar(45)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
userRoles UserRole[]
|
||||
qualityReviews QualityReview[]
|
||||
sessions UserSession[]
|
||||
|
||||
@@index([status])
|
||||
@@index([deletedAt])
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model UserSession {
|
||||
id String @id @db.VarChar(40)
|
||||
userId String @map("user_id") @db.VarChar(32)
|
||||
refreshTokenHash String @unique @map("refresh_token_hash") @db.Char(64)
|
||||
userAgent String? @map("user_agent") @db.VarChar(500)
|
||||
ip String? @db.VarChar(45)
|
||||
expiresAt DateTime @map("expires_at") @db.DateTime(3)
|
||||
revokedAt DateTime? @map("revoked_at") @db.DateTime(3)
|
||||
rotatedFromId String? @map("rotated_from_id") @db.VarChar(40)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId, createdAt])
|
||||
@@index([expiresAt])
|
||||
@@index([revokedAt])
|
||||
@@map("user_sessions")
|
||||
}
|
||||
|
||||
model Role {
|
||||
id String @id @db.VarChar(32)
|
||||
name String @unique @db.VarChar(80)
|
||||
description String? @db.VarChar(300)
|
||||
builtIn Boolean @default(false) @map("built_in")
|
||||
status EntityStatus @default(ENABLED)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
updatedBy String? @map("updated_by") @db.VarChar(32)
|
||||
version Int @default(1)
|
||||
deletedAt DateTime? @map("deleted_at") @db.DateTime(3)
|
||||
|
||||
userRoles UserRole[]
|
||||
permissions RolePermission[]
|
||||
|
||||
@@index([status])
|
||||
@@index([deletedAt])
|
||||
@@map("roles")
|
||||
}
|
||||
|
||||
model Permission {
|
||||
id String @id @db.VarChar(80)
|
||||
module String @db.VarChar(80)
|
||||
action String @db.VarChar(80)
|
||||
description String? @db.VarChar(300)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
|
||||
roles RolePermission[]
|
||||
|
||||
@@unique([module, action])
|
||||
@@map("permissions")
|
||||
}
|
||||
|
||||
model UserRole {
|
||||
userId String @map("user_id") @db.VarChar(32)
|
||||
roleId String @map("role_id") @db.VarChar(32)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([userId, roleId])
|
||||
@@index([roleId])
|
||||
@@map("user_roles")
|
||||
}
|
||||
|
||||
model RolePermission {
|
||||
roleId String @map("role_id") @db.VarChar(32)
|
||||
permissionId String @map("permission_id") @db.VarChar(80)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
createdBy String? @map("created_by") @db.VarChar(32)
|
||||
|
||||
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
||||
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([roleId, permissionId])
|
||||
@@index([permissionId])
|
||||
@@map("role_permissions")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @db.VarChar(40)
|
||||
requestId String @map("request_id") @db.VarChar(64)
|
||||
userId String? @map("user_id") @db.VarChar(32)
|
||||
username String? @db.VarChar(80)
|
||||
roleNames String? @map("role_names") @db.VarChar(300)
|
||||
ip String? @db.VarChar(45)
|
||||
userAgent String? @map("user_agent") @db.VarChar(500)
|
||||
module String @db.VarChar(80)
|
||||
action String @db.VarChar(80)
|
||||
objectType String @map("object_type") @db.VarChar(80)
|
||||
objectId String? @map("object_id") @db.VarChar(80)
|
||||
beforeSummary Json? @map("before_summary")
|
||||
afterSummary Json? @map("after_summary")
|
||||
result AuditResult
|
||||
errorCode String? @map("error_code") @db.VarChar(80)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
|
||||
@@index([userId, createdAt])
|
||||
@@index([module, action, createdAt])
|
||||
@@index([objectType, objectId])
|
||||
@@map("audit_logs")
|
||||
}
|
||||
|
||||
model OutboxEvent {
|
||||
id String @id @db.VarChar(40)
|
||||
aggregateType String @map("aggregate_type") @db.VarChar(80)
|
||||
aggregateId String @map("aggregate_id") @db.VarChar(80)
|
||||
eventType String @map("event_type") @db.VarChar(120)
|
||||
payload Json
|
||||
status OutboxStatus @default(PENDING)
|
||||
attempts Int @default(0)
|
||||
availableAt DateTime @default(now()) @map("available_at") @db.DateTime(3)
|
||||
lockedAt DateTime? @map("locked_at") @db.DateTime(3)
|
||||
processedAt DateTime? @map("processed_at") @db.DateTime(3)
|
||||
lastError String? @map("last_error") @db.VarChar(1000)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
|
||||
@@index([status, availableAt])
|
||||
@@index([aggregateType, aggregateId])
|
||||
@@map("outbox_events")
|
||||
}
|
||||
|
||||
model IdempotencyKey {
|
||||
id String @id @db.VarChar(40)
|
||||
key String @unique @db.VarChar(128)
|
||||
scope String @db.VarChar(80)
|
||||
requestHash String @map("request_hash") @db.Char(64)
|
||||
responseStatus Int? @map("response_status")
|
||||
responseBody Json? @map("response_body")
|
||||
status IdempotencyStatus @default(IN_PROGRESS)
|
||||
lockedUntil DateTime? @map("locked_until") @db.DateTime(3)
|
||||
expiresAt DateTime @map("expires_at") @db.DateTime(3)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.DateTime(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.DateTime(3)
|
||||
|
||||
@@index([scope, status])
|
||||
@@index([expiresAt])
|
||||
@@map("idempotency_keys")
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const permissions = [
|
||||
['dashboard.view', 'dashboard', 'view', '查看 Dashboard 指标'],
|
||||
['customers.view', 'customers', 'view', '查看客户'],
|
||||
['customers.manage', 'customers', 'manage', '管理客户'],
|
||||
['customer_gateways.view', 'customer_gateways', 'view', '查看客户网关'],
|
||||
['customer_gateways.manage', 'customer_gateways', 'manage', '管理客户网关和策略'],
|
||||
['vendors.view', 'vendors', 'view', '查看供应商'],
|
||||
['vendors.manage', 'vendors', 'manage', '管理供应商'],
|
||||
['vendor_gateways.view', 'vendor_gateways', 'view', '查看落地网关'],
|
||||
['vendor_gateways.manage', 'vendor_gateways', 'manage', '管理落地网关'],
|
||||
['line_groups.view', 'line_groups', 'view', '查看落地线路组'],
|
||||
['line_groups.manage', 'line_groups', 'manage', '管理落地线路组'],
|
||||
['recharges.view', 'recharges', 'view', '查看充值流水'],
|
||||
['recharges.manage', 'recharges', 'manage', '执行客户或供应商充值'],
|
||||
['cdr.view', 'cdr', 'view', '查看话单'],
|
||||
['recordings.play', 'recordings', 'play', '播放录音'],
|
||||
['quality.view', 'quality', 'view', '查看质检任务'],
|
||||
['quality.manage', 'quality', 'manage', '保存质检结果'],
|
||||
['users.view', 'users', 'view', '查看用户'],
|
||||
['users.manage', 'users', 'manage', '管理用户'],
|
||||
['roles.view', 'roles', 'view', '查看角色权限'],
|
||||
['roles.manage', 'roles', 'manage', '管理角色权限'],
|
||||
['audit.view', 'audit', 'view', '查看操作日志']
|
||||
] as const;
|
||||
|
||||
const roles = [
|
||||
{
|
||||
id: 'ROLE_SUPER_ADMIN',
|
||||
name: '超级管理员',
|
||||
description: '系统内置最高权限角色',
|
||||
permissionIds: permissions.map(([id]) => id)
|
||||
},
|
||||
{
|
||||
id: 'ROLE_OPERATOR',
|
||||
name: '运营管理员',
|
||||
description: '客户、网关、线路和话单运营',
|
||||
permissionIds: [
|
||||
'dashboard.view',
|
||||
'customers.view',
|
||||
'customers.manage',
|
||||
'customer_gateways.view',
|
||||
'customer_gateways.manage',
|
||||
'vendors.view',
|
||||
'vendor_gateways.view',
|
||||
'line_groups.view',
|
||||
'line_groups.manage',
|
||||
'cdr.view',
|
||||
'recordings.play'
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'ROLE_FINANCE',
|
||||
name: '财务',
|
||||
description: '充值、余额和财务流水',
|
||||
permissionIds: ['dashboard.view', 'customers.view', 'vendors.view', 'recharges.view', 'recharges.manage', 'cdr.view']
|
||||
},
|
||||
{
|
||||
id: 'ROLE_QUALITY',
|
||||
name: '质检',
|
||||
description: '录音抽检和质检结果维护',
|
||||
permissionIds: ['dashboard.view', 'cdr.view', 'recordings.play', 'quality.view', 'quality.manage']
|
||||
},
|
||||
{
|
||||
id: 'ROLE_TECH_OPS',
|
||||
name: '技术运维',
|
||||
description: '网关、线路、信令和审计排障',
|
||||
permissionIds: [
|
||||
'dashboard.view',
|
||||
'customer_gateways.view',
|
||||
'vendors.view',
|
||||
'vendor_gateways.view',
|
||||
'vendor_gateways.manage',
|
||||
'line_groups.view',
|
||||
'cdr.view',
|
||||
'recordings.play',
|
||||
'audit.view'
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
async function main(): Promise<void> {
|
||||
await prisma.$transaction(
|
||||
async (tx) => {
|
||||
for (const [id, module, action, description] of permissions) {
|
||||
await tx.permission.upsert({
|
||||
where: { id },
|
||||
update: { module, action, description },
|
||||
create: { id, module, action, description }
|
||||
});
|
||||
}
|
||||
|
||||
for (const role of roles) {
|
||||
await tx.role.upsert({
|
||||
where: { id: role.id },
|
||||
update: {
|
||||
name: role.name,
|
||||
description: role.description,
|
||||
builtIn: true,
|
||||
status: 'ENABLED'
|
||||
},
|
||||
create: {
|
||||
id: role.id,
|
||||
name: role.name,
|
||||
description: role.description,
|
||||
builtIn: true,
|
||||
status: 'ENABLED'
|
||||
}
|
||||
});
|
||||
|
||||
for (const permissionId of role.permissionIds) {
|
||||
await tx.rolePermission.upsert({
|
||||
where: {
|
||||
roleId_permissionId: {
|
||||
roleId: role.id,
|
||||
permissionId
|
||||
}
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
roleId: role.id,
|
||||
permissionId
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
timeout: 30000
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
main()
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user