feat(connector): core banking / LMS seam, one real adapter and four dialects
The loan book is the training label and the one input no public feed
supplies. Integrating with a lender's core is not a technical unknown —
it is an onboarding process per bank, with a schema agreed in a room.
What can be built before that room is the seam, and this is it.
CoreBankingConnector fetches and returns rows; it never writes. Mapped
rows go to LoanBookEntryService.stage — the same validator an uploaded
spreadsheet goes through, landing in the same manual_entry_batch with
the same preview. A parallel validator for the automated path would be
the obvious shape and would eventually enforce the no-PII rule
differently.
FileDropConnector is real: it reads the newest matching file from a
directory a bank delivers to, and leaves it there so a failed run is
repeatable. Finacle, FLEXCUBE, BaNCS and an in-house REST LMS are
simulated, each emitting the same portfolio in its own column dialect —
DPD_DAYS, OVERDUE_DAYS, DAYS_OVERDUE, daysPastDue — which is what makes
the case for a mapping layer rather than asserting it.
The mapping is {canonical: vendor}, keyed by canonical name, so an
unmapped vendor column has no route through and is dropped at the
boundary. CUST_NAME and MOBILE_NO stay out structurally rather than by
anyone remembering. Auto-commit is off on every profile: a sync stages
and stops, keeping the rule that nothing is written until someone has
seen what will be. simulated is stamped per run, not read from the
profile, so switching a profile live cannot make old runs look real.
Fixes a real defect this surfaced: FORBIDDEN_COLUMNS matched on the
exact normalised name, so CUST_NAME — what Finacle actually calls it —
was missed, and a directly uploaded bank file would have kept the
borrower's name in manual_entry_line.raw_row. Matching now splits
separators and camelCase, catching borrowerMobile too, while
loan_account_ref still splits clean.
Verified against a running instance: Finacle 44/44 accepted with 4
columns dropped, the file drop 2 accepted and 1 UNKNOWN_ENTERPRISE
rejected from a real CSV, and both CUST_NAME and borrowerMobile refused
at mapping save.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,7 @@ public class UdyamDataSeeder implements CommandLineRunner {
|
||||
private final UdyamUserRepository userRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final InstitutionSeeder institutionSeeder;
|
||||
private final com.lincfusion.udyamlinc.connector.ConnectorProfileSeeder connectorProfileSeeder;
|
||||
|
||||
@Value("${udyam.seed.enabled:true}")
|
||||
private boolean seedEnabled;
|
||||
@@ -114,6 +115,9 @@ public class UdyamDataSeeder implements CommandLineRunner {
|
||||
// The institutional tier last: it assigns the portfolio the steps above
|
||||
// created, so it has to see a finished book.
|
||||
institutionSeeder.seed();
|
||||
// Connector profiles after the institutions they read from, since each
|
||||
// names a partner bank by code.
|
||||
connectorProfileSeeder.seed();
|
||||
log.info("UdyamLinc seed complete — {} enterprises on book", enterpriseRepository.count());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user