-- ============================================================================= -- KYC Module – Table Creation Script (MySQL / MariaDB) -- ============================================================================= -- DB Connection (from config/docker/env/fineract-common.env & mariadb.env): -- Host : localhost (or 'db' inside Docker) -- Port : 3306 -- Database : fineract_default ← tenant database (your actual data lives here) -- Username : root -- Password : skdcnwauicn2ucnaecasdsajdnizucawencascdca -- -- Run command: -- mysql -h localhost -P 3306 -u root -p'skdcnwauicn2ucnaecasdsajdnizucawencascdca' fineract_default < create_kyc_tables_mysql_mariadb.sql -- ============================================================================= USE fineract_default; -- ============================================================================= -- TABLE: m_client_kyc -- One KYC record per client (enforced by UNIQUE on client_id). -- Stores PAN, Aadhaar (masked), GSTIN, CKYCRR number, risk category, -- lifecycle dates and audit fields. -- ============================================================================= CREATE TABLE IF NOT EXISTS `m_client_kyc` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `client_id` BIGINT NOT NULL, -- kyc_status : 100=PENDING | 200=IN_PROGRESS | 300=VERIFIED | 400=REJECTED | 500=EXPIRED `kyc_status` SMALLINT NOT NULL DEFAULT 100, -- kyc_type : 1=INDIVIDUAL | 2=NON_INDIVIDUAL `kyc_type` SMALLINT NOT NULL, -- risk_category : 1=LOW (re-KYC 10yr) | 2=MEDIUM (8yr) | 3=HIGH (2yr) `risk_category` SMALLINT NOT NULL DEFAULT 1, -- PAN (Permanent Account Number – Income Tax Dept) -- Format: 5 uppercase letters + 4 digits + 1 uppercase letter e.g. ABCDE1234F `pan_number` VARCHAR(10) NULL, `pan_verified` TINYINT(1) NOT NULL DEFAULT 0, `pan_verified_on` DATE NULL, -- Aadhaar – ONLY masked form stored (last 4 digits visible) per UIDAI directive -- e.g. XXXXXXXX1234 `aadhaar_number_masked` VARCHAR(12) NULL, `aadhaar_verified` TINYINT(1) NOT NULL DEFAULT 0, `aadhaar_verified_on` DATE NULL, -- GSTIN (15-char GST Identification Number – mandatory for NON_INDIVIDUAL) -- Format: 2-digit state code + 10-char PAN + 1 entity num + Z + check digit `gstin_number` VARCHAR(15) NULL, `gstin_verified` TINYINT(1) NOT NULL DEFAULT 0, `gstin_verified_on` DATE NULL, -- CKYCRR – Central KYC Records Registry number (issued by CERSAI, 14 digits) `ckyc_number` VARCHAR(14) NULL, -- Lifecycle timestamps `initiated_on` DATE NULL, `verified_on` DATE NULL, `rejected_on` DATE NULL, -- expiry_date computed as: verified_on + risk_category years offset `expiry_date` DATE NULL, `remarks` VARCHAR(500) NULL, -- Audit fields (AbstractAuditableWithUTCDateTimeCustom) `created_by` BIGINT NOT NULL, `created_on_utc` DATETIME NOT NULL, `last_modified_by` BIGINT NOT NULL, `last_modified_on_utc` DATETIME NOT NULL, `version` BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY `uq_m_client_kyc_client_id` (`client_id`), CONSTRAINT `FK_m_client_kyc_client_id` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ============================================================================= -- TABLE: m_client_kyc_verification_log -- Immutable audit trail for every 3rd-party PAN / Aadhaar / GSTIN API call. -- ============================================================================= CREATE TABLE IF NOT EXISTS `m_client_kyc_verification_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `kyc_id` BIGINT NOT NULL, -- verification_type: PAN | AADHAAR | GSTIN `verification_type` VARCHAR(20) NOT NULL, -- verification_status: SUCCESS | FAILURE | PENDING | ERROR `verification_status` VARCHAR(20) NOT NULL, -- External reference id returned by the 3rd-party vendor API `request_reference` VARCHAR(100) NULL, -- Full raw JSON response from the vendor – stored for compliance audit `api_response` TEXT NULL, `remarks` VARCHAR(500) NULL, -- Audit fields `created_by` BIGINT NOT NULL, `created_on_utc` DATETIME NOT NULL, `last_modified_by` BIGINT NOT NULL, `last_modified_on_utc` DATETIME NOT NULL, `version` BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), CONSTRAINT `FK_m_kyc_verification_log_kyc_id` FOREIGN KEY (`kyc_id`) REFERENCES `m_client_kyc` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ============================================================================= -- PERMISSIONS – Insert into m_permission -- ============================================================================= INSERT IGNORE INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'READ_CLIENTKYC', 'CLIENTKYC', 'READ', 0), ('portfolio', 'CREATE_CLIENTKYC', 'CLIENTKYC', 'CREATE', 1), ('portfolio', 'UPDATE_CLIENTKYC', 'CLIENTKYC', 'UPDATE', 1), ('portfolio', 'VERIFY_CLIENTKYC', 'CLIENTKYC', 'VERIFY', 1), ('portfolio', 'REJECT_CLIENTKYC', 'CLIENTKYC', 'REJECT', 1); -- ============================================================================= -- VERIFY CREATION -- ============================================================================= SELECT 'Tables created:' AS info; SHOW TABLES LIKE 'm_client_kyc%'; SELECT 'Permissions inserted:' AS info; SELECT code, entity_name, action_name FROM m_permission WHERE entity_name = 'CLIENTKYC';