Add customer contract clearance console

This commit is contained in:
xz
2026-09-01 14:38:42 +08:00
parent 1d4154dd20
commit 5849705d1e
19 changed files with 2431 additions and 25 deletions
+99
View File
@@ -561,6 +561,98 @@ CREATE TABLE IF NOT EXISTS commercial_approval_requests (
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS customers (
id TEXT PRIMARY KEY,
organization_id TEXT NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
name TEXT NOT NULL,
legal_name TEXT NOT NULL DEFAULT '',
code TEXT NOT NULL,
customer_type TEXT NOT NULL DEFAULT 'platform' CHECK (customer_type IN ('platform', 'brand', 'agency', 'distributor', 'internal')),
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('prospect', 'active', 'paused', 'archived')),
industry TEXT NOT NULL DEFAULT '',
region TEXT NOT NULL DEFAULT '',
billing_email TEXT NOT NULL DEFAULT '',
tax_id TEXT NOT NULL DEFAULT '',
notes TEXT NOT NULL DEFAULT '',
tags_json TEXT NOT NULL DEFAULT '[]',
metadata_json TEXT NOT NULL DEFAULT '{}',
created_by TEXT NOT NULL REFERENCES users(id),
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
UNIQUE (organization_id, code)
);
CREATE TABLE IF NOT EXISTS customer_contacts (
id TEXT PRIMARY KEY,
organization_id TEXT NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
customer_id TEXT NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
name TEXT NOT NULL,
role TEXT NOT NULL DEFAULT '',
email TEXT NOT NULL DEFAULT '',
phone TEXT NOT NULL DEFAULT '',
is_primary INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive')),
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS production_contracts (
id TEXT PRIMARY KEY,
organization_id TEXT NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
customer_id TEXT NOT NULL REFERENCES customers(id) ON DELETE RESTRICT,
contract_number TEXT NOT NULL,
title TEXT NOT NULL,
contract_type TEXT NOT NULL DEFAULT 'production_license' CHECK (contract_type IN ('production_license', 'distribution', 'work_for_hire', 'revenue_share', 'internal')),
status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'submitted', 'active', 'expiring', 'expired', 'suspended', 'terminated')),
approval_status TEXT NOT NULL DEFAULT 'draft' CHECK (approval_status IN ('draft', 'legal_review', 'approved', 'blocked')),
effective_at TEXT,
expires_at TEXT,
signed_at TEXT,
currency TEXT NOT NULL DEFAULT 'CNY',
amount REAL NOT NULL DEFAULT 0,
license_scope_json TEXT NOT NULL DEFAULT '{}',
rights_json TEXT NOT NULL DEFAULT '{}',
delivery_terms_json TEXT NOT NULL DEFAULT '{}',
evidence_json TEXT NOT NULL DEFAULT '{}',
risk_json TEXT NOT NULL DEFAULT '{}',
approval_note TEXT NOT NULL DEFAULT '',
created_by TEXT NOT NULL REFERENCES users(id),
updated_by TEXT REFERENCES users(id),
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
UNIQUE (organization_id, contract_number)
);
CREATE TABLE IF NOT EXISTS contract_project_bindings (
id TEXT PRIMARY KEY,
organization_id TEXT NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
contract_id TEXT NOT NULL REFERENCES production_contracts(id) ON DELETE CASCADE,
customer_id TEXT NOT NULL REFERENCES customers(id) ON DELETE RESTRICT,
usage_mode TEXT NOT NULL DEFAULT 'primary-license' CHECK (usage_mode IN ('primary-license', 'supplemental-rights', 'delivery-only', 'internal-review')),
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'review', 'blocked', 'archived')),
notes TEXT NOT NULL DEFAULT '',
created_by TEXT NOT NULL REFERENCES users(id),
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
UNIQUE (organization_id, project_id, contract_id)
);
CREATE TABLE IF NOT EXISTS contract_license_events (
id TEXT PRIMARY KEY,
organization_id TEXT NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
contract_id TEXT REFERENCES production_contracts(id) ON DELETE CASCADE,
customer_id TEXT REFERENCES customers(id) ON DELETE SET NULL,
workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL,
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
event_type TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'recorded',
actor_user_id TEXT REFERENCES users(id),
metadata_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL
);
-- Local invoice ledger. This is intentionally payment-provider agnostic: the
-- platform records billing snapshots and lifecycle state, while an external
-- accounting or payment system can be connected later through an adapter.
@@ -1594,6 +1686,13 @@ CREATE INDEX IF NOT EXISTS idx_delivery_access_events_link ON delivery_access_ev
CREATE INDEX IF NOT EXISTS idx_delivery_access_events_release ON delivery_access_events(release_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_delivery_access_feedback_link ON delivery_access_feedback(link_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_delivery_access_feedback_release ON delivery_access_feedback(release_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_customers_org_status ON customers(organization_id, status, updated_at DESC);
CREATE INDEX IF NOT EXISTS idx_customer_contacts_customer ON customer_contacts(customer_id, is_primary DESC, status);
CREATE INDEX IF NOT EXISTS idx_production_contracts_org_status ON production_contracts(organization_id, status, approval_status, updated_at DESC);
CREATE INDEX IF NOT EXISTS idx_production_contracts_customer ON production_contracts(customer_id, status, updated_at DESC);
CREATE INDEX IF NOT EXISTS idx_contract_project_bindings_project ON contract_project_bindings(organization_id, workspace_id, project_id, status);
CREATE INDEX IF NOT EXISTS idx_contract_project_bindings_contract ON contract_project_bindings(contract_id, status, updated_at DESC);
CREATE INDEX IF NOT EXISTS idx_contract_license_events_scope ON contract_license_events(organization_id, contract_id, project_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_service_health_status ON service_health(status, updated_at);
CREATE INDEX IF NOT EXISTS idx_auth_sessions_user ON auth_sessions(user_id, expires_at, revoked_at);
CREATE INDEX IF NOT EXISTS idx_mfa_challenges_hash ON auth_mfa_challenges(challenge_hash, expires_at, consumed_at);