CREATE TABLE IF NOT EXISTS institution_identifier_application (
    id BIGINT PRIMARY KEY,
    bank_code VARCHAR(32) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    school_id BIGINT NOT NULL,
    class_id BIGINT NOT NULL,
    request_timestamp CHAR(14) NOT NULL,
    original_text VARCHAR(80) NOT NULL,
    digest CHAR(64),
    bank_signature VARCHAR(512),
    status VARCHAR(32) NOT NULL,
    verification_key_id VARCHAR(64),
    signature_valid BOOLEAN,
    digest_matches BOOLEAN,
    signing_key_id VARCHAR(64),
    institution_identifier VARCHAR(32),
    central_bank_signature VARCHAR(512),
    training_round INT NOT NULL DEFAULT 1,
    scoring_criteria INT NOT NULL DEFAULT 0,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    updated_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT uk_identifier_training_round UNIQUE (bank_code, created_by, training_round)
);

CREATE INDEX IF NOT EXISTS idx_institution_identifier_status
    ON institution_identifier_application(status);

CREATE INDEX IF NOT EXISTS idx_identifier_training_user
    ON institution_identifier_application(created_by, training_round);

CREATE TABLE IF NOT EXISTS institution_identifier_operation_log (
    id BIGINT PRIMARY KEY,
    application_id BIGINT NOT NULL,
    operation VARCHAR(32) NOT NULL,
    from_status VARCHAR(32),
    to_status VARCHAR(32) NOT NULL,
    operation_detail VARCHAR(1024) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT fk_identifier_operation_application
        FOREIGN KEY (application_id) REFERENCES institution_identifier_application(id)
);

CREATE INDEX IF NOT EXISTS idx_identifier_operation_application
    ON institution_identifier_operation_log(application_id);

CREATE TABLE IF NOT EXISTS institution_identifier_training_error (
    id BIGINT PRIMARY KEY,
    application_id BIGINT NOT NULL,
    training_round INT NOT NULL,
    error_sequence INT NOT NULL,
    error_type VARCHAR(32) NOT NULL,
    operation_step VARCHAR(32) NOT NULL,
    application_status VARCHAR(32) NOT NULL,
    provided_key_id VARCHAR(64),
    error_message VARCHAR(512) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT uk_identifier_training_error UNIQUE (application_id, error_sequence),
    CONSTRAINT fk_identifier_error_application
        FOREIGN KEY (application_id) REFERENCES institution_identifier_application(id)
);

CREATE INDEX IF NOT EXISTS idx_identifier_error_application
    ON institution_identifier_training_error(application_id);

CREATE TABLE IF NOT EXISTS institution_sm2_key (
    id BIGINT PRIMARY KEY,
    key_id VARCHAR(64) NOT NULL,
    key_name VARCHAR(64) NOT NULL,
    key_owner VARCHAR(32) NOT NULL,
    key_purpose VARCHAR(32) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    school_id BIGINT NOT NULL,
    class_id BIGINT NOT NULL,
    public_key VARCHAR(256) NOT NULL,
    encrypted_private_key VARCHAR(512) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    updated_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE
);

CREATE INDEX IF NOT EXISTS idx_institution_sm2_key_subject
    ON institution_sm2_key(user_id, school_id, class_id, key_owner, deleted);

CREATE TABLE IF NOT EXISTS institution_sm2_key_audit (
    id BIGINT PRIMARY KEY,
    key_record_id BIGINT NOT NULL,
    key_id VARCHAR(64) NOT NULL,
    operation VARCHAR(32) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    school_id BIGINT NOT NULL,
    class_id BIGINT NOT NULL,
    operation_detail VARCHAR(512) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT fk_institution_key_audit_key
        FOREIGN KEY (key_record_id) REFERENCES institution_sm2_key(id)
);

CREATE INDEX IF NOT EXISTS idx_institution_key_audit_record
    ON institution_sm2_key_audit(key_record_id, created_at);

