Adds a maker-checker-gated "return" command on cheque books that flags
presented-and-dishonoured leaves as terminal RETURNED (distinct from
STOP_PAYMENT/drawer-initiated and LOST/custody-failure), following the
same reason/actor/timestamp pattern already used for lost/cancelled/used
leaves on m_cheque_leaf.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
introducer_required, share_linking_enabled, terminate_true were missing
from m_savings_account in fineract_saga. Applied directly to DB and
added 0368 catch-up migration with preConditions for idempotency.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Combines election module + UAT catch-up migrations (0338-0367) with
minor-update changes: soft delete for tellers (0338), share linking
for current account (0339), terminate flag for savings/current (0340).
Resolved changelog conflict by appending minor-update entries after 0367.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add CommitteeMeetingAgenda entity + repository for relational agenda storage
- Liquibase migration 0353: create m_election_committee_meeting_agenda table,
drop old agenda TEXT column from m_election_committee_meeting
- Update CommitteeMeeting: replace String agenda with List<CommitteeMeetingAgenda>
(EAGER, no cascade — writes handled explicitly via repository)
- Update CommitteeMeetingRepository: explicit JPQL with SELECT DISTINCT + LEFT JOIN
FETCH to load agendaItems and prevent NonUniqueResultException on Optional returns
- Fix email sending stale agenda: inject EntityManager, call refresh() after
agendaRepository.flush() so EclipseLink reloads the collection from DB
- Redesign buildMeetingInviteHtml: table-based email layout, icon+label+value rows,
amber agenda section with numbered badges, compact two-column footer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ElectionConfig: add isCandidateModificationLocked() — blocks remove/update/symbol after voting starts
- ElectionWritePlatformServiceImpl: full audit logging on all 16 operations; failures logged in new transaction (REQUIRES_NEW) so they survive main tx rollback
- DirectorAppointmentData: add memberId field for client photo lookup
- DirectorAppointmentServiceImpl: batch-fetch candidate memberId via ElectionCandidateRepository; pass to response
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add durationYears to ElectionConfig with Liquibase migration (0348)
- Block new election creation when previous election duration is still active (PostgreSQL-compatible native query)
- Auto-override director tenureEndDate from election durationEndDate on appoint and update
- Add ElectionSchedulerConfiguration to enable @Scheduled support
- Fix JPQL EclipseLink enum compatibility in expireByTenureDate query
- Add full audit logging to DirectorAppointmentServiceImpl (appoint, update, remove, auto-expire)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DirectorAppointment entity + Liquibase migration (0347)
- CRUD API: POST/GET/PUT/DELETE /v1/election/directors with @Valid Bean Validation
- GET /v1/election/directors/pending — WON candidates not yet appointed
- Duplicate prevention: existsByElectionIdAndCandidateId check on appoint
- Business validation: tenure end must be after start; tenure start cannot be before appointment date
- @Scheduled daily midnight job to auto-expire tenure-ended directors via bulk JPQL UPDATE
- Full audit logging for all director actions (success + failure) via ElectionAuditService
- PendingDirectorData DTO; DirectorAppointmentStatus enum (ACTIVE/RESIGNED/REMOVED/TENURE_ENDED)
- ElectionAuditAction: added APPOINT_DIRECTOR, UPDATE_DIRECTOR_APPOINTMENT, REMOVE_DIRECTOR_APPOINTMENT + FAILED variants
- ElectionResultRepository: findByResult(String) for pending director lookup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ElectionAnalyticsServiceImpl: fix SQL_FAMILY to count candidate's own family members who are active shareholders (candidate-specific, not system-wide)
- ElectionAnalyticsServiceImpl: SQL_SUB_CASTE now groups by m_client.lastname instead of sub_caste_cv_id
- ElectionAnalyticsServiceImpl: SQL_CANDIDATE_INFO fetches candidate client_id, lastname, religion for match highlighting
- ElectionAnalyticsServiceImpl: add getOverallShareholderAnalysis() — returns all demographic breakdowns with no candidate matching
- ElectionAnalyticsService: add getOverallShareholderAnalysis() interface method
- ElectionCandidateApiResource: add GET /{electionId}/shareholders/analysis endpoint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New ElectionAnalyticsServiceImpl with 14 SQL breakdown queries:
gender, age, area, social category (caste), sub-caste, religion,
occupation, share-holding, tenure, loan, education, marital status,
monthly income, savings account depth
- Cross-dimension match: caste + area simultaneously (core voter base)
- Zero-count row injection for caste/gender/sub-caste when candidate's
category has no shareholder matches in GROUP BY result
- Liquibase 0343: sub_caste_cv_id column on m_client with 33 pre-seeded
sub-caste values across General / OBC / SC / ST categories
- Liquibase 0342: election post eligibility columns
- CandidateVoterAnalysisData DTO with education, marital, income,
savings, activeSavingsHolders, crossMatchCount fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Delete all fineract-provider/logs/*.log from version control
- Add fineract-provider/logs/ to .gitignore so runtime logs are
never tracked again
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ElectionCandidateData: replace String symbol with Boolean hasSymbol + add memberId
- ElectionCandidateApiResource: symbol upload/download via ContentStoreService
(mimeType|storagePath format, backward-compatible with legacy base64 records)
- ElectionVotingApiResource: add GET /vote-summary endpoint (totalVotes, totalVoters,
per-candidate breakdown) using ElectionVoteRepository queries
- ElectionVoteRepository: add countByElectionConfigId and voteSummaryByCandidate queries
- ElectionReadPlatformServiceImpl: map hasSymbol and memberId in candidate list response
- ElectionWritePlatformServiceImpl: set photoUrl from memberId on approveCandidate,
delete old symbol file from ContentStore on removeCandidate
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PagedResponse<T>: generic paginated wrapper with statusCounts and summary fields
- ElectionConfigRepository: pageable query + countGroupByStatus
- ElectionNominationRepository: pageable queries + count-by-status helpers
- ElectionCandidateRepository: pageable queries by election and post
- ElectionReadPlatformService: all list methods return PagedResponse with page/size params
- ElectionReadPlatformServiceImpl: add missing Pageable import; paginated impls with summary data
- API resources: @QueryParam page/size with @DefaultValue on all 3 list endpoints
- ElectionCeoPrecheck: add familyLoanCheckResult + familyLoanCheckRemarks (7th auto-check)
- ElectionCeoPreCheckServiceImpl: fix directorLoan check (overdue only); add family loan check covering manual members (unverifiable→FAIL) and linked CBS clients (overdue→FAIL)
- Liquibase 0338/0339: extended CEO pre-check columns + family loan check columns
- changelog-tenant.xml: include both new changesets
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add borrower name, savings account, guaranteed/released/remaining amounts, loan timeline, and overdue info to GuarantorAccountSummaryData
- Fix duplicate rows in GuarantorLoanAccountSummaryDataMapper by joining savings account via guarantor funding details instead of client ID
- Fix NPE in GuarantorDomainServiceImpl when loan product guarantee details are null
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The 5 missing permissions were added to the already-executed changeset
causing checksum mismatch on restart. Move them to a new changeset
0337_seed_election_permissions_v2 with a preCondition guard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add 5 permissions that the write service enforces but were absent from
the DB seed: UPDATE_ELECTION, ELIGIBILITY_CHECK_ELECTION,
CEO_PRECHECK_ELECTION, APPROVE_ELECTION_NOMINATION,
APPROVE_ELECTION_CANDIDATE — without these, role assignments for those
operations would fail at runtime.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ShareAccountWritePlatformServiceJpaRepositoryImpl:
- Remove m_share_cashier_collection validation from activateShareAccount() —
cashier now enters GL directly via transaction entry workstation
- Mark all share account charges as paid on activation instead of posting
duplicate GL (cashier already posted DR Cash -> CR Charges GL directly)
- Remove unused imports: java.sql.Date, EmptyResultDataAccessException, Collectors
- Update createShareAccount() comment to reflect new cashier GL flow
ClerkDisbursementRequestApiResource:
- Add null guard for clerk_id before cast in approve() — returns 500 with
clear message if DB record is missing the field
- Add null/blank guard for credit_entries in approve() — returns 400 with
clear message instead of NPE on gson.fromJson
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace Fineract cash deposit API with direct INSERT for both savings and current accounts
→ Zero CashVault entries created anywhere in DB for disbursements
- Savings: directCreditSavingsAccount now sets running_balance_derived and updates
total_deposits_derived alongside account_balance_derived (parity with current account)
- Current: directCreditCurrentAccount — direct INSERT into m_current_account_transaction
with running_balance_derived, total_deposits_derived update, and remarks audit field
- getCurrentControlGlId: looks up SAVINGS_CONTROL GL for current account products
via acc_product_mapping (product_type=2, financial_account_type=2)
- directReverseCurrentCredit: compensation restores both account_balance_derived
and total_deposits_derived on rollback
- GL: combined DR sourceGL / CR SavingsControl entry posted for both savings and
current account credits; linkGlEntriesToSavingsAccounts sets entity_type_enum=2
so ACCOUNT NO column shows in journal entries view
- Hide reversed=true GL entries from all GL views in JournalEntryReadPlatformServiceImpl
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use parseTxnIdToLong() for voucherService.linkSavingsTransaction() to
handle hex GL txnId (e.g. "a2070e542bab") without NumberFormatException
- Add GL deposit maker-checker: submit stores gl_account_id, contra_gl_id,
office_id, currency_code; approve routes to executeGlJournalEntry()
- Save denomination at submit time (cash physically received); update
txn_id to real Fineract ID on approve, delete on reject
- Add Liquibase migration 0331 to add GL columns to m_cashier_deposit_request
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CashierDepositRequestApiResource:
- approve(): use isCurrentAccountById() to detect current accounts, route to
executeCurrentAccountDeposit() instead of executeSavingsDeposit()
- Add executeCurrentAccountDeposit() using CommandWrapperBuilder.currentAccountDeposit()
- Add isCurrentAccountById() helper querying m_current_account table
- Add POST /{id}/reprocess endpoint to fix already-approved CA records that
were wrongly posted to savings account
ClerkWithdrawalRequestApiResource:
- approve(): use isCurrentAccountById() to detect current accounts, route to
executeCurrentAccountWithdrawal() instead of executeSavingsWithdrawal()
- Add executeCurrentAccountWithdrawal() using CommandWrapperBuilder.currentAccountWithdrawal()
- Add isCurrentAccountById() helper querying m_current_account table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- VoucherService: central voucher register with globally unique voucher numbers
- CashierDepositRequestApiResource: full submit/approve/reject/list flow
- Cashier submits deposit request; balance credited only on manager approval
- Self-approval blocked (maker cannot be checker)
- Role guard: only manager/head-cashier/ALL_FUNCTIONS can approve/reject
- Race condition guard: WHERE status='PENDING' on approve/reject UPDATE
- Clean JSON error responses (no 500 stack traces) via apiError() helper
- Denomination total validation at submit and approve
- ClerkWithdrawalRequestApiResource: refactored to use m_voucher
- Voucher created at submit, linked to savings txn at approve
- Same role guard and self-approval block as deposit flow
- Disburse: denomination validation, null denoms for non-cash payments
- Migrations 0327-0330:
- 0327: add voucher_no to m_clerk_withdrawal_request
- 0328: add voucher_no to m_savings_account_transaction
- 0329: create m_voucher central table (globally unique voucher_no)
- 0330: create m_cashier_deposit_request table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add offset/limit query params with defaults (limit=20, offset=0)
- Return totalFilteredRecords + pageItems response structure
- Compute totalDr/totalCr from all records (not just current page)
- Fix ordering: ORDER BY MAX(created_at) for correct chronological sort
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add CashierGlDenominationApiResource: new POST /v1/cashier/gl-denomination endpoint
to record denomination breakdown for GL journal entries in m_savings_txn_denomination
- Fix GL account real-time balance in GLAccountReadPlatformServiceImpl using live SUM query
- Add Liquibase migrations 0318/0319/0320: make savings_account_id and txn_id nullable,
add payment_type column to m_savings_txn_denomination
- Add validCheckSum to 0317b changeset to resolve checksum mismatch on existing installs
- Enhance GL entries closing report SQL with date, time, teller, payment type, txn source
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix searchParam SQL syntax: parameterized LIKE with %value% instead of literal %?%
- Fix organizationRunningBalance: correlated subquery for latest journal entry (ORDER BY id DESC LIMIT 1)
- Migration 0317: grant READ_GLACCOUNT, READ_LOAN, READ_SHAREACCOUNT to CASHIER role
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>