@@ -8543,6 +8582,7 @@ Request Body:
"incomeFromFeeAccountId":"37",
"incomeFromPenaltyAccountId":"35",
"writeOffAccountId":"41",
+ "transfersInSuspenseAccountId":"4",
"paymentChannelToFundSourceMappings": [
{
"paymentTypeId": "11",
@@ -12323,7 +12363,7 @@ Content-Type: application/json
Mandatory Fields for Cash based accounting (accountingRule = 2) |
- | savingsReferenceAccountId,savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId |
+ savingsReferenceAccountId,savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId, transfersInSuspenseAccountId |
@@ -12384,6 +12424,7 @@ Request Body:
"annualFeeOnMonthDay": "01 May",
"accountingRule": "2",
"savingsReferenceAccountId": "16",
+ "transfersInSuspenseAccountId": "16",
"savingsControlAccountId": "15",
"interestOnSavingsAccountId": "18",
"incomeFromFeeAccountId": "4",
diff --git a/mifosng-db/migrations/core_db/V118_3__permissions_form_propose_and_accept_client_transfers.sql b/mifosng-db/migrations/core_db/V118_3__permissions_form_propose_and_accept_client_transfers.sql
new file mode 100644
index 000000000..215d73c8b
--- /dev/null
+++ b/mifosng-db/migrations/core_db/V118_3__permissions_form_propose_and_accept_client_transfers.sql
@@ -0,0 +1,7 @@
+/**Permissions for proposing and accepting a transfer**/
+INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
+VALUES ('portfolio', 'PROPOSEANDACCEPTTRANSFER_CLIENT', 'CLIENT', 'PROPOSEANDACCEPTTRANSFER', 0);
+
+INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
+VALUES ('portfolio', 'PROPOSEANDACCEPTTRANSFER_CLIENT_CHECKER', 'CLIENT', 'PROPOSEANDACCEPTTRANSFER', 0);
+
diff --git a/mifosng-db/migrations/core_db/V118_4__reset_default_transfers_in_suspense_account_for_existing_savings_products.sql b/mifosng-db/migrations/core_db/V118_4__reset_default_transfers_in_suspense_account_for_existing_savings_products.sql
new file mode 100644
index 000000000..6fbb2e3d4
--- /dev/null
+++ b/mifosng-db/migrations/core_db/V118_4__reset_default_transfers_in_suspense_account_for_existing_savings_products.sql
@@ -0,0 +1,8 @@
+/***Delete previously set defaults**/
+delete from acc_product_mapping where financial_account_type=10 and product_type=2;
+
+/***Set the proper defaults**/
+INSERT INTO `acc_product_mapping` (`gl_account_id`,`product_id`,`product_type`,`payment_type`,`charge_id`,`financial_account_type`)
+select mapping.gl_account_id,mapping.product_id,mapping.product_type,mapping.payment_type,mapping.charge_id, 10
+from acc_product_mapping mapping
+where mapping.financial_account_type = 2 and mapping.product_type=2;
\ No newline at end of file
diff --git a/mifosng-provider/gradle.properties b/mifosng-provider/gradle.properties
index 02ffe6690..9df97c7ed 100644
--- a/mifosng-provider/gradle.properties
+++ b/mifosng-provider/gradle.properties
@@ -1,2 +1,2 @@
-releaseVersion=1.10.1.RELEASE
+releaseVersion=1.10.2.RELEASE
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java
index 4975a18c5..279eb0acc 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java
@@ -612,6 +612,10 @@ public class CommandWrapper {
return this.actionName.equalsIgnoreCase("PROPOSETRANSFER") && this.entityName.equalsIgnoreCase("CLIENT");
}
+ public boolean isProposeAndAcceptClientTransfer() {
+ return this.actionName.equalsIgnoreCase("PROPOSEANDACCEPTTRANSFER") && this.entityName.equalsIgnoreCase("CLIENT");
+ }
+
public boolean isWithdrawClientTransfer() {
return this.actionName.equalsIgnoreCase("WITHDRAWTRANSFER") && this.entityName.equalsIgnoreCase("CLIENT");
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java
index 362259eb6..650683a41 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java
@@ -361,6 +361,15 @@ public class CommandWrapperBuilder {
this.href = "/clientId/" + clientId + "?command=proposeTransfer";
return this;
}
+
+ public CommandWrapperBuilder proposeAndAcceptClientTransfer(final Long clientId) {
+ this.actionName = "PROPOSEANDACCEPTTRANSFER";
+ this.entityName = "CLIENT";
+ this.entityId = clientId;
+ this.clientId = clientId;
+ this.href = "/clientId/" + clientId + "?command=proposeAndAcceptTransfer";
+ return this;
+ }
public CommandWrapperBuilder withdrawClientTransferRequest(final Long clientId) {
this.actionName = "WITHDRAWTRANSFER";
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java
index 70ad36a57..1940a4322 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java
@@ -171,6 +171,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = this.applicationContext.getBean("closeClientCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isProposeClientTransfer()) {
handler = this.applicationContext.getBean("proposeClientTransferCommandHandler", NewCommandSourceHandler.class);
+ } else if (wrapper.isProposeAndAcceptClientTransfer()) {
+ handler = this.applicationContext.getBean("proposeAndAcceptClientTransferCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isWithdrawClientTransfer()) {
handler = this.applicationContext.getBean("withdrawClientTransferCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isAcceptClientTransfer()) {
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java
index 362da5993..c4e23f962 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java
@@ -212,6 +212,9 @@ public class ClientsApiResource {
} else if (is(commandParam, "proposeTransfer")) {
commandRequest = builder.proposeClientTransfer(clientId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ } else if (is(commandParam, "proposeAndAcceptTransfer")) {
+ commandRequest = builder.proposeAndAcceptClientTransfer(clientId).build();
+ result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, "withdrawTransfer")) {
commandRequest = builder.withdrawClientTransferRequest(clientId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java
index e7c48f926..c45fc7215 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java
@@ -5,6 +5,7 @@
*/
package org.mifosplatform.portfolio.group.domain;
+import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -31,6 +32,12 @@ public class GroupRepositoryWrapper {
return entity;
}
+ public Group findByOfficeWithNotFoundDetection(final Long id, final Office office) {
+ final Group group = findOneWithNotFoundDetection(id);
+ if (group.getOffice().getId() != office.getId()) { throw new GroupNotFoundException(id); }
+ return group;
+ }
+
public void save(final Group entity) {
this.repository.save(entity);
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java
index 42c827f72..2b57156ef 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java
@@ -19,8 +19,9 @@ public enum SavingsAccountTransactionType {
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), //
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), //
ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), //
- WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharges"), APPLY_CHARGES(7, "savingsAccountTransactionType.applyCharges"), INITIATE_TRANSFER(
- 12, "savingsAccountTransactionType.initiateTransfer"), //
+ WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharges"), //
+ PAY_CHARGE(7, "savingsAccountTransactionType.payCharge"), //
+ INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), //
APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer");
@@ -66,7 +67,7 @@ public enum SavingsAccountTransactionType {
savingsAccountTransactionType = SavingsAccountTransactionType.WAIVE_CHARGES;
break;
case 7:
- savingsAccountTransactionType = SavingsAccountTransactionType.APPLY_CHARGES;
+ savingsAccountTransactionType = SavingsAccountTransactionType.PAY_CHARGE;
break;
case 12:
savingsAccountTransactionType = SavingsAccountTransactionType.INITIATE_TRANSFER;
@@ -105,7 +106,7 @@ public enum SavingsAccountTransactionType {
}
public boolean isCharge() {
- return this.value.equals(SavingsAccountTransactionType.APPLY_CHARGES.getValue());
+ return this.value.equals(SavingsAccountTransactionType.PAY_CHARGE.getValue());
}
public boolean isWaiveCharge() {
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java
index f82e028e6..da9a442a6 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java
@@ -35,7 +35,8 @@ public class SavingsAccountTransactionEnumData {
this.withdrawal = Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL.getValue()).equals(this.id);
this.interestPosting = Long.valueOf(SavingsAccountTransactionType.INTEREST_POSTING.getValue()).equals(this.id);
this.feeDeduction = Long.valueOf(SavingsAccountTransactionType.ANNUAL_FEE.getValue()).equals(this.id)
- || Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()).equals(this.id);
+ || Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()).equals(this.id)
+ || Long.valueOf(SavingsAccountTransactionType.PAY_CHARGE.getValue()).equals(this.id);
this.initiateTransfer = Long.valueOf(SavingsAccountTransactionType.INITIATE_TRANSFER.getValue()).equals(this.id);
this.approveTransfer = Long.valueOf(SavingsAccountTransactionType.APPROVE_TRANSFER.getValue()).equals(this.id);
this.withdrawTransfer = Long.valueOf(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue()).equals(this.id);
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java
index f5b8d6035..7475e64aa 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java
@@ -131,7 +131,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable
{
public static SavingsAccountTransaction charge(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
final Money amount) {
final boolean isReversed = false;
- return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.APPLY_CHARGES.getValue(), date, amount,
+ return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.PAY_CHARGE.getValue(), date, amount,
isReversed);
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
index f971bc94d..56eeefc9b 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -514,6 +514,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
savingsAccount.office(), transferDate);
savingsAccount.getTransactions().add(newTransferTransaction);
savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue());
+ final MathContext mc = MathContext.DECIMAL64;
+ savingsAccount.calculateInterestUsing(mc, transferDate);
this.savingsAccountTransactionRepository.save(newTransferTransaction);
this.savingAccountRepository.save(savingsAccount);
@@ -534,6 +536,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
savingsAccount.office(), transferDate);
savingsAccount.getTransactions().add(withdrawtransferTransaction);
savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue());
+ final MathContext mc = MathContext.DECIMAL64;
+ savingsAccount.calculateInterestUsing(mc, transferDate);
this.savingsAccountTransactionRepository.save(withdrawtransferTransaction);
this.savingAccountRepository.save(savingsAccount);
@@ -565,6 +569,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
if (fieldOfficer != null) {
savingsAccount.update(fieldOfficer);
}
+
+ final MathContext mc = MathContext.DECIMAL64;
+ savingsAccount.calculateInterestUsing(mc, transferDate);
this.savingsAccountTransactionRepository.save(acceptTransferTransaction);
this.savingAccountRepository.save(savingsAccount);
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java
index 59b45ed00..1f8e8945d 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java
@@ -101,9 +101,9 @@ public class SavingsEnumerations {
SavingsAccountTransactionType.WITHDRAW_TRANSFER.getCode(), "Transfer Withdrawn");
break;
default:
- case APPLY_CHARGES:
- optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.APPLY_CHARGES.getValue().longValue(),
- SavingsAccountTransactionType.APPLY_CHARGES.getCode(), "Apply Charge");
+ case PAY_CHARGE:
+ optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.PAY_CHARGE.getValue().longValue(),
+ SavingsAccountTransactionType.PAY_CHARGE.getCode(), "Pay Charge");
break;
case WAIVE_CHARGES:
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WAIVE_CHARGES.getValue().longValue(),
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java
index d375f17c7..7e962e1b2 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java
@@ -35,6 +35,9 @@ public class TransferApiConstants {
public static final Set ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(newStaffIdParamName,
destinationGroupIdParamName, note));
+ public static final Set PROPOSE_AND_ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(localeParamName,
+ dateFormatParamName, destinationOfficeIdParamName, transferActiveLoans, newStaffIdParamName, destinationGroupIdParamName, note));
+
public static final Set REJECT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(note));
public static final Set WITHDRAW_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(note));
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java
index 1ea8a16ca..7067d8858 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java
@@ -125,6 +125,41 @@ public final class TransfersDataValidator {
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
+ public void validateForProposeAndAcceptClientTransfer(final String json) {
+ if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
+
+ final Type typeOfMap = new TypeToken