package com.test.payment.models; import java.util.List; /** * The database schema as code — executed statement-by-statement at startup by * DatabaseSchemaInitializer (replaces the old classpath schema.sql). */ public final class DatabaseSchema { private DatabaseSchema() { } public static final List STATEMENTS = List.of( """ CREATE TABLE IF NOT EXISTS provider_tokens ( id BIGINT AUTO_INCREMENT PRIMARY KEY, provider VARCHAR(20) NOT NULL, access_token VARCHAR(512) NOT NULL, expires_at TIMESTAMP NOT NULL, created_at TIMESTAMP NOT NULL ) """, """ CREATE TABLE IF NOT EXISTS payment_initiations ( id BIGINT AUTO_INCREMENT PRIMARY KEY, provider VARCHAR(20) NOT NULL, phone_number VARCHAR(15) NOT NULL, amount DECIMAL(10,2) NOT NULL, account_reference VARCHAR(50), transaction_desc VARCHAR(100), status VARCHAR(20) NOT NULL, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP ) """, """ CREATE INDEX IF NOT EXISTS idx_initiations_status_created ON payment_initiations (status, created_at) """, // One response per initiation (UNIQUE on initiation_id enforces the 1:1 link). // provider_reference is the ID used for callbacks/status checks // (M-Pesa CheckoutRequestID, Airtel transaction id, MTN X-Reference-Id). """ CREATE TABLE IF NOT EXISTS payment_responses ( id BIGINT AUTO_INCREMENT PRIMARY KEY, initiation_id BIGINT NOT NULL UNIQUE, provider VARCHAR(20) NOT NULL, provider_reference VARCHAR(100) UNIQUE, secondary_reference VARCHAR(100), response_code VARCHAR(30), response_description VARCHAR(255), customer_message VARCHAR(255), created_at TIMESTAMP NOT NULL, CONSTRAINT fk_response_initiation FOREIGN KEY (initiation_id) REFERENCES payment_initiations (id) ) """, // One callback per initiation (UNIQUE on initiation_id enforces the 1:1 link) """ CREATE TABLE IF NOT EXISTS payment_callbacks ( id BIGINT AUTO_INCREMENT PRIMARY KEY, initiation_id BIGINT NOT NULL UNIQUE, provider VARCHAR(20) NOT NULL, provider_reference VARCHAR(100), result_code VARCHAR(30), result_desc VARCHAR(255), receipt_number VARCHAR(50), amount DECIMAL(10,2), phone_number VARCHAR(15), transaction_date VARCHAR(20), raw_payload CLOB, created_at TIMESTAMP NOT NULL, CONSTRAINT fk_callback_initiation FOREIGN KEY (initiation_id) REFERENCES payment_initiations (id) ) """, // Consolidated transaction record, written when an initiation reaches a // terminal state (SUCCESS/FAILED). UNIQUE initiation_id: one per initiation. """ CREATE TABLE IF NOT EXISTS transactions ( id BIGINT AUTO_INCREMENT PRIMARY KEY, initiation_id BIGINT NOT NULL UNIQUE, provider VARCHAR(20) NOT NULL, provider_reference VARCHAR(100), secondary_reference VARCHAR(100), phone_number VARCHAR(15), amount DECIMAL(10,2), account_reference VARCHAR(50), status VARCHAR(20) NOT NULL, result_code VARCHAR(30), result_desc VARCHAR(255), receipt_number VARCHAR(50), transaction_date VARCHAR(20), resolved_by VARCHAR(20), created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP, CONSTRAINT fk_transaction_initiation FOREIGN KEY (initiation_id) REFERENCES payment_initiations (id) ) """ ); }