From 686bf6c3955579b56a64a3484ef65f1fb29c8d0f Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 23 Feb 2026 22:01:20 -0800 Subject: [PATCH] =?UTF-8?q?fix(schema):=20=E7=BB=9F=E4=B8=80=20disputes=20?= =?UTF-8?q?+=20audit=5Flogs=20=E8=BF=81=E7=A7=BB=E4=B8=8E=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 045_align_disputes_audit_logs.sql: ALTER迁移对齐021/022旧schema到实体期望schema - disputes: buyer_id→plaintiff_id, seller_id→defendant_id, 添加amount+version列 - audit_logs: actor_id→admin_id, resource_type→resource, 添加admin_name+result+updated_at+version列 - 将028/029改为no-op (已被045取代) - Dispute entity: enum类型改为varchar (匹配CHECK约束而非PostgreSQL原生enum) Co-Authored-By: Claude Opus 4.6 --- backend/migrations/028_create_disputes.sql | 30 ++----- backend/migrations/029_create_audit_logs.sql | 28 ++---- .../045_align_disputes_audit_logs.sql | 88 +++++++++++++++++++ .../src/domain/entities/dispute.entity.ts | 4 +- 4 files changed, 100 insertions(+), 50 deletions(-) create mode 100644 backend/migrations/045_align_disputes_audit_logs.sql diff --git a/backend/migrations/028_create_disputes.sql b/backend/migrations/028_create_disputes.sql index 8e5b727..3ef9c2f 100644 --- a/backend/migrations/028_create_disputes.sql +++ b/backend/migrations/028_create_disputes.sql @@ -1,25 +1,5 @@ --- 028: Disputes (admin compliance - plaintiff/defendant model) --- Complements 021_create_disputes.sql with the updated entity schema used by admin controllers. --- If 021 already created the disputes table, run ALTER or skip. This DDL is for fresh installs. - -CREATE TABLE IF NOT EXISTS disputes ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - order_id UUID NOT NULL, - plaintiff_id UUID NOT NULL REFERENCES users(id), - defendant_id UUID REFERENCES users(id), - type VARCHAR(30) NOT NULL CHECK (type IN ('buyer_claim', 'seller_claim', 'refund_request')), - status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'resolved', 'rejected')), - amount NUMERIC(18, 2) NOT NULL DEFAULT 0, - description TEXT, - resolution TEXT, - resolved_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - version INT NOT NULL DEFAULT 1 -); - -CREATE INDEX IF NOT EXISTS idx_disputes_status ON disputes(status); -CREATE INDEX IF NOT EXISTS idx_disputes_plaintiff_id ON disputes(plaintiff_id); -CREATE INDEX IF NOT EXISTS idx_disputes_defendant_id ON disputes(defendant_id); -CREATE INDEX IF NOT EXISTS idx_disputes_order_id ON disputes(order_id); -CREATE INDEX IF NOT EXISTS idx_disputes_created_at ON disputes(created_at DESC); +-- 028: (SUPERSEDED by 045_align_disputes_audit_logs.sql) +-- Original migration tried to create disputes with plaintiff/defendant schema, +-- but 021 already creates disputes with buyer/seller schema. +-- Migration 045 now handles the ALTER to reconcile both schemas. +-- This file is kept as a no-op for migration ordering consistency. diff --git a/backend/migrations/029_create_audit_logs.sql b/backend/migrations/029_create_audit_logs.sql index d5c41e1..5d4356d 100644 --- a/backend/migrations/029_create_audit_logs.sql +++ b/backend/migrations/029_create_audit_logs.sql @@ -1,23 +1,5 @@ --- 029: Admin audit logs (compliance-service admin actions) --- Complements 022_create_audit_logs.sql with the admin-focused schema. --- If 022 already created the audit_logs table, run ALTER or skip. This DDL is for fresh installs. - -CREATE TABLE IF NOT EXISTS audit_logs ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - admin_id UUID NOT NULL REFERENCES users(id), - admin_name VARCHAR(200) NOT NULL, - action VARCHAR(100) NOT NULL, - resource VARCHAR(100) NOT NULL, - resource_id VARCHAR(100), - ip_address VARCHAR(45), - result VARCHAR(20) NOT NULL DEFAULT 'success', - details JSONB, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - version INT NOT NULL DEFAULT 1 -); - -CREATE INDEX IF NOT EXISTS idx_audit_logs_admin_id ON audit_logs(admin_id); -CREATE INDEX IF NOT EXISTS idx_audit_logs_action ON audit_logs(action); -CREATE INDEX IF NOT EXISTS idx_audit_logs_resource ON audit_logs(resource, resource_id); -CREATE INDEX IF NOT EXISTS idx_audit_logs_created_at ON audit_logs(created_at DESC); +-- 029: (SUPERSEDED by 045_align_disputes_audit_logs.sql) +-- Original migration tried to create audit_logs with admin schema, +-- but 022 already creates audit_logs with actor schema. +-- Migration 045 now handles the ALTER to reconcile both schemas. +-- This file is kept as a no-op for migration ordering consistency. diff --git a/backend/migrations/045_align_disputes_audit_logs.sql b/backend/migrations/045_align_disputes_audit_logs.sql new file mode 100644 index 0000000..64a97e1 --- /dev/null +++ b/backend/migrations/045_align_disputes_audit_logs.sql @@ -0,0 +1,88 @@ +-- 045: Align disputes & audit_logs tables with current entity schema +-- Migration 021/022 created these tables with an older schema. +-- The entities (and migration 028/029) expect the updated schema. +-- This ALTER migration reconciles the actual DB with the entity definitions. + +-- ============================================================ +-- 1. disputes: 021 schema → 028 entity schema +-- ============================================================ + +-- Drop CHECK constraint on type (changing enum values) +ALTER TABLE disputes DROP CONSTRAINT IF EXISTS disputes_type_check; + +-- Drop CHECK constraint on status (changing enum values) +ALTER TABLE disputes DROP CONSTRAINT IF EXISTS disputes_status_check; + +-- Rename columns: buyer_id → plaintiff_id, seller_id → defendant_id +ALTER TABLE disputes RENAME COLUMN buyer_id TO plaintiff_id; +ALTER TABLE disputes RENAME COLUMN seller_id TO defendant_id; + +-- Make defendant_id nullable (entity: nullable: true) +ALTER TABLE disputes ALTER COLUMN defendant_id DROP NOT NULL; + +-- Add missing columns +ALTER TABLE disputes ADD COLUMN IF NOT EXISTS amount NUMERIC(18, 2) NOT NULL DEFAULT 0; +ALTER TABLE disputes ADD COLUMN IF NOT EXISTS version INT NOT NULL DEFAULT 1; + +-- Drop columns not in entity +ALTER TABLE disputes DROP COLUMN IF EXISTS coupon_id; +ALTER TABLE disputes DROP COLUMN IF EXISTS evidence; +ALTER TABLE disputes DROP COLUMN IF EXISTS chain_evidence; +ALTER TABLE disputes DROP COLUMN IF EXISTS refund_approved; +ALTER TABLE disputes DROP COLUMN IF EXISTS sla_deadline; +ALTER TABLE disputes DROP COLUMN IF EXISTS resolved_by; + +-- Re-add CHECK constraints with new enum values +-- Note: entity uses TypeORM enum type, but we add a CHECK to match the values +ALTER TABLE disputes ADD CONSTRAINT disputes_type_check + CHECK (type IN ('buyer_claim', 'seller_claim', 'refund_request')); + +ALTER TABLE disputes ADD CONSTRAINT disputes_status_check + CHECK (status IN ('pending', 'processing', 'resolved', 'rejected')); + +-- Update existing data to match new enum values +UPDATE disputes SET type = 'buyer_claim' WHERE type = 'buyer_complaint'; +UPDATE disputes SET type = 'seller_claim' WHERE type = 'seller_complaint'; +UPDATE disputes SET status = 'pending' WHERE status = 'submitted'; +UPDATE disputes SET status = 'processing' WHERE status IN ('evidence_collection', 'arbitration'); +UPDATE disputes SET status = 'rejected' WHERE status = 'escalated'; + +-- Fix indexes: rename buyer/seller indexes +DROP INDEX IF EXISTS idx_disputes_buyer_id; +DROP INDEX IF EXISTS idx_disputes_seller_id; +CREATE INDEX IF NOT EXISTS idx_disputes_plaintiff_id ON disputes(plaintiff_id); +CREATE INDEX IF NOT EXISTS idx_disputes_defendant_id ON disputes(defendant_id); +CREATE INDEX IF NOT EXISTS idx_disputes_order_id ON disputes(order_id); +CREATE INDEX IF NOT EXISTS idx_disputes_created_at ON disputes(created_at DESC); + +-- ============================================================ +-- 2. audit_logs: 022 schema → 029 entity schema +-- ============================================================ + +-- Rename columns +ALTER TABLE audit_logs RENAME COLUMN actor_id TO admin_id; +ALTER TABLE audit_logs RENAME COLUMN resource_type TO resource; + +-- Change resource_id from UUID to VARCHAR(100) +ALTER TABLE audit_logs ALTER COLUMN resource_id TYPE VARCHAR(100) USING resource_id::VARCHAR; + +-- Change ip_address from INET to VARCHAR(45) +ALTER TABLE audit_logs ALTER COLUMN ip_address TYPE VARCHAR(45) USING ip_address::VARCHAR; + +-- Add missing columns +ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS admin_name VARCHAR(200) NOT NULL DEFAULT ''; +ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS result VARCHAR(20) NOT NULL DEFAULT 'success'; +ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(); +ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS version INT NOT NULL DEFAULT 1; + +-- Drop columns not in entity +ALTER TABLE audit_logs DROP COLUMN IF EXISTS actor_role; +ALTER TABLE audit_logs DROP COLUMN IF EXISTS user_agent; +ALTER TABLE audit_logs DROP COLUMN IF EXISTS chain_hash; +ALTER TABLE audit_logs DROP COLUMN IF EXISTS previous_hash; + +-- Fix indexes +DROP INDEX IF EXISTS idx_audit_logs_actor_id; +CREATE INDEX IF NOT EXISTS idx_audit_logs_admin_id ON audit_logs(admin_id); +DROP INDEX IF EXISTS idx_audit_logs_resource; +CREATE INDEX IF NOT EXISTS idx_audit_logs_resource ON audit_logs(resource, resource_id); diff --git a/backend/services/compliance-service/src/domain/entities/dispute.entity.ts b/backend/services/compliance-service/src/domain/entities/dispute.entity.ts index 668cf75..5f444de 100644 --- a/backend/services/compliance-service/src/domain/entities/dispute.entity.ts +++ b/backend/services/compliance-service/src/domain/entities/dispute.entity.ts @@ -25,10 +25,10 @@ export class Dispute extends BaseEntity { @Column({ name: 'defendant_id', type: 'uuid', nullable: true }) defendantId: string; - @Column({ type: 'enum', enum: DisputeType }) + @Column({ type: 'varchar', length: 30 }) type: DisputeType; - @Column({ type: 'enum', enum: DisputeStatus, default: DisputeStatus.PENDING }) + @Column({ type: 'varchar', length: 20, default: DisputeStatus.PENDING }) status: DisputeStatus; @Column({ type: 'decimal', precision: 18, scale: 2 })