Merge pull request #773 from pramodn02/savings
MIFOSX-931 - added current account
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
ALTER TABLE `m_savings_product`
|
||||
ADD COLUMN `allow_overdraft` TINYINT(1) NOT NULL DEFAULT '0' AFTER `withdrawal_fee_for_transfer`,
|
||||
ADD COLUMN `overdraft_limit` DECIMAL(19,6) NULL DEFAULT NULL AFTER `allow_overdraft`;
|
||||
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `allow_overdraft` TINYINT(1) NOT NULL DEFAULT '0' AFTER `withdrawal_fee_for_transfer`,
|
||||
ADD COLUMN `overdraft_limit` DECIMAL(19,6) NULL DEFAULT NULL AFTER `allow_overdraft`;
|
||||
|
||||
ALTER TABLE `m_savings_account_transaction`
|
||||
ADD COLUMN `overdraft_amount_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `amount`;
|
||||
|
||||
ALTER TABLE `m_client`
|
||||
ADD COLUMN `default_savings_product` BIGINT(20) NULL DEFAULT NULL AFTER `closedon_userid`,
|
||||
ADD CONSTRAINT `FK_m_client_m_savings_product` FOREIGN KEY (`default_savings_product`) REFERENCES `m_savings_product` (`id`);
|
||||
+6
-3
@@ -133,7 +133,8 @@ public class AccountingConstants {
|
||||
/*** Accounting placeholders for cash based accounting for savings products ***/
|
||||
public static enum CASH_ACCOUNTS_FOR_SAVINGS {
|
||||
SAVINGS_REFERENCE(1), SAVINGS_CONTROL(2), INTEREST_ON_SAVINGS(3), INCOME_FROM_FEES(4), INCOME_FROM_PENALTIES(5), TRANSFERS_SUSPENSE(
|
||||
10);
|
||||
10),OVERDRAFT_PORTFOLIO_CONTROL(11),INCOME_FROM_INTEREST(12),
|
||||
LOSSES_WRITTEN_OFF(13);
|
||||
|
||||
private final Integer value;
|
||||
|
||||
@@ -173,7 +174,8 @@ public class AccountingConstants {
|
||||
"interestOnSavingsAccountId"), PAYMENT_CHANNEL_FUND_SOURCE_MAPPING("paymentChannelToFundSourceMappings"), PAYMENT_TYPE(
|
||||
"paymentTypeId"), FUND_SOURCE("fundSourceAccountId"), TRANSFERS_SUSPENSE("transfersInSuspenseAccountId"), FEE_INCOME_ACCOUNT_MAPPING(
|
||||
"feeToIncomeAccountMappings"), PENALTY_INCOME_ACCOUNT_MAPPING("penaltyToIncomeAccountMappings"), CHARGE_ID("chargeId"), INCOME_ACCOUNT_ID(
|
||||
"incomeAccountId");
|
||||
"incomeAccountId"),OVERDRAFT_PORTFOLIO_CONTROL("overdraftPortfolioControlId"),INCOME_FROM_INTEREST("incomeFromInterestId"),
|
||||
LOSSES_WRITTEN_OFF("writeOffAccountId");
|
||||
|
||||
private final String value;
|
||||
|
||||
@@ -196,7 +198,8 @@ public class AccountingConstants {
|
||||
"incomeFromFeeAccount"), INCOME_FROM_PENALTIES("incomeFromPenaltyAccount"), INTEREST_ON_SAVINGS(
|
||||
"interestOnSavingsAccount"), PAYMENT_TYPE("paymentType"), FUND_SOURCE("fundSourceAccount"),
|
||||
TRANSFERS_SUSPENSE("transfersInSuspenseAccount"), PENALTY_INCOME_ACCOUNT_MAPPING("penaltyToIncomeAccountMappings"), CHARGE_ID("charge"), INCOME_ACCOUNT_ID(
|
||||
"incomeAccount");
|
||||
"incomeAccount"),OVERDRAFT_PORTFOLIO_CONTROL("overdraftPortfolioControl"),INCOME_FROM_INTEREST("incomeFromInterest"),
|
||||
LOSSES_WRITTEN_OFF("writeOffAccount");
|
||||
|
||||
private final String value;
|
||||
|
||||
|
||||
+12
-1
@@ -20,6 +20,7 @@ public class SavingsTransactionDTO {
|
||||
private final SavingsAccountTransactionEnumData transactionType;
|
||||
|
||||
private final BigDecimal amount;
|
||||
private final BigDecimal overdraftAmount;
|
||||
|
||||
/*** Boolean values determines if the transaction is reversed ***/
|
||||
private final boolean reversed;
|
||||
@@ -30,7 +31,7 @@ public class SavingsTransactionDTO {
|
||||
|
||||
public SavingsTransactionDTO(final Long officeId, final Long paymentTypeId, final String transactionId, final Date transactionDate,
|
||||
final SavingsAccountTransactionEnumData transactionType, final BigDecimal amount, final boolean reversed,
|
||||
final List<ChargePaymentDTO> feePayments, final List<ChargePaymentDTO> penaltyPayments) {
|
||||
final List<ChargePaymentDTO> feePayments, final List<ChargePaymentDTO> penaltyPayments,final BigDecimal overdraftAmount) {
|
||||
this.paymentTypeId = paymentTypeId;
|
||||
this.transactionId = transactionId;
|
||||
this.transactionDate = transactionDate;
|
||||
@@ -40,6 +41,7 @@ public class SavingsTransactionDTO {
|
||||
this.feePayments = feePayments;
|
||||
this.penaltyPayments = penaltyPayments;
|
||||
this.officeId = officeId;
|
||||
this.overdraftAmount = overdraftAmount;
|
||||
}
|
||||
|
||||
public Long getOfficeId() {
|
||||
@@ -78,4 +80,13 @@ public class SavingsTransactionDTO {
|
||||
return this.feePayments;
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal getOverdraftAmount() {
|
||||
return this.overdraftAmount;
|
||||
}
|
||||
|
||||
public boolean isOverdraftTransaction(){
|
||||
return this.overdraftAmount!=null && this.overdraftAmount.doubleValue() > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -150,6 +150,7 @@ public class AccountingProcessorHelper {
|
||||
final BigDecimal amount = (BigDecimal) map.get("amount");
|
||||
final boolean reversed = (Boolean) map.get("reversed");
|
||||
final Long paymentTypeId = (Long) map.get("paymentTypeId");
|
||||
final BigDecimal overdraftAmount = (BigDecimal) map.get("overdraftAmount");
|
||||
|
||||
final List<ChargePaymentDTO> feePayments = new ArrayList<ChargePaymentDTO>();
|
||||
final List<ChargePaymentDTO> penaltyPayments = new ArrayList<ChargePaymentDTO>();
|
||||
@@ -172,7 +173,7 @@ public class AccountingProcessorHelper {
|
||||
}
|
||||
|
||||
final SavingsTransactionDTO transaction = new SavingsTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
|
||||
transactionDate, transactionType, amount, reversed, feePayments, penaltyPayments);
|
||||
transactionDate, transactionType, amount, reversed, feePayments, penaltyPayments,overdraftAmount);
|
||||
|
||||
newSavingsTransactions.add(transaction);
|
||||
|
||||
|
||||
+40
-2
@@ -41,13 +41,35 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
final Long paymentTypeId = savingsTransactionDTO.getPaymentTypeId();
|
||||
final boolean isReversal = savingsTransactionDTO.isReversed();
|
||||
final BigDecimal amount = savingsTransactionDTO.getAmount();
|
||||
final BigDecimal overdraftAmount = savingsTransactionDTO.getOverdraftAmount();
|
||||
final List<ChargePaymentDTO> feePayments = savingsTransactionDTO.getFeePayments();
|
||||
final List<ChargePaymentDTO> penaltyPayments = savingsTransactionDTO.getPenaltyPayments();
|
||||
|
||||
this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
|
||||
|
||||
if (savingsTransactionDTO.getTransactionType().isWithdrawal() && savingsTransactionDTO.isOverdraftTransaction()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal);
|
||||
if(amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1){
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
|
||||
}
|
||||
}
|
||||
else if (savingsTransactionDTO.getTransactionType().isDeposit() && savingsTransactionDTO.isOverdraftTransaction()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
if(amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1){
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle Deposits and reversals of deposits **/
|
||||
if (savingsTransactionDTO.getTransactionType().isDeposit()) {
|
||||
else if (savingsTransactionDTO.getTransactionType().isDeposit()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
@@ -98,7 +120,23 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
}
|
||||
|
||||
|
||||
/** overdraft **/
|
||||
else if (savingsTransactionDTO.getTransactionType().isOverdraftInterest()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
}
|
||||
else if (savingsTransactionDTO.getTransactionType().isWrittenoff()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.LOSSES_WRITTEN_OFF, CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
}
|
||||
else if (savingsTransactionDTO.getTransactionType().isOverdraftFee()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal, feePayments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -186,6 +186,21 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
||||
.value(incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long overdraftAccount = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue())
|
||||
.value(overdraftAccount).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromInterest = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue())
|
||||
.value(incomeFromInterest).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long writtenOff = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue())
|
||||
.value(writtenOff).notNull().integerGreaterThanZero();
|
||||
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
+6
@@ -204,6 +204,12 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.TRANSFERS_SUSPENSE.getValue(), gLAccountData);
|
||||
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS)) {
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.INTEREST_ON_SAVINGS.getValue(), gLAccountData);
|
||||
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL)) {
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), gLAccountData);
|
||||
}else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.LOSSES_WRITTEN_OFF)) {
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.LOSSES_WRITTEN_OFF.getValue(), gLAccountData);
|
||||
}else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST)) {
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS.INCOME_FROM_INTEREST.getValue(), gLAccountData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -158,6 +158,9 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToAssetAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue());
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToAssetAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue());
|
||||
|
||||
// income
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
@@ -167,11 +170,20 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES.getValue());
|
||||
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST.getValue());
|
||||
|
||||
|
||||
// expenses
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToExpenseAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue());
|
||||
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToExpenseAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.LOSSES_WRITTEN_OFF.getValue());
|
||||
|
||||
// liability
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||
|
||||
+20
-1
@@ -124,7 +124,12 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
element);
|
||||
final Long transfersInSuspenseAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), element);
|
||||
|
||||
final Long overdraftControlId = this.fromApiJsonHelper.extractLongNamed(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||
element);
|
||||
final Long incomeFromInterest = this.fromApiJsonHelper.extractLongNamed(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(),
|
||||
element);
|
||||
final Long writeOffId = this.fromApiJsonHelper.extractLongNamed(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
element);
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
@@ -135,6 +140,9 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), incomeFromFeesId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), incomeFromPenaltiesId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), transfersInSuspenseAccountId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), overdraftControlId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), incomeFromInterest);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), writeOffId);
|
||||
break;
|
||||
case ACCRUAL_BASED:
|
||||
break;
|
||||
@@ -161,6 +169,10 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
mergeSavingsToAssetAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(),
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.toString(), changes);
|
||||
|
||||
mergeSavingsToAssetAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.toString(), changes);
|
||||
|
||||
// income
|
||||
mergeSavingsToIncomeAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
@@ -171,10 +183,17 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES.toString(), changes);
|
||||
|
||||
mergeSavingsToIncomeAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(),
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST.toString(), changes);
|
||||
|
||||
// expenses
|
||||
mergeSavingsToExpenseAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(),
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.toString(), changes);
|
||||
mergeSavingsToExpenseAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.LOSSES_WRITTEN_OFF.toString(), changes);
|
||||
|
||||
// liability
|
||||
mergeSavingsToLiabilityAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(),
|
||||
|
||||
+13
-3
@@ -18,7 +18,8 @@ public enum ChargeTimeType {
|
||||
ANNUAL_FEE(6, "chargeTimeType.annualFee"), // only for savings
|
||||
MONTHLY_FEE(7, "chargeTimeType.monthlyFee"), // only for savings
|
||||
INSTALMENT_FEE(8, "chargeTimeType.instalmentFee"),// only for loan charges
|
||||
OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"); // only for loan charges
|
||||
OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"), // only for loan charges
|
||||
OVERDRAFT_FEE(10,"chargeTimeType.overdraftFee");// only for savings
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -44,7 +45,7 @@ public enum ChargeTimeType {
|
||||
public static Object[] validSavingsValues() {
|
||||
return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue(), ChargeTimeType.SAVINGS_ACTIVATION.getValue(),
|
||||
ChargeTimeType.SAVINGS_CLOSURE.getValue(), ChargeTimeType.WITHDRAWAL_FEE.getValue(), ChargeTimeType.ANNUAL_FEE.getValue(),
|
||||
ChargeTimeType.MONTHLY_FEE.getValue() };
|
||||
ChargeTimeType.MONTHLY_FEE.getValue(),ChargeTimeType.OVERDRAFT_FEE.getValue() };
|
||||
}
|
||||
|
||||
public static ChargeTimeType fromInt(final Integer chargeTime) {
|
||||
@@ -78,6 +79,9 @@ public enum ChargeTimeType {
|
||||
case 9:
|
||||
chargeTimeType = OVERDUE_INSTALLMENT;
|
||||
break;
|
||||
case 10:
|
||||
chargeTimeType = OVERDRAFT_FEE;
|
||||
break;
|
||||
default:
|
||||
chargeTimeType = INVALID;
|
||||
break;
|
||||
@@ -128,6 +132,12 @@ public enum ChargeTimeType {
|
||||
|
||||
public boolean isAllowedSavingsChargeTime() {
|
||||
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee()
|
||||
|| isMonthlyFee();
|
||||
|| isMonthlyFee() || isOverdraftFee();
|
||||
}
|
||||
|
||||
public boolean isOverdraftFee() {
|
||||
return this.value.equals(ChargeTimeType.OVERDRAFT_FEE.getValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+2
-1
@@ -81,6 +81,7 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE), chargeTimeType(ChargeTimeType.SAVINGS_ACTIVATION),
|
||||
//chargeTimeType(ChargeTimeType.SAVINGS_CLOSURE),
|
||||
chargeTimeType(ChargeTimeType.WITHDRAWAL_FEE),
|
||||
chargeTimeType(ChargeTimeType.ANNUAL_FEE), chargeTimeType(ChargeTimeType.MONTHLY_FEE));
|
||||
chargeTimeType(ChargeTimeType.ANNUAL_FEE), chargeTimeType(ChargeTimeType.MONTHLY_FEE),
|
||||
chargeTimeType(ChargeTimeType.OVERDRAFT_FEE));
|
||||
}
|
||||
}
|
||||
+3
@@ -49,6 +49,9 @@ public class ChargeEnumerations {
|
||||
case OVERDUE_INSTALLMENT:
|
||||
optionData = new EnumOptionData(ChargeTimeType.OVERDUE_INSTALLMENT.getValue().longValue(),ChargeTimeType.OVERDUE_INSTALLMENT.getCode(),"overdue fees") ;
|
||||
break;
|
||||
case OVERDRAFT_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.OVERDRAFT_FEE.getValue().longValue(), ChargeTimeType.OVERDRAFT_FEE.getCode(), "Overdraft Fee");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
|
||||
+3
-2
@@ -38,6 +38,7 @@ public class ClientApiConstants {
|
||||
public static final String closureDateParamName = "closureDate";
|
||||
public static final String closureReasonIdParamName = "closureReasonId";
|
||||
public static final String submittedOnDateParamName="submittedOnDate";
|
||||
public static final String savingsProductIdParamName="savingsProductId";
|
||||
// response parameters
|
||||
public static final String statusParamName = "status";
|
||||
public static final String hierarchyParamName = "hierarchy";
|
||||
@@ -62,11 +63,11 @@ public class ClientApiConstants {
|
||||
public static final Set<String> CLIENT_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName, mobileNoParamName, firstnameParamName,
|
||||
middlenameParamName, lastnameParamName, fullnameParamName, officeIdParamName, activeParamName, activationDateParamName,
|
||||
staffIdParamName,submittedOnDateParamName));
|
||||
staffIdParamName,submittedOnDateParamName,savingsProductIdParamName));
|
||||
|
||||
public static final Set<String> CLIENT_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, accountNoParamName, externalIdParamName, mobileNoParamName, firstnameParamName, middlenameParamName,
|
||||
lastnameParamName, fullnameParamName, activeParamName, activationDateParamName, staffIdParamName));
|
||||
lastnameParamName, fullnameParamName, activeParamName, activationDateParamName, staffIdParamName,savingsProductIdParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
|
||||
+24
-10
@@ -17,6 +17,7 @@ import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing client data.
|
||||
@@ -49,6 +50,9 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
private final Long staffId;
|
||||
private final String staffName;
|
||||
private final ClientTimelineData timeline;
|
||||
|
||||
private final Long savingsProductId;
|
||||
private final String savingsProductName;
|
||||
|
||||
// associations
|
||||
private final Collection<GroupGeneralData> groups;
|
||||
@@ -58,11 +62,13 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
private final Collection<StaffData> staffOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<CodeValueData> closureReasons;
|
||||
private final Collection<SavingsProductData> savingProductOptions;
|
||||
|
||||
public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection<OfficeData> officeOptions,
|
||||
final Collection<StaffData> staffOptions, final Collection<CodeValueData> closureReasons) {
|
||||
final Collection<StaffData> staffOptions, final Collection<CodeValueData> closureReasons,
|
||||
final Collection<SavingsProductData> savingProductOptions) {
|
||||
return new ClientData(null, null, officeId, null, null, null, null, null, null, null, null, null, null, null, joinedDate, null,
|
||||
null, null, officeOptions, null, staffOptions, closureReasons,null);
|
||||
null, null, officeOptions, null, staffOptions, closureReasons,null, savingProductOptions,null,null);
|
||||
|
||||
}
|
||||
|
||||
@@ -72,7 +78,8 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
|
||||
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
|
||||
clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName, templateData.officeOptions,
|
||||
clientData.groups, templateData.staffOptions, null,null);
|
||||
clientData.groups, templateData.staffOptions, null,null, templateData.savingProductOptions,
|
||||
clientData.savingsProductId, clientData.savingsProductName);
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +88,8 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename,
|
||||
clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo,
|
||||
clientData.activationDate, clientData.imageId, clientData.staffId, clientData.staffName, clientData.officeOptions,
|
||||
parentGroups, clientData.staffOptions, null,clientData.timeline);
|
||||
parentGroups, clientData.staffOptions, null,clientData.timeline, clientData.savingProductOptions,
|
||||
clientData.savingsProductId, clientData.savingsProductName);
|
||||
|
||||
}
|
||||
|
||||
@@ -90,31 +98,34 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
final String officeName) {
|
||||
|
||||
return new ClientData(accountNo, status, officeId, officeName, null, null, id, firstname, middlename, lastname, fullname,
|
||||
displayName, null, null, null, null, null, null, null, null, null, null,null);
|
||||
displayName, null, null, null, null, null, null, null, null, null, null,null, null,null,null);
|
||||
|
||||
}
|
||||
|
||||
public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) {
|
||||
return new ClientData(null, null, officeId, officeName, null, null, id, null, null, null, null, displayName, null, null, null,
|
||||
null, null, null, null, null, null, null,null);
|
||||
null, null, null, null, null, null, null,null, null,null,null);
|
||||
|
||||
}
|
||||
|
||||
public static ClientData instance(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName,
|
||||
final Long transferToOfficeId, final String transferToOfficeName, final Long id, final String firstname,
|
||||
final String middlename, final String lastname, final String fullname, final String displayName, final String externalId,
|
||||
final String mobileNo, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,final ClientTimelineData timeline) {
|
||||
final String mobileNo, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,
|
||||
final ClientTimelineData timeline,final Long savingsProductId,final String savingsProductName) {
|
||||
return new ClientData(accountNo, status, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename,
|
||||
lastname, fullname, displayName, externalId, mobileNo, activationDate, imageId, staffId, staffName, null, null, null, null,timeline);
|
||||
lastname, fullname, displayName, externalId, mobileNo, activationDate, imageId, staffId, staffName, null, null, null, null,
|
||||
timeline, null,savingsProductId,savingsProductName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private ClientData(final String accountNo, final EnumOptionData status, final Long officeId, final String officeName,
|
||||
final Long transferToOfficeId, final String transferToOfficeName, final Long id, final String firstname,
|
||||
final String middlename, final String lastname, final String fullname, final String displayName, final String externalId,
|
||||
final String mobileNo, final LocalDate activationDate, final Long imageId, final Long staffId, final String staffName,
|
||||
final Collection<OfficeData> allowedOffices, final Collection<GroupGeneralData> groups,
|
||||
final Collection<StaffData> staffOptions, final Collection<CodeValueData> closureReasons,final ClientTimelineData timeline) {
|
||||
final Collection<StaffData> staffOptions, final Collection<CodeValueData> closureReasons,final ClientTimelineData timeline,
|
||||
final Collection<SavingsProductData> savingProductOptions,final Long savingsProductId, final String savingsProductName) {
|
||||
this.accountNo = accountNo;
|
||||
this.status = status;
|
||||
if (status != null) {
|
||||
@@ -153,6 +164,9 @@ final public class ClientData implements Comparable<ClientData> {
|
||||
this.closureReasons = closureReasons;
|
||||
|
||||
this.timeline = timeline;
|
||||
this.savingProductOptions = savingProductOptions;
|
||||
this.savingsProductId = savingsProductId;
|
||||
this.savingsProductName = savingsProductName;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
|
||||
+10
@@ -68,6 +68,11 @@ public final class ClientDataValidator {
|
||||
final String accountNo = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.savingsProductIdParamName, element)) {
|
||||
final Long savingsProductId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.savingsProductIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.savingsProductIdParamName).value(savingsProductId).ignoreIfNull().longGreaterThanZero();
|
||||
}
|
||||
|
||||
if (isFullnameProvided(element) || isIndividualNameProvided(element)) {
|
||||
|
||||
@@ -305,6 +310,11 @@ public final class ClientDataValidator {
|
||||
final Long staffId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.staffIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.staffIdParamName).value(staffId).ignoreIfNull().longGreaterThanZero();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ClientApiConstants.savingsProductIdParamName, element)) {
|
||||
final Long savingsProductId = this.fromApiJsonHelper.extractLongNamed(ClientApiConstants.savingsProductIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ClientApiConstants.savingsProductIdParamName).value(savingsProductId).ignoreIfNull().longGreaterThanZero();
|
||||
}
|
||||
|
||||
if (!atLeastOneParameterPassedForUpdate) {
|
||||
final Object forceError = null;
|
||||
|
||||
+38
-3
@@ -45,6 +45,7 @@ import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||
import org.mifosplatform.portfolio.client.api.ClientApiConstants;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsProduct;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@@ -138,9 +139,13 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "activatedon_userid", nullable = true)
|
||||
private AppUser activatedBy;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "default_savings_product", nullable = true)
|
||||
private SavingsProduct savingsProduct;
|
||||
|
||||
public static Client createNew(final AppUser currentUser, final Office clientOffice, final Group clientParentGroup, final Staff staff,
|
||||
final JsonCommand command) {
|
||||
final SavingsProduct savingsProduct, final JsonCommand command) {
|
||||
|
||||
final String accountNo = command.stringValueOfParameterNamed(ClientApiConstants.accountNoParamName);
|
||||
final String externalId = command.stringValueOfParameterNamed(ClientApiConstants.externalIdParamName);
|
||||
@@ -174,7 +179,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
return new Client(currentUser, status, clientOffice, clientParentGroup, accountNo, firstname, middlename, lastname, fullname,
|
||||
activationDate, officeJoiningDate, externalId, mobileNo, staff, submittedOnDate);
|
||||
activationDate, officeJoiningDate, externalId, mobileNo, staff, submittedOnDate,savingsProduct);
|
||||
}
|
||||
|
||||
protected Client() {
|
||||
@@ -184,7 +189,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
private Client(final AppUser currentUser, final ClientStatus status, final Office office, final Group clientParentGroup,
|
||||
final String accountNo, final String firstname, final String middlename, final String lastname, final String fullname,
|
||||
final LocalDate activationDate, final LocalDate officeJoiningDate, final String externalId, final String mobileNo,
|
||||
final Staff staff, final LocalDate submittedOnDate) {
|
||||
final Staff staff, final LocalDate submittedOnDate, final SavingsProduct savingsProduct) {
|
||||
|
||||
if (StringUtils.isBlank(accountNo)) {
|
||||
this.accountNumber = new RandomPasswordGenerator(19).generate();
|
||||
@@ -247,6 +252,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
this.staff = staff;
|
||||
this.savingsProduct = savingsProduct;
|
||||
|
||||
deriveDisplayName();
|
||||
validate();
|
||||
@@ -394,6 +400,11 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
actualChanges.put(ClientApiConstants.staffIdParamName, newValue);
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(ClientApiConstants.savingsProductIdParamName, savingsProductId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.savingsProductIdParamName);
|
||||
actualChanges.put(ClientApiConstants.savingsProductIdParamName, newValue);
|
||||
}
|
||||
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
@@ -628,4 +639,28 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private Long savingsProductId() {
|
||||
Long savingsProductId = null;
|
||||
if (this.savingsProduct != null) {
|
||||
savingsProductId = this.savingsProduct.getId();
|
||||
}
|
||||
return savingsProductId;
|
||||
}
|
||||
|
||||
|
||||
public SavingsProduct SavingsProduct() {
|
||||
return this.savingsProduct;
|
||||
}
|
||||
|
||||
|
||||
public void updateSavingsProduct(SavingsProduct savingsProduct) {
|
||||
this.savingsProduct = savingsProduct;
|
||||
}
|
||||
|
||||
|
||||
public AppUser activatedBy() {
|
||||
return this.activatedBy;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.mifosplatform.portfolio.client.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class ClientActiveForUpdateException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ClientActiveForUpdateException(final Long clientId,final String parameterName) {
|
||||
super("error.msg.client.active.for.update.parameter."+parameterName, "The Client with id `" + clientId + "` is active,can't update parameter "+parameterName, clientId,parameterName);
|
||||
}
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.portfolio.client.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown an action to transition a
|
||||
* loan from one state to another violates a domain rule.
|
||||
*/
|
||||
public class InvalidClientSavingProductException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public InvalidClientSavingProductException(final String action, final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg.client." + action + "." + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+28
-6
@@ -33,6 +33,8 @@ import org.mifosplatform.portfolio.client.domain.ClientStatus;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
|
||||
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
||||
import org.mifosplatform.portfolio.savings.service.SavingsProductReadPlatformService;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
@@ -49,6 +51,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final StaffReadPlatformService staffReadPlatformService;
|
||||
private final CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
private final SavingsProductReadPlatformService savingsProductReadPlatformService;
|
||||
// data mappers
|
||||
private final PaginationHelper<ClientData> paginationHelper = new PaginationHelper<ClientData>();
|
||||
private final ClientMapper clientMapper = new ClientMapper();
|
||||
@@ -59,12 +62,14 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
@Autowired
|
||||
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
|
||||
final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService,
|
||||
final CodeValueReadPlatformService codeValueReadPlatformService) {
|
||||
final CodeValueReadPlatformService codeValueReadPlatformService,
|
||||
final SavingsProductReadPlatformService savingsProductReadPlatformService) {
|
||||
this.context = context;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.staffReadPlatformService = staffReadPlatformService;
|
||||
this.codeValueReadPlatformService = codeValueReadPlatformService;
|
||||
this.savingsProductReadPlatformService = savingsProductReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,6 +79,9 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
|
||||
|
||||
final Collection<OfficeData> offices = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
|
||||
final Collection<SavingsProductData> savingsProductDatas = this.savingsProductReadPlatformService.retrieveAllForLookupByType(true);
|
||||
|
||||
|
||||
Collection<StaffData> staffOptions = null;
|
||||
|
||||
@@ -88,7 +96,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
staffOptions = null;
|
||||
}
|
||||
|
||||
return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions, null);
|
||||
return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions, null,savingsProductDatas);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -265,6 +273,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
sqlBuilder.append("c.mobile_no as mobileNo, ");
|
||||
sqlBuilder.append("c.activation_date as activationDate, c.image_id as imageId, ");
|
||||
sqlBuilder.append("c.staff_id as staffId, s.display_name as staffName,");
|
||||
sqlBuilder.append("c.default_savings_product as savingsProductId, sp.name as savingsProductName, ");
|
||||
|
||||
sqlBuilder.append("c.submittedon_date as submittedOnDate, ");
|
||||
sqlBuilder.append("sbu.username as submittedByUsername, ");
|
||||
@@ -284,6 +293,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
sqlBuilder.append("join m_office o on o.id = c.office_id ");
|
||||
sqlBuilder.append("join m_group_client pgc on pgc.client_id = c.id ");
|
||||
sqlBuilder.append("left join m_staff s on s.id = c.staff_id ");
|
||||
sqlBuilder.append("left join m_savings_product sp on sp.id = c.default_savings_product ");
|
||||
sqlBuilder.append("left join m_office transferToOffice on transferToOffice.id = c.transfer_to_office_id ");
|
||||
|
||||
sqlBuilder.append("left join m_appuser sbu on sbu.id = c.submittedon_userid ");
|
||||
@@ -324,6 +334,10 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
final Long imageId = JdbcSupport.getLong(rs, "imageId");
|
||||
final Long staffId = JdbcSupport.getLong(rs, "staffId");
|
||||
final String staffName = rs.getString("staffName");
|
||||
|
||||
final Long savingsProductId = JdbcSupport.getLong(rs, "savingsProductId");
|
||||
final String savingsProductName = rs.getString("savingsProductName");
|
||||
|
||||
|
||||
final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate");
|
||||
final String closedByUsername = rs.getString("closedByUsername");
|
||||
@@ -345,7 +359,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
closedByFirstname, closedByLastname);
|
||||
|
||||
return ClientData.instance(accountNo, status, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, activationDate, imageId, staffId, staffName,timeline);
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, activationDate, imageId, staffId, staffName,timeline,
|
||||
savingsProductId, savingsProductName);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -397,10 +412,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
|
||||
|
||||
builder.append("c.activation_date as activationDate, c.image_id as imageId, ");
|
||||
builder.append("c.staff_id as staffId, s.display_name as staffName ");
|
||||
builder.append("c.staff_id as staffId, s.display_name as staffName, ");
|
||||
builder.append("c.default_savings_product as savingsProductId, sp.name as savingsProductName ");
|
||||
builder.append("from m_client c ");
|
||||
builder.append("join m_office o on o.id = c.office_id ");
|
||||
builder.append("left join m_staff s on s.id = c.staff_id ");
|
||||
builder.append("left join m_savings_product sp on sp.id = c.default_savings_product ");
|
||||
builder.append("left join m_office transferToOffice on transferToOffice.id = c.transfer_to_office_id ");
|
||||
builder.append("left join m_appuser sbu on sbu.id = c.submittedon_userid ");
|
||||
builder.append("left join m_appuser acu on acu.id = c.activatedon_userid ");
|
||||
@@ -440,6 +457,10 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
final Long staffId = JdbcSupport.getLong(rs, "staffId");
|
||||
final String staffName = rs.getString("staffName");
|
||||
|
||||
final Long savingsProductId = JdbcSupport.getLong(rs, "savingsProductId");
|
||||
final String savingsProductName = rs.getString("savingsProductName");
|
||||
|
||||
|
||||
final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate");
|
||||
final String closedByUsername = rs.getString("closedByUsername");
|
||||
final String closedByFirstname = rs.getString("closedByFirstname");
|
||||
@@ -459,7 +480,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
closedByFirstname, closedByLastname);
|
||||
|
||||
return ClientData.instance(accountNo, status, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname,
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, activationDate, imageId, staffId, staffName,timeline);
|
||||
middlename, lastname, fullname, displayName, externalId, mobileNo, activationDate, imageId, staffId, staffName,timeline,
|
||||
savingsProductId, savingsProductName);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -571,7 +593,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
public ClientData retrieveAllClosureReasons(final String clientClosureReason) {
|
||||
final List<CodeValueData> closureReasons = new ArrayList<CodeValueData>(
|
||||
this.codeValueReadPlatformService.retrieveCodeValuesByCode(clientClosureReason));
|
||||
return ClientData.template(null, null, null, null, closureReasons);
|
||||
return ClientData.template(null, null, null, null, closureReasons,null);
|
||||
}
|
||||
|
||||
}
|
||||
+57
-3
@@ -32,8 +32,10 @@ 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.domain.ClientStatus;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientActiveForUpdateException;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientHasNoStaffException;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
|
||||
import org.mifosplatform.portfolio.client.exception.InvalidClientSavingProductException;
|
||||
import org.mifosplatform.portfolio.client.exception.InvalidClientStateTransitionException;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRepository;
|
||||
@@ -42,8 +44,13 @@ 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.data.SavingsAccountDataDTO;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepository;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsProduct;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsProductRepository;
|
||||
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
|
||||
import org.mifosplatform.portfolio.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -68,6 +75,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
private final CodeValueRepositoryWrapper codeValueRepository;
|
||||
private final LoanRepository loanRepository;
|
||||
private final SavingsAccountRepository savingsRepository;
|
||||
private final SavingsProductRepository savingsProductRepository;
|
||||
private final SavingsApplicationProcessWritePlatformService savingsApplicationProcessWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -75,7 +84,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
|
||||
final GroupRepository groupRepository, final StaffRepositoryWrapper staffRepository,
|
||||
final CodeValueRepositoryWrapper codeValueRepository, final LoanRepository loanRepository,
|
||||
final SavingsAccountRepository savingsRepository) {
|
||||
final SavingsAccountRepository savingsRepository,final SavingsProductRepository savingsProductRepository,
|
||||
final SavingsApplicationProcessWritePlatformService savingsApplicationProcessWritePlatformService) {
|
||||
this.context = context;
|
||||
this.clientRepository = clientRepository;
|
||||
this.officeRepository = officeRepository;
|
||||
@@ -87,6 +97,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
this.codeValueRepository = codeValueRepository;
|
||||
this.loanRepository = loanRepository;
|
||||
this.savingsRepository = savingsRepository;
|
||||
this.savingsProductRepository = savingsProductRepository;
|
||||
this.savingsApplicationProcessWritePlatformService = savingsApplicationProcessWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -163,8 +175,16 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
if (staffId != null) {
|
||||
staff = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(staffId, clientOffice.getHierarchy());
|
||||
}
|
||||
|
||||
SavingsProduct savingsProduct = null;
|
||||
final Long savingsProductId = command.longValueOfParameterNamed(ClientApiConstants.savingsProductIdParamName);
|
||||
if(savingsProductId != null){
|
||||
savingsProduct = this.savingsProductRepository.findOne(savingsProductId);
|
||||
if (savingsProduct == null) { throw new SavingsProductNotFoundException(savingsProductId); }
|
||||
|
||||
final Client newClient = Client.createNew(currentUser,clientOffice, clientParentGroup, staff, command);
|
||||
}
|
||||
|
||||
final Client newClient = Client.createNew(currentUser,clientOffice, clientParentGroup, staff, savingsProduct, command);
|
||||
|
||||
this.clientRepository.save(newClient);
|
||||
|
||||
@@ -174,6 +194,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
newClient.updateAccountNo(accountNoGenerator.generate());
|
||||
this.clientRepository.save(newClient);
|
||||
}
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
Long savingsId = openOverdraftSavingsAccount(newClient, fmt);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
@@ -181,6 +205,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
.withClientId(newClient.getId()) //
|
||||
.withGroupId(groupId) //
|
||||
.withEntityId(newClient.getId()) //
|
||||
.withSavingsId(savingsId)//
|
||||
.build();
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
@@ -199,6 +224,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
final String clientHierarchy = clientForUpdate.getOffice().getHierarchy();
|
||||
|
||||
this.context.validateAccessRights(clientHierarchy);
|
||||
|
||||
|
||||
final Map<String, Object> changes = clientForUpdate.update(command);
|
||||
|
||||
@@ -212,6 +238,20 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
}
|
||||
clientForUpdate.updateStaff(newStaff);
|
||||
}
|
||||
|
||||
if (changes.containsKey(ClientApiConstants.savingsProductIdParamName)) {
|
||||
if(clientForUpdate.isActive()){
|
||||
throw new ClientActiveForUpdateException(clientId, ClientApiConstants.savingsProductIdParamName);
|
||||
}
|
||||
SavingsProduct savingsProduct = null;
|
||||
final Long savingsProductId = command.longValueOfParameterNamed(ClientApiConstants.savingsProductIdParamName);
|
||||
if(savingsProductId != null){
|
||||
savingsProduct = this.savingsProductRepository.findOne(savingsProductId);
|
||||
if (savingsProduct == null) { throw new SavingsProductNotFoundException(savingsProductId); }
|
||||
}
|
||||
clientForUpdate.updateSavingsProduct(savingsProduct);
|
||||
}
|
||||
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.clientRepository.saveAndFlush(clientForUpdate);
|
||||
@@ -244,7 +284,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
|
||||
final AppUser currentUser = this.context.authenticatedUser();
|
||||
client.activate(currentUser, fmt, activationDate);
|
||||
|
||||
Long savingsId = openOverdraftSavingsAccount(client, fmt);
|
||||
this.clientRepository.saveAndFlush(client);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
@@ -252,6 +292,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
.withOfficeId(client.officeId()) //
|
||||
.withClientId(clientId) //
|
||||
.withEntityId(clientId) //
|
||||
.withSavingsId(savingsId)//
|
||||
.build();
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
@@ -259,6 +300,19 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
}
|
||||
}
|
||||
|
||||
private Long openOverdraftSavingsAccount(final Client client, final DateTimeFormatter fmt) {
|
||||
Long accountId = null;
|
||||
if(client.isActive() && client.SavingsProduct() != null){
|
||||
if(!client.SavingsProduct().isAllowOverdraft()){
|
||||
String defaultUserMessage = "Client's saving account must be a overdraft account";
|
||||
throw new InvalidClientSavingProductException("saving.product", "must.be.ovrdraft.account", defaultUserMessage, client.SavingsProduct().getId(),client.getId());
|
||||
}
|
||||
SavingsAccountDataDTO savingsAccountDataDTO = new SavingsAccountDataDTO(client, null, client.SavingsProduct(), client.getActivationLocalDate(), client.activatedBy(), fmt);
|
||||
accountId = this.savingsApplicationProcessWritePlatformService.createActiveApplication(savingsAccountDataDTO);
|
||||
}
|
||||
return accountId;
|
||||
}
|
||||
|
||||
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
|
||||
logger.error(dve.getMessage(), dve);
|
||||
}
|
||||
|
||||
+17
-1
@@ -24,7 +24,9 @@ public enum SavingsAccountTransactionType {
|
||||
INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), //
|
||||
APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
|
||||
WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
|
||||
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer");
|
||||
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"),
|
||||
WRITTEN_OFF(16, "savingsAccountTransactionType.writtenoff"), //
|
||||
OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest"); //
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -81,6 +83,12 @@ public enum SavingsAccountTransactionType {
|
||||
case 15:
|
||||
savingsAccountTransactionType = SavingsAccountTransactionType.REJECT_TRANSFER;
|
||||
break;
|
||||
case 18:
|
||||
savingsAccountTransactionType = SavingsAccountTransactionType.WRITTEN_OFF;
|
||||
break;
|
||||
case 19:
|
||||
savingsAccountTransactionType = SavingsAccountTransactionType.OVERDRAFT_INTEREST;
|
||||
break;
|
||||
}
|
||||
return savingsAccountTransactionType;
|
||||
}
|
||||
@@ -132,6 +140,14 @@ public enum SavingsAccountTransactionType {
|
||||
public boolean isTransferWithdrawal() {
|
||||
return this.value.equals(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue());
|
||||
}
|
||||
|
||||
public boolean isWrittenoff(){
|
||||
return this.value.equals(SavingsAccountTransactionType.WRITTEN_OFF.getValue());
|
||||
}
|
||||
|
||||
public boolean isIncomeFromInterest(){
|
||||
return this.value.equals(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue());
|
||||
}
|
||||
|
||||
public boolean isDebit() {
|
||||
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isPayCharge();
|
||||
|
||||
+8
-2
@@ -92,6 +92,8 @@ public class SavingsApiConstants {
|
||||
public static final String routingCodeParamName = "routingCode";
|
||||
public static final String receiptNumberParamName = "receiptNumber";
|
||||
public static final String bankNumberParamName = "bankNumber";
|
||||
public static final String allowOverdraftParamName = "allowOverdraft";
|
||||
public static final String overdraftLimitParamName = "overdraftLimit";
|
||||
|
||||
// transaction parameters
|
||||
public static final String transactionDateParamName = "transactionDate";
|
||||
@@ -143,7 +145,11 @@ public class SavingsApiConstants {
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue()));
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(),
|
||||
allowOverdraftParamName,overdraftLimitParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -167,7 +173,7 @@ public class SavingsApiConstants {
|
||||
lockinPeriodFrequencyTypeParamName,
|
||||
//withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
withdrawalFeeForTransfersParamName,
|
||||
feeAmountParamName, feeOnMonthDayParamName, chargesParamName));
|
||||
feeAmountParamName, feeOnMonthDayParamName, chargesParamName,allowOverdraftParamName,overdraftLimitParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
|
||||
+19
-7
@@ -44,6 +44,8 @@ public class SavingsAccountData {
|
||||
private final Integer lockinPeriodFrequency;
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final boolean withdrawalFeeForTransfers;
|
||||
private final boolean allowOverdraft;
|
||||
private final BigDecimal overdraftLimit;
|
||||
|
||||
// associations
|
||||
private final SavingsAccountSummaryData summary;
|
||||
@@ -75,7 +77,8 @@ public class SavingsAccountData {
|
||||
final EnumOptionData interestCompoundingPeriodType, final EnumOptionData interestPostingPeriodType,
|
||||
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||
final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, final SavingsAccountSummaryData summary) {
|
||||
final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, final SavingsAccountSummaryData summary,
|
||||
final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<StaffData> fieldOfficerOptions = null;
|
||||
@@ -96,7 +99,7 @@ public class SavingsAccountData {
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsAccountData lookup(final Long accountId, final String accountNo) {
|
||||
@@ -127,6 +130,8 @@ public class SavingsAccountData {
|
||||
// final BigDecimal annualFeeAmount = null;
|
||||
// final MonthDay annualFeeOnMonthDay = null;
|
||||
// final LocalDate annualFeeNextDueDate = null;
|
||||
final boolean allowOverdraft = false;
|
||||
final BigDecimal overdraftLimit = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
@@ -149,7 +154,7 @@ public class SavingsAccountData {
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
|
||||
@@ -180,7 +185,8 @@ public class SavingsAccountData {
|
||||
template.productOptions, template.fieldOfficerOptions, template.interestCompoundingPeriodTypeOptions,
|
||||
template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions,
|
||||
template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions,
|
||||
template.withdrawalFeeTypeOptions, charges, template.chargeOptions);
|
||||
template.withdrawalFeeTypeOptions, charges, template.chargeOptions,account.allowOverdraft,
|
||||
account.overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||
@@ -201,7 +207,7 @@ public class SavingsAccountData {
|
||||
account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions,account.allowOverdraft,account.overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||
@@ -231,6 +237,9 @@ public class SavingsAccountData {
|
||||
// final BigDecimal annualFeeAmount = null;
|
||||
// final MonthDay annualFeeOnMonthDay = null;
|
||||
// final LocalDate annualFeeNextDueDate = null;
|
||||
final boolean allowOverdraft = false;
|
||||
final BigDecimal overdraftLimit = null;
|
||||
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
@@ -253,7 +262,7 @@ public class SavingsAccountData {
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions,
|
||||
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions);
|
||||
withdrawalFeeTypeOptions, charges, chargeOptions,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, final String groupName,
|
||||
@@ -270,7 +279,8 @@ public class SavingsAccountData {
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
||||
final Collection<SavingsAccountChargeData> charges, final Collection<ChargeData> chargeOptions) {
|
||||
final Collection<SavingsAccountChargeData> charges, final Collection<ChargeData> chargeOptions,
|
||||
final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
@@ -319,6 +329,8 @@ public class SavingsAccountData {
|
||||
this.withdrawalFee = getWithdrawalFee();
|
||||
|
||||
this.annualFee = getAnnualFee();
|
||||
this.allowOverdraft = allowOverdraft;
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
}
|
||||
|
||||
private SavingsAccountChargeData getWithdrawalFee() {
|
||||
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
package org.mifosplatform.portfolio.savings.data;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsProduct;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
|
||||
public class SavingsAccountDataDTO {
|
||||
|
||||
private final Client client;
|
||||
private final Group group;
|
||||
private final SavingsProduct savingsProduct;
|
||||
private final LocalDate applicationDate;
|
||||
private final AppUser appliedBy;
|
||||
private final DateTimeFormatter fmt;
|
||||
|
||||
public SavingsAccountDataDTO(final Client client, final Group group, final SavingsProduct savingsProduct,
|
||||
final LocalDate applicationDate, final AppUser appliedBy, final DateTimeFormatter fmt) {
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
this.savingsProduct = savingsProduct;
|
||||
this.applicationDate = applicationDate;
|
||||
this.appliedBy = appliedBy;
|
||||
this.fmt = fmt;
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
public Group getGroup() {
|
||||
return this.group;
|
||||
}
|
||||
|
||||
public SavingsProduct getSavingsProduct() {
|
||||
return this.savingsProduct;
|
||||
}
|
||||
|
||||
public LocalDate getApplicationDate() {
|
||||
return this.applicationDate;
|
||||
}
|
||||
|
||||
public AppUser getAppliedBy() {
|
||||
return this.appliedBy;
|
||||
}
|
||||
|
||||
public DateTimeFormatter getFmt() {
|
||||
return this.fmt;
|
||||
}
|
||||
}
|
||||
+21
@@ -6,6 +6,7 @@
|
||||
package org.mifosplatform.portfolio.savings.data;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountNoParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.amountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargeIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
@@ -23,6 +24,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
@@ -188,6 +190,8 @@ public class SavingsAccountDataValidator {
|
||||
|
||||
validateSavingsCharges(element, baseDataValidator);
|
||||
|
||||
validateOverdraftParams(baseDataValidator, element);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -359,10 +363,27 @@ public class SavingsAccountDataValidator {
|
||||
.ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
validateOverdraftParams(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
private void validateOverdraftParams(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (this.fromApiJsonHelper.parameterExists(allowOverdraftParamName, element)) {
|
||||
final Boolean allowOverdraft = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
allowOverdraftParamName, element);
|
||||
baseDataValidator.reset().parameter(allowOverdraftParamName).value(allowOverdraft)
|
||||
.ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(overdraftLimitParamName, element)) {
|
||||
final BigDecimal overdraftLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
overdraftLimitParamName, element);
|
||||
baseDataValidator.reset().parameter(overdraftLimitParamName).value(overdraftLimit).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+19
@@ -25,6 +25,9 @@ public class SavingsAccountTransactionEnumData {
|
||||
private final boolean approveTransfer;
|
||||
private final boolean withdrawTransfer;
|
||||
private final boolean rejectTransfer;
|
||||
private final boolean overdraftInterest;
|
||||
private final boolean writtenoff ;
|
||||
private final boolean overdraftFee =true;
|
||||
|
||||
public SavingsAccountTransactionEnumData(final Long id, final String code, final String value) {
|
||||
this.id = id;
|
||||
@@ -40,6 +43,9 @@ public class SavingsAccountTransactionEnumData {
|
||||
this.approveTransfer = Long.valueOf(SavingsAccountTransactionType.APPROVE_TRANSFER.getValue()).equals(this.id);
|
||||
this.withdrawTransfer = Long.valueOf(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue()).equals(this.id);
|
||||
this.rejectTransfer = Long.valueOf(SavingsAccountTransactionType.REJECT_TRANSFER.getValue()).equals(this.id);
|
||||
this.writtenoff = Long.valueOf(SavingsAccountTransactionType.WRITTEN_OFF.getValue()).equals(this.id);
|
||||
this.overdraftInterest = Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
|
||||
// this.overdraftFee = Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
@@ -89,5 +95,18 @@ public class SavingsAccountTransactionEnumData {
|
||||
public boolean isRejectTransfer() {
|
||||
return this.rejectTransfer;
|
||||
}
|
||||
|
||||
public boolean isOverdraftInterest() {
|
||||
return this.overdraftInterest;
|
||||
}
|
||||
|
||||
|
||||
public boolean isWrittenoff() {
|
||||
return this.writtenoff;
|
||||
}
|
||||
|
||||
public boolean isOverdraftFee() {
|
||||
return this.overdraftFee;
|
||||
}
|
||||
|
||||
}
|
||||
+21
-8
@@ -38,6 +38,8 @@ public class SavingsProductData {
|
||||
private final Integer lockinPeriodFrequency;
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final boolean withdrawalFeeForTransfers;
|
||||
private final boolean allowOverdraft;
|
||||
private final BigDecimal overdraftLimit;
|
||||
|
||||
// accounting
|
||||
private final EnumOptionData accountingRule;
|
||||
@@ -89,6 +91,9 @@ public class SavingsProductData {
|
||||
final Collection<ChargeData> charges = null;
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
|
||||
final boolean allowOverdraft = false;
|
||||
final BigDecimal overdraftLimit = null;
|
||||
|
||||
|
||||
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
@@ -97,7 +102,7 @@ public class SavingsProductData {
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
penaltyToIncomeAccountMappings,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsProductData withCharges(final SavingsProductData product, final Collection<ChargeData> charges) {
|
||||
@@ -110,7 +115,7 @@ public class SavingsProductData {
|
||||
product.interestCalculationDaysInYearTypeOptions, product.lockinPeriodFrequencyTypeOptions,
|
||||
product.withdrawalFeeTypeOptions, product.paymentTypeOptions, product.accountingRuleOptions,
|
||||
product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions,
|
||||
product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings);
|
||||
product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings,product.allowOverdraft,product.overdraftLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +142,8 @@ public class SavingsProductData {
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions,
|
||||
existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings);
|
||||
existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings,
|
||||
existingProduct.allowOverdraft,existingProduct.overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct,
|
||||
@@ -169,7 +175,7 @@ public class SavingsProductData {
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
penaltyToIncomeAccountMappings,existingProduct.allowOverdraft,existingProduct.overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description,
|
||||
@@ -177,7 +183,7 @@ public class SavingsProductData {
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers,
|
||||
final EnumOptionData accountingType) {
|
||||
final EnumOptionData accountingType,final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
|
||||
final Map<String, Object> accountingMappings = null;
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
||||
@@ -205,7 +211,7 @@ public class SavingsProductData {
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
penaltyToIncomeAccountMappings,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
public static SavingsProductData lookup(final Long id, final String name) {
|
||||
@@ -225,6 +231,8 @@ public class SavingsProductData {
|
||||
final EnumOptionData accountingType = null;
|
||||
final Map<String, Object> accountingMappings = null;
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
||||
final boolean allowOverdraft = false;
|
||||
final BigDecimal overdraftLimit = null;
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -241,6 +249,8 @@ public class SavingsProductData {
|
||||
final Collection<ChargeData> penaltyOptions = null;
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
|
||||
|
||||
|
||||
|
||||
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
@@ -249,7 +259,7 @@ public class SavingsProductData {
|
||||
currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
penaltyToIncomeAccountMappings,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
private SavingsProductData(final Long id, final String name, final String shortName, final String description, final CurrencyData currency,
|
||||
@@ -268,7 +278,8 @@ public class SavingsProductData {
|
||||
final Map<String, List<GLAccountData>> accountingMappingOptions, final Collection<ChargeData> charges,
|
||||
final Collection<ChargeData> chargeOptions, final Collection<ChargeData> penaltyOptions,
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings,
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings) {
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings,
|
||||
final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
@@ -311,6 +322,8 @@ public class SavingsProductData {
|
||||
|
||||
this.feeToIncomeAccountMappings = feeToIncomeAccountMappings;
|
||||
this.penaltyToIncomeAccountMappings = penaltyToIncomeAccountMappings;
|
||||
this.allowOverdraft = allowOverdraft;
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
}
|
||||
|
||||
public boolean hasAccountingEnabled() {
|
||||
|
||||
+55
-1
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.savings.data;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
@@ -22,6 +23,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||
|
||||
@@ -240,10 +242,28 @@ public class SavingsProductDataValidator {
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
||||
.value(incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long overdraftControlAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue())
|
||||
.value(overdraftControlAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromInterest = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue())
|
||||
.value(incomeFromInterest).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long writtenoff = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue())
|
||||
.value(writtenoff).notNull().integerGreaterThanZero();
|
||||
|
||||
|
||||
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
||||
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
||||
}
|
||||
|
||||
validateOverdraftParams(baseDataValidator, element);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
@@ -383,10 +403,27 @@ public class SavingsProductDataValidator {
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue()).value(incomeFromPenaltyId)
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long overdraftAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue())
|
||||
.value(overdraftAccountId).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromInterest = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue())
|
||||
.value(incomeFromInterest).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long writtenoff = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue())
|
||||
.value(writtenoff).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
|
||||
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
||||
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
||||
|
||||
validateOverdraftParams(baseDataValidator, element);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -467,4 +504,21 @@ public class SavingsProductDataValidator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateOverdraftParams(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (this.fromApiJsonHelper.parameterExists(allowOverdraftParamName, element)) {
|
||||
final Boolean allowOverdraft = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
allowOverdraftParamName, element);
|
||||
baseDataValidator.reset().parameter(allowOverdraftParamName).value(allowOverdraft)
|
||||
.ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(overdraftLimitParamName, element)) {
|
||||
final BigDecimal overdraftLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
overdraftLimitParamName, element);
|
||||
baseDataValidator.reset().parameter(overdraftLimitParamName).value(overdraftLimit).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+132
-13
@@ -6,9 +6,12 @@
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -218,6 +221,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "withdrawal_fee_for_transfer", nullable = true)
|
||||
private boolean withdrawalFeeApplicableForTransfer;
|
||||
|
||||
@Column(name = "allow_overdraft")
|
||||
private boolean allowOverdraft;
|
||||
|
||||
@Column(name = "overdraft_limit", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal overdraftLimit;
|
||||
|
||||
@Embedded
|
||||
private SavingsAccountSummary summary;
|
||||
@@ -249,13 +258,14 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges,
|
||||
final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
|
||||
final SavingsAccountStatusType status = SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL;
|
||||
return new SavingsAccount(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate, submittedBy,
|
||||
interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeApplicableForTransfer, savingsAccountCharges);
|
||||
withdrawalFeeApplicableForTransfer, savingsAccountCharges,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
private SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer,
|
||||
@@ -265,7 +275,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final Set<SavingsAccountCharge> savingsAccountCharges,
|
||||
final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
this.product = product;
|
||||
@@ -300,6 +311,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
this.summary = new SavingsAccountSummary();
|
||||
this.allowOverdraft = allowOverdraft;
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,24 +509,57 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
|
||||
Money runningBalance = openingAccountBalance.copy();
|
||||
|
||||
final List<SavingsAccountTransaction> accountTransactionsSorted = retreiveListOfTransactions();
|
||||
|
||||
List<SavingsAccountTransaction> accountTransactionsSorted = retreiveListOfTransactions();
|
||||
boolean isTransactionsModified = false;
|
||||
for (final SavingsAccountTransaction transaction : accountTransactionsSorted) {
|
||||
if (transaction.isReversed()) {
|
||||
transaction.zeroBalanceFields();
|
||||
} else {
|
||||
Money overdraftAmount = Money.zero(this.currency);
|
||||
Money transactionAmount = Money.zero(this.currency);
|
||||
if (transaction.isCredit()) {
|
||||
if(runningBalance.isLessThanZero()){
|
||||
Money diffAmount = transaction.getAmount(this.currency).plus(runningBalance);
|
||||
if(diffAmount.isGreaterThanZero()){
|
||||
overdraftAmount = transaction.getAmount(this.currency).minus(diffAmount);
|
||||
}else{
|
||||
overdraftAmount = transaction.getAmount(this.currency);
|
||||
}
|
||||
}
|
||||
transactionAmount = transactionAmount.plus(transaction.getAmount(this.currency));
|
||||
} else if (transaction.isDebit()) {
|
||||
if(runningBalance.isLessThanZero()){
|
||||
overdraftAmount = transaction.getAmount(this.currency);
|
||||
}
|
||||
transactionAmount = transactionAmount.minus(transaction.getAmount(this.currency));
|
||||
}
|
||||
|
||||
|
||||
runningBalance = runningBalance.plus(transactionAmount);
|
||||
transaction.updateRunningBalance(runningBalance);
|
||||
if(overdraftAmount.isZero() && runningBalance.isLessThanZero()){
|
||||
overdraftAmount = overdraftAmount.plus(runningBalance.getAmount().negate());
|
||||
}
|
||||
if(transaction.getId() == null && overdraftAmount.isGreaterThanZero()){
|
||||
transaction.updateOverdraftAmount(overdraftAmount.getAmount());
|
||||
}else if(overdraftAmount.isNotEqualTo(transaction.getOverdraftAmount(getCurrency()))){
|
||||
SavingsAccountTransaction accountTransaction = SavingsAccountTransaction.copyTransaction(transaction);
|
||||
transaction.reverse();
|
||||
if(overdraftAmount.isGreaterThanZero()){
|
||||
accountTransaction.updateOverdraftAmount(overdraftAmount.getAmount());
|
||||
}
|
||||
accountTransaction.updateRunningBalance(runningBalance);
|
||||
this.transactions.add(accountTransaction);
|
||||
isTransactionsModified = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(isTransactionsModified){
|
||||
accountTransactionsSorted = retreiveListOfTransactions();
|
||||
}
|
||||
// loop over transactions in reverse
|
||||
LocalDate endOfBalanceDate = DateUtils.getLocalDateOfTenant();
|
||||
for (int i = accountTransactionsSorted.size() - 1; i >= 0; i--) {
|
||||
@@ -687,10 +733,20 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
if (runningBalance.isLessThanZero()) {
|
||||
//
|
||||
final BigDecimal withdrawalFee = null;
|
||||
throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(), withdrawalFee, transactionAmount);
|
||||
Money limit = runningBalance.zero();
|
||||
if(this.allowOverdraft){
|
||||
if(this.overdraftLimit != null){
|
||||
limit = limit.plus(this.overdraftLimit);
|
||||
}
|
||||
}
|
||||
if(limit.plus(runningBalance).isLessThanZero()){
|
||||
throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(), withdrawalFee, transactionAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void validateAccountBalanceDoesNotBecomeNegative(final String transactionAction) {
|
||||
|
||||
@@ -709,9 +765,18 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME + transactionAction);
|
||||
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("results.in.balance.going.negative");
|
||||
|
||||
|
||||
if(this.allowOverdraft){
|
||||
Money limit = runningBalance.zero();
|
||||
if(this.overdraftLimit != null){
|
||||
limit = limit.plus(this.overdraftLimit);
|
||||
}
|
||||
if(limit.plus(runningBalance).isLessThanZero()){
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("results.in.balance.exceeding.overdraft.limit");
|
||||
}
|
||||
}else{
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("results.in.balance.going.negative");
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
@@ -878,6 +943,24 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
actualChanges.put(chargesParamName, command.jsonFragment(chargesParamName));
|
||||
}
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(allowOverdraftParamName, this.allowOverdraft)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftParamName);
|
||||
actualChanges.put(allowOverdraftParamName, newValue);
|
||||
this.allowOverdraft = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(overdraftLimitParamName,
|
||||
this.overdraftLimit)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(overdraftLimitParamName);
|
||||
actualChanges.put(overdraftLimitParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.overdraftLimit = newValue;
|
||||
}
|
||||
|
||||
if(!this.allowOverdraft){
|
||||
this.overdraftLimit = null;
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
|
||||
@@ -1438,9 +1521,15 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
|
||||
// auto enter deposit for minimum required opening balance when
|
||||
// activating account.
|
||||
processAccountUponActivation(fmt);
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void processAccountUponActivation(final DateTimeFormatter fmt) {
|
||||
final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance);
|
||||
if (minRequiredOpeningBalance.isGreaterThanZero()) {
|
||||
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, activationDate,
|
||||
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
|
||||
minRequiredOpeningBalance.getAmount(), null);
|
||||
deposit(transactionDTO);
|
||||
|
||||
@@ -1463,8 +1552,22 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
//auto pay the activation time charges
|
||||
this.payActivationCharges();
|
||||
//TODO : AA add activation charges to actual changes list
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public void approveAndActivateApplication(final Date appliedonDate,final AppUser appliedBy,final DateTimeFormatter fmt){
|
||||
this.status = SavingsAccountStatusType.ACTIVE.getValue();
|
||||
this.approvedOnDate = appliedonDate;
|
||||
this.approvedBy = appliedBy;
|
||||
this.rejectedOnDate = null;
|
||||
this.rejectedBy = null;
|
||||
this.withdrawnOnDate = null;
|
||||
this.withdrawnBy = null;
|
||||
this.closedOnDate = null;
|
||||
this.closedBy = null;
|
||||
this.activatedOnDate = appliedonDate;
|
||||
this.activatedBy = appliedBy;
|
||||
this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate());
|
||||
processAccountUponActivation(fmt);
|
||||
}
|
||||
|
||||
private void payActivationCharges() {
|
||||
@@ -1894,4 +1997,20 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
public Set<SavingsAccountCharge> charges() {
|
||||
return (this.charges == null) ? new HashSet<SavingsAccountCharge>() : this.charges;
|
||||
}
|
||||
|
||||
public void validateAccountValuesWithProduct() {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||
|
||||
if(this.overdraftLimit != null && this.product.overdraftLimit() != null && this.overdraftLimit.compareTo(this.product.overdraftLimit()) == 1){
|
||||
baseDataValidator.reset().parameter(SavingsApiConstants.overdraftLimitParamName).value(this.overdraftLimit)
|
||||
.failWithCode("cannot.exceed.product.value");
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors);}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+61
-5
@@ -6,6 +6,7 @@
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountNoParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.clientIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.externalIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.fieldOfficerIdParamName;
|
||||
@@ -18,11 +19,13 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
@@ -112,15 +115,15 @@ public class SavingsAccountAssembler {
|
||||
if (groupId != null) {
|
||||
group = this.groupRepository.findOneWithNotFoundDetection(groupId);
|
||||
accountType = AccountType.GROUP;
|
||||
if (group.isNotActive()) {
|
||||
if (group.isCenter()) { throw new CenterNotActiveException(groupId); }
|
||||
throw new GroupNotActiveException(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
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 = this.fromApiJsonHelper.extractLongNamed(fieldOfficerIdParamName, element);
|
||||
@@ -202,13 +205,23 @@ public class SavingsAccountAssembler {
|
||||
|
||||
final Set<SavingsAccountCharge> charges = this.savingsAccountChargeAssembler.fromParsedJson(element, product.currency().getCode());
|
||||
|
||||
boolean allowOverdraft = false;
|
||||
if (command.parameterExists(allowOverdraftParamName)) {
|
||||
allowOverdraft = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftParamName);
|
||||
}
|
||||
|
||||
final BigDecimal overdraftLimit = command
|
||||
.bigDecimalValueOfParameterNamedDefaultToNullIfZero(overdraftLimitParamName);
|
||||
|
||||
final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNo,
|
||||
externalId, accountType, submittedOnDate, submittedBy, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, charges);
|
||||
lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, charges,allowOverdraft,overdraftLimit);
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
|
||||
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant());
|
||||
|
||||
account.validateAccountValuesWithProduct();
|
||||
|
||||
return account;
|
||||
}
|
||||
@@ -216,10 +229,53 @@ public class SavingsAccountAssembler {
|
||||
public SavingsAccount assembleFrom(final Long savingsId) {
|
||||
final SavingsAccount account = this.savingsAccountRepository.findOneWithNotFoundDetection(savingsId);
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
return account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a new {@link SavingsAccount} from JSON details passed in
|
||||
* request inheriting details where relevant from chosen
|
||||
* {@link SavingsProduct}.
|
||||
*/
|
||||
public SavingsAccount assembleFrom(final Client client ,final Group group, final SavingsProduct product,final LocalDate appliedonDate,final AppUser appliedBy) {
|
||||
|
||||
AccountType accountType = AccountType.INVALID;
|
||||
if (client != null) {
|
||||
accountType = AccountType.INDIVIDUAL;
|
||||
if (client.isNotActive()) { throw new ClientNotActiveException(client.getId()); }
|
||||
}
|
||||
|
||||
if (group != null) {
|
||||
accountType = AccountType.GROUP;
|
||||
if(group.isNotActive()){
|
||||
if (group.isCenter()) { throw new CenterNotActiveException(group.getId()); }
|
||||
throw new GroupNotActiveException(group.getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (group != null && client != null) {
|
||||
if (!group.hasClientAsMember(client)) { throw new ClientNotInGroupException(client.getId(), group.getId()); }
|
||||
accountType = AccountType.JLG;
|
||||
}
|
||||
|
||||
final Set<SavingsAccountCharge> charges = this.savingsAccountChargeAssembler.fromSavingsProduct(product);
|
||||
|
||||
|
||||
final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, null, null,
|
||||
null, accountType, appliedonDate, appliedBy, product.nominalAnnualInterestRate(), product.interestCompoundingPeriodType(),
|
||||
product.interestPostingPeriodType(),
|
||||
product.interestCalculationType(), product.interestCalculationDaysInYearType(), product.minRequiredOpeningBalance(), product.lockinPeriodFrequency(),
|
||||
product.lockinPeriodFrequencyType(), product.isWithdrawalFeeApplicableForTransfer(), charges ,product.isAllowOverdraft(),product.overdraftLimit());
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
|
||||
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant());
|
||||
|
||||
account.validateAccountValuesWithProduct();
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
|
||||
public void assignSavingAccountHelpers(final SavingsAccount savingsAccount) {
|
||||
savingsAccount.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
}
|
||||
|
||||
+4
@@ -614,6 +614,10 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
||||
public boolean isWithdrawalFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isWithdrawalFee();
|
||||
}
|
||||
|
||||
public boolean isOverdraftFee(){
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isOverdraftFee();
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isAnnualFee();
|
||||
|
||||
+26
@@ -126,6 +126,32 @@ public class SavingsAccountChargeAssembler {
|
||||
return savingsAccountCharges;
|
||||
}
|
||||
|
||||
public Set<SavingsAccountCharge> fromSavingsProduct(final SavingsProduct savingsProduct) {
|
||||
|
||||
final Set<SavingsAccountCharge> savingsAccountCharges = new HashSet<SavingsAccountCharge>();
|
||||
Set<Charge> productCharges = savingsProduct.charges();
|
||||
for (Charge charge : productCharges) {
|
||||
ChargeTimeType chargeTime = null;
|
||||
if (charge.getChargeTime() != null) {
|
||||
chargeTime = ChargeTimeType.fromInt(charge.getChargeTime());
|
||||
}
|
||||
if(chargeTime !=null && chargeTime.isOnSpecifiedDueDate()){
|
||||
continue;
|
||||
}
|
||||
|
||||
ChargeCalculationType chargeCalculation = null;
|
||||
if (charge.getChargeCalculation() != null) {
|
||||
chargeCalculation = ChargeCalculationType.fromInt(charge.getChargeCalculation());
|
||||
}
|
||||
final boolean status = true;
|
||||
final SavingsAccountCharge savingsAccountCharge = SavingsAccountCharge.createNewWithoutSavingsAccount(
|
||||
charge, charge.getAmount(),chargeTime ,chargeCalculation , null, status, charge.getFeeOnMonthDay(), charge.feeInterval());
|
||||
savingsAccountCharges.add(savingsAccountCharge);
|
||||
}
|
||||
return savingsAccountCharges;
|
||||
}
|
||||
|
||||
|
||||
private void validateSavingsCharges(final Set<SavingsAccountCharge> charges, final String productCurrencyCode) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
|
||||
+21
@@ -89,6 +89,9 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsAccountTransaction", orphanRemoval = true)
|
||||
private final Set<SavingsAccountChargePaidBy> savingsAccountChargesPaid = new HashSet<SavingsAccountChargePaidBy>();
|
||||
|
||||
@Column(name = "overdraft_amount_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal overdraftAmount;
|
||||
|
||||
protected SavingsAccountTransaction() {
|
||||
this.dateOf = null;
|
||||
@@ -167,6 +170,13 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(),
|
||||
isReversed);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction copyTransaction(SavingsAccountTransaction accountTransaction) {
|
||||
return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail,
|
||||
accountTransaction.typeOf, accountTransaction.transactionLocalDate(), accountTransaction.amount,
|
||||
accountTransaction.reversed);
|
||||
}
|
||||
|
||||
|
||||
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final Integer typeOf,
|
||||
final LocalDate transactionLocalDate, final Money amount, final boolean isReversed) {
|
||||
@@ -331,6 +341,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
thisTransactionData.put("date", getTransactionLocalDate());
|
||||
thisTransactionData.put("currency", currencyData);
|
||||
thisTransactionData.put("amount", this.amount);
|
||||
thisTransactionData.put("overdraftAmount", this.overdraftAmount);
|
||||
|
||||
if (this.paymentDetail != null) {
|
||||
thisTransactionData.put("paymentTypeId", this.paymentDetail.getPaymentType().getId());
|
||||
@@ -535,4 +546,14 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
return this.savingsAccountChargesPaid;
|
||||
}
|
||||
|
||||
|
||||
public void updateOverdraftAmount(BigDecimal overdraftAmount) {
|
||||
this.overdraftAmount = overdraftAmount;
|
||||
}
|
||||
|
||||
public Money getOverdraftAmount(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.overdraftAmount);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+55
-5
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||
@@ -22,8 +23,9 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@@ -129,17 +131,25 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
@ManyToMany
|
||||
@JoinTable(name = "m_savings_product_charge", joinColumns = @JoinColumn(name = "savings_product_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
||||
private Set<Charge> charges;
|
||||
|
||||
|
||||
@Column(name = "allow_overdraft")
|
||||
private boolean allowOverdraft;
|
||||
|
||||
@Column(name = "overdraft_limit", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal overdraftLimit;
|
||||
|
||||
public static SavingsProduct createNew(final String name, final String shortName, final String description, final MonetaryCurrency currency,
|
||||
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges,
|
||||
final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
|
||||
return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges);
|
||||
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
||||
allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
protected SavingsProduct() {
|
||||
@@ -152,7 +162,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges) {
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges,
|
||||
final boolean allowOverdraft,final BigDecimal overdraftLimit) {
|
||||
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
@@ -192,6 +203,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
validateLockinDetails();
|
||||
//validateWithdrawalFeeDetails();
|
||||
//validateAnnualFeeDetails();
|
||||
this.allowOverdraft = allowOverdraft;
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
}
|
||||
|
||||
public MonetaryCurrency currency() {
|
||||
@@ -411,6 +424,23 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(allowOverdraftParamName, this.allowOverdraft)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftParamName);
|
||||
actualChanges.put(allowOverdraftParamName, newValue);
|
||||
this.allowOverdraft = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(overdraftLimitParamName,
|
||||
this.overdraftLimit)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(overdraftLimitParamName);
|
||||
actualChanges.put(overdraftLimitParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.overdraftLimit = newValue;
|
||||
}
|
||||
if(!this.allowOverdraft){
|
||||
this.overdraftLimit = null;
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
//validateWithdrawalFeeDetails();
|
||||
//validateAnnualFeeDetails();
|
||||
@@ -517,4 +547,24 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal overdraftLimit() {
|
||||
return this.overdraftLimit;
|
||||
}
|
||||
|
||||
|
||||
public boolean isWithdrawalFeeApplicableForTransfer() {
|
||||
return this.withdrawalFeeApplicableForTransfer;
|
||||
}
|
||||
|
||||
|
||||
public boolean isAllowOverdraft() {
|
||||
return this.allowOverdraft;
|
||||
}
|
||||
|
||||
|
||||
public Set<Charge> charges() {
|
||||
return this.charges;
|
||||
}
|
||||
}
|
||||
+13
-1
@@ -22,6 +22,9 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamN
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
@@ -112,10 +115,19 @@ public class SavingsProductAssembler {
|
||||
|
||||
// Savings product charges
|
||||
final Set<Charge> charges = assembleListOfSavingsProductCharges(command, currencyCode);
|
||||
|
||||
boolean allowOverdraft = false;
|
||||
if (command.parameterExists(allowOverdraftParamName)) {
|
||||
allowOverdraft = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftParamName);
|
||||
}
|
||||
|
||||
final BigDecimal overdraftLimit = command
|
||||
.bigDecimalValueOfParameterNamedDefaultToNullIfZero(overdraftLimitParamName);
|
||||
|
||||
return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
||||
allowOverdraft,overdraftLimit);
|
||||
}
|
||||
|
||||
public Set<Charge> assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) {
|
||||
|
||||
+13
-3
@@ -223,6 +223,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
// sqlBuilder.append("sa.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
// sqlBuilder.append("sa.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sa.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("sa.allow_overdraft as allowOverdraft, ");
|
||||
sqlBuilder.append("sa.overdraft_limit as overdraftLimit, ");
|
||||
// sqlBuilder.append("sa.annual_fee_amount as annualFeeAmount,");
|
||||
// sqlBuilder.append("sa.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
// sqlBuilder.append("sa.annual_fee_on_day as annualFeeOnDay, ");
|
||||
@@ -358,6 +360,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
}*/
|
||||
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
|
||||
final BigDecimal overdraftLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "overdraftLimit");
|
||||
|
||||
/*final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
@@ -388,7 +393,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
return SavingsAccountData.instance(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,7 +736,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
// sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
// sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("sp.allow_overdraft as allowOverdraft, ");
|
||||
sqlBuilder.append("sp.overdraft_limit as overdraftLimit ");
|
||||
// sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
// sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
// sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
|
||||
@@ -795,6 +802,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
}
|
||||
*/
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
|
||||
final BigDecimal overdraftLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "overdraftLimit");
|
||||
|
||||
//final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
@@ -830,7 +840,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
return SavingsAccountData.instance(null, null, null, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.savings.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountDataDTO;
|
||||
|
||||
public interface SavingsApplicationProcessWritePlatformService {
|
||||
|
||||
@@ -23,4 +24,6 @@ public interface SavingsApplicationProcessWritePlatformService {
|
||||
CommandProcessingResult rejectApplication(Long savingsId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult applicantWithdrawsFromApplication(Long savingsId, JsonCommand command);
|
||||
|
||||
Long createActiveApplication(SavingsAccountDataDTO savingsAccountDataDTO);
|
||||
}
|
||||
+21
@@ -8,12 +8,14 @@ package org.mifosplatform.portfolio.savings.service;
|
||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
@@ -38,6 +40,7 @@ import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
|
||||
import org.mifosplatform.portfolio.note.domain.Note;
|
||||
import org.mifosplatform.portfolio.note.domain.NoteRepository;
|
||||
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountDataDTO;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountDataValidator;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
@@ -169,6 +172,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
checkClientOrGroupActive(account);
|
||||
account.modifyApplication(command, changes);
|
||||
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant());
|
||||
account.validateAccountValuesWithProduct();
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
|
||||
@@ -427,4 +431,21 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createActiveApplication(final SavingsAccountDataDTO savingsAccountDataDTO) {
|
||||
|
||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccountDataDTO.getClient(),savingsAccountDataDTO.getGroup(),
|
||||
savingsAccountDataDTO.getSavingsProduct(),savingsAccountDataDTO.getApplicationDate(),savingsAccountDataDTO.getAppliedBy());
|
||||
account.approveAndActivateApplication(savingsAccountDataDTO.getApplicationDate().toDate(), savingsAccountDataDTO.getAppliedBy(), savingsAccountDataDTO.getFmt());
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
if (account.isAccountNumberRequiresAutoGeneration()) {
|
||||
final AccountNumberGenerator accountNoGenerator = this.accountIdentifierGeneratorFactory
|
||||
.determineSavingsAccountNoGenerator(account.getId());
|
||||
account.updateAccountNo(accountNoGenerator.generate());
|
||||
this.savingAccountRepository.save(account);
|
||||
}
|
||||
return account.getId();
|
||||
}
|
||||
}
|
||||
+8
@@ -109,6 +109,14 @@ public class SavingsEnumerations {
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WAIVE_CHARGES.getValue().longValue(),
|
||||
SavingsAccountTransactionType.WAIVE_CHARGES.getCode(), "Waive Charge");
|
||||
break;
|
||||
case WRITTEN_OFF:
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WRITTEN_OFF.getValue().longValue(),
|
||||
SavingsAccountTransactionType.WRITTEN_OFF.getCode(), "writtenoff");
|
||||
break;
|
||||
case OVERDRAFT_INTEREST:
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue().longValue(),
|
||||
SavingsAccountTransactionType.OVERDRAFT_INTEREST.getCode(), "Overdraft Interest");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ public interface SavingsProductReadPlatformService {
|
||||
Collection<SavingsProductData> retrieveAll();
|
||||
|
||||
Collection<SavingsProductData> retrieveAllForLookup();
|
||||
|
||||
Collection<SavingsProductData> retrieveAllForLookupByType(boolean isOverdraftType);
|
||||
|
||||
SavingsProductData retrieveOne(Long productId);
|
||||
|
||||
|
||||
+13
-2
@@ -88,6 +88,8 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
// sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
// sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("sp.allow_overdraft as allowOverdraft, ");
|
||||
sqlBuilder.append("sp.overdraft_limit as overdraftLimit, ");
|
||||
// sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
// sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
// sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay, ");
|
||||
@@ -158,7 +160,8 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
}
|
||||
*/
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
|
||||
final BigDecimal overdraftLimit = rs.getBigDecimal("overdraftLimit");
|
||||
/* final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
MonthDay annualFeeOnMonthDay = null;
|
||||
@@ -170,7 +173,7 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
*/
|
||||
return SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingRuleType);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, accountingRuleType,allowOverdraft,overdraftLimit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,4 +192,12 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
return SavingsProductData.lookup(id, name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SavingsProductData> retrieveAllForLookupByType(boolean isOverdraftType) {
|
||||
final String sql = "select " + this.savingsProductLookupsRowMapper.schema() + " where sp.allow_overdraft=?";
|
||||
|
||||
return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper,isOverdraftType);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user