Add Current Account module mirroring Savings Account infrastructure

- CurrentAccount entity (@DiscriminatorValue 400) extending SavingsAccount
- 4 JAX-RS API resources: /v1/currentaccounts, /v1/currentproducts, transactions, charges
- 38 command handlers delegating to existing savings services
- ~35 CommandWrapperBuilder methods for current account commands
- DB migration 0225 with 67 permissions (CURRENTACCOUNT, CURRENTPRODUCT, CURRENTACCOUNTCHARGE)
- DepositsApiConstants and DepositAccountType enum updated for CURRENT_DEPOSIT

Reuses existing m_savings_account table (deposit_type_enum=400), GL accounting,
interest calculation, and all savings write/read services — no code duplication.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aditya
2026-03-17 18:16:36 +05:30
co-authored by Claude Opus 4.6
parent 5d4f57912d
commit 6a464291d5
48 changed files with 3626 additions and 0 deletions
@@ -573,6 +573,80 @@ public class CommandWrapperBuilder {
return this;
}
// ── KYC ──────────────────────────────────────────────────────────────────
public CommandWrapperBuilder initiateClientKyc(final Long clientId) {
this.actionName = "CREATE";
this.entityName = "CLIENTKYC";
this.entityId = null;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc";
return this;
}
public CommandWrapperBuilder updateClientKyc(final Long clientId, final Long kycId) {
this.actionName = "UPDATE";
this.entityName = "CLIENTKYC";
this.entityId = kycId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc/" + kycId;
return this;
}
public CommandWrapperBuilder verifyClientKyc(final Long clientId, final Long kycId) {
this.actionName = "VERIFY";
this.entityName = "CLIENTKYC";
this.entityId = kycId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc/" + kycId + "?command=verify";
return this;
}
public CommandWrapperBuilder rejectClientKyc(final Long clientId, final Long kycId) {
this.actionName = "REJECT";
this.entityName = "CLIENTKYC";
this.entityId = kycId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc/" + kycId + "?command=reject";
return this;
}
public CommandWrapperBuilder generateAadhaarOtpClientKyc(final Long clientId, final Long kycId) {
this.actionName = "GENERATEAADHAROTP";
this.entityName = "CLIENTKYC";
this.entityId = kycId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc/" + kycId + "?command=aadhaar-generate-otp";
return this;
}
public CommandWrapperBuilder verifyPanClientKyc(final Long clientId, final Long kycId) {
this.actionName = "VERIFYPAN";
this.entityName = "CLIENTKYC";
this.entityId = kycId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc/" + kycId + "?command=verify-pan";
return this;
}
public CommandWrapperBuilder verifyAadhaarClientKyc(final Long clientId, final Long kycId) {
this.actionName = "VERIFYAADHAAR";
this.entityName = "CLIENTKYC";
this.entityId = kycId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc/" + kycId + "?command=verify-aadhaar";
return this;
}
public CommandWrapperBuilder verifyGstinClientKyc(final Long clientId, final Long kycId) {
this.actionName = "VERIFYGSTIN";
this.entityName = "CLIENTKYC";
this.entityId = kycId;
this.clientId = clientId;
this.href = "/clients/" + clientId + "/kyc/" + kycId + "?command=verify-gstin";
return this;
}
public CommandWrapperBuilder createClient() {
this.actionName = "CREATE";
this.entityName = "CLIENT";
@@ -3354,6 +3428,351 @@ public class CommandWrapperBuilder {
return this;
}
// ── Current Account ─────────────────────────────────────────────────────────
public CommandWrapperBuilder createCurrentProduct() {
this.actionName = "CREATE";
this.entityName = "CURRENTPRODUCT";
this.entityId = null;
this.href = "/currentproducts/template";
return this;
}
public CommandWrapperBuilder updateCurrentProduct(final Long productId) {
this.actionName = "UPDATE";
this.entityName = "CURRENTPRODUCT";
this.entityId = productId;
this.href = "/currentproducts/" + productId;
return this;
}
public CommandWrapperBuilder deleteCurrentProduct(final Long productId) {
this.actionName = "DELETE";
this.entityName = "CURRENTPRODUCT";
this.entityId = productId;
this.href = "/currentproducts/" + productId;
return this;
}
public CommandWrapperBuilder createCurrentAccount() {
this.actionName = "CREATE";
this.entityName = "CURRENTACCOUNT";
this.entityId = null;
this.href = "/currentaccounts/template";
return this;
}
public CommandWrapperBuilder updateCurrentAccount(final Long accountId) {
this.actionName = "UPDATE";
this.entityName = "CURRENTACCOUNT";
this.entityId = accountId;
this.href = "/currentaccounts/" + accountId;
return this;
}
public CommandWrapperBuilder deleteCurrentAccount(final Long accountId) {
this.actionName = "DELETE";
this.entityName = "CURRENTACCOUNT";
this.entityId = accountId;
this.href = "/currentaccounts/" + accountId;
return this;
}
public CommandWrapperBuilder rejectCurrentAccountApplication(final Long accountId) {
this.actionName = "REJECT";
this.entityName = "CURRENTACCOUNT";
this.entityId = accountId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=reject";
return this;
}
public CommandWrapperBuilder withdrawCurrentAccountApplication(final Long accountId) {
this.actionName = "WITHDRAW";
this.entityName = "CURRENTACCOUNT";
this.entityId = accountId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=withdrawnByApplicant";
return this;
}
public CommandWrapperBuilder approveCurrentAccountApplication(final Long accountId) {
this.actionName = "APPROVE";
this.entityName = "CURRENTACCOUNT";
this.entityId = accountId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=approve";
return this;
}
public CommandWrapperBuilder undoCurrentAccountApplication(final Long accountId) {
this.actionName = "APPROVALUNDO";
this.entityName = "CURRENTACCOUNT";
this.entityId = accountId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=undoapproval";
return this;
}
public CommandWrapperBuilder currentAccountActivation(final Long accountId) {
this.actionName = "ACTIVATE";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=activate";
return this;
}
public CommandWrapperBuilder closeCurrentAccountApplication(final Long accountId) {
this.actionName = "CLOSE";
this.entityName = "CURRENTACCOUNT";
this.entityId = accountId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=close";
return this;
}
public CommandWrapperBuilder currentAccountDeposit(final Long accountId) {
this.actionName = "DEPOSIT";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "/transactions";
return this;
}
public CommandWrapperBuilder currentAccountWithdrawal(final Long accountId) {
this.actionName = "WITHDRAWAL";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "/transactions";
return this;
}
public CommandWrapperBuilder undoCurrentAccountTransaction(final Long accountId, final Long transactionId) {
this.actionName = "UNDOTRANSACTION";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.subentityId = transactionId;
this.transactionId = transactionId.toString();
this.href = "/currentaccounts/" + accountId + "/transactions/" + transactionId + "?command=undo";
return this;
}
public CommandWrapperBuilder reverseCurrentAccountTransaction(final Long accountId, final Long transactionId) {
this.actionName = "REVERSETRANSACTION";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.subentityId = transactionId;
this.transactionId = transactionId.toString();
this.href = "/currentaccounts/" + accountId + "/transactions/" + transactionId + "?command=reverse";
return this;
}
public CommandWrapperBuilder adjustCurrentAccountTransaction(final Long accountId, final Long transactionId) {
this.actionName = "ADJUSTTRANSACTION";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.subentityId = transactionId;
this.transactionId = transactionId.toString();
this.href = "/currentaccounts/" + accountId + "/transactions/" + transactionId + "?command=modify";
return this;
}
public CommandWrapperBuilder currentAccountInterestCalculation(final Long accountId) {
this.actionName = "CALCULATEINTEREST";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=calculateInterest";
return this;
}
public CommandWrapperBuilder currentAccountInterestPosting(final Long accountId) {
this.actionName = "POSTINTEREST";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=postInterest";
return this;
}
public CommandWrapperBuilder currentAccountInterestPostingAsOnDate(final Long accountId) {
this.actionName = "POSTINTERESTASONDATE";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=postInterestAsOnDate";
return this;
}
public CommandWrapperBuilder currentAccountApplyAnnualFees(final Long accountId) {
this.actionName = "APPLYANNUALFEE";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=applyAnnualFees";
return this;
}
public CommandWrapperBuilder holdAmountCurrentAccount(final Long accountId) {
this.actionName = "HOLDAMOUNT";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "/transactions";
return this;
}
public CommandWrapperBuilder releaseAmountCurrentAccount(final Long accountId, final Long transactionId) {
this.actionName = "RELEASEAMOUNT";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.subentityId = transactionId;
this.transactionId = transactionId.toString();
this.href = "/currentaccounts/" + accountId + "/transactions/" + transactionId + "?command=releaseAmount";
return this;
}
public CommandWrapperBuilder blockCurrentAccount(final Long accountId) {
this.actionName = "BLOCK";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=block";
return this;
}
public CommandWrapperBuilder unblockCurrentAccount(final Long accountId) {
this.actionName = "UNBLOCK";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=unblock";
return this;
}
public CommandWrapperBuilder blockDebitsFromCurrentAccount(final Long accountId) {
this.actionName = "BLOCKDEBIT";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=blockDebit";
return this;
}
public CommandWrapperBuilder unblockDebitsFromCurrentAccount(final Long accountId) {
this.actionName = "UNBLOCKDEBIT";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=unblockDebit";
return this;
}
public CommandWrapperBuilder blockCreditsToCurrentAccount(final Long accountId) {
this.actionName = "BLOCKCREDIT";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=blockCredit";
return this;
}
public CommandWrapperBuilder unblockCreditsToCurrentAccount(final Long accountId) {
this.actionName = "UNBLOCKCREDIT";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=unblockCredit";
return this;
}
public CommandWrapperBuilder assignCurrentAccountOfficer(final Long accountId) {
this.actionName = "UPDATESAVINGSOFFICER";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=assignSavingsOfficer";
return this;
}
public CommandWrapperBuilder unassignCurrentAccountOfficer(final Long accountId) {
this.actionName = "REMOVESAVINGSOFFICER";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/currentaccounts/" + accountId + "?command=unassignSavingsOfficer";
return this;
}
public CommandWrapperBuilder updateWithHoldTaxCurrentAccount(final Long accountId) {
this.actionName = "UPDATEWITHHOLDTAX";
this.entityName = "CURRENTACCOUNT";
this.savingsId = accountId;
this.entityId = accountId;
this.href = "/currentaccounts/" + accountId + "?command=updateWithHoldTax";
return this;
}
public CommandWrapperBuilder createCurrentAccountCharge(final Long accountId) {
this.actionName = "CREATE";
this.entityName = "CURRENTACCOUNTCHARGE";
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "/charges";
return this;
}
public CommandWrapperBuilder updateCurrentAccountCharge(final Long accountId, final Long chargeId) {
this.actionName = "UPDATE";
this.entityName = "CURRENTACCOUNTCHARGE";
this.entityId = chargeId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "/charges/" + chargeId;
return this;
}
public CommandWrapperBuilder waiveCurrentAccountCharge(final Long accountId, final Long chargeId) {
this.actionName = "WAIVE";
this.entityName = "CURRENTACCOUNTCHARGE";
this.entityId = chargeId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "/charges/" + chargeId;
return this;
}
public CommandWrapperBuilder payCurrentAccountCharge(final Long accountId, final Long chargeId) {
this.actionName = "PAY";
this.entityName = "CURRENTACCOUNTCHARGE";
this.entityId = chargeId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "/charges/" + chargeId;
return this;
}
public CommandWrapperBuilder inactivateCurrentAccountCharge(final Long accountId, final Long chargeId) {
this.actionName = "INACTIVATE";
this.entityName = "CURRENTACCOUNTCHARGE";
this.entityId = chargeId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "/charges/" + chargeId;
return this;
}
public CommandWrapperBuilder deleteCurrentAccountCharge(final Long accountId, final Long chargeId) {
this.actionName = "DELETE";
this.entityName = "CURRENTACCOUNTCHARGE";
this.entityId = chargeId;
this.savingsId = accountId;
this.href = "/currentaccounts/" + accountId + "/charges/" + chargeId;
return this;
}
public CommandWrapperBuilder disableAdHoc(Long adHocId) {
this.actionName = "DISABLE";
this.entityName = "ADHOC";
@@ -91,6 +91,7 @@ public enum DepositAccountType {
case FIXED_DEPOSIT -> DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME;
case RECURRING_DEPOSIT -> DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME;
case SAVINGS_DEPOSIT -> DepositsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
case CURRENT_DEPOSIT -> DepositsApiConstants.CURRENT_ACCOUNT_RESOURCE_NAME;
default -> "INVALID";
};
}
@@ -41,6 +41,11 @@ public final class DepositsApiConstants {
public static final String SAVINGS_ACCOUNT_TRANSACTION_RESOURCE_NAME = "savingsaccount.transaction";
public static final String SAVINGS_ACCOUNT_CHARGE_RESOURCE_NAME = "savingsaccountcharge";
// Current accounts
public static final String CURRENT_ACCOUNT_RESOURCE_NAME = "currentaccount";
public static final String CURRENT_PRODUCT_RESOURCE_NAME = "currentproduct";
public static final String CURRENT_ACCOUNT_CHARGE_RESOURCE_NAME = "currentaccountcharge";
// deposit product actions
public static final String summitalAction = ".summital";
public static final String approvalAction = ".approval";