CREATE TABLE IF NOT EXISTS currency_generation_request (
    id BIGINT PRIMARY KEY,
    identifier_application_id BIGINT NOT NULL,
    institution_identifier VARCHAR(32) NOT NULL,
    full_institution_identifier CHAR(64) NOT NULL,
    amount DECIMAL(18, 2) NOT NULL,
    delivery_node_code VARCHAR(32) NOT NULL,
    request_timestamp CHAR(14) NOT NULL,
    request_original_text VARCHAR(256),
    request_digest CHAR(64),
    bank_signature VARCHAR(512),
    signing_key_id VARCHAR(64),
    request_message VARCHAR(2048),
    status VARCHAR(32) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    school_id BIGINT NOT NULL,
    class_id BIGINT NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    updated_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT fk_currency_request_identifier_application
        FOREIGN KEY (identifier_application_id) REFERENCES institution_identifier_application(id)
);

CREATE INDEX IF NOT EXISTS idx_currency_request_identifier_application
    ON currency_generation_request(identifier_application_id, user_id, school_id, class_id, deleted);

CREATE INDEX IF NOT EXISTS idx_currency_request_status
    ON currency_generation_request(status);

CREATE TABLE IF NOT EXISTS currency_generation_request_operation_log (
    id BIGINT PRIMARY KEY,
    request_id BIGINT NOT NULL,
    operation VARCHAR(32) NOT NULL,
    from_status VARCHAR(32),
    to_status VARCHAR(32) NOT NULL,
    operation_detail VARCHAR(1024) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT fk_currency_request_operation_request
        FOREIGN KEY (request_id) REFERENCES currency_generation_request(id)
);

CREATE INDEX IF NOT EXISTS idx_currency_request_operation_request
    ON currency_generation_request_operation_log(request_id, created_at);

CREATE TABLE IF NOT EXISTS currency_generation_verification (
    id BIGINT PRIMARY KEY,
    request_id BIGINT NOT NULL,
    request_message VARCHAR(2048) NOT NULL,
    request_original_text VARCHAR(256) NOT NULL,
    request_digest CHAR(64) NOT NULL,
    bank_signature VARCHAR(512) NOT NULL,
    bank_key_id VARCHAR(64) NOT NULL,
    amount DECIMAL(18, 2) NOT NULL,
    signature_valid BOOLEAN,
    recomputed_digest CHAR(64),
    digest_matches BOOLEAN,
    total_quota DECIMAL(18, 2),
    used_quota DECIMAL(18, 2),
    remaining_quota DECIMAL(18, 2),
    quota_sufficient BOOLEAN,
    central_bank_key_id VARCHAR(64),
    central_bank_signature VARCHAR(512),
    confirmation_time CHAR(14),
    confirmation_message VARCHAR(2048),
    status VARCHAR(32) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    school_id BIGINT NOT NULL,
    class_id BIGINT NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    updated_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT uk_currency_verification_request UNIQUE (request_id),
    CONSTRAINT fk_currency_verification_request
        FOREIGN KEY (request_id) REFERENCES currency_generation_request(id)
);

CREATE INDEX IF NOT EXISTS idx_currency_verification_subject
    ON currency_generation_verification(request_id, user_id, school_id, class_id, deleted);

CREATE TABLE IF NOT EXISTS currency_generation_verification_operation_log (
    id BIGINT PRIMARY KEY,
    verification_id BIGINT NOT NULL,
    operation VARCHAR(32) NOT NULL,
    from_status VARCHAR(32),
    to_status VARCHAR(32) NOT NULL,
    operation_detail VARCHAR(1024) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT fk_currency_verification_operation
        FOREIGN KEY (verification_id) REFERENCES currency_generation_verification(id)
);

CREATE INDEX IF NOT EXISTS idx_currency_verification_operation
    ON currency_generation_verification_operation_log(verification_id, created_at);

CREATE TABLE IF NOT EXISTS stu_module_score_details (
    id VARCHAR(64) NOT NULL,
    moudule VARCHAR(100) NOT NULL,
    learning_projects VARCHAR(100),
    assessment_items VARCHAR(100),
    scoring_criteria VARCHAR(100),
    completion_status VARCHAR(100),
    score_project DOUBLE,
    user_id VARCHAR(64) NOT NULL,
    total_score DECIMAL(10, 2) NOT NULL DEFAULT 100.00,
    serial_number INT,
    schedule DOUBLE,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    PRIMARY KEY (id),
    CONSTRAINT uk_user_moudule_serial UNIQUE (user_id, moudule, serial_number)
);

