Files
company-tool/backend/company-migrations/0010_communications_documents.sql
Torsten Schulz (local) 0e539710c0 feat: Add password reset functionality with request and reset forms
feat: Implement price list import feature with preview and apply options

feat: Create price rules management page with CRUD operations

feat: Develop quotes management page with itemized quotes and status tracking

feat: Introduce organization registration page for new users

feat: Build suppliers management page with detailed supplier information

feat: Create users management page for inviting and managing roles

chore: Add TypeScript configuration for improved type checking

chore: Set up Vite configuration for development server and API proxy

chore: Add Vite environment type definitions for better TypeScript support
2026-06-02 15:28:38 +02:00

154 lines
5.2 KiB
SQL

-- Template migration for each organization schema.
-- Replace {schema} with the real schema name, e.g. company_<organization_id>.
create table if not exists {schema}.communications (
id uuid primary key,
communication_type text not null,
direction text not null,
subject_ciphertext bytea not null,
subject_nonce bytea not null,
subject_key_id text not null,
body_ciphertext bytea,
body_nonce bytea,
body_key_id text,
status text not null default 'open',
occurred_at timestamptz,
created_by_user_id uuid,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
constraint communications_type_valid check (
communication_type in ('email', 'phone', 'letter', 'meeting', 'internal_note')
),
constraint communications_direction_valid check (
direction in ('inbound', 'outbound', 'internal')
),
constraint communications_status_valid check (
status in ('open', 'done', 'archived')
),
constraint communications_body_encryption_complete check (
(
body_ciphertext is null
and body_nonce is null
and body_key_id is null
)
or (
body_ciphertext is not null
and body_nonce is not null
and body_key_id is not null
)
)
);
create index if not exists idx_communications_type_status
on {schema}.communications (communication_type, status, occurred_at desc);
create table if not exists {schema}.communication_links (
communication_id uuid not null references {schema}.communications(id) on delete cascade,
entity_type text not null,
entity_id uuid not null,
created_at timestamptz not null default now(),
primary key (communication_id, entity_type, entity_id),
constraint communication_links_entity_type_valid check (
entity_type in (
'customer',
'supplier',
'activity',
'quote',
'outgoing_invoice',
'incoming_invoice',
'item',
'document'
)
)
);
create index if not exists idx_communication_links_entity
on {schema}.communication_links (entity_type, entity_id);
create table if not exists {schema}.documents (
id uuid primary key,
title_ciphertext bytea not null,
title_nonce bytea not null,
title_key_id text not null,
description_ciphertext bytea,
description_nonce bytea,
description_key_id text,
status text not null default 'active',
created_by_user_id uuid,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
constraint documents_status_valid check (status in ('active', 'archived', 'deleted')),
constraint documents_description_encryption_complete check (
(
description_ciphertext is null
and description_nonce is null
and description_key_id is null
)
or (
description_ciphertext is not null
and description_nonce is not null
and description_key_id is not null
)
)
);
create table if not exists {schema}.document_versions (
id uuid primary key,
document_id uuid not null references {schema}.documents(id) on delete cascade,
version_no integer not null,
file_name_ciphertext bytea not null,
file_name_nonce bytea not null,
file_name_key_id text not null,
content_type_ciphertext bytea not null,
content_type_nonce bytea not null,
content_type_key_id text not null,
file_size bigint not null,
storage_path text not null,
checksum_sha256 text not null,
uploaded_by_user_id uuid,
created_at timestamptz not null default now(),
unique (document_id, version_no),
constraint document_versions_file_size_valid check (file_size >= 0)
);
create index if not exists idx_document_versions_document_version
on {schema}.document_versions (document_id, version_no desc);
create table if not exists {schema}.document_links (
document_id uuid not null references {schema}.documents(id) on delete cascade,
entity_type text not null,
entity_id uuid not null,
created_at timestamptz not null default now(),
primary key (document_id, entity_type, entity_id),
constraint document_links_entity_type_valid check (
entity_type in (
'customer',
'supplier',
'activity',
'communication',
'quote',
'outgoing_invoice',
'incoming_invoice',
'item'
)
)
);
create index if not exists idx_document_links_entity
on {schema}.document_links (entity_type, entity_id);
create table if not exists {schema}.document_audit_log (
id uuid primary key,
document_id uuid not null references {schema}.documents(id) on delete cascade,
version_id uuid references {schema}.document_versions(id) on delete set null,
action text not null,
user_id uuid,
created_at timestamptz not null default now(),
constraint document_audit_log_action_valid check (
action in ('upload', 'download', 'archive')
)
);
create index if not exists idx_document_audit_log_document
on {schema}.document_audit_log (document_id, created_at desc);