Updates, overview extended, club view implemented

This commit is contained in:
Torsten Schulz (local)
2026-06-23 16:17:07 +02:00
parent dd91c07694
commit 90e6c2f9f6
82 changed files with 11226 additions and 201 deletions

View File

@@ -16,6 +16,7 @@ ALTER TABLE `clubs`
ADD COLUMN IF NOT EXISTS `billing_email` varchar(255) NULL,
ADD COLUMN IF NOT EXISTS `iban` varchar(34) NULL,
ADD COLUMN IF NOT EXISTS `bic` varchar(11) NULL,
ADD COLUMN IF NOT EXISTS `fee_rules` json NULL,
ADD COLUMN IF NOT EXISTS `outgoing_invoice_prefix` varchar(24) NOT NULL DEFAULT 'RE',
ADD COLUMN IF NOT EXISTS `outgoing_invoice_next_number` int NOT NULL DEFAULT 1,
ADD COLUMN IF NOT EXISTS `incoming_invoice_prefix` varchar(24) NOT NULL DEFAULT 'EI',
@@ -61,6 +62,148 @@ CREATE TABLE IF NOT EXISTS `club_requests` (
KEY `idx_club_requests_club_status` (`club_id`, `status`, `request_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_distribution_groups` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_id` bigint NOT NULL,
`name` varchar(255) NOT NULL,
`description` text NULL,
`group_type` varchar(32) NOT NULL DEFAULT 'custom',
`is_system_group` tinyint(1) NOT NULL DEFAULT 0,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_distribution_groups_club` (`club_id`, `name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_distribution_group_members` (
`id` bigint NOT NULL AUTO_INCREMENT,
`group_id` bigint NOT NULL,
`member_id` bigint NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_club_distribution_group_member` (`group_id`, `member_id`),
KEY `idx_club_distribution_group_members_member` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_communication_threads` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_id` bigint NOT NULL,
`thread_type` varchar(32) NOT NULL DEFAULT 'direct',
`subject` varchar(255) NOT NULL,
`status` varchar(32) NOT NULL DEFAULT 'draft',
`created_by_user_id` bigint NULL,
`distribution_group_id` bigint NULL,
`recipient_member_id` bigint NULL,
`scheduled_at` datetime NULL,
`sent_at` datetime NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_communication_threads_club` (`club_id`, `status`, `thread_type`),
KEY `idx_club_communication_threads_group` (`distribution_group_id`),
KEY `idx_club_communication_threads_member` (`recipient_member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_communication_messages` (
`id` bigint NOT NULL AUTO_INCREMENT,
`thread_id` bigint NOT NULL,
`club_id` bigint NOT NULL,
`message_type` varchar(32) NOT NULL DEFAULT 'message',
`direction` varchar(32) NOT NULL DEFAULT 'outbound',
`body` text NOT NULL,
`created_by_user_id` bigint NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_communication_messages_thread` (`thread_id`, `created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_communication_recipients` (
`id` bigint NOT NULL AUTO_INCREMENT,
`thread_id` bigint NOT NULL,
`club_id` bigint NOT NULL,
`member_id` bigint NULL,
`recipient_name` varchar(255) NOT NULL,
`email_snapshot` varchar(255) NULL,
`delivery_status` varchar(32) NOT NULL DEFAULT 'pending',
`delivered_at` datetime NULL,
`last_attempt_at` datetime NULL,
`attempt_count` int NOT NULL DEFAULT 0,
`retryable` tinyint(1) NOT NULL DEFAULT 0,
`error_code` varchar(64) NULL,
`transport_message_id` varchar(255) NULL,
`error_message` text NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_communication_recipients_thread` (`thread_id`, `delivery_status`),
KEY `idx_club_communication_recipients_member` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_communication_delivery_logs` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_id` bigint NOT NULL,
`thread_id` bigint NOT NULL,
`recipient_id` bigint NULL,
`created_by_user_id` bigint NULL,
`status` varchar(32) NOT NULL DEFAULT 'failed',
`attempt_no` int NOT NULL DEFAULT 1,
`retryable` tinyint(1) NOT NULL DEFAULT 0,
`error_code` varchar(64) NULL,
`error_message` text NULL,
`transport_message_id` varchar(255) NULL,
`transport_response` text NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_communication_delivery_logs_thread` (`thread_id`, `created_at`),
KEY `idx_club_communication_delivery_logs_recipient` (`recipient_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `club_distribution_groups`
ADD COLUMN IF NOT EXISTS `filter_definition` json NULL;
ALTER TABLE `club_communication_threads`
ADD COLUMN IF NOT EXISTS `recipient_filters` json NULL;
CREATE TABLE IF NOT EXISTS `club_communication_templates` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_id` bigint NOT NULL,
`name` varchar(160) NOT NULL,
`category` varchar(64) NOT NULL DEFAULT 'general',
`subject_template` varchar(255) NULL,
`body_template` text NULL,
`variables_hint` text NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_communication_templates_club` (`club_id`, `category`, `name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_account_transactions` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_id` bigint NOT NULL,
`account_id` bigint NOT NULL,
`invoice_id` bigint NULL,
`created_by_user_id` bigint NULL,
`direction` varchar(16) NOT NULL DEFAULT 'credit',
`booking_type` varchar(32) NOT NULL DEFAULT 'manual',
`status` varchar(32) NOT NULL DEFAULT 'booked',
`booking_date` date NOT NULL,
`value_date` date NULL,
`amount_cents` bigint NOT NULL DEFAULT 0,
`currency_code` varchar(3) NOT NULL DEFAULT 'EUR',
`reference` varchar(255) NULL,
`notes` text NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_account_transactions_club_date` (`club_id`, `booking_date`, `status`),
KEY `idx_club_account_transactions_account_date` (`account_id`, `booking_date`),
KEY `idx_club_account_transactions_invoice` (`invoice_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_request_notes` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_request_id` bigint NOT NULL,
@@ -209,7 +352,11 @@ CREATE TABLE IF NOT EXISTS `club_invoice_parties` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_id` bigint NOT NULL,
`party_type` varchar(32) NOT NULL DEFAULT 'customer',
`status` varchar(32) NOT NULL DEFAULT 'active',
`name` varchar(255) NOT NULL,
`contract_reference` varchar(120) NULL,
`valid_from` date NULL,
`valid_to` date NULL,
`contact_name` varchar(255) NULL,
`email` varchar(255) NULL,
`phone` varchar(80) NULL,
@@ -224,7 +371,10 @@ CREATE TABLE IF NOT EXISTS `club_invoice_parties` (
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_invoice_parties_club_type` (`club_id`, `party_type`)
KEY `idx_club_invoice_parties_club_type` (`club_id`, `party_type`),
KEY `idx_club_invoice_parties_club_status` (`club_id`, `status`),
KEY `idx_club_invoice_parties_club_valid_from` (`club_id`, `valid_from`),
KEY `idx_club_invoice_parties_club_valid_to` (`club_id`, `valid_to`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `club_invoices` (
@@ -251,9 +401,26 @@ CREATE TABLE IF NOT EXISTS `club_invoices` (
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`archived_at` datetime NULL,
PRIMARY KEY (`id`),
KEY `idx_club_invoices_club_direction_status` (`club_id`, `invoice_direction`, `status`, `due_on`)
KEY `idx_club_invoices_club_direction_status` (`club_id`, `invoice_direction`, `status`, `due_on`),
UNIQUE KEY `uq_club_invoices_number` (`club_id`, `invoice_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SET @club_invoices_number_index_exists := (
SELECT COUNT(*)
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'club_invoices'
AND index_name = 'uq_club_invoices_number'
);
SET @club_invoices_number_index_sql := IF(
@club_invoices_number_index_exists = 0,
'ALTER TABLE `club_invoices` ADD UNIQUE KEY `uq_club_invoices_number` (`club_id`, `invoice_number`)',
'SELECT 1'
);
PREPARE club_invoices_number_index_stmt FROM @club_invoices_number_index_sql;
EXECUTE club_invoices_number_index_stmt;
DEALLOCATE PREPARE club_invoices_number_index_stmt;
CREATE TABLE IF NOT EXISTS `club_invoice_items` (
`id` bigint NOT NULL AUTO_INCREMENT,
`invoice_id` bigint NOT NULL,
@@ -268,3 +435,30 @@ CREATE TABLE IF NOT EXISTS `club_invoice_items` (
PRIMARY KEY (`id`),
UNIQUE KEY `uq_club_invoice_items_line` (`invoice_id`, `line_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `club_communication_recipients`
ADD COLUMN IF NOT EXISTS `last_attempt_at` datetime NULL,
ADD COLUMN IF NOT EXISTS `attempt_count` int NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS `retryable` tinyint(1) NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS `error_code` varchar(64) NULL,
ADD COLUMN IF NOT EXISTS `transport_message_id` varchar(255) NULL;
CREATE TABLE IF NOT EXISTS `club_communication_delivery_logs` (
`id` bigint NOT NULL AUTO_INCREMENT,
`club_id` bigint NOT NULL,
`thread_id` bigint NOT NULL,
`recipient_id` bigint NULL,
`created_by_user_id` bigint NULL,
`status` varchar(32) NOT NULL DEFAULT 'failed',
`attempt_no` int NOT NULL DEFAULT 1,
`retryable` tinyint(1) NOT NULL DEFAULT 0,
`error_code` varchar(64) NULL,
`error_message` text NULL,
`transport_message_id` varchar(255) NULL,
`transport_response` text NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_club_communication_delivery_logs_thread` (`thread_id`, `created_at`),
KEY `idx_club_communication_delivery_logs_recipient` (`recipient_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@@ -21,6 +21,7 @@ ALTER TABLE IF EXISTS clubs
ADD COLUMN IF NOT EXISTS billing_email varchar(255),
ADD COLUMN IF NOT EXISTS iban varchar(34),
ADD COLUMN IF NOT EXISTS bic varchar(11),
ADD COLUMN IF NOT EXISTS fee_rules jsonb,
ADD COLUMN IF NOT EXISTS outgoing_invoice_prefix varchar(24) NOT NULL DEFAULT 'RE',
ADD COLUMN IF NOT EXISTS outgoing_invoice_next_number integer NOT NULL DEFAULT 1,
ADD COLUMN IF NOT EXISTS incoming_invoice_prefix varchar(24) NOT NULL DEFAULT 'EI',
@@ -67,6 +68,110 @@ CREATE TABLE IF NOT EXISTS club_requests (
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS club_distribution_groups (
id bigserial PRIMARY KEY,
club_id bigint NOT NULL,
name varchar(255) NOT NULL,
description text,
group_type varchar(32) NOT NULL DEFAULT 'custom',
is_system_group boolean NOT NULL DEFAULT false,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_distribution_groups_club
ON club_distribution_groups (club_id, name);
CREATE TABLE IF NOT EXISTS club_distribution_group_members (
id bigserial PRIMARY KEY,
group_id bigint NOT NULL,
member_id bigint NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (group_id, member_id)
);
CREATE INDEX IF NOT EXISTS idx_club_distribution_group_members_member
ON club_distribution_group_members (member_id);
CREATE TABLE IF NOT EXISTS club_communication_threads (
id bigserial PRIMARY KEY,
club_id bigint NOT NULL,
thread_type varchar(32) NOT NULL DEFAULT 'direct',
subject varchar(255) NOT NULL,
status varchar(32) NOT NULL DEFAULT 'draft',
created_by_user_id bigint,
distribution_group_id bigint,
recipient_member_id bigint,
scheduled_at timestamptz,
sent_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_communication_threads_club
ON club_communication_threads (club_id, status, thread_type);
CREATE TABLE IF NOT EXISTS club_communication_messages (
id bigserial PRIMARY KEY,
thread_id bigint NOT NULL,
club_id bigint NOT NULL,
message_type varchar(32) NOT NULL DEFAULT 'message',
direction varchar(32) NOT NULL DEFAULT 'outbound',
body text NOT NULL,
created_by_user_id bigint,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_communication_messages_thread
ON club_communication_messages (thread_id, created_at DESC);
CREATE TABLE IF NOT EXISTS club_communication_recipients (
id bigserial PRIMARY KEY,
thread_id bigint NOT NULL,
club_id bigint NOT NULL,
member_id bigint,
recipient_name varchar(255) NOT NULL,
email_snapshot varchar(255),
delivery_status varchar(32) NOT NULL DEFAULT 'pending',
delivered_at timestamptz,
last_attempt_at timestamptz,
attempt_count integer NOT NULL DEFAULT 0,
retryable boolean NOT NULL DEFAULT false,
error_code varchar(64),
transport_message_id varchar(255),
error_message text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_communication_recipients_thread
ON club_communication_recipients (thread_id, delivery_status);
CREATE TABLE IF NOT EXISTS club_communication_delivery_logs (
id bigserial PRIMARY KEY,
club_id bigint NOT NULL,
thread_id bigint NOT NULL,
recipient_id bigint,
created_by_user_id bigint,
status varchar(32) NOT NULL DEFAULT 'failed',
attempt_no integer NOT NULL DEFAULT 1,
retryable boolean NOT NULL DEFAULT false,
error_code varchar(64),
error_message text,
transport_message_id varchar(255),
transport_response text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_communication_delivery_logs_thread
ON club_communication_delivery_logs (thread_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_club_communication_delivery_logs_recipient
ON club_communication_delivery_logs (recipient_id);
CREATE INDEX IF NOT EXISTS idx_club_requests_club_status
ON club_requests (club_id, status, request_type);
@@ -483,7 +588,11 @@ CREATE TABLE IF NOT EXISTS club_invoice_parties (
id bigserial PRIMARY KEY,
club_id bigint NOT NULL,
party_type varchar(32) NOT NULL,
status varchar(32) NOT NULL DEFAULT 'active',
name varchar(255) NOT NULL,
contract_reference varchar(120),
valid_from date,
valid_to date,
contact_name varchar(255),
email varchar(255),
phone varchar(80),
@@ -501,6 +610,12 @@ CREATE TABLE IF NOT EXISTS club_invoice_parties (
CREATE INDEX IF NOT EXISTS idx_club_invoice_parties_club_type
ON club_invoice_parties (club_id, party_type);
CREATE INDEX IF NOT EXISTS idx_club_invoice_parties_club_status
ON club_invoice_parties (club_id, status);
CREATE INDEX IF NOT EXISTS idx_club_invoice_parties_club_valid_from
ON club_invoice_parties (club_id, valid_from);
CREATE INDEX IF NOT EXISTS idx_club_invoice_parties_club_valid_to
ON club_invoice_parties (club_id, valid_to);
CREATE TABLE IF NOT EXISTS club_invoices (
id bigserial PRIMARY KEY,
@@ -530,6 +645,10 @@ CREATE TABLE IF NOT EXISTS club_invoices (
CREATE INDEX IF NOT EXISTS idx_club_invoices_club_direction_status
ON club_invoices (club_id, invoice_direction, status, due_on);
CREATE UNIQUE INDEX IF NOT EXISTS uq_club_invoices_number
ON club_invoices (club_id, invoice_number)
WHERE invoice_number IS NOT NULL;
CREATE TABLE IF NOT EXISTS club_invoice_items (
id bigserial PRIMARY KEY,
invoice_id bigint NOT NULL,
@@ -652,4 +771,83 @@ BEGIN
END
$$;
ALTER TABLE IF EXISTS club_communication_recipients
ADD COLUMN IF NOT EXISTS last_attempt_at timestamptz,
ADD COLUMN IF NOT EXISTS attempt_count integer NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS retryable boolean NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS error_code varchar(64),
ADD COLUMN IF NOT EXISTS transport_message_id varchar(255);
CREATE TABLE IF NOT EXISTS club_communication_delivery_logs (
id bigserial PRIMARY KEY,
club_id bigint NOT NULL,
thread_id bigint NOT NULL,
recipient_id bigint,
created_by_user_id bigint,
status varchar(32) NOT NULL DEFAULT 'failed',
attempt_no integer NOT NULL DEFAULT 1,
retryable boolean NOT NULL DEFAULT false,
error_code varchar(64),
error_message text,
transport_message_id varchar(255),
transport_response text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_communication_delivery_logs_thread
ON club_communication_delivery_logs (thread_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_club_communication_delivery_logs_recipient
ON club_communication_delivery_logs (recipient_id);
ALTER TABLE IF EXISTS club_distribution_groups
ADD COLUMN IF NOT EXISTS filter_definition jsonb;
ALTER TABLE IF EXISTS club_communication_threads
ADD COLUMN IF NOT EXISTS recipient_filters jsonb;
CREATE TABLE IF NOT EXISTS club_communication_templates (
id bigserial PRIMARY KEY,
club_id bigint NOT NULL,
name varchar(160) NOT NULL,
category varchar(64) NOT NULL DEFAULT 'general',
subject_template varchar(255),
body_template text,
variables_hint text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_communication_templates_club
ON club_communication_templates (club_id, category, name);
CREATE TABLE IF NOT EXISTS club_account_transactions (
id bigserial PRIMARY KEY,
club_id bigint NOT NULL,
account_id bigint NOT NULL,
invoice_id bigint,
created_by_user_id bigint,
direction varchar(16) NOT NULL DEFAULT 'credit',
booking_type varchar(32) NOT NULL DEFAULT 'manual',
status varchar(32) NOT NULL DEFAULT 'booked',
booking_date date NOT NULL,
value_date date,
amount_cents bigint NOT NULL DEFAULT 0,
currency_code varchar(3) NOT NULL DEFAULT 'EUR',
reference varchar(255),
notes text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_club_account_transactions_club_date
ON club_account_transactions (club_id, booking_date DESC, status);
CREATE INDEX IF NOT EXISTS idx_club_account_transactions_account_date
ON club_account_transactions (account_id, booking_date DESC);
CREATE INDEX IF NOT EXISTS idx_club_account_transactions_invoice
ON club_account_transactions (invoice_id);
COMMIT;