Add all CBS custom modules: KYC, Sanctions, RBI Feed, OpenProject, Mobile Lookup, Charges, Avro schemas

Includes all prior work not yet committed on this branch:
- KYC module (LincPay eKYC: PAN, Aadhaar OTP, GSTIN verification)
- Sanctions screening (UN Security Council consolidated list)
- RBI Feed integration with scheduled jobs
- OpenProject API integration
- Mobile lookup service
- Charge module enhancements (current account support)
- Client family member nominee fields
- Avro schema updates
- Liquibase migrations 0216-0224
- Postman collections for OpenProject, RBI Feeds, Sanctions
- SQL seed scripts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aditya
2026-03-18 17:54:10 +05:30
co-authored by Claude Opus 4.6
parent 78f37257a7
commit ba5365d4af
102 changed files with 9757 additions and 18 deletions
@@ -42,9 +42,9 @@ fineract.security.oauth2.client.registrations.frontend-client.redirect-uris=${FI
fineract.security.oauth2.client.registrations.frontend-client.require-authorization-consent=${FINERACT_SECURITY_OAUTH2_CLIENTS_FRONTEND_CONSENT:false}
fineract.tenant.host=${FINERACT_DEFAULT_TENANTDB_HOSTNAME:localhost}
fineract.tenant.port=${FINERACT_DEFAULT_TENANTDB_PORT:3306}
fineract.tenant.username=${FINERACT_DEFAULT_TENANTDB_UID:root}
fineract.tenant.password=${FINERACT_DEFAULT_TENANTDB_PWD:mysql}
fineract.tenant.port=${FINERACT_DEFAULT_TENANTDB_PORT:5432}
fineract.tenant.username=${FINERACT_DEFAULT_TENANTDB_UID:postgres}
fineract.tenant.password=${FINERACT_DEFAULT_TENANTDB_PWD:root}
fineract.tenant.parameters=${FINERACT_DEFAULT_TENANTDB_CONN_PARAMS:}
fineract.tenant.timezone=${FINERACT_DEFAULT_TENANTDB_TIMEZONE:Asia/Kolkata}
fineract.tenant.identifier=${FINERACT_DEFAULT_TENANTDB_IDENTIFIER:default}
@@ -402,10 +402,10 @@ server.tomcat.max-keep-alive-requests=${FINERACT_SERVER_TOMCAT_MAX_KEEP_ALIVE_RE
server.tomcat.threads.max=${FINERACT_SERVER_TOMCAT_THREADS_MAX:200}
server.tomcat.threads.min-spare=${FINERACT_SERVER_TOMCAT_THREADS_MIN_SPARE:10}
server.tomcat.mbeanregistry.enabled=${FINERACT_SERVER_TOMCAT_MBEANREGISTRY_ENABLED:false}
spring.datasource.hikari.driverClassName=${FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME:org.mariadb.jdbc.Driver}
spring.datasource.hikari.jdbcUrl=${FINERACT_HIKARI_JDBC_URL:jdbc:mariadb://localhost:3306/fineract_tenants}
spring.datasource.hikari.username=${FINERACT_HIKARI_USERNAME:root}
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:mysql}
spring.datasource.hikari.driverClassName=${FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME:org.postgresql.Driver}
spring.datasource.hikari.jdbcUrl=${FINERACT_HIKARI_JDBC_URL:jdbc:postgresql://localhost:5432/fineract_tenants}
spring.datasource.hikari.username=${FINERACT_HIKARI_USERNAME:postgres}
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:root}
spring.datasource.hikari.minimumIdle=${FINERACT_HIKARI_MINIMUM_IDLE:3}
spring.datasource.hikari.maximumPoolSize=${FINERACT_HIKARI_MAXIMUM_POOL_SIZE:10}
spring.datasource.hikari.idleTimeout=${FINERACT_HIKARI_IDLE_TIMEOUT:60000}
@@ -640,3 +640,25 @@ resilience4j.retry.instances.commandAuditFallback.wait-duration=${FINERACT_COMMA
resilience4j.retry.instances.commandAuditFallback.enable-exponential-backoff=${FINERACT_COMMAND_AUDIT_FALLBACK_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
resilience4j.retry.instances.commandAuditFallback.exponential-backoff-multiplier=${FINERACT_COMMAND_AUDIT_FALLBACK_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
resilience4j.retry.instances.commandAuditFallback.retryExceptions=${FINERACT_COMMAND_AUDIT_FALLBACK_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
# ── LincPay eKYC API ──────────────────────────────────────────────────────────
# Set FINERACT_KYC_LINCPAY_API_KEY and FINERACT_KYC_LINCPAY_SECRET as env vars
# in production. Never commit real credentials to source control.
fineract.kyc.lincpay.api-key=${FINERACT_KYC_LINCPAY_API_KEY:api_7c9e3a1f6d4b2a8c5e1f3d7b9a2c6e4f}
fineract.kyc.lincpay.secret=${FINERACT_KYC_LINCPAY_SECRET:secret_4e8a2d7c1f9b3a6e5d2c8f1a7b4e9c3d}
fineract.kyc.lincpay.base-url=${FINERACT_KYC_LINCPAY_BASE_URL:https://ekyc.lincpay.in/EKYC/ekyc}
fineract.kyc.lincpay.path.aadhaar-generate-otp=${FINERACT_KYC_LINCPAY_PATH_AADHAAR_GENERATE_OTP:/aadhaar/generate-otp}
fineract.kyc.lincpay.path.aadhaar-verify-otp=${FINERACT_KYC_LINCPAY_PATH_AADHAAR_VERIFY_OTP:/aadhaar/verify-otp}
fineract.kyc.lincpay.path.pan-validate=${FINERACT_KYC_LINCPAY_PATH_PAN_VALIDATE:/validate-pan}
fineract.kyc.lincpay.path.gstin-validate=${FINERACT_KYC_LINCPAY_PATH_GSTIN_VALIDATE:/validate-gstn}
# ── OpenProject Integration ──────────────────────────────────────────────────
# Set FINERACT_OPENPROJECT_API_TOKEN as env var in production.
fineract.openproject.enabled=${FINERACT_OPENPROJECT_ENABLED:true}
fineract.openproject.base-url=${FINERACT_OPENPROJECT_BASE_URL:https://Sm.godemo.in}
fineract.openproject.project-id=${FINERACT_OPENPROJECT_PROJECT_ID:cbsnexora}
fineract.openproject.api-token=${FINERACT_OPENPROJECT_API_TOKEN:57dd9f933f113c7274e3ed3d5ca82e1e45e040c857160975087694f4d39ff596}
# ── DIP / MNRL Mobile Number Lookup ──────────────────────────────────────────
fineract.mobile-lookup.base-url=${FINERACT_MOBILE_LOOKUP_BASE_URL:http://localhost:8080}
@@ -0,0 +1,336 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
KYC module – compliant with RBI Master Direction on KYC (updated 2023).
Tables created:
m_client_kyc – one KYC record per client
m_client_kyc_verification_log – 3rd-party API call audit trail
Permissions inserted:
READ_CLIENTKYC, CREATE_CLIENTKYC, UPDATE_CLIENTKYC,
VERIFY_CLIENTKYC, REJECT_CLIENTKYC
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<!-- ═══════════════════════════════════════════════════════════════════════
MySQL – m_client_kyc
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="1" context="mysql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_client_kyc"/></not>
</preConditions>
<createTable tableName="m_client_kyc">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="client_id" type="BIGINT">
<constraints nullable="false" unique="true" uniqueConstraintName="uq_m_client_kyc_client_id"/>
</column>
<!-- kyc_status: 100=PENDING 200=IN_PROGRESS 300=VERIFIED 400=REJECTED 500=EXPIRED -->
<!-- INTEGER used (not SMALLINT) to match Java Integer JPA default mapping -->
<column name="kyc_status" type="INTEGER" defaultValueNumeric="100">
<constraints nullable="false"/>
</column>
<!-- kyc_type: 1=INDIVIDUAL 2=NON_INDIVIDUAL -->
<column name="kyc_type" type="INTEGER">
<constraints nullable="false"/>
</column>
<!-- risk_category: 1=LOW(10yr) 2=MEDIUM(8yr) 3=HIGH(2yr) -->
<column name="risk_category" type="INTEGER" defaultValueNumeric="1">
<constraints nullable="false"/>
</column>
<!-- PAN (Permanent Account Number – Income Tax Dept) -->
<column name="pan_number" type="VARCHAR(10)"/>
<column name="pan_verified" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="pan_verified_on" type="DATE"/>
<!-- Aadhaar – stored masked per UIDAI directive (only last 4 digits) -->
<column name="aadhaar_number_masked" type="VARCHAR(12)"/>
<column name="aadhaar_verified" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="aadhaar_verified_on" type="DATE"/>
<!-- GSTIN – mandatory for NON_INDIVIDUAL clients -->
<column name="gstin_number" type="VARCHAR(15)"/>
<column name="gstin_verified" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="gstin_verified_on" type="DATE"/>
<!-- CKYCRR – Central KYC Records Registry number (CERSAI) -->
<column name="ckyc_number" type="VARCHAR(14)"/>
<!-- Lifecycle timestamps -->
<column name="initiated_on" type="DATE"/>
<column name="verified_on" type="DATE"/>
<column name="rejected_on" type="DATE"/>
<!-- expiry_date: derived from risk_category * verified_on year offset -->
<column name="expiry_date" type="DATE"/>
<column name="remarks" type="VARCHAR(500)"/>
<!-- Audit fields (AbstractAuditableWithUTCDateTimeCustom) -->
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
PostgreSQL – m_client_kyc
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="1" context="postgresql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_client_kyc"/></not>
</preConditions>
<createTable tableName="m_client_kyc">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="client_id" type="BIGINT">
<constraints nullable="false" unique="true" uniqueConstraintName="uq_m_client_kyc_client_id"/>
</column>
<!-- INTEGER used (not SMALLINT) to match Java Integer JPA default mapping -->
<column name="kyc_status" type="INTEGER" defaultValueNumeric="100">
<constraints nullable="false"/>
</column>
<column name="kyc_type" type="INTEGER">
<constraints nullable="false"/>
</column>
<column name="risk_category" type="INTEGER" defaultValueNumeric="1">
<constraints nullable="false"/>
</column>
<column name="pan_number" type="VARCHAR(10)"/>
<column name="pan_verified" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="pan_verified_on" type="DATE"/>
<column name="aadhaar_number_masked" type="VARCHAR(12)"/>
<column name="aadhaar_verified" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="aadhaar_verified_on" type="DATE"/>
<column name="gstin_number" type="VARCHAR(15)"/>
<column name="gstin_verified" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="gstin_verified_on" type="DATE"/>
<column name="ckyc_number" type="VARCHAR(14)"/>
<column name="initiated_on" type="DATE"/>
<column name="verified_on" type="DATE"/>
<column name="rejected_on" type="DATE"/>
<column name="expiry_date" type="DATE"/>
<column name="remarks" type="VARCHAR(500)"/>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
FK: m_client_kyc.client_id → m_client.id
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="2">
<preConditions onFail="MARK_RAN">
<not>
<foreignKeyConstraintExists foreignKeyTableName="m_client_kyc"
foreignKeyName="FK_m_client_kyc_client_id"/>
</not>
</preConditions>
<addForeignKeyConstraint
baseTableName="m_client_kyc"
baseColumnNames="client_id"
constraintName="FK_m_client_kyc_client_id"
referencedTableName="m_client"
referencedColumnNames="id"
onDelete="RESTRICT" onUpdate="RESTRICT"
deferrable="false" initiallyDeferred="false" validate="true"/>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
MySQL – m_client_kyc_verification_log (3rd-party API audit trail)
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="3" context="mysql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_client_kyc_verification_log"/></not>
</preConditions>
<createTable tableName="m_client_kyc_verification_log">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="kyc_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<!-- verification_type: PAN | AADHAAR | GSTIN -->
<column name="verification_type" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<!-- Status: SUCCESS | FAILURE | PENDING | ERROR -->
<column name="verification_status" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<!-- External reference id returned by the 3rd-party API -->
<column name="request_reference" type="VARCHAR(100)"/>
<!-- Raw API response stored for audit -->
<column name="api_response" type="TEXT"/>
<column name="remarks" type="VARCHAR(500)"/>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- PostgreSQL – m_client_kyc_verification_log -->
<changeSet author="fineract" id="3" context="postgresql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_client_kyc_verification_log"/></not>
</preConditions>
<createTable tableName="m_client_kyc_verification_log">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="kyc_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="verification_type" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<column name="verification_status" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<column name="request_reference" type="VARCHAR(100)"/>
<column name="api_response" type="TEXT"/>
<column name="remarks" type="VARCHAR(500)"/>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- FK: m_client_kyc_verification_log.kyc_id → m_client_kyc.id -->
<changeSet author="fineract" id="4">
<preConditions onFail="MARK_RAN">
<not>
<foreignKeyConstraintExists foreignKeyTableName="m_client_kyc_verification_log"
foreignKeyName="FK_m_kyc_verification_log_kyc_id"/>
</not>
</preConditions>
<addForeignKeyConstraint
baseTableName="m_client_kyc_verification_log"
baseColumnNames="kyc_id"
constraintName="FK_m_kyc_verification_log_kyc_id"
referencedTableName="m_client_kyc"
referencedColumnNames="id"
onDelete="CASCADE" onUpdate="RESTRICT"
deferrable="false" initiallyDeferred="false" validate="true"/>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
Permissions – inserted into m_permission
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="5">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">
SELECT COUNT(*) FROM m_permission WHERE code = 'READ_CLIENTKYC'
</sqlCheck>
</preConditions>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="READ_CLIENTKYC"/>
<column name="entity_name" value="CLIENTKYC"/>
<column name="action_name" value="READ"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="CREATE_CLIENTKYC"/>
<column name="entity_name" value="CLIENTKYC"/>
<column name="action_name" value="CREATE"/>
<column name="can_maker_checker" valueBoolean="true"/>
</insert>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="UPDATE_CLIENTKYC"/>
<column name="entity_name" value="CLIENTKYC"/>
<column name="action_name" value="UPDATE"/>
<column name="can_maker_checker" valueBoolean="true"/>
</insert>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="VERIFY_CLIENTKYC"/>
<column name="entity_name" value="CLIENTKYC"/>
<column name="action_name" value="VERIFY"/>
<column name="can_maker_checker" valueBoolean="true"/>
</insert>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="REJECT_CLIENTKYC"/>
<column name="entity_name" value="CLIENTKYC"/>
<column name="action_name" value="REJECT"/>
<column name="can_maker_checker" valueBoolean="true"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.13.xsd">
<changeSet author="fineract" id="0217-1">
<addColumn tableName="m_family_members">
<column name="nomination_type" type="VARCHAR(50)" defaultValue="NULL">
<constraints nullable="true"/>
</column>
<column name="percentage_share" type="DECIMAL(5,2)" defaultValue="NULL">
<constraints nullable="true"/>
</column>
<column name="remarks" type="VARCHAR(500)" defaultValue="NULL">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">
<changeSet author="fineract" id="0218-1" context="mysql">
<addColumn tableName="m_client_kyc">
<column name="pan_full_name" type="VARCHAR(200)" />
<column name="pan_aadhaar_seeding_status" type="VARCHAR(5)" remarks="Y=YES, N=NO, NA=Not Available" />
<column name="pan_category" type="VARCHAR(50)" remarks="PAN card category e.g. individual, company, firm" />
<column name="pan_status" type="VARCHAR(20)" remarks="valid or invalid" />
</addColumn>
</changeSet>
<changeSet author="fineract" id="0218-1" context="postgresql">
<addColumn tableName="m_client_kyc">
<column name="pan_full_name" type="VARCHAR(200)" />
<column name="pan_aadhaar_seeding_status" type="VARCHAR(5)" remarks="Y=YES, N=NO, NA=Not Available" />
<column name="pan_category" type="VARCHAR(50)" remarks="PAN card category e.g. individual, company, firm" />
<column name="pan_status" type="VARCHAR(20)" remarks="valid or invalid" />
</addColumn>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="rbi_feed-1">
<createTable tableName="m_rbi_feed_item">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="title" type="VARCHAR(1000)">
<constraints nullable="false"/>
</column>
<column name="description" type="TEXT"/>
<column name="link" type="VARCHAR(1000)">
<constraints nullable="false"/>
</column>
<column name="pub_date" type="DATETIME"/>
<column name="category" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<column name="fetched_on" type="DATETIME"/>
</createTable>
<addUniqueConstraint tableName="m_rbi_feed_item" columnNames="link" constraintName="uk_rbi_feed_item_link"/>
</changeSet>
<changeSet author="fineract" id="rbi_feed-2">
<insert tableName="m_permission">
<column name="grouping" value="organisation"/>
<column name="code" value="READ_RBI_FEED"/>
<column name="entity_name" value="RBI_FEED"/>
<column name="action_name" value="READ"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
<insert tableName="m_permission">
<column name="grouping" value="organisation"/>
<column name="code" value="FETCH_RBI_FEED"/>
<column name="entity_name" value="RBI_FEED"/>
<column name="action_name" value="FETCH"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
</changeSet>
<changeSet author="fineract" id="rbi_feed-3">
<validCheckSum>ANY</validCheckSum>
<insert tableName="job">
<column name="name" value="Fetch RBI RSS Feeds"/>
<column name="display_name" value="Fetch RBI RSS Feeds"/>
<column name="short_name" value="RBIRSS"/>
<column name="cron_expression" value="0 0 */6 * * ?"/>
<column name="create_time" valueDate="${current_datetime}"/>
<column name="task_priority" valueNumeric="5"/>
<column name="group_name"/>
<column name="previous_run_start_time"/>
<column name="job_key" value="Fetch RBI RSS FeedsDetail1 _ DEFAULT"/>
<column name="initializing_errorlog"/>
<column name="is_active" valueBoolean="true"/>
<column name="currently_running" valueBoolean="false"/>
<column name="updates_allowed" valueBoolean="true"/>
<column name="scheduler_group" valueNumeric="0"/>
<column name="is_misfired" valueBoolean="false"/>
<column name="node_id" valueNumeric="1"/>
<column name="is_mismatched_job" valueBoolean="true"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet author="fineract" id="0220-1" context="default">
<comment>Add OpenProject read permission</comment>
<insert tableName="m_permission">
<column name="grouping" value="infrastructure"/>
<column name="code" value="READ_OPENPROJECT"/>
<column name="entity_name" value="OPENPROJECT"/>
<column name="action_name" value="READ"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
</changeSet>
<changeSet author="fineract" id="0220-2" context="default">
<comment>Add OpenProject create/write permission</comment>
<insert tableName="m_permission">
<column name="grouping" value="infrastructure"/>
<column name="code" value="CREATE_OPENPROJECT"/>
<column name="entity_name" value="OPENPROJECT"/>
<column name="action_name" value="CREATE"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet author="fineract" id="0221-1" context="default">
<comment>Add OpenProject work package ID and status columns to RBI feed items for tracking</comment>
<addColumn tableName="m_rbi_feed_item">
<column name="openproject_wp_id" type="BIGINT" defaultValue="null">
<constraints nullable="true"/>
</column>
<column name="openproject_wp_status" type="VARCHAR(100)" defaultValue="null">
<constraints nullable="true"/>
</column>
<column name="openproject_wp_progress" type="INT" defaultValue="null">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,276 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
Sanctions screening module – stores UN Security Council consolidated sanctions list.
Tables created:
m_sanctions_entry – individuals and entities from the UN consolidated list
m_sanctions_alias – aliases (aka) for each sanctions entry
Permissions inserted:
READ_SANCTIONS, SCREEN_SANCTIONS, LOAD_SANCTIONS
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<!-- ═══════════════════════════════════════════════════════════════════════
MySQL – m_sanctions_entry
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="1" context="mysql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_sanctions_entry"/></not>
</preConditions>
<createTable tableName="m_sanctions_entry">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="data_id" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<!-- entry_type: INDIVIDUAL or ENTITY -->
<column name="entry_type" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<column name="first_name" type="VARCHAR(255)"/>
<column name="second_name" type="VARCHAR(255)"/>
<column name="third_name" type="VARCHAR(255)"/>
<column name="fourth_name" type="VARCHAR(255)"/>
<!-- full_name: concatenation of all name parts for easy searching -->
<column name="full_name" type="VARCHAR(500)"/>
<column name="un_list_type" type="VARCHAR(255)"/>
<column name="reference_number" type="VARCHAR(255)"/>
<column name="listed_on" type="DATE"/>
<column name="gender" type="VARCHAR(20)"/>
<column name="nationality" type="VARCHAR(500)"/>
<column name="comments" type="TEXT"/>
<column name="designation" type="TEXT"/>
<column name="date_of_birth" type="VARCHAR(500)"/>
<column name="place_of_birth" type="VARCHAR(500)"/>
<column name="is_active" type="BOOLEAN" defaultValueBoolean="true">
<constraints nullable="false"/>
</column>
<!-- Audit fields -->
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
PostgreSQL – m_sanctions_entry
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="1" context="postgresql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_sanctions_entry"/></not>
</preConditions>
<createTable tableName="m_sanctions_entry">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="data_id" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<column name="entry_type" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<column name="first_name" type="VARCHAR(255)"/>
<column name="second_name" type="VARCHAR(255)"/>
<column name="third_name" type="VARCHAR(255)"/>
<column name="fourth_name" type="VARCHAR(255)"/>
<column name="full_name" type="VARCHAR(500)"/>
<column name="un_list_type" type="VARCHAR(255)"/>
<column name="reference_number" type="VARCHAR(255)"/>
<column name="listed_on" type="DATE"/>
<column name="gender" type="VARCHAR(20)"/>
<column name="nationality" type="VARCHAR(500)"/>
<column name="comments" type="TEXT"/>
<column name="designation" type="TEXT"/>
<column name="date_of_birth" type="VARCHAR(500)"/>
<column name="place_of_birth" type="VARCHAR(500)"/>
<column name="is_active" type="BOOLEAN" defaultValueBoolean="true">
<constraints nullable="false"/>
</column>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
MySQL – m_sanctions_alias (aka names for sanctions entries)
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="2" context="mysql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_sanctions_alias"/></not>
</preConditions>
<createTable tableName="m_sanctions_alias">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="sanctions_entry_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="alias_quality" type="VARCHAR(50)"/>
<column name="alias_name" type="VARCHAR(500)">
<constraints nullable="false"/>
</column>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- PostgreSQL – m_sanctions_alias -->
<changeSet author="fineract" id="2" context="postgresql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_sanctions_alias"/></not>
</preConditions>
<createTable tableName="m_sanctions_alias">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="sanctions_entry_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="alias_quality" type="VARCHAR(50)"/>
<column name="alias_name" type="VARCHAR(500)">
<constraints nullable="false"/>
</column>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- FK: m_sanctions_alias.sanctions_entry_id → m_sanctions_entry.id -->
<changeSet author="fineract" id="3">
<preConditions onFail="MARK_RAN">
<not>
<foreignKeyConstraintExists foreignKeyTableName="m_sanctions_alias"
foreignKeyName="FK_m_sanctions_alias_entry_id"/>
</not>
</preConditions>
<addForeignKeyConstraint
baseTableName="m_sanctions_alias"
baseColumnNames="sanctions_entry_id"
constraintName="FK_m_sanctions_alias_entry_id"
referencedTableName="m_sanctions_entry"
referencedColumnNames="id"
onDelete="CASCADE" onUpdate="RESTRICT"
deferrable="false" initiallyDeferred="false" validate="true"/>
</changeSet>
<!-- Index on full_name for faster name searches -->
<changeSet author="fineract" id="4">
<preConditions onFail="MARK_RAN">
<not>
<indexExists indexName="idx_sanctions_entry_full_name"/>
</not>
</preConditions>
<createIndex tableName="m_sanctions_entry" indexName="idx_sanctions_entry_full_name">
<column name="full_name"/>
</createIndex>
</changeSet>
<!-- Index on alias_name for faster alias searches -->
<changeSet author="fineract" id="5">
<preConditions onFail="MARK_RAN">
<not>
<indexExists indexName="idx_sanctions_alias_name"/>
</not>
</preConditions>
<createIndex tableName="m_sanctions_alias" indexName="idx_sanctions_alias_name">
<column name="alias_name"/>
</createIndex>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
Permissions
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="6">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">
SELECT COUNT(*) FROM m_permission WHERE code = 'READ_SANCTIONS'
</sqlCheck>
</preConditions>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="READ_SANCTIONS"/>
<column name="entity_name" value="SANCTIONS"/>
<column name="action_name" value="READ"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="SCREEN_SANCTIONS"/>
<column name="entity_name" value="SANCTIONS"/>
<column name="action_name" value="SCREEN"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="LOAD_SANCTIONS"/>
<column name="entity_name" value="SANCTIONS"/>
<column name="action_name" value="LOAD"/>
<column name="can_maker_checker" valueBoolean="true"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
Sanctions screening activity log – records every name screening request and result.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<!-- MySQL – m_sanctions_screening_log -->
<changeSet author="fineract" id="1" context="mysql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_sanctions_screening_log"/></not>
</preConditions>
<createTable tableName="m_sanctions_screening_log">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="screened_name" type="VARCHAR(500)">
<constraints nullable="false"/>
</column>
<!-- FLAGGED or CLEAR -->
<column name="screening_result" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<column name="match_count" type="INTEGER" defaultValueNumeric="0">
<constraints nullable="false"/>
</column>
<!-- Comma-separated matched entry IDs for reference -->
<column name="matched_entry_ids" type="VARCHAR(1000)"/>
<!-- Comma-separated matched names for quick reference -->
<column name="matched_names" type="VARCHAR(2000)"/>
<!-- CLIENT_CREATION, MANUAL_CHECK, etc. -->
<column name="screening_source" type="VARCHAR(50)"/>
<!-- Optional: client ID if screening during client creation -->
<column name="client_id" type="BIGINT"/>
<column name="ip_address" type="VARCHAR(50)"/>
<column name="screened_on" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- PostgreSQL – m_sanctions_screening_log -->
<changeSet author="fineract" id="1" context="postgresql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_sanctions_screening_log"/></not>
</preConditions>
<createTable tableName="m_sanctions_screening_log">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="screened_name" type="VARCHAR(500)">
<constraints nullable="false"/>
</column>
<column name="screening_result" type="VARCHAR(20)">
<constraints nullable="false"/>
</column>
<column name="match_count" type="INTEGER" defaultValueNumeric="0">
<constraints nullable="false"/>
</column>
<column name="matched_entry_ids" type="VARCHAR(1000)"/>
<column name="matched_names" type="VARCHAR(2000)"/>
<column name="screening_source" type="VARCHAR(50)"/>
<column name="client_id" type="BIGINT"/>
<column name="ip_address" type="VARCHAR(50)"/>
<column name="screened_on" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- Index on screened_name for searching logs -->
<changeSet author="fineract" id="2">
<preConditions onFail="MARK_RAN">
<not><indexExists indexName="idx_sanctions_log_screened_name"/></not>
</preConditions>
<createIndex tableName="m_sanctions_screening_log" indexName="idx_sanctions_log_screened_name">
<column name="screened_name"/>
</createIndex>
</changeSet>
<!-- Index on screened_on for date range queries -->
<changeSet author="fineract" id="3">
<preConditions onFail="MARK_RAN">
<not><indexExists indexName="idx_sanctions_log_screened_on"/></not>
</preConditions>
<createIndex tableName="m_sanctions_screening_log" indexName="idx_sanctions_log_screened_on">
<column name="screened_on"/>
</createIndex>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
Mobile Number Lookup – activity log for DIP / MNRL lookups.
Table created:
m_mobile_lookup_log – logs every mobile number lookup request and response
Permissions inserted:
READ_MOBILE_LOOKUP
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<!-- ═══════════════════════════════════════════════════════════════════════
MySQL – m_mobile_lookup_log
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="1" context="mysql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_mobile_lookup_log"/></not>
</preConditions>
<createTable tableName="m_mobile_lookup_log">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="mobile_number" type="VARCHAR(15)">
<constraints nullable="false"/>
</column>
<!-- CLEAN, SUSPECTED, DISCONNECTED, SUSPECTED_AND_DISCONNECTED, ERROR -->
<column name="lookup_status" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<column name="suspected" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="disconnected" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="response_message" type="VARCHAR(500)"/>
<column name="raw_response" type="TEXT"/>
<!-- CLIENT_REGISTRATION, MANUAL_CHECK, API -->
<column name="lookup_source" type="VARCHAR(50)"/>
<column name="client_id" type="BIGINT"/>
<column name="looked_up_on" type="DATETIME">
<constraints nullable="false"/>
</column>
<!-- Audit fields -->
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="DATETIME">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- PostgreSQL – m_mobile_lookup_log -->
<changeSet author="fineract" id="1" context="postgresql">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_mobile_lookup_log"/></not>
</preConditions>
<createTable tableName="m_mobile_lookup_log">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="mobile_number" type="VARCHAR(15)">
<constraints nullable="false"/>
</column>
<column name="lookup_status" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<column name="suspected" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="disconnected" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="response_message" type="VARCHAR(500)"/>
<column name="raw_response" type="TEXT"/>
<column name="lookup_source" type="VARCHAR(50)"/>
<column name="client_id" type="BIGINT"/>
<column name="looked_up_on" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="created_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
<column name="last_modified_by" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- Index on mobile_number for faster lookups -->
<changeSet author="fineract" id="2">
<preConditions onFail="MARK_RAN">
<not>
<indexExists indexName="idx_mobile_lookup_log_number"/>
</not>
</preConditions>
<createIndex tableName="m_mobile_lookup_log" indexName="idx_mobile_lookup_log_number">
<column name="mobile_number"/>
</createIndex>
</changeSet>
<!-- Index on looked_up_on for recent-first queries -->
<changeSet author="fineract" id="3">
<preConditions onFail="MARK_RAN">
<not>
<indexExists indexName="idx_mobile_lookup_log_looked_up_on"/>
</not>
</preConditions>
<createIndex tableName="m_mobile_lookup_log" indexName="idx_mobile_lookup_log_looked_up_on">
<column name="looked_up_on"/>
</createIndex>
</changeSet>
<!-- ═══════════════════════════════════════════════════════════════════════
Permissions
═══════════════════════════════════════════════════════════════════ -->
<changeSet author="fineract" id="4">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">
SELECT COUNT(*) FROM m_permission WHERE code = 'READ_MOBILE_LOOKUP'
</sqlCheck>
</preConditions>
<insert tableName="m_permission">
<column name="grouping" value="portfolio"/>
<column name="code" value="READ_MOBILE_LOOKUP"/>
<column name="entity_name" value="MOBILE_LOOKUP"/>
<column name="action_name" value="READ"/>
<column name="can_maker_checker" valueBoolean="false"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -35,10 +35,25 @@
</encoder>
</appender>
<!-- File appender — logs saved to logs/fineract.log, rotated daily, max 30 days -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/fineract.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/fineract.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} : %msg%n</pattern>
</encoder>
</appender>
<!-- But these three INFO are still handy ;-) just to see when it's up and running -->
<logger name="org.springframework.boot.web.embedded.tomcat.TomcatWebServer" level="info"/>
<logger name="org.apache.fineract.ServerApplication" level="info"/>
<logger name="org.apache.fineract" level="${FINERACT_LOGGING_LEVEL:-INFO}"/>
<!-- DEBUG for RBI Feed and OpenProject modules -->
<logger name="org.apache.fineract.infrastructure.rbifeed" level="DEBUG"/>
<logger name="org.apache.fineract.infrastructure.openproject" level="DEBUG"/>
<logger name="liquibase" level="warn"/>
<if condition="${jsonLoggingEnabled} == true">
@@ -61,6 +76,7 @@
but it's still possible to override this using java -Dlogging.level.root=info -jar fineract-provider.jar, as per https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-custom-log-levels -->
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</else>
</if>