Validation check for loans and savings for client or group status

This commit is contained in:
mifoscontributer
2013-08-09 13:40:14 +05:30
parent f1c2c2c342
commit 57eecb4b1b
18 changed files with 223 additions and 9 deletions
@@ -0,0 +1,11 @@
package org.mifosplatform.portfolio.client.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class ClientNotActiveException extends AbstractPlatformDomainRuleException {
public ClientNotActiveException(final Long clientId) {
super("error.msg.client.not.active.exception", "The Client with id `" + clientId + "` is not active", clientId);
}
}
@@ -263,7 +263,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
public ClientMembersOfGroupMapper() {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("c.id as id, c.account_no as accountNo, c.external_id as externalId, ");
sqlBuilder.append("c.id as id, c.account_no as accountNo, c.external_id as externalId, c.status_enum as statusEnum, ");
sqlBuilder.append("c.office_id as officeId, o.name as officeName, ");
sqlBuilder.append("c.firstname as firstname, c.middlename as middlename, c.lastname as lastname, ");
sqlBuilder.append("c.fullname as fullname, c.display_name as displayName, ");
@@ -286,7 +286,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
final String accountNo = rs.getString("accountNo");
final EnumOptionData status = null;
final Integer statusEnum = JdbcSupport.getInteger(rs, "statusEnum");
final EnumOptionData status = ClientEnumerations.status(statusEnum);
final Long officeId = JdbcSupport.getLong(rs, "officeId");
final Long id = JdbcSupport.getLong(rs, "id");
@@ -359,6 +359,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
} else if (loanStatus.isPendingApproval()) {
final String errorMessage = "Client cannot be closed because of non-closed loans.";
throw new InvalidClientStateTransitionException("close", "loan.non-closed", errorMessage);
} else if (loanStatus.isAwaitingDisbursal()) {
final String errorMessage = "Client cannot be closed because of non-closed loans.";
throw new InvalidClientStateTransitionException("close", "loan.non-closed", errorMessage);
}
}
List<SavingsAccount> clientSavingAccounts = this.savingsRepository.findSavingAccountByClientId(clientId);
@@ -367,6 +370,12 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
if (saving.isActive()) {
final String errorMessage = "Client cannot be closed because of non-closed savings account.";
throw new InvalidClientStateTransitionException("close", "non-closed.savings.account", errorMessage);
} else if (saving.isSubmittedAndPendingApproval()) {
final String errorMessage = "Client cannot be closed because of non-closed savings account.";
throw new InvalidClientStateTransitionException("close", "non-closed.savings.account", errorMessage);
} else if (saving.isApproved()) {
final String errorMessage = "Client cannot be closed because of non-closed savings account.";
throw new InvalidClientStateTransitionException("close", "non-closed.savings.account", errorMessage);
}
}
@@ -380,4 +380,8 @@ public final class Group extends AbstractPersistable<Long> {
public Office getOffice() {
return this.office;
}
public boolean isCenter() {
return this.groupLevel.isCenter();
}
}
@@ -74,4 +74,8 @@ public class GroupLevel extends AbstractPersistable<Long> {
public boolean isIdentifiedByParentId(final Long parentLevelId) {
return this.parentId.equals(parentLevelId);
}
public boolean isCenter() {
return this.levelName.equalsIgnoreCase("Center");
}
}
@@ -0,0 +1,11 @@
package org.mifosplatform.portfolio.group.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class CenterNotActiveException extends AbstractPlatformDomainRuleException {
public CenterNotActiveException(final Long centerId) {
super("error.msg.center.not.active.exception", "The Center with id `" + centerId + "` is not active", centerId);
}
}
@@ -7,9 +7,9 @@ package org.mifosplatform.portfolio.group.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class GroupLoanExistsException extends AbstractPlatformDomainRuleException {
public class GroupAccountExistsException extends AbstractPlatformDomainRuleException {
public GroupLoanExistsException(final String action, String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) {
public GroupAccountExistsException(final String action, String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) {
super("error.msg.group." + action + "." + postFix, defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -0,0 +1,11 @@
package org.mifosplatform.portfolio.group.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class GroupNotActiveException extends AbstractPlatformDomainRuleException {
public GroupNotActiveException(final Long groupId) {
super("error.msg.group.not.active.exception", "The Group with id `" + groupId + "` is not active", groupId);
}
}
@@ -36,8 +36,8 @@ import org.mifosplatform.portfolio.group.domain.GroupLevel;
import org.mifosplatform.portfolio.group.domain.GroupLevelRepository;
import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
import org.mifosplatform.portfolio.group.domain.GroupTypes;
import org.mifosplatform.portfolio.group.exception.GroupAccountExistsException;
import org.mifosplatform.portfolio.group.exception.GroupHasNoStaffException;
import org.mifosplatform.portfolio.group.exception.GroupLoanExistsException;
import org.mifosplatform.portfolio.group.exception.GroupMustBePendingToBeDeletedException;
import org.mifosplatform.portfolio.group.exception.InvalidGroupLevelException;
import org.mifosplatform.portfolio.group.exception.InvalidGroupStateTransitionException;
@@ -46,6 +46,8 @@ import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository;
import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -69,13 +71,14 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
private final GroupLevelRepository groupLevelRepository;
private final GroupingTypesDataValidator fromApiJsonDeserializer;
private final LoanRepository loanRepository;
private final SavingsAccountRepository savingsRepository;
@Autowired
public GroupingTypesWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final GroupRepositoryWrapper groupRepository, final ClientRepositoryWrapper clientRepository,
final OfficeRepository officeRepository, final StaffRepositoryWrapper staffRepository, final NoteRepository noteRepository,
final GroupLevelRepository groupLevelRepository, final GroupingTypesDataValidator fromApiJsonDeserializer,
final LoanRepository loanRepository) {
final LoanRepository loanRepository, final SavingsAccountRepository savingsRepository) {
this.context = context;
this.groupRepository = groupRepository;
this.clientRepository = clientRepository;
@@ -85,6 +88,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
this.groupLevelRepository = groupLevelRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.loanRepository = loanRepository;
this.savingsRepository = savingsRepository;
}
private CommandProcessingResult createGroupingType(final JsonCommand command, final GroupTypes groupingType, final Long centerId) {
@@ -491,6 +495,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
// check if any client has got group loans
validateForJLGLoan(groupForUpdate.getId(), clientMembers);
validateForJLGSavings(groupForUpdate.getId(), clientMembers);
final Map<String, Object> actualChanges = new HashMap<String, Object>();
final List<String> changes = groupForUpdate.disassociateClients(clientMembers);
@@ -516,7 +521,20 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
if (!CollectionUtils.isEmpty(loans)) {
final String defaultUserMessage = "Client with identifier " + client.getId()
+ " cannot be disassociated it has group loans.";
throw new GroupLoanExistsException("disassociate", "client.has.group.loan", defaultUserMessage, client.getId(), groupId);
throw new GroupAccountExistsException("disassociate", "client.has.group.loan", defaultUserMessage, client.getId(), groupId);
}
}
}
@Transactional
private void validateForJLGSavings(final Long groupId, final Set<Client> clientMembers) {
for (final Client client : clientMembers) {
final Collection<SavingsAccount> savings = this.savingsRepository.findByClientIdAndGroupId(client.getId(), groupId);
if (!CollectionUtils.isEmpty(savings)) {
final String defaultUserMessage = "Client with identifier " + client.getId()
+ " cannot be disassociated it has group savings.";
throw new GroupAccountExistsException("disassociate", "client.has.group.saving", defaultUserMessage, client.getId(),
groupId);
}
}
}
@@ -2564,4 +2564,8 @@ public class Loan extends AbstractPersistable<Long> {
}
public void updateGroup(Group group) {
this.group = group;
}
}
@@ -35,9 +35,13 @@ import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
import org.mifosplatform.portfolio.collateral.domain.LoanCollateral;
import org.mifosplatform.portfolio.collateral.service.CollateralAssembler;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
@@ -94,6 +98,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
private final AprCalculator aprCalculator;
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
private final LoanSummaryWrapper loanSummaryWrapper;
private final GroupRepositoryWrapper groupRepository;
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
private final CalendarRepository calendarRepository;
private final CalendarInstanceRepository calendarInstanceRepository;
@@ -107,7 +112,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final CollateralAssembler loanCollateralAssembler, final LoanRepository loanRepository, final NoteRepository noteRepository,
final LoanScheduleCalculationPlatformService calculationPlatformService, final ClientRepositoryWrapper clientRepository,
final LoanProductRepository loanProductRepository, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
final LoanSummaryWrapper loanSummaryWrapper,
final LoanSummaryWrapper loanSummaryWrapper, final GroupRepositoryWrapper groupRepository,
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository) {
this.context = context;
@@ -126,6 +131,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.loanProductRepository = loanProductRepository;
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
this.loanSummaryWrapper = loanSummaryWrapper;
this.groupRepository = groupRepository;
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
this.calendarRepository = calendarRepository;
this.calendarInstanceRepository = calendarInstanceRepository;
@@ -213,6 +219,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.fromApiJsonDeserializer.validateForModify(command.json());
final Loan existingLoanApplication = retrieveLoanBy(loanId);
checkClientOrGroupActive(existingLoanApplication);
if (!existingLoanApplication.isSubmittedAndPendingApproval()) { throw new LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeModified(
loanId); }
@@ -232,10 +239,20 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
if (changes.containsKey(clientIdParamName)) {
final Long clientId = command.longValueOfParameterNamed(clientIdParamName);
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
if (client.isNotActive()) { throw new ClientNotActiveException(clientId); }
existingLoanApplication.updateClient(client);
}
final String groupIdParamName = "groupId";
if (changes.containsKey(groupIdParamName)) {
final Long groupId = command.longValueOfParameterNamed(groupIdParamName);
final Group group = this.groupRepository.findOneWithNotFoundDetection(groupId);
if (group.isNotActive()) { throw new GroupNotActiveException(groupId); }
existingLoanApplication.updateGroup(group);
}
final String productIdParamName = "productId";
if (changes.containsKey(productIdParamName)) {
final Long productId = command.longValueOfParameterNamed(productIdParamName);
@@ -392,6 +409,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
context.authenticatedUser();
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
if (loan.isNotSubmittedAndPendingApproval()) { throw new LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeDeleted(loanId); }
@@ -418,6 +436,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.loanApplicationTransitionApiJsonValidator.validateApproval(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final Map<String, Object> changes = loan.loanApplicationApproval(currentUser, command, defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) {
@@ -451,6 +470,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.fromApiJsonDeserializer.validateForUndo(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final Map<String, Object> changes = loan.undoApproval(defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) {
@@ -483,6 +503,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.loanApplicationTransitionApiJsonValidator.validateRejection(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final Map<String, Object> changes = loan.loanApplicationRejection(currentUser, command, defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) {
@@ -515,6 +536,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.loanApplicationTransitionApiJsonValidator.validateApplicantWithdrawal(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final Map<String, Object> changes = loan.loanApplicationWithdrawnByApplicant(currentUser, command,
defaultLoanLifecycleStateMachine());
@@ -565,4 +587,15 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
}
}
private void checkClientOrGroupActive(final Loan loan) {
final Client client = loan.client();
if (client != null) {
if (client.isNotActive()) { throw new ClientNotActiveException(client.getId()); }
}
final Group group = loan.group();
if (group != null) {
if (group.isNotActive()) { throw new GroupNotActiveException(group.getId()); }
}
}
}
@@ -26,6 +26,7 @@ import org.mifosplatform.organisation.workingdays.domain.WorkingDays;
import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
import org.mifosplatform.portfolio.collateral.domain.LoanCollateral;
import org.mifosplatform.portfolio.collateral.service.CollateralAssembler;
import org.mifosplatform.portfolio.fund.domain.Fund;
@@ -34,6 +35,7 @@ import org.mifosplatform.portfolio.fund.exception.FundNotFoundException;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.exception.ClientNotInGroupException;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
@@ -158,6 +160,9 @@ public class LoanAssembler {
if (clientId != null) {
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
if (client.isNotActive()) {
throw new ClientNotActiveException(clientId);
}
loanApplication = Loan.newIndividualLoanApplication(accountNo, client, loanType.getId().intValue(), loanProduct, fund,
loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral);
@@ -166,6 +171,9 @@ public class LoanAssembler {
if (groupId != null) {
group = this.groupRepository.findOne(groupId);
if (group == null) { throw new GroupNotFoundException(groupId); }
if (group.isNotActive()) {
throw new GroupNotActiveException(groupId);
}
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanType.getId().intValue(), loanProduct, fund, loanOfficer,
loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, syncDisbursementWithMeeting);
@@ -48,10 +48,14 @@ import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeUpdatedExc
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException;
import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException.LOAN_CHARGE_CANNOT_BE_WAIVED_REASON;
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand;
import org.mifosplatform.portfolio.collectionsheet.command.SingleDisbursalCommand;
import org.mifosplatform.portfolio.collectionsheet.command.SingleRepaymentCommand;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
import org.mifosplatform.portfolio.loanaccount.domain.ChangedTransactionDetail;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
@@ -162,6 +166,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanEventApiJsonValidator.validateDisbursement(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
//check for product mix validations
checkForProductMixRestrictions(loan);
@@ -265,6 +270,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
SingleDisbursalCommand singleLoanDisbursalCommand = disbursalCommand[i];
final Loan loan = retrieveLoanBy(singleLoanDisbursalCommand.getLoanId());
checkClientOrGroupActive(loan);
final MonetaryCurrency currency = loan.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
@@ -314,6 +320,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
context.authenticatedUser();
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
removeLoanCycle(loan);
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
@@ -382,6 +389,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private CommandProcessingResultBuilder saveLoanRepayment(final Long loanId, final PaymentDetail paymentDetail,
final BigDecimal transactionAmount, final LocalDate transactionDate, final String noteText) {
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
// TODO: Is it required to validate transaction date with meeting dates
// if repayments is synced with meeting?
@@ -472,6 +480,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanEventApiJsonValidator.validateTransaction(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final LoanTransaction transactionToAdjust = this.loanTransactionRepository.findOne(transactionId);
if (transactionToAdjust == null) { throw new LoanTransactionNotFoundException(transactionId); }
@@ -572,6 +581,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
@@ -632,6 +642,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
changes.put("dateFormat", command.dateFormat());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
removeLoanCycle(loan);
final List<Long> existingTransactionIds = new ArrayList<Long>();
@@ -671,6 +682,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanEventApiJsonValidator.validateTransactionWithNoAmount(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final Map<String, Object> changes = new LinkedHashMap<String, Object>();
changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate"));
@@ -733,6 +745,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanEventApiJsonValidator.validateTransactionWithNoAmount(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
removeLoanCycle(loan);
final Map<String, Object> changes = new LinkedHashMap<String, Object>();
@@ -771,6 +784,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanEventApiJsonValidator.validateAddLoanCharge(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final Long chargeDefinitionId = command.longValueOfParameterNamed("chargeId");
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
@@ -831,6 +845,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanEventApiJsonValidator.validateUpdateOfLoanCharge(command.json());
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
// Charges may be edited only when the loan associated with them are
@@ -860,6 +875,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.context.authenticatedUser();
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
// Charges may be waived only when the loan associated with them are
@@ -904,6 +920,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.context.authenticatedUser();
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
// Charges may be deleted only when the loan associated with them are
@@ -955,6 +972,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final LocalDate dateOfLoanOfficerAssignment = command.localDateValueOfParameterNamed("assignmentDate");
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
if (!loan.hasLoanOfficer(fromLoanOfficer)) { throw new LoanOfficerAssignmentException(loanId, fromLoanOfficerId); }
@@ -990,6 +1008,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
for (final String loanIdString : loanIds) {
final Long loanId = Long.valueOf(loanIdString);
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
if (!loan.hasLoanOfficer(fromLoanOfficer)) { throw new LoanOfficerAssignmentException(loanId, fromLoanOfficerId); }
@@ -1017,6 +1036,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final LocalDate dateOfLoanOfficerunAssigned = command.localDateValueOfParameterNamed("unassignedDate");
final Loan loan = retrieveLoanBy(loanId);
checkClientOrGroupActive(loan);
if (loan.getLoanOfficer() == null) { throw new LoanOfficerUnassignmentException(loanId); }
@@ -1286,4 +1306,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
}
}
}
private void checkClientOrGroupActive(final Loan loan) {
final Client client = loan.client();
if (client != null) {
if (client.isNotActive()) { throw new ClientNotActiveException(client.getId()); }
}
final Group group = loan.group();
if (group != null) {
if (group.isNotActive()) { throw new GroupNotActiveException(group.getId()); }
}
}
}
@@ -342,6 +342,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return SavingsAccountStatusType.fromInt(this.status).isSubmittedAndPendingApproval();
}
public boolean isApproved() {
return SavingsAccountStatusType.fromInt(this.status).isApproved();
}
public void postInterest(final MathContext mc, final LocalDate interestPostingUpToDate, final List<Long> existingTransactionIds,
final List<Long> existingReversedTransactionIds) {
@@ -1677,4 +1681,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return lockedInUntilLocalDate;
}
public Group group() {
return this.group;
}
}
@@ -36,8 +36,11 @@ import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
import org.mifosplatform.portfolio.group.exception.CenterNotActiveException;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
@@ -100,11 +103,17 @@ public class SavingsAccountAssembler {
final Long clientId = fromApiJsonHelper.extractLongNamed(clientIdParamName, element);
if (clientId != null) {
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
if (client.isNotActive()) { throw new ClientNotActiveException(clientId); }
}
final Long groupId = fromApiJsonHelper.extractLongNamed(groupIdParamName, element);
if (groupId != null) {
group = this.groupRepository.findOneWithNotFoundDetection(groupId);
if (group.isNotActive()) {
if (group.isCenter()) { throw new CenterNotActiveException(groupId); }
throw new GroupNotActiveException(groupId);
}
}
final Long fieldOfficerId = fromApiJsonHelper.extractLongNamed(fieldOfficerIdParamName, element);
@@ -16,4 +16,7 @@ public interface SavingsAccountRepository extends JpaRepository<SavingsAccount,
@Query("from SavingsAccount s_acc where s_acc.client.id = :clientId")
List<SavingsAccount> findSavingAccountByClientId(@Param("clientId") Long clientId);
@Query("from SavingsAccount sa where sa.client.id = :clientId and sa.group.id = :groupId")
List<SavingsAccount> findByClientIdAndGroupId(@Param("clientId") Long clientId, @Param("groupId") Long groupId);
}
@@ -26,6 +26,10 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
import org.mifosplatform.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDataValidator;
@@ -79,6 +83,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
this.savingsAccountTransactionDataValidator.validateActivation(command);
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
@@ -110,6 +115,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
this.savingsAccountTransactionDataValidator.validate(command);
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final Locale locale = command.extractLocale();
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
@@ -164,6 +170,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
this.savingsAccountTransactionDataValidator.validate(command);
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
@@ -208,6 +215,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
public CommandProcessingResult applyAnnualFee(final Long savingsId, final LocalDate annualFeeTransactionDate) {
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final DateTimeFormatter fmt = DateTimeFormat.forPattern("dd MM yyyy");
@@ -238,6 +246,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
public CommandProcessingResult calculateInterest(final Long savingsId) {
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final LocalDate today = DateUtils.getLocalDateOfTenant();
final MathContext mc = new MathContext(15, RoundingMode.HALF_EVEN);
@@ -263,6 +272,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final LocalDate today = DateUtils.getLocalDateOfTenant();
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
@@ -298,6 +308,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
account.undoTransaction(transactionId, reversedTransactionIds, mc, today);
checkClientOrGroupActive(account);
postJournalEntries(account, newTransactionIds, reversedTransactionIds);
@@ -320,4 +331,15 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
existingTransactionIds, existingReversedTransactionIds);
journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
}
private void checkClientOrGroupActive(final SavingsAccount account) {
final Client client = account.getClient();
if (client != null) {
if (client.isNotActive()) { throw new ClientNotActiveException(client.getId()); }
}
final Group group = account.group();
if (group != null) {
if (group.isNotActive()) { throw new GroupNotActiveException(group.getId()); }
}
}
}
@@ -32,8 +32,11 @@ import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupRepository;
import org.mifosplatform.portfolio.group.exception.CenterNotActiveException;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.portfolio.note.domain.Note;
import org.mifosplatform.portfolio.note.domain.NoteRepository;
@@ -170,7 +173,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
final Map<String, Object> changes = new LinkedHashMap<String, Object>(20);
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
account.modifyApplication(command, changes);
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant());
@@ -180,6 +183,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
final Long clientId = command.longValueOfParameterNamed(SavingsApiConstants.clientIdParamName);
if (clientId != null) {
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
if (client.isNotActive()) { throw new ClientNotActiveException(clientId); }
account.update(client);
} else {
final Client client = null;
@@ -192,6 +196,10 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
if (groupId != null) {
final Group group = this.groupRepository.findOne(groupId);
if (group == null) { throw new GroupNotFoundException(groupId); }
if (group.isNotActive()) {
if (group.isCenter()) { throw new CenterNotActiveException(groupId); }
throw new GroupNotActiveException(groupId);
}
account.update(group);
} else {
final Group group = null;
@@ -241,6 +249,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
public CommandProcessingResult deleteApplication(final Long savingsId) {
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
if (account.isNotSubmittedAndPendingApproval()) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
@@ -276,6 +285,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountApplicationTransitionApiJsonValidator.validateApproval(command.json());
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(savingsAccount);
final Map<String, Object> changes = savingsAccount.approveApplication(currentUser, command, DateUtils.getLocalDateOfTenant());
if (!changes.isEmpty()) {
@@ -309,6 +319,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountApplicationTransitionApiJsonValidator.validateForUndo(command.json());
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(savingsAccount);
final Map<String, Object> changes = savingsAccount.undoApplicationApproval();
if (!changes.isEmpty()) {
@@ -342,6 +353,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountApplicationTransitionApiJsonValidator.validateRejection(command.json());
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(savingsAccount);
final Map<String, Object> changes = savingsAccount.rejectApplication(currentUser, command, DateUtils.getLocalDateOfTenant());
if (!changes.isEmpty()) {
@@ -374,6 +386,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountApplicationTransitionApiJsonValidator.validateApplicantWithdrawal(command.json());
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(savingsAccount);
final Map<String, Object> changes = savingsAccount.applicantWithdrawsFromApplication(currentUser, command,
DateUtils.getLocalDateOfTenant());
@@ -409,4 +422,18 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
existingTransactionIds, existingReversedTransactionIds);
journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
}
private void checkClientOrGroupActive(final SavingsAccount account) {
final Client client = account.getClient();
if (client != null) {
if (client.isNotActive()) { throw new ClientNotActiveException(client.getId()); }
}
final Group group = account.group();
if (group != null) {
if (group.isNotActive()) {
if (group.isCenter()) { throw new CenterNotActiveException(group.getId()); }
throw new GroupNotActiveException(group.getId());
}
}
}
}