CREATE INDEX IF NOT EXISTS idx_user_moudule
    ON stu_module_score_details(user_id, moudule);

CREATE TABLE IF NOT EXISTS transaction_information_identifier (
    id BIGINT PRIMARY KEY,
    verification_id BIGINT NOT NULL,
    request_id BIGINT NOT NULL,
    identifier_application_id BIGINT NOT NULL,
    amount DECIMAL(18, 2) NOT NULL,
    institution_identifier VARCHAR(32) NOT NULL,
    transaction_timestamp CHAR(14) NOT NULL,
    original_text VARCHAR(256) NOT NULL,
    digest CHAR(64),
    transaction_identifier VARCHAR(80),
    quota_request_id VARCHAR(32),
    quota_original_text VARCHAR(256),
    quota_digest CHAR(64),
    quota_signature VARCHAR(512),
    quota_signing_key_id VARCHAR(64),
    quota_request_message VARCHAR(2048),
    quota_verification_key_id VARCHAR(64),
    quota_recomputed_digest VARCHAR(64),
    quota_signature_digest VARCHAR(64),
    quota_signature_valid BOOLEAN,
    quota_digest_matches BOOLEAN,
    status VARCHAR(32) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    school_id BIGINT NOT NULL,
    class_id BIGINT NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    updated_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT uk_transaction_identifier_verification UNIQUE
        (verification_id, user_id, school_id, class_id),
    CONSTRAINT fk_transaction_identifier_verification FOREIGN KEY (verification_id)
        REFERENCES currency_generation_verification(id),
    CONSTRAINT fk_transaction_identifier_request FOREIGN KEY (request_id)
        REFERENCES currency_generation_request(id),
    CONSTRAINT fk_transaction_identifier_application FOREIGN KEY (identifier_application_id)
        REFERENCES institution_identifier_application(id)
);

CREATE INDEX IF NOT EXISTS idx_transaction_identifier_subject
    ON transaction_information_identifier(user_id, school_id, class_id, status, deleted);

CREATE TABLE IF NOT EXISTS transaction_information_identifier_operation_log (
    id BIGINT PRIMARY KEY,
    transaction_identifier_id BIGINT NOT NULL,
    operation VARCHAR(32) NOT NULL,
    from_status VARCHAR(32),
    to_status VARCHAR(32) NOT NULL,
    operation_detail VARCHAR(1024) NOT NULL,
    created_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT fk_transaction_identifier_operation FOREIGN KEY (transaction_identifier_id)
        REFERENCES transaction_information_identifier(id)
);

CREATE INDEX IF NOT EXISTS idx_transaction_identifier_operation
    ON transaction_information_identifier_operation_log(transaction_identifier_id, created_at);

CREATE TABLE IF NOT EXISTS control_system_signature (
    id BIGINT PRIMARY KEY,
    transaction_identifier_id BIGINT NOT NULL,
    control_id VARCHAR(32) NOT NULL,
    amount DECIMAL(18, 2) NOT NULL,
    institution_identifier VARCHAR(32) NOT NULL,
    transaction_identifier VARCHAR(80) NOT NULL,
    original_text VARCHAR(256) NOT NULL,
    digest CHAR(64),
    signing_key_id VARCHAR(64),
    signature VARCHAR(512),
    control_signature VARCHAR(256),
    response_message VARCHAR(2048),
    status VARCHAR(32) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    school_id BIGINT NOT NULL,
    class_id BIGINT NOT NULL,
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL,
    created_by VARCHAR(64) NOT NULL,
    updated_by VARCHAR(64) NOT NULL,
    deleted BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT uk_control_signature_transaction UNIQUE
        (transaction_identifier_id, user_id, school_id, class_id),
    CONSTRAINT fk_control_signature_transaction FOREIGN KEY (transaction_identifier_id)
        REFERENCES transaction_information_identifier(id)
);

CREATE INDEX IF NOT EXISTS idx_control_signature_subject
    ON control_system_signature(user_id, school_id, class_id, status, deleted);
