merging 1.7.1 release into develop branch
This commit is contained in:
-2
@@ -1,2 +0,0 @@
|
||||
INSERT INTO `c_configuration` (`name`, `enabled`) VALUES ('allow-transactions-on-holiday', 0);
|
||||
INSERT INTO `c_configuration` (`name`, `enabled`) VALUES ('allow-transactions-on-non_workingday', 0);
|
||||
@@ -1 +0,0 @@
|
||||
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`, `task_priority`, `group_name`, `previous_run_start_time`, `next_run_time`, `job_key`, `initializing_errorlog`, `is_active`, `currently_running`, `updates_allowed`, `scheduler_group`) VALUES ('Post Interest For Savings', 'Post Interest For Savings', '0 0 0 1/1 * ? *', now(), 5, NULL, NULL, NULL, NULL, NULL, 1, 0, 1, 0);
|
||||
@@ -1,56 +0,0 @@
|
||||
INSERT INTO `m_permission`
|
||||
(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`)
|
||||
VALUES
|
||||
('transaction_savings', 'READ_ACCOUNTTRANSFER', 'ACCOUNTTRANSFER', 'READ', 0),
|
||||
('transaction_savings', 'CREATE_ACCOUNTTRANSFER', 'ACCOUNTTRANSFER', 'CREATE', 1),
|
||||
('transaction_savings', 'CREATE_ACCOUNTTRANSFER_CHECKER', 'ACCOUNTTRANSFER', 'CREATE', 0);
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `m_savings_account_transfer`;
|
||||
|
||||
CREATE TABLE `m_savings_account_transfer` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`from_office_id` bigint(20) NOT NULL,
|
||||
`to_office_id` bigint(20) NOT NULL,
|
||||
`from_client_id` bigint(20) NOT NULL,
|
||||
`to_client_id` bigint(20) NOT NULL,
|
||||
`from_savings_account_id` bigint(20) DEFAULT NULL,
|
||||
`to_savings_account_id` bigint(20) DEFAULT NULL,
|
||||
`from_loan_account_id` bigint(20) DEFAULT NULL,
|
||||
`to_loan_account_id` bigint(20) DEFAULT NULL,
|
||||
`from_savings_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`from_loan_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`to_savings_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`to_loan_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`is_reversed` tinyint(1) NOT NULL,
|
||||
`transaction_date` date NOT NULL,
|
||||
`currency_code` varchar(3) NOT NULL,
|
||||
`currency_digits` smallint(5) NOT NULL,
|
||||
`amount` decimal(19,6) NOT NULL,
|
||||
`description` varchar(200) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `FKTRAN000000001` (`from_office_id`),
|
||||
KEY `FKTRAN000000002` (`from_client_id`),
|
||||
KEY `FKTRAN000000003` (`from_savings_account_id`),
|
||||
KEY `FKTRAN000000004` (`to_office_id`),
|
||||
KEY `FKTRAN000000005` (`to_client_id`),
|
||||
KEY `FKTRAN000000006` (`to_savings_account_id`),
|
||||
KEY `FKTRAN000000007` (`to_loan_account_id`),
|
||||
KEY `FKTRAN000000008` (`from_savings_transaction_id`),
|
||||
KEY `FKTRAN000000009` (`to_savings_transaction_id`),
|
||||
KEY `FKTRAN000000010` (`to_loan_transaction_id`),
|
||||
KEY `FKTRAN000000011` (`from_loan_account_id`),
|
||||
KEY `FKTRAN000000012` (`from_loan_transaction_id`),
|
||||
CONSTRAINT `FKTRAN000000001` FOREIGN KEY (`from_office_id`) REFERENCES `m_office` (`id`),
|
||||
CONSTRAINT `FKTRAN000000002` FOREIGN KEY (`from_client_id`) REFERENCES `m_client` (`id`),
|
||||
CONSTRAINT `FKTRAN000000003` FOREIGN KEY (`from_savings_account_id`) REFERENCES `m_savings_account` (`id`),
|
||||
CONSTRAINT `FKTRAN000000004` FOREIGN KEY (`to_office_id`) REFERENCES `m_office` (`id`),
|
||||
CONSTRAINT `FKTRAN000000005` FOREIGN KEY (`to_client_id`) REFERENCES `m_client` (`id`),
|
||||
CONSTRAINT `FKTRAN000000006` FOREIGN KEY (`to_savings_account_id`) REFERENCES `m_savings_account` (`id`),
|
||||
CONSTRAINT `FKTRAN000000007` FOREIGN KEY (`to_loan_account_id`) REFERENCES `m_loan` (`id`),
|
||||
CONSTRAINT `FKTRAN000000008` FOREIGN KEY (`from_savings_transaction_id`) REFERENCES `m_savings_account_transaction` (`id`),
|
||||
CONSTRAINT `FKTRAN000000009` FOREIGN KEY (`to_savings_transaction_id`) REFERENCES `m_savings_account_transaction` (`id`),
|
||||
CONSTRAINT `FKTRAN000000010` FOREIGN KEY (`to_loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`),
|
||||
CONSTRAINT `FKTRAN000000011` FOREIGN KEY (`from_loan_account_id`) REFERENCES `m_loan` (`id`),
|
||||
CONSTRAINT `FKTRAN000000012` FOREIGN KEY (`from_loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
@@ -1 +0,0 @@
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('transaction_savings', 'ADJUSTTRANSACTION_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'ADJUSTTRANSACTION', 0);
|
||||
@@ -1,12 +0,0 @@
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_savings_product`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_loan`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_product_loan`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_currency`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `decimal_places`;
|
||||
ALTER TABLE `m_organisation_currency`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `decimal_places`;
|
||||
@@ -1 +1,5 @@
|
||||
releaseVersion=1.8.0.DEVELOP
|
||||
<<<<<<< HEAD
|
||||
releaseVersion=1.8.0.DEVELOP
|
||||
=======
|
||||
releaseVersion=1.7.1.RELEASE
|
||||
>>>>>>> master
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ public class TenantDatabaseUpgradeService {
|
||||
Flyway flyway = new Flyway();
|
||||
flyway.setDataSource(tenant.databaseURL(), tenant.getSchemaUsername(), tenant.getSchemaPassword());
|
||||
flyway.setLocations("sql");
|
||||
flyway.setOutOfOrder(true);
|
||||
flyway.migrate();
|
||||
}
|
||||
}
|
||||
|
||||
+32
-21
@@ -312,30 +312,41 @@ public class CalendarHelper {
|
||||
public static LocalDate getNewRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate oldRepaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays){
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
if (recur == null) { return null; }
|
||||
|
||||
if(isValidRecurringDate(recur, seedDate, oldRepaymentDate)){
|
||||
return oldRepaymentDate;
|
||||
}
|
||||
/* Recurring dates should follow loanRepaymentInterval.
|
||||
e.g. The weekly meeting will have interval of 1, if the loan product with fortnightly frequency will have interval of 2,
|
||||
to generate right set of meeting dates reset interval same as loan repayment interval.
|
||||
*/
|
||||
recur.setInterval(loanRepaymentInterval);
|
||||
|
||||
/*Recurring dates should follow loanRepayment frequency.
|
||||
//e.g. daily meeting frequency should support all loan products with any type of frequency.
|
||||
to generate right set of meeting dates reset frequency same as loan repayment frequency.
|
||||
*/
|
||||
if(recur.getFrequency().equals(Recur.DAILY)){
|
||||
recur.setFrequency(frequency);
|
||||
}
|
||||
|
||||
LocalDate newRepaymentDate = getNextRecurringDate(recur, seedDate, oldRepaymentDate);
|
||||
LocalDate nextRepaymentDate = getNextRecurringDate(recur, seedDate, newRepaymentDate);
|
||||
|
||||
newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDate, nextRepaymentDate, workingDays);
|
||||
|
||||
return newRepaymentDate;
|
||||
return getNextRepaymentMeetingDate(recurringRule, seedDate, oldRepaymentDate, loanRepaymentInterval, frequency, workingDays);
|
||||
}
|
||||
|
||||
public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate repaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays){
|
||||
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
if (recur == null) { return null; }
|
||||
LocalDate tmpDate = repaymentDate;
|
||||
if(isValidRecurringDate(recur, seedDate, repaymentDate)){
|
||||
tmpDate = repaymentDate.plusDays(1);
|
||||
}
|
||||
/* Recurring dates should follow loanRepaymentInterval.
|
||||
*
|
||||
e.g. The weekly meeting will have interval of 1, if the loan product with fortnightly frequency will have interval of 2,
|
||||
to generate right set of meeting dates reset interval same as loan repayment interval.
|
||||
*/
|
||||
recur.setInterval(loanRepaymentInterval);
|
||||
|
||||
/*Recurring dates should follow loanRepayment frequency.
|
||||
//e.g. daily meeting frequency should support all loan products with any type of frequency.
|
||||
to generate right set of meeting dates reset frequency same as loan repayment frequency.
|
||||
*/
|
||||
if(recur.getFrequency().equals(Recur.DAILY)){
|
||||
recur.setFrequency(frequency);
|
||||
}
|
||||
|
||||
LocalDate newRepaymentDate = getNextRecurringDate(recur, seedDate, tmpDate);
|
||||
LocalDate nextRepaymentDate = getNextRecurringDate(recur, seedDate, newRepaymentDate);
|
||||
|
||||
newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDate, nextRepaymentDate, workingDays);
|
||||
|
||||
return newRepaymentDate;
|
||||
}
|
||||
|
||||
public static boolean isFrequencySame(final String oldRRule, final String newRRule) {
|
||||
|
||||
+11
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+3
-2
@@ -253,7 +253,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, ");
|
||||
@@ -276,7 +276,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");
|
||||
|
||||
+9
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -381,4 +381,7 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
return this.office;
|
||||
}
|
||||
|
||||
public boolean isCenter() {
|
||||
return this.groupLevel.isCenter();
|
||||
}
|
||||
}
|
||||
+4
@@ -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");
|
||||
}
|
||||
}
|
||||
+11
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
+11
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+21
-3
@@ -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) {
|
||||
@@ -519,6 +523,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);
|
||||
@@ -544,7 +549,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
-8
@@ -2388,22 +2388,32 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
public void updateLoanRepaymentScheduleDates(final LocalDate meetingStartDate, final String recuringRule,
|
||||
final boolean isHolidayEnabled, final List<Holiday> holidays, final WorkingDays workingDays) {
|
||||
//update repayment dates of repayment schedule installaments
|
||||
LocalDate tmpFromDate = getDisbursementDate();//first repayment's from date is same as disbursement date.
|
||||
LocalDate tmpFromDate = this.getDisbursementDate();//first repayment's from date is same as disbursement date.
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
|
||||
final Integer loanRepaymentInterval = this.loanRepaymentScheduleDetail.getRepayEvery();
|
||||
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
|
||||
|
||||
LocalDate newRepaymentDate = null;
|
||||
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
|
||||
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||
// FIXME: AA this won't update repayment dates before current date.
|
||||
if (oldDueDate.isAfter(meetingStartDate) && oldDueDate.isAfter(DateUtils.getLocalDateOfTenant())) {
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
|
||||
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
|
||||
final Integer loanRepaymentInterval = this.loanRepaymentScheduleDetail.getRepayEvery();
|
||||
|
||||
// reset repayment date with new meeting date
|
||||
newRepaymentDate = CalendarHelper.getNewRepaymentMeetingDate(recuringRule, meetingStartDate, oldDueDate, loanRepaymentInterval, frequency, workingDays);
|
||||
if(isHolidayEnabled){
|
||||
newRepaymentDate = CalendarHelper.getNewRepaymentMeetingDate(recuringRule, meetingStartDate, oldDueDate,
|
||||
loanRepaymentInterval, frequency, workingDays);
|
||||
|
||||
final LocalDate maxDateLimitForNewRepayment = getMaxDateLimitForNewRepayment(repaymentPeriodFrequencyType,
|
||||
loanRepaymentInterval, tmpFromDate);
|
||||
|
||||
if (newRepaymentDate.isAfter(maxDateLimitForNewRepayment)) {
|
||||
newRepaymentDate = CalendarHelper.getNextRepaymentMeetingDate(recuringRule, meetingStartDate, tmpFromDate,
|
||||
loanRepaymentInterval, frequency, workingDays);
|
||||
}
|
||||
|
||||
if (isHolidayEnabled) {
|
||||
newRepaymentDate = HolidayUtil.getRepaymentRescheduleDateToIfHoliday(newRepaymentDate, holidays);
|
||||
}
|
||||
|
||||
|
||||
loanRepaymentScheduleInstallment.updateDueDate(newRepaymentDate);
|
||||
// reset from date to get actual daysInPeriod
|
||||
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
||||
@@ -2415,6 +2425,29 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
private LocalDate getMaxDateLimitForNewRepayment(final PeriodFrequencyType periodFrequencyType, final Integer loanRepaymentInterval,
|
||||
final LocalDate startDate) {
|
||||
LocalDate dueRepaymentPeriodDate = startDate;
|
||||
final Integer repaidEvery = 2*loanRepaymentInterval;
|
||||
switch (periodFrequencyType) {
|
||||
case DAYS:
|
||||
dueRepaymentPeriodDate = startDate.plusDays(repaidEvery);
|
||||
break;
|
||||
case WEEKS:
|
||||
dueRepaymentPeriodDate = startDate.plusWeeks(repaidEvery);
|
||||
break;
|
||||
case MONTHS:
|
||||
dueRepaymentPeriodDate = startDate.plusMonths(repaidEvery);
|
||||
break;
|
||||
case YEARS:
|
||||
dueRepaymentPeriodDate = startDate.plusYears(repaidEvery);
|
||||
break;
|
||||
case INVALID:
|
||||
break;
|
||||
}
|
||||
return dueRepaymentPeriodDate.minusDays(1);//get 2n-1 range date from startDate
|
||||
}
|
||||
|
||||
public void applyHolidayToRepaymentScheduleDates(final Holiday holiday) {
|
||||
// first repayment's from date is same as disbursement date.
|
||||
LocalDate tmpFromDate = getDisbursementDate();
|
||||
@@ -2525,4 +2558,8 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
|
||||
}
|
||||
|
||||
public void updateGroup(Group group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
}
|
||||
+34
-1
@@ -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;
|
||||
@@ -218,6 +224,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); }
|
||||
@@ -237,10 +244,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);
|
||||
@@ -397,6 +414,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
context.authenticatedUser();
|
||||
|
||||
final Loan loan = retrieveLoanBy(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
if (loan.isNotSubmittedAndPendingApproval()) { throw new LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeDeleted(loanId); }
|
||||
|
||||
@@ -423,6 +441,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()) {
|
||||
@@ -456,6 +475,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()) {
|
||||
@@ -488,6 +508,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()) {
|
||||
@@ -520,6 +541,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());
|
||||
@@ -570,4 +592,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()); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -27,6 +27,7 @@ import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWr
|
||||
import org.mifosplatform.portfolio.accountdetails.service.AccountEnumerations;
|
||||
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;
|
||||
@@ -35,6 +36,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);
|
||||
|
||||
+31
@@ -49,10 +49,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>();
|
||||
@@ -383,6 +390,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 String txnExternalId) {
|
||||
final Loan loan = retrieveLoanBy(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
// TODO: Is it required to validate transaction date with meeting dates
|
||||
// if repayments is synced with meeting?
|
||||
@@ -473,6 +481,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); }
|
||||
@@ -574,6 +583,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>();
|
||||
@@ -634,6 +644,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>();
|
||||
@@ -673,6 +684,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"));
|
||||
@@ -735,6 +747,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>();
|
||||
@@ -773,6 +786,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);
|
||||
@@ -833,6 +847,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
|
||||
@@ -862,6 +877,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
|
||||
@@ -906,6 +922,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
|
||||
@@ -957,6 +974,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); }
|
||||
|
||||
@@ -992,6 +1010,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); }
|
||||
|
||||
@@ -1019,6 +1038,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); }
|
||||
|
||||
@@ -1288,4 +1308,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()); }
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -340,6 +340,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;
|
||||
}
|
||||
}
|
||||
+8
@@ -37,9 +37,12 @@ import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.accountdetails.domain.AccountType;
|
||||
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.ClientNotInGroupException;
|
||||
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;
|
||||
@@ -102,6 +105,7 @@ public class SavingsAccountAssembler {
|
||||
if (clientId != null) {
|
||||
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||
accountType = AccountType.INDIVIDUAL;
|
||||
if (client.isNotActive()) { throw new ClientNotActiveException(clientId); }
|
||||
}
|
||||
|
||||
final Long groupId = fromApiJsonHelper.extractLongNamed(groupIdParamName, element);
|
||||
@@ -113,6 +117,10 @@ public class SavingsAccountAssembler {
|
||||
if (group != null && client != null) {
|
||||
if (!group.hasClientAsMember(client)) { throw new ClientNotInGroupException(clientId, groupId); }
|
||||
accountType = AccountType.JLG;
|
||||
if (group.isNotActive()) {
|
||||
if (group.isCenter()) { throw new CenterNotActiveException(groupId); }
|
||||
throw new GroupNotActiveException(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
final Long fieldOfficerId = fromApiJsonHelper.extractLongNamed(fieldOfficerIdParamName, element);
|
||||
|
||||
+3
@@ -20,4 +20,7 @@ public interface SavingsAccountRepository extends JpaRepository<SavingsAccount,
|
||||
@Query("from SavingsAccount s_acc where s_acc.status = :status")
|
||||
List<SavingsAccount> findSavingAccountByStatus(@Param("status") Integer status);
|
||||
|
||||
|
||||
@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);
|
||||
}
|
||||
+22
@@ -28,6 +28,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.SavingsApiConstants;
|
||||
@@ -89,6 +93,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>();
|
||||
@@ -120,6 +125,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
|
||||
PaymentDetail paymentDetail = paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
|
||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||
checkClientOrGroupActive(account);
|
||||
|
||||
SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(account, fmt, transactionDate,
|
||||
transactionAmount, paymentDetail);
|
||||
@@ -183,6 +190,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");
|
||||
|
||||
@@ -213,6 +221,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);
|
||||
@@ -235,6 +244,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
public CommandProcessingResult postInterest(final Long savingsId) {
|
||||
|
||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||
checkClientOrGroupActive(account);
|
||||
postInterest(account);
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(savingsId) //
|
||||
@@ -284,6 +294,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||
account.undoTransaction(transactionId, reversedTransactionIds);
|
||||
checkClientOrGroupActive(account);
|
||||
if ((savingsAccountTransaction.isDeposit() || savingsAccountTransaction.isWithdrawal())
|
||||
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
||||
account.postInterest(mc, today, newTransactionIds, reversedTransactionIds);
|
||||
@@ -367,4 +378,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()); }
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-1
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user