MIFOSX-90: detect in active charges on product during loan creation.

This commit is contained in:
Keith Woodlock
2012-10-23 11:52:45 +01:00
parent 585f591709
commit ccdda4287b
8 changed files with 132 additions and 96 deletions
@@ -0,0 +1,15 @@
package org.mifosng.platform.charge.service;
import java.util.List;
import org.mifosng.platform.api.data.EnumOptionData;
public interface ChargeDropdownReadPlatformService {
List<EnumOptionData> retrieveCalculationTypes();
List<EnumOptionData> retrieveApplicableToTypes();
List<EnumOptionData> retrieveCollectionTimeTypes();
}
@@ -0,0 +1,38 @@
package org.mifosng.platform.charge.service;
import static org.mifosng.platform.charge.service.ChargeEnumerations.chargeAppliesTo;
import static org.mifosng.platform.charge.service.ChargeEnumerations.chargeCalculationType;
import static org.mifosng.platform.charge.service.ChargeEnumerations.chargeTimeType;
import java.util.Arrays;
import java.util.List;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.charge.domain.ChargeAppliesTo;
import org.mifosng.platform.charge.domain.ChargeCalculationType;
import org.mifosng.platform.charge.domain.ChargeTimeType;
import org.springframework.stereotype.Service;
@Service
public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownReadPlatformService {
@Override
public List<EnumOptionData> retrieveCalculationTypes() {
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT)
// chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST),
// chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST)
);
}
@Override
public List<EnumOptionData> retrieveApplicableToTypes() {
return Arrays.asList(chargeAppliesTo(ChargeAppliesTo.LOAN));
}
@Override
public List<EnumOptionData> retrieveCollectionTimeTypes() {
return Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT));
}
}
@@ -1,12 +1,16 @@
package org.mifosng.platform.charge.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.mifosng.platform.api.data.ChargeData;
import org.mifosng.platform.api.data.CurrencyData;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.LoanChargeData;
import org.mifosng.platform.charge.domain.ChargeAppliesTo;
import org.mifosng.platform.charge.domain.ChargeCalculationType;
import org.mifosng.platform.charge.domain.ChargeTimeType;
import org.mifosng.platform.currency.service.CurrencyReadPlatformService;
import org.mifosng.platform.exceptions.ChargeNotFoundException;
import org.mifosng.platform.infrastructure.JdbcSupport;
@@ -18,55 +22,47 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static org.mifosng.platform.charge.service.ChargeEnumerations.chargeAppliesTo;
import static org.mifosng.platform.charge.service.ChargeEnumerations.chargeCalculationType;
import static org.mifosng.platform.charge.service.ChargeEnumerations.chargeTimeType;
@Service
public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final CurrencyReadPlatformService currencyReadPlatformService;
@Autowired
public ChargeReadPlatformServiceImpl(PlatformSecurityContext context,
final CurrencyReadPlatformService currencyReadPlatformService,
final TenantAwareRoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.currencyReadPlatformService = currencyReadPlatformService;
}
private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService;
@Autowired
public ChargeReadPlatformServiceImpl(
final PlatformSecurityContext context,
final CurrencyReadPlatformService currencyReadPlatformService,
final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService,
final TenantAwareRoutingDataSource dataSource) {
this.context = context;
this.chargeDropdownReadPlatformService = chargeDropdownReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.currencyReadPlatformService = currencyReadPlatformService;
}
@Override
public Collection<ChargeData> retrieveAllCharges() {
this.context.authenticatedUser();
ChargeMapper rm = new ChargeMapper();
final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 order by c.name ";
final String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] {});
}
@Override
public ChargeData retrieveCharge(Long chargeId) {
public ChargeData retrieveCharge(final Long chargeId) {
try {
this.context.authenticatedUser();
ChargeMapper rm = new ChargeMapper();
final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() + " where c.id = ? and c.is_deleted=0 ";
final String sql = "select " + rm.chargeSchema() + " where c.id = ? and c.is_deleted=0 ";
ChargeData chargeData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] {chargeId});
return chargeData;
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {chargeId});
} catch (EmptyResultDataAccessException e){
throw new ChargeNotFoundException(chargeId);
}
@@ -77,19 +73,11 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
this.context.authenticatedUser();
List<CurrencyData> currencyOptions = currencyReadPlatformService.retrieveAllowedCurrencies();
List<EnumOptionData> allowedChargeCalculationTypeOptions = Arrays.asList(
chargeCalculationType(ChargeCalculationType.FLAT),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST)
);
List<EnumOptionData> allowedChargeAppliesToOptions = Arrays.asList(chargeAppliesTo(ChargeAppliesTo.LOAN));
List<EnumOptionData> allowedChargeTimeOptions = Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT));
final List<CurrencyData> currencyOptions = currencyReadPlatformService.retrieveAllowedCurrencies();
final List<EnumOptionData> allowedChargeCalculationTypeOptions = this.chargeDropdownReadPlatformService.retrieveCalculationTypes();
final List<EnumOptionData> allowedChargeAppliesToOptions = this.chargeDropdownReadPlatformService.retrieveApplicableToTypes();
final List<EnumOptionData> allowedChargeTimeOptions = this.chargeDropdownReadPlatformService.retrieveCollectionTimeTypes();
return ChargeData.template(currencyOptions, allowedChargeCalculationTypeOptions,
allowedChargeAppliesToOptions, allowedChargeTimeOptions);
}
@@ -99,9 +87,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
this.context.authenticatedUser();
ChargeMapper rm = new ChargeMapper();
final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.loanProductChargeSchema() + " where c.is_deleted=0 and plc.product_loan_id=?";
final String sql = "select " + rm.loanProductChargeSchema() + " where c.is_deleted=0 and plc.product_loan_id=?";
return this.jdbcTemplate.query(sql, rm, new Object[] {loanProductId});
}
@@ -110,9 +98,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<LoanChargeData> retrieveLoanCharges(Long loanId) {
this.context.authenticatedUser();
LoanChargeMapper rm = new LoanChargeMapper();
final LoanChargeMapper rm = new LoanChargeMapper();
String sql = "select " + rm.loanChargeSchema() + " where c.is_deleted=0 and lc.loan_id=?";
final String sql = "select " + rm.loanChargeSchema() + " where c.is_deleted=0 and lc.loan_id=?";
return this.jdbcTemplate.query(sql, rm, new Object[] {loanId});
}
@@ -121,9 +109,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveLoanApplicableCharges() {
this.context.authenticatedUser();
ChargeMapper rm = new ChargeMapper();
final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? order by c.name ";
final String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] {ChargeAppliesTo.LOAN.getValue()});
}
@@ -132,17 +120,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public ChargeData retrieveLoanChargeTemplate() {
this.context.authenticatedUser();
List<EnumOptionData> allowedChargeCalculationTypeOptions = Arrays.asList(
chargeCalculationType(ChargeCalculationType.FLAT),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST),
chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST)
);
List<EnumOptionData> allowedChargeTimeOptions = Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT));
return ChargeData.template(null, allowedChargeCalculationTypeOptions,
null, allowedChargeTimeOptions);
final List<EnumOptionData> allowedChargeCalculationTypeOptions = this.chargeDropdownReadPlatformService.retrieveCalculationTypes();
final List<EnumOptionData> allowedChargeTimeOptions = this.chargeDropdownReadPlatformService.retrieveCollectionTimeTypes();
return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions);
}
private static final class ChargeMapper implements RowMapper<ChargeData> {
@@ -160,33 +141,30 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
return chargeSchema() + " join m_product_loan_charge plc on plc.charge_id = c.id";
}
@Override
public ChargeData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
Long id = rs.getLong("id");
String name = rs.getString("name");
BigDecimal amount = rs.getBigDecimal("amount");
public ChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final BigDecimal amount = rs.getBigDecimal("amount");
String currencyCode = rs.getString("currencyCode");
String currencyName = rs.getString("currencyName");
String currencyNameCode = rs.getString("currencyNameCode");
String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
Integer currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces");
final String currencyCode = rs.getString("currencyCode");
final String currencyName = rs.getString("currencyName");
final String currencyNameCode = rs.getString("currencyNameCode");
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
final Integer currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces");
CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDecimalPlaces,
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDecimalPlaces,
currencyDisplaySymbol, currencyNameCode);
int chargeAppliesTo = rs.getInt("chargeAppliesTo");
EnumOptionData chargeAppliesToType = ChargeEnumerations.chargeAppliesTo(chargeAppliesTo);
final int chargeAppliesTo = rs.getInt("chargeAppliesTo");
final EnumOptionData chargeAppliesToType = ChargeEnumerations.chargeAppliesTo(chargeAppliesTo);
int chargeTime = rs.getInt("chargeTime");
EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime);
final int chargeTime = rs.getInt("chargeTime");
final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime);
int chargeCalculation = rs.getInt("chargeCalculation");
EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation);
boolean active = rs.getBoolean("active");
final int chargeCalculation = rs.getInt("chargeCalculation");
final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation);
final boolean active = rs.getBoolean("active");
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesToType, chargeCalculationType, active);
}
@@ -241,4 +219,4 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountOutstanding, chargeTimeType, chargeCalculationType, percentageOf, amountPercentageAppliedTo);
}
}
}
}
@@ -1,12 +1,11 @@
package org.mifosng.platform.exceptions;
/**
* {@link AbstractPlatformDomainRuleException} thrown when charge is not active
* {@link AbstractPlatformDomainRuleException} thrown when charge is not active.
*/
public class ChargeIsNotActiveException extends AbstractPlatformDomainRuleException{
public class ChargeIsNotActiveException extends AbstractPlatformDomainRuleException {
public ChargeIsNotActiveException(final Long id) {
super("error.msg.charge.is.not.active", "Charge with identifier " + id + " is not active", id);
}
}
public ChargeIsNotActiveException(final Long id, final String name) {
super("error.msg.charge.is.not.active", "Charge '" + name + "' with identifier " + id + " is not active", name, id);
}
}
@@ -97,18 +97,18 @@ public class LoanAssembler {
}
}
MonetaryCurrency currency = loanProduct.getCurrency();
final MonetaryCurrency currency = loanProduct.getCurrency();
final Integer loanTermFrequency = command.getLoanTermFrequency();
final PeriodFrequencyType loanTermFrequencyType = PeriodFrequencyType.fromInt(command.getLoanTermFrequencyType());
LoanProductRelatedDetail loanRepaymentScheduleDetail = assembleLoanProductRelatedDetailFrom(command, currency);
final LoanProductRelatedDetail loanRepaymentScheduleDetail = assembleLoanProductRelatedDetailFrom(command, currency);
// associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(command.getFundId());
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
final Fund fund = findFundByIdIfProvided(command.getFundId());
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
//optionally associate a loan officer to the loan
Staff loanOfficer= findLoanOfficerByIdIfProvided(command.getLoanOfficerId());
final Staff loanOfficer= findLoanOfficerByIdIfProvided(command.getLoanOfficerId());
// optionally, see if charges are associated with loan on creation (through loan product or by being directly added)
final Set<LoanCharge> loanCharges = this.loanChargeAssembler.assembleFrom(command.getCharges(), loanProduct.getCharges(), command.getPrincipal());
@@ -7,6 +7,7 @@ import java.util.Set;
import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.charge.domain.Charge;
import org.mifosng.platform.charge.domain.ChargeRepository;
import org.mifosng.platform.exceptions.ChargeIsNotActiveException;
import org.mifosng.platform.exceptions.ChargeNotFoundException;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanChargeRepository;
@@ -37,6 +38,10 @@ public class LoanChargeAssembler {
if (chargeDefinition == null || chargeDefinition.isDeleted()) {
throw new ChargeNotFoundException(chargeDefinitionId);
}
if (!chargeDefinition.isActive()) {
throw new ChargeIsNotActiveException(chargeDefinitionId, chargeDefinition.getName());
}
final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, loanChargeCommand, loanPrincipal);
loanCharges.add(loanCharge);
} else {
@@ -643,11 +643,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
throw new ChargeNotFoundException(command.getChargeId());
}
LoanCharge loanCharge = LoanCharge.createNew(loan, chargeDefinition, command);
if (!chargeDefinition.isActive()) {
throw new ChargeIsNotActiveException(chargeDefinition.getId());
throw new ChargeIsNotActiveException(chargeDefinition.getId(), chargeDefinition.getName());
}
final LoanCharge loanCharge = LoanCharge.createNew(loan, chargeDefinition, command);
if (!loan.hasCurrencyCodeOf(chargeDefinition.getCurrencyCode())){
String errorMessage = "Charge and Loan must have the same currency.";
@@ -656,6 +656,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.loanChargeRepository.saveAndFlush(loanCharge);
// FIXME - KW -
loan.getCharges().add(loanCharge);
loan.updateTotalChargesDueAtDisbursement();
@@ -171,7 +171,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
throw new ChargeNotFoundException(id);
}
if (!charge.isActive()){
throw new ChargeIsNotActiveException(id);
throw new ChargeIsNotActiveException(id, charge.getName());
}
if (!loanProductCurrencyCode.equals(charge.getCurrencyCode())){
String errorMessage = "Charge and Loan Product must have the same currency.";