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
@@ -24,7 +24,8 @@ public enum ChargeAppliesTo {
LOAN(1, "chargeAppliesTo.loan"), //
SAVINGS(2, "chargeAppliesTo.savings"), //
CLIENT(3, "chargeAppliesTo.client"), //
SHARES(4, "chargeAppliesTo.shares"); //
SHARES(4, "chargeAppliesTo.shares"), //
CURRENT_ACCOUNT(5, "chargeAppliesTo.currentAccount"); //
private final Integer value;
private final String code;
@@ -59,6 +60,9 @@ public enum ChargeAppliesTo {
case 4:
chargeAppliesToType = SHARES;
break;
case 5:
chargeAppliesToType = CURRENT_ACCOUNT;
break;
default:
chargeAppliesToType = INVALID;
break;
@@ -84,8 +88,12 @@ public enum ChargeAppliesTo {
return this.value.equals(SHARES.getValue());
}
public boolean isCurrentAccountCharge() {
return this.value.equals(CURRENT_ACCOUNT.getValue());
}
public static Object[] validValues() {
return new Object[] { ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.getValue(), ChargeAppliesTo.CLIENT.getValue(),
ChargeAppliesTo.SHARES.getValue() };
ChargeAppliesTo.SHARES.getValue(), ChargeAppliesTo.CURRENT_ACCOUNT.getValue() };
}
}
@@ -53,6 +53,10 @@ public enum ChargeCalculationType {
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
}
public static Object[] validValuesForCurrentAccount() {
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
}
public static Object[] validValuesForShares() {
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
}
@@ -255,6 +255,38 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
.isOneOfTheseValues(ChargeCalculationType.validValuesForShareAccountActivation());
}
} else if (appliesTo.isCurrentAccountCharge()) {
// current account applicable validation — same rules as savings
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_TIME_TYPE, element);
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType).notNull();
if (chargeTimeType != null) {
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType)
.isOneOfTheseValues(ChargeTimeType.validCurrentAccountValues());
}
final ChargeTimeType ctt = ChargeTimeType.fromInt(chargeTimeType);
if (ctt.isWeeklyFee()) {
final String monthDay = this.fromApiJsonHelper.extractStringNamed(FEE_ON_MONTH_DAY, element);
baseDataValidator.reset().parameter(FEE_ON_MONTH_DAY).value(monthDay).mustBeBlankWhenParameterProvidedIs(CHARGE_TIME_TYPE,
chargeTimeType);
}
if (ctt.isMonthlyFee()) {
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed(FEE_ON_MONTH_DAY, element);
baseDataValidator.reset().parameter(FEE_ON_MONTH_DAY).value(monthDay).notNull();
baseDataValidator.reset().parameter(FEE_INTERVAL).value(feeInterval).notNull().inMinMaxRange(1, 12);
}
if (ctt.isAnnualFee()) {
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed(FEE_ON_MONTH_DAY, element);
baseDataValidator.reset().parameter(FEE_ON_MONTH_DAY).value(monthDay).notNull();
}
if (chargeCalculationType != null) {
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
.isOneOfTheseValues(ChargeCalculationType.validValuesForCurrentAccount());
}
}
final String name = this.fromApiJsonHelper.extractStringNamed(NAME, element);
@@ -47,4 +47,8 @@ public interface ChargeDropdownReadPlatformService {
List<EnumOptionData> retrieveSharesCollectionTimeTypes();
List<EnumOptionData> retrieveCurrentAccountCalculationTypes();
List<EnumOptionData> retrieveCurrentAccountCollectionTimeTypes();
}
@@ -124,4 +124,18 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
return Arrays.asList(chargeTimeType(ChargeTimeType.SHAREACCOUNT_ACTIVATION), chargeTimeType(ChargeTimeType.SHARE_PURCHASE),
chargeTimeType(ChargeTimeType.SHARE_REDEEM));
}
@Override
public List<EnumOptionData> retrieveCurrentAccountCalculationTypes() {
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT));
}
@Override
public List<EnumOptionData> retrieveCurrentAccountCollectionTimeTypes() {
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE), chargeTimeType(ChargeTimeType.SAVINGS_ACTIVATION),
chargeTimeType(ChargeTimeType.WITHDRAWAL_FEE), chargeTimeType(ChargeTimeType.ANNUAL_FEE),
chargeTimeType(ChargeTimeType.MONTHLY_FEE), chargeTimeType(ChargeTimeType.WEEKLY_FEE),
chargeTimeType(ChargeTimeType.OVERDRAFT_FEE), chargeTimeType(ChargeTimeType.SAVINGS_NOACTIVITY_FEE));
}
}
@@ -130,6 +130,10 @@ public final class ChargeEnumerations {
case SHARES:
optionData = new EnumOptionData(ChargeAppliesTo.SHARES.getValue().longValue(), ChargeAppliesTo.SHARES.getCode(), "Shares");
break;
case CURRENT_ACCOUNT:
optionData = new EnumOptionData(ChargeAppliesTo.CURRENT_ACCOUNT.getValue().longValue(),
ChargeAppliesTo.CURRENT_ACCOUNT.getCode(), "Current Account");
break;
default:
optionData = new EnumOptionData(ChargeAppliesTo.INVALID.getValue().longValue(), ChargeAppliesTo.INVALID.getCode(),
"Invalid");