added modifications for creating group and JLG savings account

This commit is contained in:
Pramod Nuthakki
2013-08-06 12:15:58 +05:30
parent 1320ef5080
commit 1fdf72679a
8 changed files with 297 additions and 26 deletions
+245
View File
@@ -567,6 +567,15 @@
<td></td>
<td></td>
</tr>
<tr class="alt">
<td></td>
<td>groups/{groupId}/accounts</td>
<td></td>
<td><a href="#groups_accounts">Retrive Group accounts summary</a></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
@@ -3888,6 +3897,233 @@ GET https://DomainName/mifosng-provider/api/v1/groups/1?associations=clientMembe
</div>
</div>
<!--Start of Group account summary -->
<a id="groups_accounts" name="groups_accounts" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve Group accounts overview</h4>
<p>
An example of how a loan portfolio summary can be provided. This
is requested in a specific use case of the reference application.<br> It is quite reasonable to add resources like this to simplify User Interface development.
</p>
<p>Example Requests:</p>
<div class=apiClick>groups/1/accounts</div>
<br>
<br>
<div class=apiClick>groups/1/accounts?fields=loanAccounts,savingsAccounts,memberLoanAccounts,<br> memberSavingsAccounts</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/groups/{groupId}/accounts
</code>
<code class="method-response">
{
"loanAccounts": [
{
"id": 3,
"accountNo": "000000003",
"productId": 3,
"productName": "daily product",
"status": {
"id": 100,
"code": "loanStatusType.submitted.and.pending.approval",
"value": "Submitted and pending approval",
"pendingApproval": true,
"waitingForDisbursal": false,
"active": false,
"closedObligationsMet": false,
"closedWrittenOff": false,
"closedRescheduled": false,
"closed": false,
"overpaid": false
},
"loanType": {
"id": 2,
"code": "accountType.group",
"value": "Group"
}
}
],
"savingsAccounts": [
{
"id": 9,
"accountNo": "000000009",
"productId": 1,
"productName": "p_sav",
"status": {
"id": 100,
"code": "savingsAccountStatusType.submitted.and.pending.approval",
"value": "Submitted and pending approval",
"submittedAndPendingApproval": true,
"approved": false,
"rejected": false,
"withdrawnByApplicant": false,
"active": false,
"closed": false
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"accountType": {
"id": 2,
"code": "accountType.group",
"value": "Group"
}
},
{
"id": 4,
"accountNo": "000000004",
"productId": 1,
"productName": "p_sav",
"status": {
"id": 300,
"code": "savingsAccountStatusType.active",
"value": "Active",
"submittedAndPendingApproval": false,
"approved": false,
"rejected": false,
"withdrawnByApplicant": false,
"active": true,
"closed": false
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"accountType": {
"id": 2,
"code": "accountType.group",
"value": "Group"
}
}
],
"memberLoanAccounts": [
{
"id": 4,
"accountNo": "000000004",
"productId": 1,
"productName": "testLoan",
"status": {
"id": 200,
"code": "loanStatusType.approved",
"value": "Approved",
"pendingApproval": false,
"waitingForDisbursal": true,
"active": false,
"closedObligationsMet": false,
"closedWrittenOff": false,
"closedRescheduled": false,
"closed": false,
"overpaid": false
},
"loanType": {
"id": 3,
"code": "accountType.jlg",
"value": "JLG"
}
},
{
"id": 7,
"accountNo": "000000007",
"productId": 2,
"productName": "weekly product",
"status": {
"id": 100,
"code": "loanStatusType.submitted.and.pending.approval",
"value": "Submitted and pending approval",
"pendingApproval": true,
"waitingForDisbursal": false,
"active": false,
"closedObligationsMet": false,
"closedWrittenOff": false,
"closedRescheduled": false,
"closed": false,
"overpaid": false
},
"loanType": {
"id": 3,
"code": "accountType.jlg",
"value": "JLG"
}
}
],
"memberSavingsAccounts": [
{
"id": 3,
"accountNo": "000000003",
"productId": 1,
"productName": "p_sav",
"status": {
"id": 100,
"code": "savingsAccountStatusType.submitted.and.pending.approval",
"value": "Submitted and pending approval",
"submittedAndPendingApproval": true,
"approved": false,
"rejected": false,
"withdrawnByApplicant": false,
"active": false,
"closed": false
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"accountType": {
"id": 3,
"code": "accountType.jlg",
"value": "JLG"
}
},
{
"id": 10,
"accountNo": "000000010",
"productId": 1,
"productName": "p_sav",
"status": {
"id": 100,
"code": "savingsAccountStatusType.submitted.and.pending.approval",
"value": "Submitted and pending approval",
"submittedAndPendingApproval": true,
"approved": false,
"rejected": false,
"withdrawnByApplicant": false,
"active": false,
"closed": false
},
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"accountType": {
"id": 3,
"code": "accountType.jlg",
"value": "JLG"
}
}
]
}
</code>
</div>
</div>
<!--End of Group account summary -->
<a id="groups_update" name="groups_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
@@ -17110,6 +17346,15 @@ GET https://DomainName/api/v1/search?query=000000111
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>groups/{groupId}/accounts</td>
<td></td>
<td><a href="#groups_accounts">Retrive Group accounts summary</a></td>
<td></td>
<td></td>
</tr>
<tr class="alt">
<td><a href="#loanproducts">Loan Product</a></td>
<td>loanproducts</td>
@@ -0,0 +1,2 @@
ALTER TABLE `m_savings_account`
ADD COLUMN `account_type_enum` SMALLINT(5) NOT NULL DEFAULT '1' AFTER `status_enum`;
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.accountdetails.data;
import java.math.BigDecimal;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
@@ -24,10 +25,11 @@ public class SavingsAccountSummaryData {
private final SavingsAccountStatusEnumData status;
private final CurrencyData currency;
private final BigDecimal accountBalance;
private final EnumOptionData accountType;
public SavingsAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
final String productName, final SavingsAccountStatusEnumData status, final CurrencyData currency,
final BigDecimal accountBalance) {
final BigDecimal accountBalance, final EnumOptionData accountType) {
this.id = id;
this.accountNo = accountNo;
this.externalId = externalId;
@@ -36,5 +38,6 @@ public class SavingsAccountSummaryData {
this.status = status;
this.currency = currency;
this.accountBalance = accountBalance;
this.accountType = accountType;
}
}
@@ -63,7 +63,7 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
List<LoanAccountSummaryData> memberLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForMembers, new Object[] { groupId });
List<SavingsAccountSummaryData> memberSavingsAccounts = retrieveAccountDetails(savingswhereClauseForMembers,
new Object[] { groupId });
return new AccountSummaryCollectionData(groupLoanAccounts, groupSavingsAccounts,memberLoanAccounts, memberSavingsAccounts);
return new AccountSummaryCollectionData(groupLoanAccounts, groupSavingsAccounts, memberLoanAccounts, memberSavingsAccounts);
}
@Override
@@ -105,6 +105,7 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
public SavingsAccountSummaryDataMapper() {
StringBuilder accountsSummary = new StringBuilder();
accountsSummary.append("sa.id as id, sa.account_no as accountNo, sa.external_id as externalId, sa.status_enum as statusEnum, ");
accountsSummary.append("sa.account_type_enum as accountType, ");
accountsSummary.append("sa.account_balance_derived as accountBalance, ");
accountsSummary.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, ");
accountsSummary.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
@@ -132,6 +133,8 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
final Integer statusId = JdbcSupport.getInteger(rs, "statusEnum");
final BigDecimal accountBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "accountBalance");
final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusId);
final Integer accountType = JdbcSupport.getInteger(rs, "accountType");
final EnumOptionData accountTypeData = AccountEnumerations.loanType(accountType);
final String currencyCode = rs.getString("currencyCode");
final String currencyName = rs.getString("currencyName");
@@ -141,7 +144,8 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode);
return new SavingsAccountSummaryData(id, accountNo, externalId, productId, productName, status, currency, accountBalance);
return new SavingsAccountSummaryData(id, accountNo, externalId, productId, productName, status, currency, accountBalance,
accountTypeData);
}
}
@@ -322,7 +322,7 @@ public class GroupsApiResource {
@Path("{groupId}/accounts")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveLoans(@PathParam("groupId") final Long groupId, @Context final UriInfo uriInfo) {
public String retrieveAccounts(@PathParam("groupId") final Long groupId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission("GROUP");
@@ -1108,7 +1108,8 @@ public class Loan extends AbstractPersistable<Long> {
if (client != null && client.isActivatedAfter(submittedOn)) {
final String errorMessage = "The date on which a loan is submitted cannot be earlier than client's activation date.";
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.client.activation.date", errorMessage, submittedOn);
} else if (group != null && group.isActivatedAfter(submittedOn)) {
}
if (group != null && group.isActivatedAfter(submittedOn)) {
final String errorMessage = "The date on which a loan is submitted cannot be earlier than groups's activation date.";
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.group.activation.date", errorMessage, submittedOn);
}
@@ -58,6 +58,7 @@ import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.portfolio.accountdetails.domain.AccountType;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@@ -105,6 +106,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
@Column(name = "status_enum", nullable = false)
private Integer status;
@SuppressWarnings("unused")
@Column(name = "account_type_enum", nullable = false)
private Integer accountType;
@Temporal(TemporalType.DATE)
@Column(name = "submittedon_date", nullable = true)
private Date submittedOnDate;
@@ -254,8 +259,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
}
public static SavingsAccount createNewApplicationForSubmittal(final Client client, final Group group, final SavingsProduct product,
final Staff fieldOfficer, final String accountNo, final String externalId, final LocalDate submittedOnDate,
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final Staff fieldOfficer, final String accountNo, final String externalId, final AccountType accountType,
final LocalDate submittedOnDate, final BigDecimal interestRate,
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
@@ -263,15 +269,16 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final MonthDay annualFeeOnMonthDay) {
final SavingsAccountStatusType status = SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL;
return new SavingsAccount(client, group, product, fieldOfficer, accountNo, externalId, status, submittedOnDate, interestRate,
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,
annualFeeAmount, annualFeeOnMonthDay);
return new SavingsAccount(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate,
interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay);
}
private SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer,
final String accountNo, final String externalId, final SavingsAccountStatusType status, final LocalDate submittedOnDate,
final BigDecimal nominalAnnualInterestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final String accountNo, final String externalId, final SavingsAccountStatusType status, final AccountType accountType,
final LocalDate submittedOnDate, final BigDecimal nominalAnnualInterestRate,
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
@@ -290,6 +297,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.currency = product.currency();
this.externalId = externalId;
this.status = status.getValue();
this.accountType = accountType.getValue();
this.submittedOnDate = submittedOnDate.toDate();
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
this.interestCompoundingPeriodType = interestCompoundingPeriodType.getValue();
@@ -1612,14 +1620,19 @@ public class SavingsAccount extends AbstractPersistable<Long> {
updateToNextAnnualFeeDueDateFrom(getActivationLocalDate());
}
if (this.client.isActivatedAfter(activationDate)) {
if (this.client != null && this.client.isActivatedAfter(activationDate)) {
final DateTimeFormatter formatter = DateTimeFormat.forPattern(command.dateFormat()).withLocale(command.extractLocale());
final String dateAsString = formatter.print(client.getActivationLocalDate());
baseDataValidator.reset().parameter(SavingsApiConstants.activatedOnDateParamName).value(dateAsString)
.failWithCodeNoParameterAddedToErrorCode("cannot.be.before.client.activation.date");
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
if (this.group != null && this.group.isActivatedAfter(activationDate)) {
final DateTimeFormatter formatter = DateTimeFormat.forPattern(command.dateFormat()).withLocale(command.extractLocale());
final String dateAsString = formatter.print(client.getActivationLocalDate());
baseDataValidator.reset().parameter(SavingsApiConstants.activatedOnDateParamName).value(dateAsString)
.failWithCodeNoParameterAddedToErrorCode("cannot.be.before.group.activation.date");
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
@@ -34,6 +34,7 @@ import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.organisation.staff.domain.Staff;
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.group.domain.Group;
@@ -67,8 +68,7 @@ public class SavingsAccountAssembler {
public SavingsAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
final ClientRepositoryWrapper clientRepository, final GroupRepositoryWrapper groupRepository,
final StaffRepositoryWrapper staffRepository, final SavingsProductRepository savingProductRepository,
final SavingsAccountRepositoryWrapper savingsAccountRepository,
final FromJsonHelper fromApiJsonHelper) {
final SavingsAccountRepositoryWrapper savingsAccountRepository, final FromJsonHelper fromApiJsonHelper) {
this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
this.clientRepository = clientRepository;
this.groupRepository = groupRepository;
@@ -97,19 +97,22 @@ public class SavingsAccountAssembler {
Client client = null;
Group group = null;
Staff fieldOfficer = null;
AccountType accountType = AccountType.INVALID;
final Long clientId = fromApiJsonHelper.extractLongNamed(clientIdParamName, element);
if (clientId != null) {
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
accountType = AccountType.INDIVIDUAL;
}
final Long groupId = fromApiJsonHelper.extractLongNamed(groupIdParamName, element);
if (groupId != null) {
group = this.groupRepository.findOneWithNotFoundDetection(groupId);
accountType = AccountType.GROUP;
}
if(group != null && client != null){
if (group != null && client != null) {
if (!group.hasClientAsMember(client)) { throw new ClientNotInGroupException(clientId, groupId); }
accountType = AccountType.JLG;
}
final Long fieldOfficerId = fromApiJsonHelper.extractLongNamed(fieldOfficerIdParamName, element);
@@ -215,10 +218,10 @@ public class SavingsAccountAssembler {
monthDayOfAnnualFee = product.monthDayOfAnnualFee();
}
final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNo, externalId,
submittedOnDate, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, monthDayOfAnnualFee);
final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNo,
externalId, accountType, submittedOnDate, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, monthDayOfAnnualFee);
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant());