diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java index d2ade11c0..a63b50275 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java @@ -9,7 +9,6 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -18,7 +17,6 @@ import javax.ws.rs.core.UriInfo; import org.mifosng.platform.api.commands.FundCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.FundData; -import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService; import org.mifosng.platform.fund.service.FundReadPlatformService; import org.mifosng.platform.fund.service.FundWritePlatformService; @@ -31,7 +29,6 @@ import org.springframework.stereotype.Component; @Scope("singleton") public class FundsApiResource { - private String defaultFieldList = "openingDate"; private String allowedFieldList = "allowedParents"; private String filterName = "myFilter"; @@ -41,9 +38,6 @@ public class FundsApiResource { @Autowired private FundWritePlatformService writePlatformService; - @Autowired - private ApiDataConversionService apiDataConversionService; - @Autowired private ApiJSONFormattingService jsonFormattingService; @@ -63,11 +57,6 @@ public class FundsApiResource { @Produces({ MediaType.APPLICATION_JSON }) public Response createFund(final FundCommand command) { -// LocalDate openingLocalDate = apiDataConversionService.convertFrom( -// command.getOpeningDate(), "openingDate", -// command.getDateFormat()); -// command.setOpeningLocalDate(openingLocalDate); - Long fundId = this.writePlatformService.createFund(command); return Response.ok().entity(new EntityIdentifier(fundId)).build(); @@ -77,14 +66,9 @@ public class FundsApiResource { @Path("{fundId}") @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Produces({ MediaType.APPLICATION_JSON }) - public String retreiveOffice(@PathParam("fundId") final Long fundId, - @QueryParam("template") String template, @Context UriInfo uriInfo) { + public String retreiveOffice(@PathParam("fundId") final Long fundId, @Context UriInfo uriInfo) { FundData fund = this.readPlatformService.retrieveFund(fundId); -// if (template != null && template.equalsIgnoreCase("true")) { -// office.setAllowedParents(this.readPlatformService -// .retrieveAllowedParents(officeId)); -// } String selectedFields = ""; return this.jsonFormattingService.convertRequest(fund, filterName, @@ -95,13 +79,8 @@ public class FundsApiResource { @Path("{fundId}") @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Produces({ MediaType.APPLICATION_JSON }) - public Response updateOffice(@PathParam("fundId") final Long fundId, - final FundCommand command) { + public Response updateFund(@PathParam("fundId") final Long fundId, final FundCommand command) { -// LocalDate openingLocalDate = apiDataConversionService.convertFrom( -// command.getOpeningDate(), "openingDate", -// command.getDateFormat()); -// command.setOpeningLocalDate(openingLocalDate); command.setId(fundId); Long entityId = this.writePlatformService.updateFund(command); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java index 2f1925849..d49df3a3e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java @@ -2,8 +2,6 @@ package org.mifosng.platform.api.commands; import javax.xml.bind.annotation.XmlRootElement; -import org.joda.time.LocalDate; - /** * Command used for create and update fund operations. */ @@ -14,13 +12,6 @@ public class FundCommand { private String name; private String externalId; - private String dateFormat; - private String activatedOnDate; - private LocalDate activatedOnLocalDate; - - private String deactivatedOnDate; - private LocalDate deactivatedOnLocalDate; - protected FundCommand() { // } @@ -53,44 +44,4 @@ public class FundCommand { public void setExternalId(String externalId) { this.externalId = externalId; } - - public String getDateFormat() { - return dateFormat; - } - - public void setDateFormat(String dateFormat) { - this.dateFormat = dateFormat; - } - - public String getActivatedOnDate() { - return activatedOnDate; - } - - public void setActivatedOnDate(String activatedOnDate) { - this.activatedOnDate = activatedOnDate; - } - - public LocalDate getActivatedOnLocalDate() { - return activatedOnLocalDate; - } - - public void setActivatedOnLocalDate(LocalDate activatedOnLocalDate) { - this.activatedOnLocalDate = activatedOnLocalDate; - } - - public String getDeactivatedOnDate() { - return deactivatedOnDate; - } - - public void setDeactivatedOnDate(String deactivatedOnDate) { - this.deactivatedOnDate = deactivatedOnDate; - } - - public LocalDate getDeactivatedOnLocalDate() { - return deactivatedOnLocalDate; - } - - public void setDeactivatedOnLocalDate(LocalDate deactivatedOnLocalDate) { - this.deactivatedOnLocalDate = deactivatedOnLocalDate; - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java index 4de2a7833..156017516 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java @@ -12,6 +12,8 @@ public class LoanProductCommand { private String description; private String externalId; + private Long fundId; + private String locale; private String currencyCode; private String digitsAfterDecimal; @@ -223,4 +225,12 @@ public class LoanProductCommand { Integer interestCalculationPeriodType) { this.interestCalculationPeriodType = interestCalculationPeriodType; } + + public Long getFundId() { + return fundId; + } + + public void setFundId(Long fundId) { + this.fundId = fundId; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java index 4ce9100c3..558d64ee2 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java @@ -3,6 +3,7 @@ package org.mifosng.platform.api.data; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import org.codehaus.jackson.map.annotate.JsonFilter; @@ -15,6 +16,8 @@ public class LoanProductData implements Serializable { private String name; private String description; + private FundData fund; + private MoneyData principal; private MoneyData inArrearsTolerance; @@ -33,12 +36,14 @@ public class LoanProductData implements Serializable { private DateTime lastModifedOn; private List currencyOptions = new ArrayList(); + private Collection fundOptions = new ArrayList(); private List amortizationTypeOptions = new ArrayList(); private List interestTypeOptions = new ArrayList(); private List interestCalculationPeriodTypeOptions = new ArrayList(); private List repaymentFrequencyTypeOptions = new ArrayList(); private List interestRateFrequencyTypeOptions = new ArrayList(); + public LoanProductData() { // } @@ -52,7 +57,7 @@ public class LoanProductData implements Serializable { EnumOptionData interestRateFrequencyType, EnumOptionData amortizationType, EnumOptionData interestType, - EnumOptionData interestCalculationPeriodType) { + EnumOptionData interestCalculationPeriodType, FundData fund) { this.createdOn = createdOn; this.lastModifedOn = lastModifedOn; this.id = id; @@ -69,6 +74,7 @@ public class LoanProductData implements Serializable { this.amortizationType = amortizationType; this.interestType = interestType; this.interestCalculationPeriodType = interestCalculationPeriodType; + this.fund = fund; } public Long getId() { @@ -94,6 +100,14 @@ public class LoanProductData implements Serializable { public void setDescription(String description) { this.description = description; } + + public FundData getFund() { + return fund; + } + + public void setFund(FundData fund) { + this.fund = fund; + } public MoneyData getPrincipal() { return principal; @@ -226,6 +240,14 @@ public class LoanProductData implements Serializable { public void setCurrencyOptions(List currencyOptions) { this.currencyOptions = currencyOptions; } + + public Collection getFundOptions() { + return fundOptions; + } + + public void setFundOptions(Collection fundOptions) { + this.fundOptions = fundOptions; + } public List getAmortizationTypeOptions() { return amortizationTypeOptions; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java b/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java index 17097a18b..b4a8256dc 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java @@ -1,15 +1,11 @@ package org.mifosng.platform.fund.domain; -import java.math.BigDecimal; -import java.util.Date; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import javax.persistence.UniqueConstraint; import org.mifosng.platform.api.commands.FundCommand; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; @@ -17,7 +13,10 @@ import org.mifosng.platform.organisation.domain.Organisation; import org.mifosng.platform.user.domain.AppUser; @Entity -@Table(name = "org_fund") +@Table(name = "org_fund", uniqueConstraints={ + @UniqueConstraint(columnNames = {"org_id", "name"}, name="fund_name_org"), + @UniqueConstraint(columnNames = {"org_id", "external_id"}, name="fund_externalid_org") +}) public class Fund extends AbstractAuditableCustom { @ManyToOne @@ -30,17 +29,6 @@ public class Fund extends AbstractAuditableCustom { @Column(name = "external_id", length=100) private String externalId; - @Temporal(TemporalType.DATE) - @Column(name = "activatedon_date") - private Date activatedOnDate; - - @Temporal(TemporalType.DATE) - @Column(name = "deactivatedon_date") - private Date deactivatedOnDate; - - @Column(name = "initial_balance", scale = 6, precision = 19) - private BigDecimal initialBalance; - public static Fund createNew(final Organisation organisation, final String fundName) { return new Fund(organisation, fundName); } @@ -52,7 +40,6 @@ public class Fund extends AbstractAuditableCustom { private Fund(final Organisation organisation, final String fundName) { this.organisation = organisation; this.name = fundName; - this.initialBalance = BigDecimal.ZERO; } public void update(FundCommand command) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundCommandValidator.java index 7350f81b5..f068d7224 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundCommandValidator.java @@ -22,11 +22,9 @@ public class FundCommandValidator { DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("fund"); -// baseDataValidator.reset().parameter("name").value(command.getName()).notBlank(); -// baseDataValidator.reset().parameter("openingDate").value(command.getOpeningDate()).notBlank(); -// baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).notExceedingLengthOf(100); -// baseDataValidator.reset().parameter("parentId").value(command.getParentId()).notNull().greaterThanZero(); -// + baseDataValidator.reset().parameter("name").value(command.getName()).notBlank(); + baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).notExceedingLengthOf(100); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } @@ -36,15 +34,13 @@ public class FundCommandValidator { List dataValidationErrors = new ArrayList(); DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("fund"); -// -// baseDataValidator.reset().parameter("id").value(command.getId()).notNull(); -// baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank(); -// baseDataValidator.reset().parameter("openingDate").value(command.getOpeningDate()).ignoreIfNull().notBlank(); -// baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); -// baseDataValidator.reset().parameter("parentId").value(command.getParentId()).ignoreIfNull().notNull().greaterThanZero(); -// -// baseDataValidator.reset().anyOfNotNull(command.getName(), command.getOpeningDate(), command.getExternalId(), command.getParentId()); -// + + baseDataValidator.reset().parameter("id").value(command.getId()).notNull(); + baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank(); + baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); + + baseDataValidator.reset().anyOfNotNull(command.getName(), command.getExternalId()); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundReadPlatformServiceImpl.java index 513a19939..f6c7564fc 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundReadPlatformServiceImpl.java @@ -42,7 +42,6 @@ public class FundReadPlatformServiceImpl implements FundReadPlatformService { Long id = rs.getLong("id"); String name = rs.getString("name"); String externalId = rs.getString("externalId"); -// LocalDate openingDate = JdbcSupport.getLocalDate(rs, "openingDate"); return new FundData(id, name, externalId); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java index 4ec8f4311..28908cee8 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java @@ -83,13 +83,13 @@ public class FundWritePlatformServiceJpaRepositoryImpl implements FundWritePlatf private void handleFundDataIntegrityIssues(final FundCommand command, DataIntegrityViolationException dve) { Throwable realCause = dve.getMostSpecificCause(); - if (realCause.getMessage().contains("externalid_org")) { - throw new PlatformDataIntegrityException("error.msg.office.duplicate.externalId", "Office with externalId {0} already exists", "externalId", command.getExternalId()); - } else if (realCause.getMessage().contains("name_org")) { - throw new PlatformDataIntegrityException("error.msg.office.duplicate.name", "Office with name {0} already exists", "name", command.getName()); + if (realCause.getMessage().contains("fund_externalid_org")) { + throw new PlatformDataIntegrityException("error.msg.fund.duplicate.externalId", "Fund with externalId {0} already exists", "externalId", command.getExternalId()); + } else if (realCause.getMessage().contains("fund_name_org")) { + throw new PlatformDataIntegrityException("error.msg.fund.duplicate.name", "Fund with name {0} already exists", "name", command.getName()); } logger.error(dve.getMessage(), dve); - throw new PlatformDataIntegrityException("error.msg.office.unknown.data.integrity.issue", "Unknown data integrity issue with resource."); + throw new PlatformDataIntegrityException("error.msg.fund.unknown.data.integrity.issue", "Unknown data integrity issue with resource: " + realCause.getMessage()); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanProduct.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanProduct.java index 41035d5ef..dc627fd7f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanProduct.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanProduct.java @@ -13,6 +13,7 @@ import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.commands.LoanProductCommand; import org.mifosng.platform.currency.domain.MonetaryCurrency; import org.mifosng.platform.currency.domain.Money; +import org.mifosng.platform.fund.domain.Fund; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; import org.mifosng.platform.organisation.domain.Organisation; import org.mifosng.platform.user.domain.AppUser; @@ -29,32 +30,38 @@ import org.mifosng.platform.user.domain.AppUser; @Table(name = "portfolio_product_loan") public class LoanProduct extends AbstractAuditableCustom { - @ManyToOne - @JoinColumn(name = "org_id", nullable = false) - private final Organisation organisation; + @ManyToOne + @JoinColumn(name = "org_id", nullable = false) + private final Organisation organisation; - @Column(name = "name", nullable = false) - private String name; + @ManyToOne + @JoinColumn(name = "fund_id", nullable = true) + private Fund fund; - @Column(name = "description") - private String description; + @Column(name = "name", nullable = false) + private String name; - @Embedded - private final LoanProductRelatedDetail loanProductRelatedDetail; + @Column(name = "description") + private String description; + + @Embedded + private final LoanProductRelatedDetail loanProductRelatedDetail; public LoanProduct() { this.organisation = null; + this.fund = null; this.name = null; this.description = null; this.loanProductRelatedDetail = null; } - public LoanProduct(final Organisation organisation, final String name, final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal, + public LoanProduct(final Organisation organisation, Fund fund, final String name, final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal, final BigDecimal defaultNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType, final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod, final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery, final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments, final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance) { this.organisation = organisation; + this.fund = fund; this.name = name.trim(); if (StringUtils.isNotBlank(description)) { this.description = description.trim(); @@ -132,13 +139,17 @@ public class LoanProduct extends AbstractAuditableCustom { return this.loanProductRelatedDetail.getAmortizationMethod(); } - public void update(LoanProductCommand command) { + public void update(final LoanProductCommand command, final Fund fund) { if (command.getName() != null) { this.name = command.getName(); } if (command.getDescription() != null) { this.description = command.getDescription(); } + if (fund != null) { + this.fund = fund; + } + this.loanProductRelatedDetail.update(command); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java index 6c81d5fa0..735adc1fb 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java @@ -44,7 +44,7 @@ public class LoanProductCommandValidator { baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).ignoreIfNull().notNull().inMinMaxRange(0, 1); baseDataValidator.reset().parameter("interestCalculationPeriodType").value(command.getInterestCalculationPeriodType()).ignoreIfNull().notNull().inMinMaxRange(0, 1); - baseDataValidator.reset().anyOfNotNull(command.getName(), command.getDescription(), command.getExternalId(), command.getCurrencyCode(), command.getDigitsAfterDecimal(), + baseDataValidator.reset().anyOfNotNull(command.getFundId(), command.getName(), command.getDescription(), command.getExternalId(), command.getCurrencyCode(), command.getDigitsAfterDecimal(), command.getPrincipal(), command.getInArrearsTolerance(), command.getRepaymentFrequencyType(), command.getRepaymentEvery(), command.getNumberOfRepayments(), command.getInterestRatePerPeriod(), command.getInterestRateFrequencyType(), command.getAmortizationType(), command.getInterestType(), command.getInterestCalculationPeriodType()); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java index 60b22b7e1..311980ab7 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -11,11 +11,13 @@ import javax.sql.DataSource; import org.joda.time.DateTime; import org.mifosng.platform.api.data.CurrencyData; import org.mifosng.platform.api.data.EnumOptionData; +import org.mifosng.platform.api.data.FundData; import org.mifosng.platform.api.data.LoanProductData; import org.mifosng.platform.api.data.LoanProductLookup; import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.currency.service.CurrencyReadPlatformService; import org.mifosng.platform.exceptions.LoanProductNotFoundException; +import org.mifosng.platform.fund.service.FundReadPlatformService; import org.mifosng.platform.infrastructure.JdbcSupport; import org.mifosng.platform.loan.domain.AmortizationMethod; import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod; @@ -37,15 +39,18 @@ public class LoanProductReadPlatformServiceImpl implements private final CurrencyReadPlatformService currencyReadPlatformService; private final SimpleJdbcTemplate jdbcTemplate; private final LoanDropdownReadPlatformService dropdownReadPlatformService; + private final FundReadPlatformService fundReadPlatformService; @Autowired public LoanProductReadPlatformServiceImpl( final PlatformSecurityContext context, final CurrencyReadPlatformService currencyReadPlatformService, + final FundReadPlatformService fundReadPlatformService, final LoanDropdownReadPlatformService dropdownReadPlatformService, final DataSource dataSource) { this.context = context; this.currencyReadPlatformService = currencyReadPlatformService; + this.fundReadPlatformService = fundReadPlatformService; this.dropdownReadPlatformService = dropdownReadPlatformService; this.jdbcTemplate = new SimpleJdbcTemplate(dataSource); } @@ -56,8 +61,10 @@ public class LoanProductReadPlatformServiceImpl implements try { List allowedCurrencies = currencyReadPlatformService .retrieveAllPlatformCurrencies(); + + Collection allFunds = this.fundReadPlatformService.retrieveAllFunds(); - LoanProductMapper rm = new LoanProductMapper(allowedCurrencies); + LoanProductMapper rm = new LoanProductMapper(allowedCurrencies, allFunds); String sql = "select " + rm.loanProductSchema() + " where lp.id = ?"; @@ -76,11 +83,12 @@ public class LoanProductReadPlatformServiceImpl implements public Collection retrieveAllLoanProducts() { AppUser currentUser = this.context.authenticatedUser(); + // TODO - include currency read in the sql - List allowedCurrencies = currencyReadPlatformService - .retrieveAllPlatformCurrencies(); + List allowedCurrencies = currencyReadPlatformService.retrieveAllPlatformCurrencies(); + Collection allFunds = this.fundReadPlatformService.retrieveAllFunds(); - LoanProductMapper rm = new LoanProductMapper(allowedCurrencies); + LoanProductMapper rm = new LoanProductMapper(allowedCurrencies, allFunds); String sql = "select " + rm.loanProductSchema() + " where lp.org_id = ?"; @@ -132,17 +140,18 @@ public class LoanProductReadPlatformServiceImpl implements return productData; } - private static final class LoanProductMapper implements - RowMapper { + private static final class LoanProductMapper implements RowMapper { private final List allowedCurrencies; + private final Collection allFunds; - public LoanProductMapper(List allowedCurrencies) { + public LoanProductMapper(List allowedCurrencies, Collection allFunds) { this.allowedCurrencies = allowedCurrencies; + this.allFunds = allFunds; } public String loanProductSchema() { - return "lp.id as id, lp.name as name, lp.description as description, lp.flexible_repayment_schedule as isFlexible, lp.interest_rebate as isInterestRebateAllowed, " + return "lp.id as id, lp.fund_id as fundId, lp.name as name, lp.description as description, lp.flexible_repayment_schedule as isFlexible, lp.interest_rebate as isInterestRebateAllowed, " + "lp.principal_amount as principal, lp.currency_code as currencyCode, lp.currency_digits as currencyDigits, " + "lp.nominal_interest_rate_per_period as interestRatePerPeriod, lp.interest_period_frequency_enum as interestRatePerPeriodFreq, " + "lp.annual_nominal_interest_rate as annualInterestRate, lp.interest_method_enum as interestMethod, lp.interest_calculated_in_period_enum as interestCalculationInPeriodMethod," @@ -160,6 +169,9 @@ public class LoanProductReadPlatformServiceImpl implements String name = rs.getString("name"); String description = rs.getString("description"); + Long fundId = rs.getLong("fundId"); + FundData fund = findFundDataById(fundId, allFunds); + String currencyCode = rs.getString("currencyCode"); Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits"); @@ -216,11 +228,20 @@ public class LoanProductReadPlatformServiceImpl implements numberOfRepayments, repaymentEvery, interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, - interestCalculationPeriodType); + interestCalculationPeriodType, fund); } - private CurrencyData findCurrencyByCode(String currencyCode, - List allowedCurrencies) { + private FundData findFundDataById(Long fundId, Collection allFunds) { + FundData match = null; + for (FundData fundData : allFunds) { + if (fundData.getId().equals(fundId)) { + match = fundData; + } + } + return match; + } + + private CurrencyData findCurrencyByCode(String currencyCode, List allowedCurrencies) { CurrencyData match = null; for (CurrencyData currencyData : allowedCurrencies) { if (currencyData.getCode().equalsIgnoreCase(currencyCode)) { @@ -251,8 +272,7 @@ public class LoanProductReadPlatformServiceImpl implements } - private void populateProductDataWithDropdownOptions( - LoanProductData productData) { + private void populateProductDataWithDropdownOptions(LoanProductData productData) { List currencyOptions = currencyReadPlatformService .retrieveAllowedCurrencies(); @@ -266,6 +286,8 @@ public class LoanProductReadPlatformServiceImpl implements .retrieveRepaymentFrequencyTypeOptions(); List interestRateFrequencyTypeOptions = dropdownReadPlatformService .retrieveInterestRateFrequencyTypeOptions(); + + Collection fundOptions = this.fundReadPlatformService.retrieveAllFunds(); productData.setCurrencyOptions(currencyOptions); productData.setAmortizationTypeOptions(amortizationTypeOptions); @@ -276,6 +298,7 @@ public class LoanProductReadPlatformServiceImpl implements .setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions); productData .setInterestRateFrequencyTypeOptions(interestRateFrequencyTypeOptions); + productData.setFundOptions(fundOptions); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java index c1400554b..abbca000b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java @@ -1,13 +1,16 @@ package org.mifosng.platform.loanproduct.service; -import static org.mifosng.platform.Specifications.productThatMatches; +import static org.mifosng.platform.Specifications.*; import java.math.BigDecimal; import org.mifosng.platform.api.commands.LoanProductCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.currency.domain.MonetaryCurrency; +import org.mifosng.platform.exceptions.FundNotFoundException; import org.mifosng.platform.exceptions.LoanProductNotFoundException; +import org.mifosng.platform.fund.domain.Fund; +import org.mifosng.platform.fund.domain.FundRepository; import org.mifosng.platform.loan.domain.AmortizationMethod; import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod; import org.mifosng.platform.loan.domain.InterestMethod; @@ -15,6 +18,7 @@ import org.mifosng.platform.loan.domain.LoanProduct; import org.mifosng.platform.loan.domain.LoanProductRepository; import org.mifosng.platform.loan.domain.PeriodFrequencyType; import org.mifosng.platform.loanschedule.domain.AprCalculator; +import org.mifosng.platform.organisation.domain.Organisation; import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.user.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; @@ -27,12 +31,15 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro private final PlatformSecurityContext context; private final LoanProductRepository loanProductRepository; private final AprCalculator aprCalculator; + private final FundRepository fundRepository; @Autowired - public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanProductRepository loanProductRepository, final AprCalculator aprCalculator) { + public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanProductRepository loanProductRepository, + final AprCalculator aprCalculator, final FundRepository fundRepository) { this.context = context; this.loanProductRepository = loanProductRepository; this.aprCalculator = aprCalculator; + this.fundRepository = fundRepository; } @Transactional @@ -60,7 +67,10 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro BigDecimal annualInterestRate = this.aprCalculator.calculateFrom(interestFrequencyType, command.getInterestRatePerPeriodValue()); - LoanProduct loanproduct = new LoanProduct(currentUser.getOrganisation(), command.getName(), command.getDescription(), + // associating fund with loan product at creation is optional for now. + Fund fund = findFundByIdIfProvided(currentUser.getOrganisation(), command.getFundId()); + + LoanProduct loanproduct = new LoanProduct(currentUser.getOrganisation(), fund, command.getName(), command.getDescription(), currency, command.getPrincipalValue(), command.getInterestRatePerPeriodValue(), interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod, command.getRepaymentEveryValue(), repaymentFrequencyType, command.getNumberOfRepaymentsValue(), @@ -71,6 +81,17 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro return new EntityIdentifier(loanproduct.getId()); } + private Fund findFundByIdIfProvided(final Organisation organisation, final Long fundId) { + Fund fund = null; + if (fundId != null) { + fund = this.fundRepository.findOne(fundsThatMatch(organisation, fundId)); + if (fund == null) { + throw new FundNotFoundException(fundId); + } + } + return fund; + } + @Transactional @Override public EntityIdentifier updateLoanProduct(LoanProductCommand command) { @@ -85,7 +106,10 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro throw new LoanProductNotFoundException(command.getId()); } - product.update(command); + // associating fund with loan product at creation is optional for now. + Fund fund = findFundByIdIfProvided(currentUser.getOrganisation(), command.getFundId()); + + product.update(command, fund); this.loanProductRepository.save(product);