26 Commits
Author SHA1 Message Date
Aditya ae7017ca81 @
feat(fundtransfer+imps+mfa): fund transfer module, IMPS switch client, MFA log API

- Fund transfer: NEFT/RTGS/IMPS/internal strategies, limit resolution, bulk
  transfer, verification tokens, suspense GL, recall/approval flow, jobs
- IMPS CBS switch client with crypto (JWT/envelope) and transaction domain
- MFA log read API (audit of MFA events)
- Liquibase migrations 0300-0311 for fund transfer / IMPS tables, permissions,
  roles, and suspense account
- JobName, SecurityConfig, dependencies.gradle wiring

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
2026-06-01 12:18:30 +05:30
Aditya 6413befe07 Merge self-hosted/feature/account-charges into feature/Backend-DSC-MFA 2026-06-01 12:14:49 +05:30
AdityaandClaude Opus 4.7 45585ecc10 Fix family-member PUT 500; CORS POST 403; Hikari local password default
- ClientFamilyMembersWritePlatformServiceImpl#updateFamilyMember: guard
  maritalStatusId/genderId/professionId with != null instead of != 0 so a
  payload that omits these keys doesn't NPE when the boxed Long is unboxed.
- application.properties: fix the broken property name
  `fineract.security.cors.allowed-metho pas` -> `allowed-methods`. The typo
  left CORS allowed-methods empty, which made Spring reject every browser
  POST with "Invalid CORS request" 403 once the SPA sent an Origin header.
- application.properties: change the Hikari default password from 313863
  to root so the local devRun matches the tenant-DB default at line 49.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 13:07:24 +05:30
AdityaandClaude Opus 4.7 7dea88d30f Fix family-member PUT 500; CORS POST 403; Hikari local password default
- ClientFamilyMembersWritePlatformServiceImpl#updateFamilyMember: guard
  maritalStatusId/genderId/professionId with != null instead of != 0 so a
  payload that omits these keys doesn't NPE when the boxed Long is unboxed.
- application.properties: fix the broken property name
  `fineract.security.cors.allowed-metho pas` -> `allowed-methods`. The typo
  left CORS allowed-methods empty, which made Spring reject every browser
  POST with "Invalid CORS request" 403 once the SPA sent an Origin header.
- application.properties: change the Hikari default password from 313863
  to root so the local devRun matches the tenant-DB default at line 49.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 13:06:38 +05:30
AdityaandClaude Opus 4.7 5a98a89839 KYC: PAN entity-branch, defensive LincPay parse, family/nominee rules for non-individuals
PAN verify for non-individual clients was sending name="" + dob=null to LincPay because
the code path always read firstname/middlename/lastname (NULL on entities) and
client.dateOfBirth (also NULL on entities). LincPay then returned plain-text "Invalid
DOB format. Required format is dd/MM/yyyy", which Gson can't parse (MalformedJsonException
at line 1 col 10), surfacing as a useless 503. Now ClientKycWritePlatformServiceJpa-
RepositoryImpl.verifyPan branches on LegalForm:
  - PERSON  → name = firstname + middlename + lastname,    dob = client.dateOfBirth
  - ENTITY  → name = client.fullname,                       dob = clientNonPerson.dateOfRegistration
Injected ClientNonPersonRepositoryWrapper for the entity branch.

ClientNonPerson got two missing getters (getConstitution, getDateOfRegistration) needed
by the above plus the family/nominee rules below.

