chore: 提交剩余开发改动
包含商务通消息映射、会话时间与未读状态、前端消息展示、数据库修复迁移、测试覆盖备份及 Captain 设计文档。
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
DROP INDEX IF EXISTS idx_channel_shangwutong_config_version;
|
||||
DROP INDEX IF EXISTS idx_channel_shangwutong_deleted_at;
|
||||
DROP INDEX IF EXISTS uq_channel_shangwutong_active_identity;
|
||||
DROP INDEX IF EXISTS idx_messages_swt_source;
|
||||
ALTER TABLE messages DROP COLUMN IF EXISTS external_request_hash;
|
||||
DROP TABLE IF EXISTS channel_shangwutong_configs;
|
||||
DROP TABLE IF EXISTS channel_api;
|
||||
@@ -0,0 +1,51 @@
|
||||
CREATE TABLE IF NOT EXISTS channel_api (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
inbox_id BIGINT NOT NULL UNIQUE REFERENCES inboxes(id) ON DELETE CASCADE,
|
||||
webhook_url VARCHAR(512),
|
||||
secret VARCHAR(255),
|
||||
hmac_token VARCHAR(255),
|
||||
hmac_mandatory BOOLEAN DEFAULT FALSE,
|
||||
additional_attributes JSONB DEFAULT '{}'::jsonb,
|
||||
identifier VARCHAR(255),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channel_shangwutong_configs (
|
||||
inbox_id BIGINT PRIMARY KEY REFERENCES inboxes(id) ON DELETE CASCADE,
|
||||
session_id VARCHAR(64) NOT NULL,
|
||||
username VARCHAR(255) NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
desired_presence VARCHAR(20) NOT NULL DEFAULT 'online',
|
||||
config_version BIGINT NOT NULL DEFAULT 1,
|
||||
actual_presence VARCHAR(20) NOT NULL DEFAULT 'offline',
|
||||
connection_status VARCHAR(40) NOT NULL DEFAULT 'pending',
|
||||
credential_status VARCHAR(40) NOT NULL DEFAULT 'pending',
|
||||
last_heartbeat_at TIMESTAMPTZ,
|
||||
last_error_code VARCHAR(255),
|
||||
status_updated_at TIMESTAMPTZ,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT ck_channel_shangwutong_desired_presence CHECK (desired_presence IN ('online', 'busy', 'away', 'offline')),
|
||||
CONSTRAINT ck_channel_shangwutong_actual_presence CHECK (actual_presence IN ('online', 'busy', 'away', 'offline')),
|
||||
CONSTRAINT ck_channel_shangwutong_connection_status CHECK (connection_status IN ('pending', 'logging_in', 'connected', 'degraded', 'relogin_required', 'verification_required', 'auth_failed', 'disabled', 'offline')),
|
||||
CONSTRAINT ck_channel_shangwutong_credential_status CHECK (credential_status IN ('pending', 'verifying', 'applied', 'rejected', 'verification_required'))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_channel_shangwutong_active_identity
|
||||
ON channel_shangwutong_configs(session_id, username)
|
||||
WHERE deleted_at IS NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_channel_shangwutong_deleted_at
|
||||
ON channel_shangwutong_configs(deleted_at);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_channel_shangwutong_config_version
|
||||
ON channel_shangwutong_configs(config_version, inbox_id);
|
||||
|
||||
ALTER TABLE messages
|
||||
ADD COLUMN IF NOT EXISTS external_request_hash VARCHAR(64);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_swt_source
|
||||
ON messages(inbox_id, source_id)
|
||||
WHERE source_id LIKE 'swt:%';
|
||||
@@ -0,0 +1,9 @@
|
||||
DROP INDEX IF EXISTS idx_working_hours_account_id;
|
||||
ALTER TABLE working_hours
|
||||
DROP COLUMN IF EXISTS close_minutes,
|
||||
DROP COLUMN IF EXISTS close_hour,
|
||||
DROP COLUMN IF EXISTS open_minutes,
|
||||
DROP COLUMN IF EXISTS open_hour,
|
||||
DROP COLUMN IF EXISTS open_all_day,
|
||||
DROP COLUMN IF EXISTS closed_all_day,
|
||||
DROP COLUMN IF EXISTS account_id;
|
||||
@@ -0,0 +1,11 @@
|
||||
ALTER TABLE working_hours
|
||||
ADD COLUMN IF NOT EXISTS account_id BIGINT,
|
||||
ADD COLUMN IF NOT EXISTS closed_all_day BOOLEAN DEFAULT false,
|
||||
ADD COLUMN IF NOT EXISTS open_all_day BOOLEAN DEFAULT false,
|
||||
ADD COLUMN IF NOT EXISTS open_hour INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS open_minutes INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS close_hour INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS close_minutes INTEGER;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_working_hours_account_id
|
||||
ON working_hours(account_id);
|
||||
@@ -0,0 +1,4 @@
|
||||
-- This migration repairs existing data. The restored timestamps cannot be
|
||||
-- distinguished from timestamps written by normal application traffic, so the
|
||||
-- rollback intentionally preserves the repaired values.
|
||||
SELECT 1;
|
||||
@@ -0,0 +1,41 @@
|
||||
UPDATE conversations AS c
|
||||
SET
|
||||
last_activity_at = COALESCE(
|
||||
c.last_activity_at,
|
||||
(
|
||||
SELECT EXTRACT(EPOCH FROM m.created_at)::bigint
|
||||
FROM messages AS m
|
||||
WHERE m.conversation_id = c.id
|
||||
ORDER BY m.created_at DESC, m.id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
),
|
||||
last_message_at = COALESCE(
|
||||
c.last_message_at,
|
||||
(
|
||||
SELECT EXTRACT(EPOCH FROM m.created_at)::bigint
|
||||
FROM messages AS m
|
||||
WHERE m.conversation_id = c.id
|
||||
ORDER BY m.created_at DESC, m.id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
),
|
||||
last_non_sys_msg_at = COALESCE(
|
||||
c.last_non_sys_msg_at,
|
||||
(
|
||||
SELECT EXTRACT(EPOCH FROM m.created_at)::bigint
|
||||
FROM messages AS m
|
||||
WHERE m.conversation_id = c.id
|
||||
AND m.message_type <> 'activity'
|
||||
ORDER BY m.created_at DESC, m.id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
)
|
||||
WHERE (c.last_activity_at IS NULL
|
||||
OR c.last_message_at IS NULL
|
||||
OR c.last_non_sys_msg_at IS NULL)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM messages AS m
|
||||
WHERE m.conversation_id = c.id
|
||||
);
|
||||
Reference in New Issue
Block a user