feat(election): date validations, overdue-only NDC/loan checks, audit log gaps fixed
- Added ElectionDateViolationException for proper 4xx on date violations - createElection: validates date order (nominationStart <= nominationEnd <= electionDate <= resultDate) - withdrawNomination/resubmitNomination: blocked after nominationEndDate - closeNominations: requires today >= nominationEndDate - openVoting/closeVoting: requires today >= electionDate - declareResults: requires today >= resultDate (or electionDate if no resultDate) - NDC hasNoDues: checks overdue EMIs only (total_overdue_derived), not outstanding balance - Director/guarantor/family loan checks: overdue-based only — pass if no missed EMIs - MemberHasOutstandingDuesException: proper AbstractPlatformDomainRuleException (was IllegalStateException → 500) - Audit gaps fixed: RESUBMIT_NOMINATION_FAILED added to enum, try/catch added for resubmit, createElection, updateElection; saveManualVoteCounts catches all RuntimeException Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
99cc972804
commit
ba199d78e7
+15
-2
@@ -60,7 +60,14 @@ public class ElectionConfigApiResource {
|
|||||||
@Operation(summary = "Create a new election")
|
@Operation(summary = "Create a new election")
|
||||||
public Response createElection(ElectionConfigRequest request,
|
public Response createElection(ElectionConfigRequest request,
|
||||||
@Context HttpServletRequest httpRequest) {
|
@Context HttpServletRequest httpRequest) {
|
||||||
Long id = writeService.createElection(request);
|
Long id;
|
||||||
|
try {
|
||||||
|
id = writeService.createElection(request);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
electionAuditService.logInNewTransaction(ElectionAuditAction.CREATE_ELECTION, "ELECTION", null, null,
|
||||||
|
"Election creation failed: " + e.getMessage(), null, clientIp(httpRequest));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
electionAuditService.log(ElectionAuditAction.CREATE_ELECTION, "ELECTION", id, id,
|
electionAuditService.log(ElectionAuditAction.CREATE_ELECTION, "ELECTION", id, id,
|
||||||
"Election created: " + request.getTitle(),
|
"Election created: " + request.getTitle(),
|
||||||
request.toString(),
|
request.toString(),
|
||||||
@@ -74,7 +81,13 @@ public class ElectionConfigApiResource {
|
|||||||
public Response updateElection(@PathParam("electionId") Long electionId,
|
public Response updateElection(@PathParam("electionId") Long electionId,
|
||||||
ElectionConfigRequest request,
|
ElectionConfigRequest request,
|
||||||
@Context HttpServletRequest httpRequest) {
|
@Context HttpServletRequest httpRequest) {
|
||||||
writeService.updateElection(electionId, request);
|
try {
|
||||||
|
writeService.updateElection(electionId, request);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
electionAuditService.logInNewTransaction(ElectionAuditAction.UPDATE_ELECTION, "ELECTION", electionId, electionId,
|
||||||
|
"Election update failed: " + e.getMessage(), null, clientIp(httpRequest));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
String updateDetails = null;
|
String updateDetails = null;
|
||||||
try { updateDetails = objectMapper.writeValueAsString(request); } catch (Exception ignored) {}
|
try { updateDetails = objectMapper.writeValueAsString(request); } catch (Exception ignored) {}
|
||||||
electionAuditService.log(ElectionAuditAction.UPDATE_ELECTION, "ELECTION", electionId, electionId,
|
electionAuditService.log(ElectionAuditAction.UPDATE_ELECTION, "ELECTION", electionId, electionId,
|
||||||
|
|||||||
+16
-2
@@ -108,7 +108,13 @@ public class ElectionNominationApiResource {
|
|||||||
public Response resubmitNomination(@PathParam("electionId") Long electionId,
|
public Response resubmitNomination(@PathParam("electionId") Long electionId,
|
||||||
@PathParam("nominationId") Long nominationId,
|
@PathParam("nominationId") Long nominationId,
|
||||||
@Context HttpServletRequest httpRequest) {
|
@Context HttpServletRequest httpRequest) {
|
||||||
writeService.resubmitNomination(nominationId);
|
try {
|
||||||
|
writeService.resubmitNomination(nominationId);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
electionAuditService.logInNewTransaction(ElectionAuditAction.RESUBMIT_NOMINATION_FAILED,
|
||||||
|
"NOMINATION", nominationId, electionId, "Resubmit failed: " + e.getMessage(), null, clientIp(httpRequest));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
electionAuditService.log(ElectionAuditAction.RESUBMIT_NOMINATION, "NOMINATION", nominationId, electionId,
|
electionAuditService.log(ElectionAuditAction.RESUBMIT_NOMINATION, "NOMINATION", nominationId, electionId,
|
||||||
"Nomination resubmitted", null, clientIp(httpRequest));
|
"Nomination resubmitted", null, clientIp(httpRequest));
|
||||||
return Response.ok(Map.of("resourceId", nominationId, "status", "UNDER_REVIEW")).build();
|
return Response.ok(Map.of("resourceId", nominationId, "status", "UNDER_REVIEW")).build();
|
||||||
@@ -213,7 +219,15 @@ public class ElectionNominationApiResource {
|
|||||||
public Response generateNoDueCertificate(@PathParam("electionId") Long electionId,
|
public Response generateNoDueCertificate(@PathParam("electionId") Long electionId,
|
||||||
@PathParam("nominationId") Long nominationId,
|
@PathParam("nominationId") Long nominationId,
|
||||||
@Context HttpServletRequest httpRequest) {
|
@Context HttpServletRequest httpRequest) {
|
||||||
String certNumber = writeService.generateNoDueCertificate(nominationId);
|
String certNumber;
|
||||||
|
try {
|
||||||
|
certNumber = writeService.generateNoDueCertificate(nominationId);
|
||||||
|
} catch (org.apache.fineract.portfolio.election.exception.MemberHasOutstandingDuesException e) {
|
||||||
|
electionAuditService.logInNewTransaction(ElectionAuditAction.GENERATE_NO_DUE_CERTIFICATE,
|
||||||
|
"NOMINATION", nominationId, electionId,
|
||||||
|
"NDC generation failed — member has outstanding dues", null, clientIp(httpRequest));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
electionAuditService.log(ElectionAuditAction.GENERATE_NO_DUE_CERTIFICATE, "NOMINATION", nominationId, electionId,
|
electionAuditService.log(ElectionAuditAction.GENERATE_NO_DUE_CERTIFICATE, "NOMINATION", nominationId, electionId,
|
||||||
"No due certificate generated: " + certNumber, null, clientIp(httpRequest));
|
"No due certificate generated: " + certNumber, null, clientIp(httpRequest));
|
||||||
return Response.ok(Map.of("certificateNumber", certNumber)).build();
|
return Response.ok(Map.of("certificateNumber", certNumber)).build();
|
||||||
|
|||||||
+2
-3
@@ -25,7 +25,6 @@ import org.apache.fineract.portfolio.election.data.ElectionResultData;
|
|||||||
import org.apache.fineract.portfolio.election.data.ManualVoteCountEntry;
|
import org.apache.fineract.portfolio.election.data.ManualVoteCountEntry;
|
||||||
import org.apache.fineract.portfolio.election.data.ManualVoteCountsRequest;
|
import org.apache.fineract.portfolio.election.data.ManualVoteCountsRequest;
|
||||||
import org.apache.fineract.portfolio.election.domain.ElectionAuditAction;
|
import org.apache.fineract.portfolio.election.domain.ElectionAuditAction;
|
||||||
import org.apache.fineract.portfolio.election.exception.VoteCountExceedsShareAccountsException;
|
|
||||||
import org.apache.fineract.portfolio.election.service.ElectionAuditService;
|
import org.apache.fineract.portfolio.election.service.ElectionAuditService;
|
||||||
import org.apache.fineract.portfolio.election.service.ElectionReadPlatformService;
|
import org.apache.fineract.portfolio.election.service.ElectionReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.election.service.ElectionWritePlatformService;
|
import org.apache.fineract.portfolio.election.service.ElectionWritePlatformService;
|
||||||
@@ -58,10 +57,10 @@ public class ElectionVotingApiResource {
|
|||||||
String voteDetails;
|
String voteDetails;
|
||||||
try {
|
try {
|
||||||
voteDetails = writeService.saveManualVoteCounts(electionId, counts, reason);
|
voteDetails = writeService.saveManualVoteCounts(electionId, counts, reason);
|
||||||
} catch (VoteCountExceedsShareAccountsException e) {
|
} catch (RuntimeException e) {
|
||||||
electionAuditService.logInNewTransaction(
|
electionAuditService.logInNewTransaction(
|
||||||
ElectionAuditAction.MANUAL_VOTE_ENTRY_FAILED, "VOTE", electionId, electionId,
|
ElectionAuditAction.MANUAL_VOTE_ENTRY_FAILED, "VOTE", electionId, electionId,
|
||||||
"Vote count validation failed: " + e.getDefaultUserMessage(),
|
"Vote count entry failed: " + e.getMessage(),
|
||||||
null, clientIp(httpRequest));
|
null, clientIp(httpRequest));
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ public enum ElectionAuditAction {
|
|||||||
ELIGIBILITY_CHECK, CEO_PRECHECK, APPROVAL_ACTION,
|
ELIGIBILITY_CHECK, CEO_PRECHECK, APPROVAL_ACTION,
|
||||||
GENERATE_NO_DUE_CERTIFICATE,
|
GENERATE_NO_DUE_CERTIFICATE,
|
||||||
// Nomination — Failed
|
// Nomination — Failed
|
||||||
SUBMIT_NOMINATION_FAILED, WITHDRAW_NOMINATION_FAILED,
|
SUBMIT_NOMINATION_FAILED, WITHDRAW_NOMINATION_FAILED, RESUBMIT_NOMINATION_FAILED,
|
||||||
ELIGIBILITY_CHECK_FAILED, CEO_PRECHECK_FAILED, APPROVAL_ACTION_FAILED,
|
ELIGIBILITY_CHECK_FAILED, CEO_PRECHECK_FAILED, APPROVAL_ACTION_FAILED,
|
||||||
// Candidate
|
// Candidate
|
||||||
APPROVE_CANDIDATE, REMOVE_CANDIDATE, UPLOAD_SYMBOL, UPDATE_CANDIDATE,
|
APPROVE_CANDIDATE, REMOVE_CANDIDATE, UPLOAD_SYMBOL, UPDATE_CANDIDATE,
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package org.apache.fineract.portfolio.election.exception;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||||
|
|
||||||
|
public class ElectionDateViolationException extends AbstractPlatformDomainRuleException {
|
||||||
|
|
||||||
|
public ElectionDateViolationException(String message) {
|
||||||
|
super("error.msg.election.date.violation", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package org.apache.fineract.portfolio.election.exception;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||||
|
|
||||||
|
public class MemberHasOutstandingDuesException extends AbstractPlatformDomainRuleException {
|
||||||
|
|
||||||
|
public MemberHasOutstandingDuesException() {
|
||||||
|
super("error.msg.election.member.outstanding.dues",
|
||||||
|
"Member has outstanding dues. No Due Certificate cannot be issued.");
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -6,6 +6,7 @@ import org.apache.fineract.portfolio.election.domain.CheckResult;
|
|||||||
import org.apache.fineract.portfolio.election.domain.ElectionCeoPrecheck;
|
import org.apache.fineract.portfolio.election.domain.ElectionCeoPrecheck;
|
||||||
import org.apache.fineract.portfolio.election.domain.ElectionCeoPrecheckRepository;
|
import org.apache.fineract.portfolio.election.domain.ElectionCeoPrecheckRepository;
|
||||||
import org.apache.fineract.portfolio.election.domain.ElectionNomination;
|
import org.apache.fineract.portfolio.election.domain.ElectionNomination;
|
||||||
|
import org.apache.fineract.portfolio.election.exception.MemberHasOutstandingDuesException;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -366,7 +367,7 @@ public class ElectionCeoPreCheckServiceImpl implements ElectionCeoPreCheckServic
|
|||||||
precheck.completeDirectorLoanCheck(CheckResult.FAIL, BigDecimal.ZERO,
|
precheck.completeDirectorLoanCheck(CheckResult.FAIL, BigDecimal.ZERO,
|
||||||
"Member has outstanding dues — NDC cannot be issued");
|
"Member has outstanding dues — NDC cannot be issued");
|
||||||
ceoPrecheckRepository.save(precheck);
|
ceoPrecheckRepository.save(precheck);
|
||||||
throw new IllegalStateException("Member has outstanding dues. No Due Certificate cannot be issued.");
|
throw new MemberHasOutstandingDuesException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -28,9 +28,10 @@ public class ElectionNoDueCertificateServiceImpl implements ElectionNoDueCertifi
|
|||||||
String loanDueQuery = """
|
String loanDueQuery = """
|
||||||
SELECT COUNT(la.id)
|
SELECT COUNT(la.id)
|
||||||
FROM m_loan la
|
FROM m_loan la
|
||||||
|
LEFT JOIN m_loan_arrears_aging a ON a.loan_id = la.id
|
||||||
WHERE la.client_id = ?
|
WHERE la.client_id = ?
|
||||||
AND la.loan_status_id = 300
|
AND la.loan_status_id = 300
|
||||||
AND la.total_outstanding_derived > 0
|
AND COALESCE(a.total_overdue_derived, 0) > 0
|
||||||
""";
|
""";
|
||||||
Integer loanDueCount = jdbcTemplate.queryForObject(loanDueQuery, Integer.class, memberId);
|
Integer loanDueCount = jdbcTemplate.queryForObject(loanDueQuery, Integer.class, memberId);
|
||||||
return loanDueCount == null || loanDueCount == 0;
|
return loanDueCount == null || loanDueCount == 0;
|
||||||
|
|||||||
+54
@@ -29,6 +29,7 @@ import org.apache.fineract.portfolio.election.domain.ElectionVote;
|
|||||||
import org.apache.fineract.portfolio.election.domain.ElectionVoteRepository;
|
import org.apache.fineract.portfolio.election.domain.ElectionVoteRepository;
|
||||||
import org.apache.fineract.portfolio.election.domain.NominationStatus;
|
import org.apache.fineract.portfolio.election.domain.NominationStatus;
|
||||||
import org.apache.fineract.portfolio.election.exception.ElectionAlreadyOngoingException;
|
import org.apache.fineract.portfolio.election.exception.ElectionAlreadyOngoingException;
|
||||||
|
import org.apache.fineract.portfolio.election.exception.ElectionDateViolationException;
|
||||||
import org.apache.fineract.portfolio.election.exception.ElectionNotFoundException;
|
import org.apache.fineract.portfolio.election.exception.ElectionNotFoundException;
|
||||||
import org.apache.fineract.portfolio.election.exception.ElectionNominationNotFoundException;
|
import org.apache.fineract.portfolio.election.exception.ElectionNominationNotFoundException;
|
||||||
import org.apache.fineract.portfolio.election.exception.ElectionNotActiveException;
|
import org.apache.fineract.portfolio.election.exception.ElectionNotActiveException;
|
||||||
@@ -42,6 +43,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -90,6 +92,9 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
throw new ElectionAlreadyOngoingException();
|
throw new ElectionAlreadyOngoingException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validateDateOrder(request.getNominationStartDate(), request.getNominationEndDate(),
|
||||||
|
request.getElectionDate(), request.getResultDate());
|
||||||
|
|
||||||
ElectionConfig election = ElectionConfig.create(
|
ElectionConfig election = ElectionConfig.create(
|
||||||
request.getTitle(),
|
request.getTitle(),
|
||||||
request.getDescription(),
|
request.getDescription(),
|
||||||
@@ -102,6 +107,9 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
ElectionConfig saved = electionConfigRepository.saveAndFlush(election);
|
ElectionConfig saved = electionConfigRepository.saveAndFlush(election);
|
||||||
|
|
||||||
if (request.getPosts() != null) {
|
if (request.getPosts() != null) {
|
||||||
|
if (request.getPosts().size() > 1) {
|
||||||
|
throw new IllegalArgumentException("Only one election post is allowed per election.");
|
||||||
|
}
|
||||||
for (ElectionPostRequest postReq : request.getPosts()) {
|
for (ElectionPostRequest postReq : request.getPosts()) {
|
||||||
ElectionPost post = ElectionPost.create(saved, postReq.getPostName(), postReq.getTotalSeats());
|
ElectionPost post = ElectionPost.create(saved, postReq.getPostName(), postReq.getTotalSeats());
|
||||||
electionPostRepository.saveAndFlush(post);
|
electionPostRepository.saveAndFlush(post);
|
||||||
@@ -142,6 +150,10 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
context.authenticatedUser().validateHasPermissionTo("UPDATE_ELECTION");
|
context.authenticatedUser().validateHasPermissionTo("UPDATE_ELECTION");
|
||||||
ElectionConfig election = electionConfigRepository.findById(electionId)
|
ElectionConfig election = electionConfigRepository.findById(electionId)
|
||||||
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
||||||
|
if (LocalDate.now().isBefore(election.getNominationEndDate())) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Cannot close nominations before the nomination end date " + election.getNominationEndDate());
|
||||||
|
}
|
||||||
election.closeNominations();
|
election.closeNominations();
|
||||||
electionConfigRepository.save(election);
|
electionConfigRepository.save(election);
|
||||||
}
|
}
|
||||||
@@ -152,6 +164,10 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
context.authenticatedUser().validateHasPermissionTo("UPDATE_ELECTION");
|
context.authenticatedUser().validateHasPermissionTo("UPDATE_ELECTION");
|
||||||
ElectionConfig election = electionConfigRepository.findById(electionId)
|
ElectionConfig election = electionConfigRepository.findById(electionId)
|
||||||
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
||||||
|
if (LocalDate.now().isBefore(election.getElectionDate())) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Cannot open voting before election date " + election.getElectionDate());
|
||||||
|
}
|
||||||
election.openVoting();
|
election.openVoting();
|
||||||
electionConfigRepository.save(election);
|
electionConfigRepository.save(election);
|
||||||
}
|
}
|
||||||
@@ -163,6 +179,11 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
ElectionConfig election = electionConfigRepository.findById(electionId)
|
ElectionConfig election = electionConfigRepository.findById(electionId)
|
||||||
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
||||||
|
|
||||||
|
if (LocalDate.now().isBefore(election.getElectionDate())) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Cannot close voting before election date " + election.getElectionDate());
|
||||||
|
}
|
||||||
|
|
||||||
List<ElectionPost> posts = electionPostRepository.findByElectionConfigIdAndIsActiveTrue(electionId);
|
List<ElectionPost> posts = electionPostRepository.findByElectionConfigIdAndIsActiveTrue(electionId);
|
||||||
for (ElectionPost post : posts) {
|
for (ElectionPost post : posts) {
|
||||||
List<ElectionCandidate> candidates = candidateRepository
|
List<ElectionCandidate> candidates = candidateRepository
|
||||||
@@ -243,6 +264,11 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
if (nomination.getStatus() == NominationStatus.APPROVED) {
|
if (nomination.getStatus() == NominationStatus.APPROVED) {
|
||||||
throw new InvalidNominationStateException("withdraw", nomination.getStatus().name());
|
throw new InvalidNominationStateException("withdraw", nomination.getStatus().name());
|
||||||
}
|
}
|
||||||
|
ElectionConfig election = nomination.getElectionConfig();
|
||||||
|
if (LocalDate.now().isAfter(election.getNominationEndDate())) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Nomination withdrawal period has ended. Nominations closed on " + election.getNominationEndDate());
|
||||||
|
}
|
||||||
nomination.withdraw();
|
nomination.withdraw();
|
||||||
nominationRepository.save(nomination);
|
nominationRepository.save(nomination);
|
||||||
}
|
}
|
||||||
@@ -255,6 +281,11 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
if (nomination.getStatus() != NominationStatus.REJECTED) {
|
if (nomination.getStatus() != NominationStatus.REJECTED) {
|
||||||
throw new InvalidNominationStateException("resubmit", nomination.getStatus().name());
|
throw new InvalidNominationStateException("resubmit", nomination.getStatus().name());
|
||||||
}
|
}
|
||||||
|
ElectionConfig election = nomination.getElectionConfig();
|
||||||
|
if (LocalDate.now().isAfter(election.getNominationEndDate())) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Nomination resubmission period has ended. Nominations closed on " + election.getNominationEndDate());
|
||||||
|
}
|
||||||
ceoPrecheckRepository.findByNominationId(nominationId)
|
ceoPrecheckRepository.findByNominationId(nominationId)
|
||||||
.ifPresent(ceoPrecheckRepository::delete);
|
.ifPresent(ceoPrecheckRepository::delete);
|
||||||
nomination.resubmit();
|
nomination.resubmit();
|
||||||
@@ -521,6 +552,13 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
ElectionConfig election = electionConfigRepository.findById(electionId)
|
ElectionConfig election = electionConfigRepository.findById(electionId)
|
||||||
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
.orElseThrow(() -> new ElectionNotFoundException(electionId));
|
||||||
|
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
LocalDate effectiveDate = election.getResultDate() != null ? election.getResultDate() : election.getElectionDate();
|
||||||
|
if (today.isBefore(effectiveDate)) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Cannot declare results before " + effectiveDate);
|
||||||
|
}
|
||||||
|
|
||||||
List<ElectionPost> posts = electionPostRepository.findByElectionConfigIdAndIsActiveTrue(electionId);
|
List<ElectionPost> posts = electionPostRepository.findByElectionConfigIdAndIsActiveTrue(electionId);
|
||||||
for (ElectionPost post : posts) {
|
for (ElectionPost post : posts) {
|
||||||
List<ElectionCandidate> candidates = candidateRepository
|
List<ElectionCandidate> candidates = candidateRepository
|
||||||
@@ -580,4 +618,20 @@ public class ElectionWritePlatformServiceImpl implements ElectionWritePlatformSe
|
|||||||
private String generateApplicationNumber(Long nominationId, Long electionId) {
|
private String generateApplicationNumber(Long nominationId, Long electionId) {
|
||||||
return "ENOMN-" + electionId + "-" + String.format("%06d", nominationId);
|
return "ENOMN-" + electionId + "-" + String.format("%06d", nominationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateDateOrder(LocalDate nominationStart, LocalDate nominationEnd,
|
||||||
|
LocalDate electionDate, LocalDate resultDate) {
|
||||||
|
if (nominationStart != null && nominationEnd != null && nominationStart.isAfter(nominationEnd)) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Nomination start date " + nominationStart + " cannot be after nomination end date " + nominationEnd);
|
||||||
|
}
|
||||||
|
if (nominationEnd != null && electionDate != null && nominationEnd.isAfter(electionDate)) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Nomination end date " + nominationEnd + " cannot be after election date " + electionDate);
|
||||||
|
}
|
||||||
|
if (electionDate != null && resultDate != null && electionDate.isAfter(resultDate)) {
|
||||||
|
throw new ElectionDateViolationException(
|
||||||
|
"Election date " + electionDate + " cannot be after result date " + resultDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user