Defensive JSON parse in LincPayKycVerificationServiceImpl: parseJson now returns null
when the body doesn't even start with '{' or '[' (i.e. vendor sent plain text or HTML),
logs the literal body at WARN, and every verify method (PAN, GSTIN, Aadhaar OTP gen,
Aadhaar OTP verify, CIN, DIN) checks for null and returns
  "<X> verification failed — vendor returned non-JSON: <first 200 chars>"
So future vendor outages surface the actual response text instead of a MalformedJson-
Exception with no context.

Non-individual client rules:
- ClientFamilyMembersWritePlatformService: addFamilyMember / addClientFamilyMember /
  updateFamilyMember now refuse with PlatformApiDataValidationException when the client
  is an entity. Family members are an individual-only concept. Delete is intentionally
  unguarded so legacy rows can be cleaned up.
- ClientNomineeWritePlatformService: addNominee / updateNominee refuse for non-individual
  clients UNLESS the constitution normalises to PROPRIETORSHIP (matches both
  "PROPRIETOR SHIP" and "PROPRIETORSHIP"). Proprietorships are operationally individuals
  with a separate trade name, so they keep nominee support; companies / LLPs / trusts /
  societies / HUFs / partnerships don't carry a nomination concept. Delete unguarded.

Verified the LincPay endpoints directly:
  /validate-pan   AQRPV8345E + "Aditya Vyas" + 19/12/1988      → valid (individual)
  /validate-pan   AAMCG5406B + "GIZMOGLADE..." + 01/12/2025    → valid (company)
  /validate-pan   AAMCG5406B + ""             + ""             → "Invalid DOB format" plain text (the failing path)
  /validate-gstn  23AADCL9984A1ZH                              → 200 with full company data
  /validate-gstn  21AAMCG5406BIZ6                              → 400 "Invalid GSTIN pattern" (bad checksum, not our bug)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:46:34 +05:30
Aditya d5157ef701 Merge remote-tracking branch 'self-hosted/feature/account-charges' into feature/Backend-DSC-MFA 2026-05-21 16:15:28 +05:30
AdityaandClaude Opus 4.7 c6f130e116 Fix BadSqlGrammarException on GET /clients?status=pending — missing SELECT column
The second schema() builder used by the clients-list query had the JOIN
  left join m_client gc on gc.id = c.guardian_client_id
and the SELECT
  c.guardian_client_id as guardianClientId
but was missing
  gc.display_name as guardianClientDisplayName
which the RowMapper still reads (rs.getString("guardianClientDisplayName")).

Result: PSQLException "The column name guardianClientDisplayName was not found
in this ResultSet" → BadSqlGrammarException → 500 on any client-list pull.

The matching first builder (~line 327) had both columns correctly. Added the
missing SELECT line to keep the pair consistent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 15:35:59 +05:30
Aditya be26ba16c9 Merge remote-tracking branch 'self-hosted/feature/account-charges' into feature/Backend-DSC-MFA
# Conflicts:
#	fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
2026-05-20 13:26:58 +05:30
AdityaandClaude Opus 4.7 8b4351013e Client uniqueness pre-save check + seed all Indian states & UTs
Pre-save validator (ClientWritePlatformServiceJpaRepositoryImpl.validateClientUniqueness)
rejects duplicate mobile / email / PAN / Aadhaar (masked) / GSTIN before saveAndFlush
and before the LincPay KYC API call. Avoids burning vendor credits on identity-duplicate
records and gives the UI a clean field-level 403 instead of waiting for the DB constraint.

Splits the new repository finders into "create" and "excluding-self" variants so a
nullable Long parameter never reaches PostgreSQL's parser (same bigint <> varchar trap
that broke the family-member POST earlier).

Also seeds the full set of 28 Indian States + 8 UTs as STATE code_values (migration
0297). Previously only MAHARASHTRA / MADHYA_PRADESH / DELHI existed and the names were
UPPER_SNAKE_CASE; the postal PIN-lookup service returns "Madhya Pradesh" so any state
other than Maharashtra/Delhi silently failed to resolve to m_address.state_province_id.
Renames the 3 existing rows in place (preserves their ids/FKs) and inserts the missing
33 with idempotent preConditions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:31:54 +05:30
AdityaandClaude Opus 4.7 026e5fb875 Fix family-member POST: null JPQL param caused bigint <> varchar SQL error
The relationship-uniqueness query used (:excludeId IS NULL OR fm.id <> :excludeId).
On create, excludeId is null and PostgreSQL parses the parameter as varchar before
the IS NULL branch can short-circuit, so adding a family member returned 403 with
"operator does not exist: bigint <> character varying". Split into two queries so
neither has a nullable Long parameter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 09:40:14 +05:30
Aditya 28fa6d9615 Merge feature/Backend-DSC-MFA into feature/merge_update_code
Brings TOTP / Google Authenticator MFA factor (device mapping at
/v1/mfa/totp/setup + /verify, login via existing twofactor pipeline),
DSC-2FA login UI fix, Individual-only filter on guardian/nominee/family
link pickers, Title Case normalization on client names, and migration
0296 unique nominee per account type.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

# Conflicts:
#	.claude/settings.local.json
#	fineract-provider/logs/fineract.log
2026-05-15 17:54:49 +05:30
AdityaandClaude Opus 4.7 45a041b023 Add Google Authenticator (TOTP) as MFA factor: device mapping + login
Backend:
- New dependency dev.samstevens.totp:totp:1.7.1 (bundles ZXing for QR PNG).
- TotpService: secret/QR/otpauth-URL/verify primitives. SHA1, 6 digits, 30s —
  the standard combo every consumer authenticator app accepts unconfigured.
  Issuer label is configurable via FINERACT_MFA_TOTP_ISSUER, defaults to
  "CBSnexora".
- Two-step device mapping driven by TotpEnrollmentService:
  * POST /v1/mfa/totp/setup  — generate secret, upsert m_user_mfa_factor row
    as factor_type=TOTP/verified=false, return {secret, qrDataUri, otpAuthUrl,
    issuer, factorId}. Refuses to overwrite an already-verified-and-active
    factor so an accidental click can't unbind the user's working device.
  * POST /v1/mfa/totp/verify — body {code}; verify against the stored secret
    and flip verified=true on success.
- Login wiring in MfaFactorBackedTwoFactorServiceImpl:
  * getDeliveryMethodsForUser surfaces verified TOTP factors as
    {name:"totp", target:"Google Authenticator"} so the picker offers it
    alongside SMS/EMAIL.
  * createNewOTPToken("totp") creates a no-op OTPRequest (no LincPay/SMTP
    round-trip) carrying the factor id in the token field so validate can
    look up the secret.
  * createAccessTokenFromOTP branches on channel — TOTP path verifies code
    vs factor.secret with totp library (sliding 1-step window) and mints
    a TFAccessToken with the same lifetime + extended-token logic as OTP.
  * Defence-in-depth: re-checks at validate time that the factor still
    belongs to the user, is verified, and not disabled.
- TwoFactorConstants.TOTP_DELIVERY_METHOD_NAME = "totp".
- SecurityConfig: /api/*/mfa/totp/** is fullyAuthenticated() (exempt from
  the TFA gate so users can enrol before they can satisfy 2FA).

UI changes pending (see chat): add a "Google Authenticator" tile on the
MFA Factors settings page that calls /setup → shows QR + secret → calls
/verify; extend two-factor-authentication.component.ts iconFor() and copy
for the new "totp" delivery method. Existing requestOTP / validateOTP
pipeline handles the login flow transparently.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:41:55 +05:30
AdityaandClaude Opus 4.7 6558ea6998 DSC-2FA login fix + Individual-only link pickers + Title Case names
- DSC-as-2FA login: UI's claimAndValidate() now calls a new
  AuthenticationService.applyTwoFactorToken(token, liveSeconds) instead of
  validateOTP(). The /v1/login/dsc/{rn}/claim response is already a minted
  TFAccessToken — POSTing it to /twofactor/validate fails because that path
  expects an in-memory OTPRequest. applyTwoFactorToken runs only the
  post-success bookkeeping (interceptor.setTwoFactorAccessToken, setCredentials,
  Authentication Success alert that drives router.navigate(['/']), and
  sessionStorage persist of {token, validFrom, validTo}). Fixes the
  OTPTokenInvalidException users hit after a successful DSC verify+claim.

- Individual-only filter for link-client pickers: ClientTextSearch gains a
  legalFormType field; SearchingClientRepository accepts an Integer legalForm
  value and adds cb.equal(r.get("legalForm"), ...) to the spec.
  ClientSearchService.parseLegalForm tolerates INDIVIDUAL/PERSON/1 and
  NON_INDIVIDUAL/ENTITY/2; unknown = no filter so a typo doesn't blank results.
  UI: clients.service.ts searchByText gains a 7th optional arg; six link
  pickers (guardian, nominee, family-member across create flow and post-create
  tabs) now pass 'INDIVIDUAL'. General client list and signatory picker are
  intentionally unchanged.

- Title-case client names on persistence: ClientWritePlatformServiceJpa
  RepositoryImpl now runs first/middle/last/full name fields through
  toTitleCase() on both create and update paths. "aditya kumar vyas",
  "ADITYA KUMAR VYAS", "Aditya Kumar Vyas" all persist as "Aditya Kumar Vyas".
  Whitespace-split title case; preserves hyphens/apostrophes inside words
  without re-capitalising after them so clerks verifying against ID documents
  see predictable output.

- Migration 0296: unique constraint to prevent duplicate nominee per account
  type (the underlying repository + service changes also persisted in this
  commit complete the enforcement path).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 11:50:04 +05:30
AdityaandClaude Opus 4.7 e1d7db9b7c DSC as first-class MFA factor + branded helper UI
- m_user_mfa_factor is now the single 2FA gate. DSC enroll callback writes a
  factor row (factor_type=DSC), revoke flips disabled_on when the last cert
  goes. AuthenticationApiResource and TwoFactorAuthenticationFilter drop the
  direct m_bank_user_dsc check so disabling from the UI actually stops the
  challenge at login.
- SecurityConfig exempts /api/*/dsc/** and /api/*/mfa/factors from the
  TWOFACTOR_AUTHENTICATED gate. Without this a user with a verified factor
  can't manage their own factors after they break the device.
- MfaFactorType gains a DSC enum value; SelfUserMfaFactorServiceImpl error
  message lists it.
- dsc-helper: CBSnexora-branded header (logo, title, subtitle, accent palette),
  8-column cert table (Holder Name, Alias, Organisation, DSC Type, Serial,
  Issuer, Valid From, Expires), LdapName-based DN parsing, sign+verify proof-
  of-possession that picks SHA256withRSA / SHA256withECDSA from the key's own
  algorithm (works on RSA, RSA Signing-only, EC), pattern-matched JNLP age
  check, dscType JNLP-arg override with KeyUsage fallback.
- generate-test-dsc.ps1 produces a realistic self-signed DSC with strong key
  protection so dev testing sees real CN/O values and a PIN prompt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:05:12 +05:30
AdityaandClaude Opus 4.7 8284851f67 Add DSC-based MFA: enrollment, login factor, JWS helper, tenant-scoped serving
Backend:
- m_bank_user_dsc + m_dsc_challenge tables (Liquibase 0292/0293/0294)
- DSC enrollment flow: start → JNLP → JWS helper → callback → upsert
- DSC login factor: challenge → sign → verify → claim minted TFA token
- 2FA gate now also accepts an active DSC mapping (AuthenticationApiResource
  + TwoFactorAuthenticationFilter), defensively wrapped so a missing DSC table
  doesn't 500 the auth path
- TenantAwareBasicAuthenticationFilter exempts /api/v*/dsc/helper.jar and
  strips Authorization header for that path so JWS's raw GET works without
  the user seeing a browser Basic-auth prompt
- DSC helper JAR served at /api/v*/dsc/helper.jar from a configurable
  filesystem path (default ~/.cbsnexora/dsc-helper.jar)

Java helper JAR (dsc-helper/):
- Standalone Gradle subproject, Java 8 target, fat jar with Gson shaded in
- Cross-platform token picker (Windows Cert Store / ePass2003 / eToken /
  ProxKey / Other) — matches the JNLP arg contract emitted by the backend
- Sets Fineract-Platform-TenantId on its callback POST from the JNLP args
- JNLP age check now reads cbsnexora-dsc.jnlp (current name) AND
  SignTender.jnlp (legacy) — picks the youngest, never blocks if none exist

Inline KYC upsert in updateClient (mirror of the create-flow path):
- ClientKycWritePlatformService.upsertKycInline() — creates or merges KYC
  fields, bumps status to IN_PROGRESS on real changes; resets PAN verification
  on PAN edit of a verified record
- ClientWritePlatformServiceJpaRepositoryImpl.updateClient() handles the
  kyc:{} sub-object on PUT /clients/{id}, matching createClient

User uniqueness:
- m_appuser.email + m_appuser.mobile_no UNIQUE (Liquibase 0295)
- Pre-flight assertEmailAndMobileUnique() in create/update with self-exclusion
- handleDataIntegrityIssues maps the two new constraints to clean
  field-scoped error messages (race-condition safety net)

Email OTP subject line now: "Your OTP for Login - <AppName> (dd-MM-yy-HH:mm)"
where AppName comes from fineract.email.from-name (default "CBSnexora").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 11:13:19 +05:30
AdityaandClaude Opus 4.7 5e3212dc54 Add MFA backend: SMS/email OTP, factor management, OTP audit log
- Login 2FA via @Primary MfaFactorBackedTwoFactorServiceImpl (replaces legacy)
- LincPay SMS OTP and SMTP email OTP with auto-promote to m_user_mfa_factor
- Reusable EmailSenderService + EmailTemplateService (CBSnexora branding)
- Admin OTP audit viewer (GET /v1/otp-logs) with paging, search, masking
- Self-service MFA factor API at /v1/mfa/factors
- READ_OTP_LOG permission + OTP Log Auditor role + bankadmin direct grant
- JsonAuthenticationEntryPoint suppresses Basic-auth popup for SPA paths
- TwoFactorAuthenticationFilter grants TWOFACTOR_AUTHENTICATED when no challenge
- Soft-delete + audit columns + deletion audit + version on client tables
- CIF number generator (TTYYYYNNNNNN format)
- DocumentNotFoundExceptionMapper to silence noisy WARN logs on missing images
- Liquibase migrations 0278-0291 (MFA, OTP log, audit/soft-delete, role wiring)

Note: application.properties intentionally not committed — contains local DB
and Gmail App Password fallbacks. Set SPRING_MAIL_PASSWORD,
FINERACT_DEFAULT_TENANTDB_PWD, FINERACT_HIKARI_PASSWORD as env vars in prod.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 13:19:10 +05:30
Aditya c51a36b4e9 Merge remote-tracking branch 'self-hosted/feature/merge-updates' into feature/reports-products
# Conflicts:
#	fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
2026-04-29 19:23:21 +05:30
AdityaandClaude Opus 4.6 43b1e1da33 Add CKYC Reports & Dashboard API module
- GET /ckyc/reports/summary — KPI cards (total, gender split, missing PAN/Aadhaar, dup mobile)
- GET /ckyc/reports/state-distribution — donut chart by state
- GET /ckyc/reports/branch-distribution — top-N branches bar chart
- GET /ckyc/reports/upload-trend — daily upload line chart
- GET /ckyc/customers — paginated, filterable customer list
- GET /ckyc/customers/search — search by name/mobile/pan/cif (capped 50)
- GET /ckyc/customers/{cif} — customer detail with addresses
- GET /ckyc/customers/export — CSV/TXT (pipe-delimited CERSAI format)
- POST /ckyc/files — parse inbound CKYC .txt file
- GET /ckyc/files — list historical uploads
- POST /ckyc/files/generate — generate outbound submission file
- GET /ckyc/branches, /states, /codes/id-types — master data
- Migration 0259: performance indexes on m_client_kyc and m_client
- Postman collection with all endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-28 16:25:41 +05:30
AdityaandClaude Opus 4.6 9fb43ad971 Add Education Level, Degree, Religion, Social Category & Income fields to Client module
- Migration 0256: EducationLevel & DegreeQualification codes with m_client FK columns
- Migration 0257: Religion & SocialCategory codes with m_client FK columns
- Migration 0258: agriculture_income & non_agriculture_income decimal columns on m_client
- Full API support: create, update, template options, and GET response for all new fields
- Postman collection for testing all new dropdowns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 16:31:55 +05:30
AdityaandClaude Opus 4.6 b4429d04b0 Add Client CKYC backend module with all source, migrations, and static resources
Includes CKYC batch processing, KYC proof types, non-CKYC client APIs,
ReKYC handler, SFTP upload service, and DB migrations (0250-0255).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:42:21 +05:30
AdityaandClaude Opus 4.6 011239f399 Fix KYC update on verified records and client address duplication
- Allow KYC updates on VERIFIED records with mandatory remarks for audit trail;
  reset PAN verification when PAN number changes, moving status to IN_PROGRESS
- Fix client address duplicates: deactivate old addresses of same type on
  create/update, persist isActive flag (missing save), filter reads by is_active

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:00:37 +05:30
AdityaandClaude Opus 4.6 87e132f93d Add extended fields to ClientNonPersonDetails: authorizedSignatory, additionalInfo, dateOfRegistration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:06:45 +05:30
AdityaandClaude Opus 4.6 90c21d40c1 Add CIF number, Occupation Category & Occupation fields to Client module
- Added mandatory unique CIF number (auto-generated as CIF+padded ID)
- Added Occupation Category dropdown (6 categories: Salaried, Business, Professional, Agriculture, Student, Others)
- Added Occupation dropdown (54 occupations mapped to categories)
- Both stored in m_code/m_code_value tables (same pattern as Gender)
- Visible in client create/update API and personal data view
- Includes Liquibase migrations 0227 & 0228
- Added Postman collection for User Management APIs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:51:26 +05:30
AdityaandClaude Opus 4.6 ba5365d4af 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>
2026-03-18 17:54:10 +05:30
AdityaandClaude Opus 4.6 78f37257a7 Add CFCFRMS (MHA/I4C) Bank API and Simulator module
CFCFRMS integration for cyber fraud complaint management:
- Bank-side: complaint CRUD, lien/freeze/resolve actions, escalation, audit trail, dashboard stats
- Simulator (I4C/MHA): push complaints, hold directives, bulk push, receive updates/escalations, account/transaction verification, bank performance metrics
- Domain: ComplaintTicket, ComplaintAuditLog, CfcfrmsSimulatorLog entities
- Liquibase 0226: 3 tables (MySQL+PostgreSQL), indexes, permissions
- Seed data: 13 realistic complaint tickets + 5 simulator log entries
- JAX-RS endpoints at /v1/cfcfrms/complaints/* and /v1/simulator/cfcfrms/*
- Full Swagger @Operation annotations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:49:54 +05:30
AdityaandClaude Opus 4.6 6a464291d5 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>
2026-03-17 18:16:36 +05:30