feat(election): production-ready audit log with server-side filter + pagination

- Add m_election_audit_log table via Liquibase (0341)
- ElectionAuditLog entity, ElectionAuditAction enum (21 actions)
- ElectionAuditService: log() with double try-catch, getAuditLogPaged()
  with entityType/action/full-text filters, size cap at 100, page safety
- ElectionAuditLogRepository: findWithFilters() JPQL with optional params
- All 4 election API resources wired with audit calls (create/update/
  activate/nominations/voting/candidates/votes/results)
- GET /{electionId}/audit-log accepts ?entityType=&action=&search=&page=&size=

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-06-29 12:57:21 +05:30
co-authored by Claude Sonnet 4.6
parent 3d30bdb788
commit 69513f25f3
13 changed files with 536 additions and 20 deletions
@@ -368,4 +368,5 @@
<include file="parts/0338_election_ceo_precheck_extended_checks.xml" relativeToChangelogFile="true"/>
<include file="parts/0339_election_ceo_precheck_family_loan_check.xml" relativeToChangelogFile="true"/>
<include file="parts/0340_election_candidate_symbol_text.xml" relativeToChangelogFile="true"/>
<include file="parts/0341_election_audit_log.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet id="0340-election-candidate-symbol-text" author="fineract">
<preConditions onFail="MARK_RAN">
<columnExists tableName="m_election_candidate" columnName="symbol"/>
</preConditions>
<modifyDataType tableName="m_election_candidate" columnName="symbol" newDataType="TEXT"/>
<comment>Expand symbol column to TEXT to support base64 image data URLs</comment>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet id="0341-election-audit-log" author="CBS">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_election_audit_log"/></not>
</preConditions>
<createTable tableName="m_election_audit_log">
<column name="id" type="BIGSERIAL" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="election_id" type="BIGINT"/>
<column name="entity_type" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<column name="entity_id" type="BIGINT"/>
<column name="action" type="VARCHAR(100)">
<constraints nullable="false"/>
</column>
<column name="performed_by_id" type="BIGINT"/>
<column name="performed_by_name" type="VARCHAR(100)"/>
<column name="office_id" type="BIGINT"/>
<column name="ip_address" type="VARCHAR(50)"/>
<column name="details" type="TEXT"/>
<column name="description" type="VARCHAR(500)"/>
<column name="created_at" type="TIMESTAMP" defaultValueComputed="NOW()">
<constraints nullable="false"/>
</column>
</createTable>
<createIndex indexName="idx_election_audit_election_created"
tableName="m_election_audit_log">
<column name="election_id"/>
<column name="created_at" descending="true"/>
</createIndex>
<createIndex indexName="idx_election_audit_entity"
tableName="m_election_audit_log">
<column name="entity_type"/>
<column name="entity_id"/>
</createIndex>
</changeSet>
</databaseChangeLog>