Shares And Dividends Implementation
This commit is contained in:
+60
-4
@@ -234,10 +234,10 @@ public class AccountingConstants {
|
||||
}
|
||||
|
||||
public static enum FINANCIAL_ACTIVITY {
|
||||
ASSET_TRANSFER(100, "assetTransfer", GLAccountType.ASSET), LIABILITY_TRANSFER(200, "liabilityTransfer", GLAccountType.LIABILITY),
|
||||
CASH_AT_MAINVAULT (101, "cashAtMainVault", GLAccountType.ASSET),
|
||||
CASH_AT_TELLER (102, "cashAtTeller", GLAccountType.ASSET),OPENING_BALANCES_TRANSFER_CONTRA (300,"openingBalancesTransferContra",GLAccountType.EQUITY),
|
||||
ASSET_FUND_SOURCE(103, "fundSource", GLAccountType.ASSET);
|
||||
ASSET_TRANSFER(100, "assetTransfer", GLAccountType.ASSET), LIABILITY_TRANSFER(200, "liabilityTransfer", GLAccountType.LIABILITY), CASH_AT_MAINVAULT(
|
||||
101, "cashAtMainVault", GLAccountType.ASSET), CASH_AT_TELLER(102, "cashAtTeller", GLAccountType.ASSET), OPENING_BALANCES_TRANSFER_CONTRA(
|
||||
300, "openingBalancesTransferContra", GLAccountType.EQUITY), ASSET_FUND_SOURCE(103, "fundSource", GLAccountType.ASSET), PAYABLE_DIVIDENDS(
|
||||
201, "payableDividends", GLAccountType.LIABILITY);
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -305,6 +305,62 @@ public class AccountingConstants {
|
||||
}
|
||||
}
|
||||
|
||||
/*** Accounting placeholders for cash based accounting for Share products ***/
|
||||
public static enum CASH_ACCOUNTS_FOR_SHARES {
|
||||
SHARES_REFERENCE(1), SHARES_SUSPENSE(2), INCOME_FROM_FEES(3), SHARES_EQUITY(4);
|
||||
|
||||
private final Integer value;
|
||||
|
||||
private CASH_ACCOUNTS_FOR_SHARES(final Integer value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
private static final Map<Integer, CASH_ACCOUNTS_FOR_SHARES> intToEnumMap = new HashMap<>();
|
||||
static {
|
||||
for (final CASH_ACCOUNTS_FOR_SHARES type : CASH_ACCOUNTS_FOR_SHARES.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static CASH_ACCOUNTS_FOR_SHARES fromInt(final int i) {
|
||||
final CASH_ACCOUNTS_FOR_SHARES type = intToEnumMap.get(Integer.valueOf(i));
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Enum of all accounting related input parameter names used while
|
||||
* creating/updating a savings product
|
||||
***/
|
||||
public static enum SHARES_PRODUCT_ACCOUNTING_PARAMS {
|
||||
SHARES_REFERENCE("shareReferenceId"), SHARES_SUSPENSE("shareSuspenseId"), INCOME_FROM_FEES("incomeFromFeeAccountId"), SHARES_EQUITY(
|
||||
"shareEquityId");
|
||||
|
||||
private final String value;
|
||||
|
||||
private SHARES_PRODUCT_ACCOUNTING_PARAMS(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String ASSESTS_TAG_OPTION_CODE_NAME = "AssetAccountTags";
|
||||
public static final String LIABILITIES_TAG_OPTION_CODE_NAME = "LiabilityAccountTags";
|
||||
public static final String EQUITY_TAG_OPTION_CODE_NAME = "EquityAccountTags";
|
||||
|
||||
+2
@@ -41,5 +41,7 @@ public interface AccountingDropdownReadPlatformService {
|
||||
public Map<String, List<GLAccountData>> retrieveAccountMappingOptionsForCharges();
|
||||
|
||||
public Map<String, List<GLAccountData>> retrieveAccountMappingOptions();
|
||||
|
||||
public Map<String, List<GLAccountData>> retrieveAccountMappingOptionsForShareProducts();
|
||||
|
||||
}
|
||||
+11
@@ -147,4 +147,15 @@ public class AccountingDropdownReadPlatformServiceImpl implements AccountingDrop
|
||||
return accountOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<GLAccountData>> retrieveAccountMappingOptionsForShareProducts() {
|
||||
boolean includeAssetAccounts = true;
|
||||
boolean includeIncomeAccounts = true;
|
||||
boolean includeExpenseAccounts = false;
|
||||
boolean includeLiabilityAccounts = true;
|
||||
boolean includeEquityAccounts = true;
|
||||
return retrieveAccountMappingOptions(includeAssetAccounts, includeIncomeAccounts, includeExpenseAccounts, includeLiabilityAccounts,
|
||||
includeEquityAccounts);
|
||||
}
|
||||
|
||||
}
|
||||
+4
-2
@@ -68,7 +68,8 @@ public final class FinancialActivityAccountDataValidator {
|
||||
baseDataValidator.reset().parameter(paramNameForFinancialActivity).value(financialActivityId).notNull().isOneOfTheseValues(
|
||||
FINANCIAL_ACTIVITY.ASSET_TRANSFER.getValue(), FINANCIAL_ACTIVITY.LIABILITY_TRANSFER.getValue(),
|
||||
FINANCIAL_ACTIVITY.CASH_AT_MAINVAULT.getValue(), FINANCIAL_ACTIVITY.CASH_AT_TELLER.getValue(),
|
||||
FINANCIAL_ACTIVITY.OPENING_BALANCES_TRANSFER_CONTRA.getValue(), FINANCIAL_ACTIVITY.ASSET_FUND_SOURCE.getValue());
|
||||
FINANCIAL_ACTIVITY.OPENING_BALANCES_TRANSFER_CONTRA.getValue(), FINANCIAL_ACTIVITY.ASSET_FUND_SOURCE.getValue(),
|
||||
FINANCIAL_ACTIVITY.PAYABLE_DIVIDENDS.getValue());
|
||||
|
||||
final Long glAccountId = this.fromApiJsonHelper.extractLongNamed(paramNameForGLAccount, element);
|
||||
baseDataValidator.reset().parameter(paramNameForGLAccount).value(glAccountId).notNull().integerGreaterThanZero();
|
||||
@@ -94,7 +95,8 @@ public final class FinancialActivityAccountDataValidator {
|
||||
element);
|
||||
baseDataValidator.reset().parameter(paramNameForFinancialActivity).value(financialActivityId).ignoreIfNull().isOneOfTheseValues(
|
||||
FINANCIAL_ACTIVITY.ASSET_TRANSFER.getValue(), FINANCIAL_ACTIVITY.LIABILITY_TRANSFER.getValue(),
|
||||
FINANCIAL_ACTIVITY.OPENING_BALANCES_TRANSFER_CONTRA.getValue(), FINANCIAL_ACTIVITY.ASSET_FUND_SOURCE.getValue());
|
||||
FINANCIAL_ACTIVITY.OPENING_BALANCES_TRANSFER_CONTRA.getValue(), FINANCIAL_ACTIVITY.ASSET_FUND_SOURCE.getValue(),
|
||||
FINANCIAL_ACTIVITY.PAYABLE_DIVIDENDS.getValue());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(paramNameForGLAccount, element)) {
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.accounting.journalentry.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SharesDTO {
|
||||
|
||||
private Long shareAccountId;
|
||||
private Long shareProductId;
|
||||
private Long officeId;
|
||||
private String currencyCode;
|
||||
private boolean cashBasedAccountingEnabled;
|
||||
private boolean accrualBasedAccountingEnabled;
|
||||
private List<SharesTransactionDTO> newTransactions;
|
||||
|
||||
public SharesDTO(final Long shareAccountId, final Long shareProductId, final Long officeId, final String currencyCode,
|
||||
final boolean cashBasedAccountingEnabled, final boolean accrualBasedAccountingEnabled,
|
||||
final List<SharesTransactionDTO> newTransactions) {
|
||||
this.shareAccountId = shareAccountId;
|
||||
this.shareProductId = shareProductId;
|
||||
this.officeId = officeId;
|
||||
this.cashBasedAccountingEnabled = cashBasedAccountingEnabled;
|
||||
this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled;
|
||||
this.newTransactions = newTransactions;
|
||||
this.currencyCode = currencyCode;
|
||||
}
|
||||
|
||||
public Long getOfficeId() {
|
||||
return this.officeId;
|
||||
}
|
||||
|
||||
public void setOfficeId(final Long officeId) {
|
||||
this.officeId = officeId;
|
||||
}
|
||||
|
||||
public boolean isCashBasedAccountingEnabled() {
|
||||
return this.cashBasedAccountingEnabled;
|
||||
}
|
||||
|
||||
public void setCashBasedAccountingEnabled(final boolean cashBasedAccountingEnabled) {
|
||||
this.cashBasedAccountingEnabled = cashBasedAccountingEnabled;
|
||||
}
|
||||
|
||||
public boolean isAccrualBasedAccountingEnabled() {
|
||||
return this.accrualBasedAccountingEnabled;
|
||||
}
|
||||
|
||||
public void setAccrualBasedAccountingEnabled(final boolean accrualBasedAccountingEnabled) {
|
||||
this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return this.currencyCode;
|
||||
}
|
||||
|
||||
public void setCurrencyCode(final String currencyCode) {
|
||||
this.currencyCode = currencyCode;
|
||||
}
|
||||
|
||||
public Long getShareAccountId() {
|
||||
return this.shareAccountId;
|
||||
}
|
||||
|
||||
public void setShareAccountId(Long shareAccountId) {
|
||||
this.shareAccountId = shareAccountId;
|
||||
}
|
||||
|
||||
public Long getShareProductId() {
|
||||
return this.shareProductId;
|
||||
}
|
||||
|
||||
public void setShareProductId(Long shareProductId) {
|
||||
this.shareProductId = shareProductId;
|
||||
}
|
||||
|
||||
public List<SharesTransactionDTO> getNewTransactions() {
|
||||
return this.newTransactions;
|
||||
}
|
||||
|
||||
public void setNewTransactions(List<SharesTransactionDTO> newTransactions) {
|
||||
this.newTransactions = newTransactions;
|
||||
}
|
||||
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.accounting.journalentry.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountTransactionEnumData;
|
||||
|
||||
public class SharesTransactionDTO {
|
||||
|
||||
private final Long officeId;
|
||||
private final String transactionId;
|
||||
private final Date transactionDate;
|
||||
private final Long paymentTypeId;
|
||||
private final ShareAccountTransactionEnumData transactionType;
|
||||
private final ShareAccountTransactionEnumData transactionStatus;
|
||||
|
||||
private final BigDecimal amount;
|
||||
|
||||
/*** Breakup of amounts **/
|
||||
private final BigDecimal chargeAmount;
|
||||
|
||||
/** Breakdowns of fees and penalties this Transaction pays **/
|
||||
private final List<ChargePaymentDTO> feePayments;
|
||||
|
||||
public SharesTransactionDTO(final Long officeId, final Long paymentTypeId, final String transactionId, final Date transactionDate,
|
||||
final ShareAccountTransactionEnumData transactionType, ShareAccountTransactionEnumData transactionStatus,
|
||||
final BigDecimal amount, final BigDecimal chargeAmount, final List<ChargePaymentDTO> feePayments) {
|
||||
this.paymentTypeId = paymentTypeId;
|
||||
this.transactionId = transactionId;
|
||||
this.transactionDate = transactionDate;
|
||||
this.amount = amount;
|
||||
this.chargeAmount = chargeAmount;
|
||||
this.transactionType = transactionType;
|
||||
this.transactionStatus = transactionStatus;
|
||||
this.feePayments = feePayments;
|
||||
this.officeId = officeId;
|
||||
}
|
||||
|
||||
public Long getOfficeId() {
|
||||
return this.officeId;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return this.transactionId;
|
||||
}
|
||||
|
||||
public Date getTransactionDate() {
|
||||
return this.transactionDate;
|
||||
}
|
||||
|
||||
public Long getPaymentTypeId() {
|
||||
return this.paymentTypeId;
|
||||
}
|
||||
|
||||
public ShareAccountTransactionEnumData getTransactionType() {
|
||||
return this.transactionType;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public List<ChargePaymentDTO> getFeePayments() {
|
||||
return this.feePayments;
|
||||
}
|
||||
|
||||
public ShareAccountTransactionEnumData getTransactionStatus() {
|
||||
return this.transactionStatus;
|
||||
}
|
||||
|
||||
public BigDecimal getChargeAmount() {
|
||||
return this.chargeAmount;
|
||||
}
|
||||
|
||||
}
|
||||
+15
-6
@@ -78,6 +78,9 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@JoinColumn(name = "client_transaction_id", nullable = false)
|
||||
private ClientTransaction clientTransaction;
|
||||
|
||||
@Column(name = "share_transaction_id", nullable = true)
|
||||
private Long shareTransactionId;
|
||||
|
||||
@Column(name = "reversed", nullable = false)
|
||||
private boolean reversed = false;
|
||||
|
||||
@@ -110,10 +113,10 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
|
||||
final String currencyCode, final String transactionId, final boolean manualEntry, final Date transactionDate,
|
||||
final JournalEntryType journalEntryType, final BigDecimal amount, final String description, final Integer entityType,
|
||||
final Long entityId, final String referenceNumber, final LoanTransaction loanTransaction,
|
||||
final SavingsAccountTransaction savingsTransaction, final ClientTransaction clientTransaction) {
|
||||
final SavingsAccountTransaction savingsTransaction, final ClientTransaction clientTransaction, Long shareTransactionId) {
|
||||
return new JournalEntry(office, paymentDetail, glAccount, currencyCode, transactionId, manualEntry, transactionDate,
|
||||
journalEntryType.getValue(), amount, description, entityType, entityId, referenceNumber, loanTransaction,
|
||||
savingsTransaction, clientTransaction);
|
||||
savingsTransaction, clientTransaction, shareTransactionId);
|
||||
}
|
||||
|
||||
protected JournalEntry() {
|
||||
@@ -124,7 +127,7 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
|
||||
final String transactionId, final boolean manualEntry, final Date transactionDate, final Integer type, final BigDecimal amount,
|
||||
final String description, final Integer entityType, final Long entityId, final String referenceNumber,
|
||||
final LoanTransaction loanTransaction, final SavingsAccountTransaction savingsTransaction,
|
||||
final ClientTransaction clientTransaction) {
|
||||
final ClientTransaction clientTransaction, final Long shareTransactionId) {
|
||||
this.office = office;
|
||||
this.glAccount = glAccount;
|
||||
this.reversalJournalEntry = null;
|
||||
@@ -143,6 +146,7 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.savingsTransaction = savingsTransaction;
|
||||
this.clientTransaction = clientTransaction;
|
||||
this.paymentDetail = paymentDetail;
|
||||
this.shareTransactionId = shareTransactionId;
|
||||
}
|
||||
|
||||
public boolean isDebitEntry() {
|
||||
@@ -206,11 +210,16 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
|
||||
}
|
||||
|
||||
public Long getEntityId() {
|
||||
return this.entityId ;
|
||||
return this.entityId;
|
||||
}
|
||||
|
||||
|
||||
public Integer getEntityType() {
|
||||
return this.entityType ;
|
||||
return this.entityType;
|
||||
}
|
||||
|
||||
|
||||
public Long getShareTransactionId() {
|
||||
return this.shareTransactionId;
|
||||
}
|
||||
|
||||
}
|
||||
+4
-7
@@ -16,15 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.service;
|
||||
package org.apache.fineract.accounting.journalentry.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.accounting.journalentry.data.SharesDTO;
|
||||
|
||||
public interface AccountingProcessorForShares {
|
||||
|
||||
public interface ShareAccountWritePlatformService {
|
||||
void createJournalEntriesForShares(SharesDTO sharesDTO);
|
||||
|
||||
public CommandProcessingResult createShareAccount(JsonCommand jsonCommand) ;
|
||||
|
||||
public CommandProcessingResult updateShareAccount(Long accountId, JsonCommand jsonCommand) ;
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.accounting.journalentry.service;
|
||||
|
||||
import org.apache.fineract.accounting.journalentry.data.SharesDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AccountingProcessorForSharesFactory {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
public AccountingProcessorForSharesFactory(final ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public AccountingProcessorForShares determineProcessor(final SharesDTO sharesDTO) {
|
||||
|
||||
AccountingProcessorForShares accountingProcessorForShares = null;
|
||||
|
||||
if (sharesDTO.isCashBasedAccountingEnabled()) {
|
||||
accountingProcessorForShares = this.applicationContext.getBean("cashBasedAccountingProcessorForShares",
|
||||
AccountingProcessorForShares.class);
|
||||
}
|
||||
|
||||
return accountingProcessorForShares;
|
||||
}
|
||||
|
||||
}
|
||||
+211
-9
@@ -31,6 +31,7 @@ import org.apache.fineract.accounting.closure.domain.GLClosureRepository;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SAVINGS;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SHARES;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.FINANCIAL_ACTIVITY;
|
||||
import org.apache.fineract.accounting.financialactivityaccount.domain.FinancialActivityAccount;
|
||||
import org.apache.fineract.accounting.financialactivityaccount.domain.FinancialActivityAccountRepositoryWrapper;
|
||||
@@ -44,6 +45,8 @@ import org.apache.fineract.accounting.journalentry.data.LoanTransactionDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SavingsDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SavingsTransactionDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.TaxPaymentDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SharesDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SharesTransactionDTO;
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntry;
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntryRepository;
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
|
||||
@@ -69,6 +72,7 @@ import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransactionRepository;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountTransactionEnumData;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -80,6 +84,7 @@ public class AccountingProcessorHelper {
|
||||
public static final String SAVINGS_TRANSACTION_IDENTIFIER = "S";
|
||||
public static final String CLIENT_TRANSACTION_IDENTIFIER = "C";
|
||||
public static final String PROVISIONING_TRANSACTION_IDENTIFIER = "P";
|
||||
public static final String SHARE_TRANSACTION_IDENTIFIER = "SH";
|
||||
private final JournalEntryRepository glJournalEntryRepository;
|
||||
private final ProductToGLAccountMappingRepository accountMappingRepository;
|
||||
private final FinancialActivityAccountRepositoryWrapper financialActivityAccountRepository;
|
||||
@@ -244,6 +249,51 @@ public class AccountingProcessorHelper {
|
||||
accrualBasedAccountingEnabled, newSavingsTransactions);
|
||||
}
|
||||
|
||||
public SharesDTO populateSharesDtoFromMap(final Map<String, Object> accountingBridgeData, final boolean cashBasedAccountingEnabled,
|
||||
final boolean accrualBasedAccountingEnabled) {
|
||||
final Long shareAccountId = (Long) accountingBridgeData.get("shareAccountId");
|
||||
final Long shareProductId = (Long) accountingBridgeData.get("shareProductId");
|
||||
final Long officeId = (Long) accountingBridgeData.get("officeId");
|
||||
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
|
||||
final List<SharesTransactionDTO> newTransactions = new ArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Map<String, Object>> newTransactionsMap = (List<Map<String, Object>>) accountingBridgeData.get("newTransactions");
|
||||
|
||||
for (final Map<String, Object> map : newTransactionsMap) {
|
||||
final Long transactionOfficeId = (Long) map.get("officeId");
|
||||
final String transactionId = ((Long) map.get("id")).toString();
|
||||
final Date transactionDate = ((LocalDate) map.get("date")).toDate();
|
||||
final ShareAccountTransactionEnumData transactionType = (ShareAccountTransactionEnumData) map.get("type");
|
||||
final ShareAccountTransactionEnumData transactionStatus = (ShareAccountTransactionEnumData) map.get("status");
|
||||
final BigDecimal amount = (BigDecimal) map.get("amount");
|
||||
final BigDecimal chargeAmount = (BigDecimal) map.get("chargeAmount");
|
||||
final Long paymentTypeId = (Long) map.get("paymentTypeId");
|
||||
|
||||
final List<ChargePaymentDTO> feePayments = new ArrayList<>();
|
||||
// extract charge payment details (if exists)
|
||||
if (map.containsKey("chargesPaid")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Map<String, Object>> chargesPaidData = (List<Map<String, Object>>) map.get("chargesPaid");
|
||||
for (final Map<String, Object> chargePaid : chargesPaidData) {
|
||||
final Long chargeId = (Long) chargePaid.get("chargeId");
|
||||
final Long loanChargeId = (Long) chargePaid.get("sharesChargeId");
|
||||
final BigDecimal chargeAmountPaid = (BigDecimal) chargePaid.get("amount");
|
||||
final ChargePaymentDTO chargePaymentDTO = new ChargePaymentDTO(chargeId, loanChargeId, chargeAmountPaid);
|
||||
feePayments.add(chargePaymentDTO);
|
||||
}
|
||||
}
|
||||
final SharesTransactionDTO transaction = new SharesTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
|
||||
transactionDate, transactionType, transactionStatus, amount, chargeAmount, feePayments);
|
||||
|
||||
newTransactions.add(transaction);
|
||||
|
||||
}
|
||||
|
||||
return new SharesDTO(shareAccountId, shareProductId, officeId, currencyData.code(), cashBasedAccountingEnabled,
|
||||
accrualBasedAccountingEnabled, newTransactions);
|
||||
}
|
||||
|
||||
public ClientTransactionDTO populateClientTransactionDtoFromMap(final Map<String, Object> accountingBridgeData) {
|
||||
|
||||
final Long transactionOfficeId = (Long) accountingBridgeData.get("officeId");
|
||||
@@ -745,6 +795,7 @@ public class AccountingProcessorHelper {
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Long shareTransactionId = null;
|
||||
|
||||
clientTransaction = this.clientTransactionRepository.findOneWithNotFoundDetection(clientId, transactionId);
|
||||
|
||||
@@ -752,7 +803,7 @@ public class AccountingProcessorHelper {
|
||||
modifiedTransactionId = CLIENT_TRANSACTION_IDENTIFIER + transactionId;
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.CLIENT.getValue(), clientId,
|
||||
null, loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
@@ -762,6 +813,7 @@ public class AccountingProcessorHelper {
|
||||
LoanTransaction loanTransaction = null;
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
final Long shareTransactionId = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
String modifiedTransactionId = transactionId;
|
||||
if (StringUtils.isNumeric(transactionId)) {
|
||||
@@ -771,7 +823,7 @@ public class AccountingProcessorHelper {
|
||||
}
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId,
|
||||
null, loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
@@ -782,6 +834,7 @@ public class AccountingProcessorHelper {
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Long shareTransactionId = null;
|
||||
String modifiedTransactionId = transactionId;
|
||||
if (StringUtils.isNumeric(transactionId)) {
|
||||
long id = Long.parseLong(transactionId);
|
||||
@@ -790,7 +843,7 @@ public class AccountingProcessorHelper {
|
||||
}
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null,
|
||||
loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
@@ -800,12 +853,12 @@ public class AccountingProcessorHelper {
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
PaymentDetail paymentDetail = null;
|
||||
final Long shareTransactionId = null;
|
||||
final boolean manualEntry = false;
|
||||
String modifiedTransactionId = PROVISIONING_TRANSACTION_IDENTIFIER + provisioningentryId;
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.PROVISIONING.getValue(),
|
||||
provisioningentryId, null, loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
|
||||
provisioningentryId, null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
@@ -815,11 +868,12 @@ public class AccountingProcessorHelper {
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
PaymentDetail paymentDetail = null;
|
||||
final Long shareTransactionId = null;
|
||||
final boolean manualEntry = false;
|
||||
String modifiedTransactionId = PROVISIONING_TRANSACTION_IDENTIFIER + provisioningentryId;
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.PROVISIONING.getValue(),
|
||||
provisioningentryId, null, loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
provisioningentryId, null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
@@ -830,6 +884,7 @@ public class AccountingProcessorHelper {
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Long shareTransactionId = null;
|
||||
String modifiedTransactionId = transactionId;
|
||||
if (StringUtils.isNumeric(transactionId)) {
|
||||
long id = Long.parseLong(transactionId);
|
||||
@@ -838,7 +893,7 @@ public class AccountingProcessorHelper {
|
||||
}
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null,
|
||||
loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
@@ -849,6 +904,7 @@ public class AccountingProcessorHelper {
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Long shareTransactionId = null;
|
||||
String modifiedTransactionId = transactionId;
|
||||
if (StringUtils.isNumeric(transactionId)) {
|
||||
long id = Long.parseLong(transactionId);
|
||||
@@ -857,7 +913,7 @@ public class AccountingProcessorHelper {
|
||||
}
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId,
|
||||
null, loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
@@ -868,6 +924,7 @@ public class AccountingProcessorHelper {
|
||||
LoanTransaction loanTransaction = null;
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final Long shareTransactionId = null;
|
||||
|
||||
clientTransaction = this.clientTransactionRepository.findOneWithNotFoundDetection(clientId, transactionId);
|
||||
String modifiedTransactionId = transactionId.toString();
|
||||
@@ -875,10 +932,113 @@ public class AccountingProcessorHelper {
|
||||
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.CLIENT.getValue(), clientId, null,
|
||||
loanTransaction, savingsAccountTransaction, clientTransaction);
|
||||
loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(journalEntry);
|
||||
}
|
||||
|
||||
public void createJournalEntriesForShares(final Office office, final String currencyCode, final int accountTypeToDebitId,
|
||||
final int accountTypeToCreditId, final Long shareProductId, final Long paymentTypeId, final Long shareAccountId,
|
||||
final String transactionId, final Date transactionDate, final BigDecimal amount) {
|
||||
createDebitJournalEntryForShares(office, currencyCode, accountTypeToDebitId, shareProductId, paymentTypeId, shareAccountId,
|
||||
transactionId, transactionDate, amount);
|
||||
createCreditJournalEntryForShares(office, currencyCode, accountTypeToCreditId, shareProductId, paymentTypeId, shareAccountId,
|
||||
transactionId, transactionDate, amount);
|
||||
}
|
||||
|
||||
public void createDebitJournalEntryForShares(final Office office, final String currencyCode, final int accountTypeToDebitId,
|
||||
final Long shareProductId, final Long paymentTypeId, final Long shareAccountId, final String transactionId,
|
||||
final Date transactionDate, final BigDecimal amount) {
|
||||
final GLAccount debitAccount = getLinkedGLAccountForShareProduct(shareProductId, accountTypeToDebitId, paymentTypeId);
|
||||
createDebitJournalEntryForShares(office, currencyCode, debitAccount, shareAccountId, transactionId, transactionDate, amount);
|
||||
}
|
||||
|
||||
public void createCreditJournalEntryForShares(final Office office, final String currencyCode, final int accountTypeToCreditId,
|
||||
final Long shareProductId, final Long paymentTypeId, final Long shareAccountId, final String transactionId,
|
||||
final Date transactionDate, final BigDecimal amount) {
|
||||
final GLAccount creditAccount = getLinkedGLAccountForShareProduct(shareProductId, accountTypeToCreditId, paymentTypeId);
|
||||
createCreditJournalEntryForShares(office, currencyCode, creditAccount, shareAccountId, transactionId, transactionDate, amount);
|
||||
}
|
||||
|
||||
public void createCashBasedJournalEntriesForSharesCharges(final Office office, final String currencyCode,
|
||||
final CASH_ACCOUNTS_FOR_SHARES accountTypeToBeDebited, final CASH_ACCOUNTS_FOR_SHARES accountTypeToBeCredited,
|
||||
final Long shareProductId, final Long paymentTypeId, final Long shareAccountId, final String transactionId,
|
||||
final Date transactionDate, final BigDecimal totalAmount, final List<ChargePaymentDTO> chargePaymentDTOs) {
|
||||
|
||||
createDebitJournalEntryForShares(office, currencyCode, accountTypeToBeDebited.getValue(), shareProductId, paymentTypeId,
|
||||
shareAccountId, transactionId, transactionDate, totalAmount);
|
||||
createCashBasedJournalEntryForSharesCharges(office, currencyCode, accountTypeToBeCredited, shareProductId, shareAccountId,
|
||||
transactionId, transactionDate, totalAmount, chargePaymentDTOs);
|
||||
}
|
||||
|
||||
public void createCashBasedJournalEntryForSharesCharges(final Office office, final String currencyCode,
|
||||
final CASH_ACCOUNTS_FOR_SHARES accountTypeToBeCredited, final Long shareProductId, final Long shareAccountId,
|
||||
final String transactionId, final Date transactionDate, final BigDecimal totalAmount,
|
||||
final List<ChargePaymentDTO> chargePaymentDTOs) {
|
||||
final Map<GLAccount, BigDecimal> creditDetailsMap = new LinkedHashMap<>();
|
||||
for (final ChargePaymentDTO chargePaymentDTO : chargePaymentDTOs) {
|
||||
final GLAccount chargeSpecificAccount = getLinkedGLAccountForShareCharges(shareProductId, accountTypeToBeCredited.getValue(),
|
||||
chargePaymentDTO.getChargeId());
|
||||
BigDecimal chargeSpecificAmount = chargePaymentDTO.getAmount();
|
||||
|
||||
// adjust net credit amount if the account is already present in the
|
||||
// map
|
||||
if (creditDetailsMap.containsKey(chargeSpecificAccount)) {
|
||||
final BigDecimal existingAmount = creditDetailsMap.get(chargeSpecificAccount);
|
||||
chargeSpecificAmount = chargeSpecificAmount.add(existingAmount);
|
||||
}
|
||||
creditDetailsMap.put(chargeSpecificAccount, chargeSpecificAmount);
|
||||
}
|
||||
|
||||
BigDecimal totalCreditedAmount = BigDecimal.ZERO;
|
||||
for (final Map.Entry<GLAccount, BigDecimal> entry : creditDetailsMap.entrySet()) {
|
||||
final GLAccount account = entry.getKey();
|
||||
final BigDecimal amount = entry.getValue();
|
||||
totalCreditedAmount = totalCreditedAmount.add(amount);
|
||||
createCreditJournalEntryForShares(office, currencyCode, account, shareAccountId, transactionId, transactionDate, amount);
|
||||
}
|
||||
if (totalAmount.compareTo(totalCreditedAmount) != 0) { throw new PlatformDataIntegrityException(
|
||||
"Recent Portfolio changes w.r.t Charges for shares have Broken the accounting code",
|
||||
"Recent Portfolio changes w.r.t Charges for shares have Broken the accounting code"); }
|
||||
}
|
||||
|
||||
private void createDebitJournalEntryForShares(final Office office, final String currencyCode, final GLAccount account,
|
||||
final Long shareAccountId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
|
||||
final boolean manualEntry = false;
|
||||
LoanTransaction loanTransaction = null;
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
Long shareTransactionId = null;
|
||||
String modifiedTransactionId = transactionId;
|
||||
if (StringUtils.isNumeric(transactionId)) {
|
||||
shareTransactionId = Long.parseLong(transactionId);
|
||||
modifiedTransactionId = SHARE_TRANSACTION_IDENTIFIER + transactionId;
|
||||
}
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.SHARES.getValue(), shareAccountId,
|
||||
null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.save(journalEntry);
|
||||
}
|
||||
|
||||
private void createCreditJournalEntryForShares(final Office office, final String currencyCode, final GLAccount account,
|
||||
final Long shareAccountId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
|
||||
final boolean manualEntry = false;
|
||||
LoanTransaction loanTransaction = null;
|
||||
SavingsAccountTransaction savingsAccountTransaction = null;
|
||||
ClientTransaction clientTransaction = null;
|
||||
Long shareTransactionId = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
String modifiedTransactionId = transactionId;
|
||||
if (StringUtils.isNumeric(transactionId)) {
|
||||
shareTransactionId = Long.parseLong(transactionId);
|
||||
modifiedTransactionId = SHARE_TRANSACTION_IDENTIFIER + transactionId;
|
||||
}
|
||||
final JournalEntry journalEntry = JournalEntry.createNew(office, paymentDetail, account, currencyCode, modifiedTransactionId,
|
||||
manualEntry, transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.SHARES.getValue(),
|
||||
shareAccountId, null, loanTransaction, savingsAccountTransaction, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.save(journalEntry);
|
||||
}
|
||||
|
||||
private GLAccount getLinkedGLAccountForLoanProduct(final Long loanProductId, final int accountMappingTypeId, final Long paymentTypeId) {
|
||||
GLAccount glAccount = null;
|
||||
if (isOrganizationAccount(accountMappingTypeId)) {
|
||||
@@ -984,6 +1144,48 @@ public class AccountingProcessorHelper {
|
||||
return glAccount;
|
||||
}
|
||||
|
||||
private GLAccount getLinkedGLAccountForShareProduct(final Long shareProductId, final int accountMappingTypeId, final Long paymentTypeId) {
|
||||
GLAccount glAccount = null;
|
||||
if (isOrganizationAccount(accountMappingTypeId)) {
|
||||
FinancialActivityAccount financialActivityAccount = this.financialActivityAccountRepository
|
||||
.findByFinancialActivityTypeWithNotFoundDetection(accountMappingTypeId);
|
||||
glAccount = financialActivityAccount.getGlAccount();
|
||||
} else {
|
||||
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(shareProductId,
|
||||
PortfolioProductType.SHARES.getValue(), accountMappingTypeId);
|
||||
|
||||
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue()) {
|
||||
final ProductToGLAccountMapping paymentChannelSpecificAccountMapping = this.accountMappingRepository
|
||||
.findByProductIdAndProductTypeAndFinancialAccountTypeAndPaymentTypeId(shareProductId,
|
||||
PortfolioProductType.SHARES.getValue(), accountMappingTypeId, paymentTypeId);
|
||||
if (paymentChannelSpecificAccountMapping != null) {
|
||||
accountMapping = paymentChannelSpecificAccountMapping;
|
||||
}
|
||||
}
|
||||
glAccount = accountMapping.getGlAccount();
|
||||
}
|
||||
return glAccount;
|
||||
}
|
||||
|
||||
private GLAccount getLinkedGLAccountForShareCharges(final Long shareProductId, final int accountMappingTypeId, final Long chargeId) {
|
||||
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(shareProductId,
|
||||
PortfolioProductType.SHARES.getValue(), accountMappingTypeId);
|
||||
/*****
|
||||
* Get more specific mappings for Charges and penalties (based on the
|
||||
* actual charge /penalty coupled with the loan product). Note the
|
||||
* income from fees and income from penalties placeholder ID would be
|
||||
* the same for both cash and accrual based accounts
|
||||
*****/
|
||||
|
||||
final ProductToGLAccountMapping chargeSpecificIncomeAccountMapping = this.accountMappingRepository
|
||||
.findByProductIdAndProductTypeAndFinancialAccountTypeAndChargeId(shareProductId, PortfolioProductType.SHARES.getValue(),
|
||||
accountMappingTypeId, chargeId);
|
||||
if (chargeSpecificIncomeAccountMapping != null) {
|
||||
accountMapping = chargeSpecificIncomeAccountMapping;
|
||||
}
|
||||
return accountMapping.getGlAccount();
|
||||
}
|
||||
|
||||
private boolean isOrganizationAccount(final int accountMappingTypeId) {
|
||||
boolean isOrganizationAccount = false;
|
||||
if (FINANCIAL_ACTIVITY.fromInt(accountMappingTypeId) != null) {
|
||||
|
||||
+6
@@ -124,6 +124,12 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle Deposits and reversals of Dividend pay outs **/
|
||||
else if (savingsTransactionDTO.getTransactionType().isDividendPayout()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
FINANCIAL_ACTIVITY.PAYABLE_DIVIDENDS.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(),
|
||||
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
}
|
||||
/** Handle withdrawals and reversals of withdrawals **/
|
||||
else if (savingsTransactionDTO.getTransactionType().isWithdrawal()) {
|
||||
if (savingsTransactionDTO.isAccountTransfer()) {
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.accounting.journalentry.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.fineract.accounting.closure.domain.GLClosure;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SHARES;
|
||||
import org.apache.fineract.accounting.journalentry.data.ChargePaymentDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SharesDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SharesTransactionDTO;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CashBasedAccountingProcessorForShares implements AccountingProcessorForShares {
|
||||
|
||||
private final AccountingProcessorHelper helper;
|
||||
|
||||
@Autowired
|
||||
public CashBasedAccountingProcessorForShares(final AccountingProcessorHelper helper) {
|
||||
this.helper = helper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createJournalEntriesForShares(SharesDTO sharesDTO) {
|
||||
final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(sharesDTO.getOfficeId());
|
||||
final Long shareAccountId = sharesDTO.getShareAccountId();
|
||||
final Long shareProductId = sharesDTO.getShareProductId();
|
||||
final String currencyCode = sharesDTO.getCurrencyCode();
|
||||
for (SharesTransactionDTO transactionDTO : sharesDTO.getNewTransactions()) {
|
||||
final Date transactionDate = transactionDTO.getTransactionDate();
|
||||
final String transactionId = transactionDTO.getTransactionId();
|
||||
final Office office = this.helper.getOfficeById(transactionDTO.getOfficeId());
|
||||
final Long paymentTypeId = transactionDTO.getPaymentTypeId();
|
||||
final BigDecimal amount = transactionDTO.getAmount();
|
||||
final BigDecimal chargeAmount = transactionDTO.getChargeAmount();
|
||||
final List<ChargePaymentDTO> feePayments = transactionDTO.getFeePayments();
|
||||
|
||||
this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
|
||||
|
||||
if (transactionDTO.getTransactionType().isPurchased()) {
|
||||
createJournalEntriesForPurchase(shareAccountId, shareProductId, currencyCode, transactionDTO, transactionDate,
|
||||
transactionId, office, paymentTypeId, amount, chargeAmount, feePayments);
|
||||
} else if (transactionDTO.getTransactionType().isRedeemed() && transactionDTO.getTransactionStatus().isApproved()) {
|
||||
createJournalEntriesForRedeem(shareAccountId, shareProductId, currencyCode, transactionDate, transactionId, office,
|
||||
paymentTypeId, amount, chargeAmount, feePayments);
|
||||
|
||||
} else if (transactionDTO.getTransactionType().isChargePayment()) {
|
||||
this.helper.createCashBasedJournalEntriesForSharesCharges(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE,
|
||||
CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES, shareProductId, paymentTypeId, shareAccountId, transactionId,
|
||||
transactionDate, amount, feePayments);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void createJournalEntriesForRedeem(final Long shareAccountId, final Long shareProductId, final String currencyCode,
|
||||
final Date transactionDate, final String transactionId, final Office office, final Long paymentTypeId, final BigDecimal amount,
|
||||
final BigDecimal chargeAmount, final List<ChargePaymentDTO> feePayments) {
|
||||
if (chargeAmount == null || chargeAmount.compareTo(BigDecimal.ZERO) != 1) {
|
||||
this.helper.createJournalEntriesForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId,
|
||||
transactionDate, amount);
|
||||
} else {
|
||||
this.helper.createDebitJournalEntryForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY.getValue(),
|
||||
shareProductId, paymentTypeId, shareAccountId, transactionId, transactionDate, amount.add(chargeAmount));
|
||||
this.helper.createCreditJournalEntryForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(),
|
||||
shareProductId, paymentTypeId, shareAccountId, transactionId, transactionDate, amount);
|
||||
this.helper.createCashBasedJournalEntryForSharesCharges(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES,
|
||||
shareProductId, shareAccountId, transactionId, transactionDate, chargeAmount, feePayments);
|
||||
}
|
||||
}
|
||||
|
||||
public void createJournalEntriesForPurchase(final Long shareAccountId, final Long shareProductId, final String currencyCode,
|
||||
SharesTransactionDTO transactionDTO, final Date transactionDate, final String transactionId, final Office office,
|
||||
final Long paymentTypeId, final BigDecimal amount, final BigDecimal chargeAmount, final List<ChargePaymentDTO> feePayments) {
|
||||
if (transactionDTO.getTransactionStatus().isApplied()) {
|
||||
if (chargeAmount == null || chargeAmount.compareTo(BigDecimal.ZERO) != 1) {
|
||||
this.helper.createJournalEntriesForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId,
|
||||
transactionDate, amount);
|
||||
} else {
|
||||
this.helper.createDebitJournalEntryForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(),
|
||||
shareProductId, paymentTypeId, shareAccountId, transactionId, transactionDate, amount);
|
||||
this.helper.createCreditJournalEntryForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(),
|
||||
shareProductId, paymentTypeId, shareAccountId, transactionId, transactionDate, amount.subtract(chargeAmount));
|
||||
this.helper.createCashBasedJournalEntryForSharesCharges(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES,
|
||||
shareProductId, shareAccountId, transactionId, transactionDate, chargeAmount, feePayments);
|
||||
}
|
||||
} else if (transactionDTO.getTransactionStatus().isApproved()) {
|
||||
BigDecimal amountForJE = amount;
|
||||
if (chargeAmount != null && chargeAmount.compareTo(BigDecimal.ZERO) == 1) {
|
||||
amountForJE = amount.subtract(chargeAmount);
|
||||
}
|
||||
this.helper.createJournalEntriesForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId,
|
||||
transactionDate, amountForJE);
|
||||
} else if (transactionDTO.getTransactionStatus().isRejected()) {
|
||||
BigDecimal amountForJE = amount;
|
||||
if (chargeAmount != null && chargeAmount.compareTo(BigDecimal.ZERO) == 1) {
|
||||
amountForJE = amount.subtract(chargeAmount);
|
||||
}
|
||||
this.helper.createJournalEntriesForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId,
|
||||
transactionDate, amountForJE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -42,4 +42,6 @@ public interface JournalEntryWritePlatformService {
|
||||
public String revertProvisioningJournalEntries(final Date reversalTransactionDate, final Long entityId, final Integer entityType) ;
|
||||
|
||||
public String createProvisioningJournalEntries(ProvisioningEntry entry) ;
|
||||
|
||||
void createJournalEntriesForShares(Map<String, Object> accountingBridgeData);
|
||||
}
|
||||
|
||||
+42
-17
@@ -45,6 +45,7 @@ import org.apache.fineract.accounting.journalentry.command.SingleDebitOrCreditEn
|
||||
import org.apache.fineract.accounting.journalentry.data.ClientTransactionDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.LoanDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SavingsDTO;
|
||||
import org.apache.fineract.accounting.journalentry.data.SharesDTO;
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntry;
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntryRepository;
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
|
||||
@@ -94,6 +95,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
private final OfficeRepository officeRepository;
|
||||
private final AccountingProcessorForLoanFactory accountingProcessorForLoanFactory;
|
||||
private final AccountingProcessorForSavingsFactory accountingProcessorForSavingsFactory;
|
||||
private final AccountingProcessorForSharesFactory accountingProcessorForSharesFactory;
|
||||
private final AccountingProcessorHelper helper;
|
||||
private final JournalEntryCommandFromApiJsonDeserializer fromApiJsonDeserializer;
|
||||
private final AccountingRuleRepository accountingRuleRepository;
|
||||
@@ -111,6 +113,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
final AccountingProcessorHelper accountingProcessorHelper, final AccountingRuleRepository accountingRuleRepository,
|
||||
final AccountingProcessorForLoanFactory accountingProcessorForLoanFactory,
|
||||
final AccountingProcessorForSavingsFactory accountingProcessorForSavingsFactory,
|
||||
final AccountingProcessorForSharesFactory accountingProcessorForSharesFactory,
|
||||
final GLAccountReadPlatformService glAccountReadPlatformService,
|
||||
final OrganisationCurrencyRepositoryWrapper organisationCurrencyRepository, final PlatformSecurityContext context,
|
||||
final PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
||||
@@ -123,6 +126,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
this.glAccountRepository = glAccountRepository;
|
||||
this.accountingProcessorForLoanFactory = accountingProcessorForLoanFactory;
|
||||
this.accountingProcessorForSavingsFactory = accountingProcessorForSavingsFactory;
|
||||
this.accountingProcessorForSharesFactory = accountingProcessorForSharesFactory;
|
||||
this.helper = accountingProcessorHelper;
|
||||
this.accountingRuleRepository = accountingRuleRepository;
|
||||
this.glAccountReadPlatformService = glAccountReadPlatformService;
|
||||
@@ -335,13 +339,13 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
journalEntry.getGlAccount(), journalEntry.getCurrencyCode(), reversalTransactionId, manualEntry,
|
||||
journalEntry.getTransactionDate(), JournalEntryType.CREDIT, journalEntry.getAmount(), reversalComment, null, null,
|
||||
journalEntry.getReferenceNumber(), journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(),
|
||||
journalEntry.getClientTransaction());
|
||||
journalEntry.getClientTransaction(), journalEntry.getShareTransactionId());
|
||||
} else {
|
||||
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getPaymentDetails(),
|
||||
journalEntry.getGlAccount(), journalEntry.getCurrencyCode(), reversalTransactionId, manualEntry,
|
||||
journalEntry.getTransactionDate(), JournalEntryType.DEBIT, journalEntry.getAmount(), reversalComment, null, null,
|
||||
journalEntry.getReferenceNumber(), journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(),
|
||||
journalEntry.getClientTransaction());
|
||||
journalEntry.getClientTransaction(), journalEntry.getShareTransactionId());
|
||||
}
|
||||
// save the reversal entry
|
||||
this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry);
|
||||
@@ -366,13 +370,15 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
journalEntry.getGlAccount(), journalEntry.getCurrencyCode(), journalEntry.getTransactionId(), Boolean.FALSE,
|
||||
reversalTransactionDate, JournalEntryType.CREDIT, journalEntry.getAmount(), reversalComment,
|
||||
journalEntry.getEntityType(), journalEntry.getEntityId(), journalEntry.getReferenceNumber(),
|
||||
journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(), journalEntry.getClientTransaction());
|
||||
journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(), journalEntry.getClientTransaction(),
|
||||
journalEntry.getShareTransactionId());
|
||||
} else {
|
||||
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getPaymentDetails(),
|
||||
journalEntry.getGlAccount(), journalEntry.getCurrencyCode(), journalEntry.getTransactionId(), Boolean.FALSE,
|
||||
reversalTransactionDate, JournalEntryType.DEBIT, journalEntry.getAmount(), reversalComment,
|
||||
journalEntry.getEntityType(), journalEntry.getEntityId(), journalEntry.getReferenceNumber(),
|
||||
journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(), journalEntry.getClientTransaction());
|
||||
journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(), journalEntry.getClientTransaction(),
|
||||
journalEntry.getShareTransactionId());
|
||||
}
|
||||
// save the reversal entry
|
||||
this.glJournalEntryRepository.save(reversalJournalEntry);
|
||||
@@ -428,26 +434,26 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
expenseMap.put(entry.getExpenseAccount(), amount);
|
||||
}
|
||||
}
|
||||
createJournalEnry(provisioningEntry.getCreatedDate(), provisioningEntry.getId(), key.office, key.currency, liabilityMap, expenseMap);
|
||||
createJournalEnry(provisioningEntry.getCreatedDate(), provisioningEntry.getId(), key.office, key.currency, liabilityMap,
|
||||
expenseMap);
|
||||
}
|
||||
return "P"+provisioningEntry.getId() ;
|
||||
return "P" + provisioningEntry.getId();
|
||||
}
|
||||
|
||||
private void createJournalEnry(Date transactionDate, Long entryId, Office office, String currencyCode, Map<GLAccount, BigDecimal> liabilityMap,
|
||||
Map<GLAccount, BigDecimal> expenseMap) {
|
||||
|
||||
private void createJournalEnry(Date transactionDate, Long entryId, Office office, String currencyCode,
|
||||
Map<GLAccount, BigDecimal> liabilityMap, Map<GLAccount, BigDecimal> expenseMap) {
|
||||
Set<GLAccount> liabilityAccounts = liabilityMap.keySet();
|
||||
for (GLAccount account : liabilityAccounts) {
|
||||
this.helper.createProvisioningCreditJournalEntry(transactionDate,entryId, office, currencyCode, account,
|
||||
this.helper.createProvisioningCreditJournalEntry(transactionDate, entryId, office, currencyCode, account,
|
||||
liabilityMap.get(account));
|
||||
}
|
||||
Set<GLAccount> expenseAccounts = expenseMap.keySet();
|
||||
for (GLAccount account : expenseAccounts) {
|
||||
this.helper.createProvisioningDebitJournalEntry(transactionDate,entryId, office, currencyCode, account,
|
||||
this.helper.createProvisioningDebitJournalEntry(transactionDate, entryId, office, currencyCode, account,
|
||||
expenseMap.get(account));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void validateCommentForReversal(final String reversalComment) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
|
||||
@@ -493,6 +499,23 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void createJournalEntriesForShares(final Map<String, Object> accountingBridgeData) {
|
||||
|
||||
final boolean cashBasedAccountingEnabled = (Boolean) accountingBridgeData.get("cashBasedAccountingEnabled");
|
||||
final boolean accrualBasedAccountingEnabled = (Boolean) accountingBridgeData.get("accrualBasedAccountingEnabled");
|
||||
|
||||
if (cashBasedAccountingEnabled) {
|
||||
final SharesDTO sharesDTO = this.helper.populateSharesDtoFromMap(accountingBridgeData, cashBasedAccountingEnabled,
|
||||
accrualBasedAccountingEnabled);
|
||||
final AccountingProcessorForShares accountingProcessorForShares = this.accountingProcessorForSharesFactory
|
||||
.determineProcessor(sharesDTO);
|
||||
accountingProcessorForShares.createJournalEntriesForShares(sharesDTO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void validateBusinessRulesForJournalEntries(final JournalEntryCommand command) {
|
||||
/** check if date of Journal entry is valid ***/
|
||||
final LocalDate entryLocalDate = command.getTransactionDate();
|
||||
@@ -539,9 +562,10 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
this.organisationCurrencyRepository.findOneWithNotFoundDetection(currencyCode);
|
||||
|
||||
final ClientTransaction clientTransaction = null;
|
||||
final Long shareTransactionId = null;
|
||||
final JournalEntry glJournalEntry = JournalEntry.createNew(office, paymentDetail, glAccount, currencyCode, transactionId,
|
||||
manualEntry, transactionDate, type, singleDebitOrCreditEntryCommand.getAmount(), comments, null, null, referenceNumber,
|
||||
null, null, clientTransaction);
|
||||
null, null, clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(glJournalEntry);
|
||||
}
|
||||
}
|
||||
@@ -648,14 +672,15 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
}
|
||||
|
||||
final ClientTransaction clientTransaction = null;
|
||||
final Long shareTransactionId = null;
|
||||
final JournalEntry glJournalEntry = JournalEntry.createNew(office, null, glAccount, currencyCode, transactionId, manualEntry,
|
||||
transactionDate, type, singleDebitOrCreditEntryCommand.getAmount(), comments, null, null, null, null, null,
|
||||
clientTransaction);
|
||||
clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(glJournalEntry);
|
||||
|
||||
final JournalEntry contraEntry = JournalEntry.createNew(office, null, contraAccount, currencyCode, transactionId, manualEntry,
|
||||
transactionDate, contraType, singleDebitOrCreditEntryCommand.getAmount(), comments, null, null, null, null, null,
|
||||
clientTransaction);
|
||||
clientTransaction, shareTransactionId);
|
||||
this.glJournalEntryRepository.saveAndFlush(contraEntry);
|
||||
}
|
||||
}
|
||||
@@ -682,7 +707,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
final ClientTransactionDTO clientTransactionDTO = this.helper.populateClientTransactionDtoFromMap(accountingBridgeData);
|
||||
accountingProcessorForClientTransactions.createJournalEntriesForClientTransaction(clientTransactionDTO);
|
||||
}
|
||||
|
||||
|
||||
private class OfficeCurrencyKey {
|
||||
|
||||
Office office;
|
||||
|
||||
+6
-1
@@ -22,7 +22,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum PortfolioProductType {
|
||||
LOAN(1, "productType.loan"), SAVING(2, "productType.saving"), CLIENT(2, "productType.client"), PROVISIONING(3, "productType.provisioning");
|
||||
LOAN(1, "productType.loan"), SAVING(2, "productType.saving"), CLIENT(2, "productType.client"), PROVISIONING(3,
|
||||
"productType.provisioning"), SHARES(4, "productType.shares");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -70,4 +71,8 @@ public enum PortfolioProductType {
|
||||
return this.value.equals(PortfolioProductType.CLIENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isShareProduct() {
|
||||
return this.value.equals(PortfolioProductType.SHARES.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+45
-2
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SHARES_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SAVINGS_PRODUCT_ACCOUNTING_PARAMS;
|
||||
@@ -38,6 +39,7 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
import org.apache.fineract.portfolio.shareproducts.constants.ShareProductApiConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -118,8 +120,8 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer {
|
||||
|
||||
final Long incomeFromRecoveryAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue()).value(incomeFromRecoveryAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue())
|
||||
.value(incomeFromRecoveryAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long writeOffAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
@@ -227,6 +229,47 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer {
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForShareProductCreate(final String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(ShareProductApiConstants.SHARE_PRODUCT_RESOURCE_NAME);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
// accounting related data validation
|
||||
final Integer accountingRuleType = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(accountingRuleParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(accountingRuleParamName).value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||
|
||||
if (isCashBasedAccounting(accountingRuleType)) {
|
||||
|
||||
final Long shareReferenceId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_REFERENCE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_REFERENCE.getValue())
|
||||
.value(shareReferenceId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long shareSuspenseId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_SUSPENSE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_SUSPENSE.getValue())
|
||||
.value(shareSuspenseId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromFeeAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SHARES_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue())
|
||||
.value(incomeFromFeeAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long shareEquityId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_EQUITY.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_EQUITY.getValue())
|
||||
.value(shareEquityId).notNull().integerGreaterThanZero();
|
||||
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private boolean isCashBasedAccounting(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
+6
@@ -41,5 +41,11 @@ public interface ProductToGLAccountMappingReadPlatformService {
|
||||
public List<ChargeToGLAccountMapper> fetchFeeToIncomeAccountMappingsForSavingsProduct(final Long savingsProductId);
|
||||
|
||||
public List<ChargeToGLAccountMapper> fetchPenaltyToIncomeAccountMappingsForSavingsProduct(final Long savingsProductId);
|
||||
|
||||
public Map<String, Object> fetchAccountMappingDetailsForShareProduct(final Long productId, final Integer accountingType);
|
||||
|
||||
public List<PaymentTypeToGLAccountMapper> fetchPaymentTypeToFundSourceMappingsForShareProduct(final Long productId);
|
||||
|
||||
public List<ChargeToGLAccountMapper> fetchFeeToIncomeAccountMappingsForShareProduct(final Long productId);
|
||||
|
||||
}
|
||||
+48
@@ -29,8 +29,10 @@ import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SAVINGS;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SHARES;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_DATA_PARAMS;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SAVINGS_PRODUCT_ACCOUNTING_DATA_PARAMS;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SHARES_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper;
|
||||
@@ -326,4 +328,50 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
return chargeToGLAccountMappers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> fetchAccountMappingDetailsForShareProduct(Long productId, Integer accountingType) {
|
||||
|
||||
final Map<String, Object> accountMappingDetails = new LinkedHashMap<>(8);
|
||||
|
||||
final ProductToGLAccountMappingMapper rm = new ProductToGLAccountMappingMapper();
|
||||
final String sql = "select " + rm.schema() + " and product_id = ? and payment_type is null and mapping.charge_id is null ";
|
||||
|
||||
final List<Map<String, Object>> listOfProductToGLAccountMaps = this.jdbcTemplate.query(sql, rm, new Object[] {
|
||||
PortfolioProductType.SHARES.getValue(), productId });
|
||||
|
||||
if (AccountingRuleType.CASH_BASED.getValue().equals(accountingType)) {
|
||||
for (final Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
final CASH_ACCOUNTS_FOR_SHARES glAccountForShares = CASH_ACCOUNTS_FOR_SHARES.fromInt(financialAccountType);
|
||||
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
final String glAccountName = (String) productToGLAccountMap.get("glAccountName");
|
||||
final String glCode = (String) productToGLAccountMap.get("glCode");
|
||||
final GLAccountData gLAccountData = new GLAccountData(glAccountId, glAccountName, glCode);
|
||||
|
||||
if (glAccountForShares.equals(CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE)) {
|
||||
accountMappingDetails.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_REFERENCE.getValue(), gLAccountData);
|
||||
} else if (glAccountForShares.equals(CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE)) {
|
||||
accountMappingDetails.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_SUSPENSE.getValue(), gLAccountData);
|
||||
} else if (glAccountForShares.equals(CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES)) {
|
||||
accountMappingDetails.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), gLAccountData);
|
||||
} else if (glAccountForShares.equals(CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY)) {
|
||||
accountMappingDetails.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_EQUITY.getValue(), gLAccountData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return accountMappingDetails;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PaymentTypeToGLAccountMapper> fetchPaymentTypeToFundSourceMappingsForShareProduct(Long productId) {
|
||||
return fetchPaymentTypeToFundSourceMappings(PortfolioProductType.SHARES, productId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChargeToGLAccountMapper> fetchFeeToIncomeAccountMappingsForShareProduct(Long productId) {
|
||||
return fetchChargeToIncomeAccountMappings(PortfolioProductType.SHARES, productId, false);
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -35,4 +35,9 @@ public interface ProductToGLAccountMappingWritePlatformService {
|
||||
Map<String, Object> updateSavingsProductToGLAccountMapping(Long savingsProductId, JsonCommand command, boolean accountingRuleChanged,
|
||||
int accountingRuleTypeId, DepositAccountType accountType);
|
||||
|
||||
void createShareProductToGLAccountMapping(Long shareProductId, JsonCommand command);
|
||||
|
||||
Map<String, Object> updateShareProductToGLAccountMapping(Long shareProductId, JsonCommand command, boolean accountingRuleChanged,
|
||||
int accountingRuleTypeId);
|
||||
|
||||
}
|
||||
+80
-1
@@ -24,10 +24,12 @@ import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SHARES_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SAVINGS;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SHARES;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SAVINGS_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.serialization.ProductToGLAccountMappingFromApiJsonDeserializer;
|
||||
@@ -47,16 +49,19 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
private final ProductToGLAccountMappingFromApiJsonDeserializer deserializer;
|
||||
private final LoanProductToGLAccountMappingHelper loanProductToGLAccountMappingHelper;
|
||||
private final SavingsProductToGLAccountMappingHelper savingsProductToGLAccountMappingHelper;
|
||||
private final ShareProductToGLAccountMappingHelper shareProductToGLAccountMappingHelper;
|
||||
|
||||
@Autowired
|
||||
public ProductToGLAccountMappingWritePlatformServiceImpl(final FromJsonHelper fromApiJsonHelper,
|
||||
final ProductToGLAccountMappingFromApiJsonDeserializer deserializer,
|
||||
final LoanProductToGLAccountMappingHelper loanProductToGLAccountMappingHelper,
|
||||
final SavingsProductToGLAccountMappingHelper savingsProductToGLAccountMappingHelper) {
|
||||
final SavingsProductToGLAccountMappingHelper savingsProductToGLAccountMappingHelper,
|
||||
final ShareProductToGLAccountMappingHelper shareProductToGLAccountMappingHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.deserializer = deserializer;
|
||||
this.loanProductToGLAccountMappingHelper = loanProductToGLAccountMappingHelper;
|
||||
this.savingsProductToGLAccountMappingHelper = savingsProductToGLAccountMappingHelper;
|
||||
this.shareProductToGLAccountMappingHelper = shareProductToGLAccountMappingHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,6 +235,50 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void createShareProductToGLAccountMapping(final Long shareProductId, final JsonCommand command) {
|
||||
|
||||
this.deserializer.validateForShareProductCreate(command.json());
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(command.json());
|
||||
final Integer accountingRuleTypeId = this.fromApiJsonHelper.extractIntegerNamed(accountingRuleParamName, element,
|
||||
Locale.getDefault());
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId);
|
||||
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
// asset
|
||||
this.shareProductToGLAccountMappingHelper.saveSharesToAssetAccountMapping(element,
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_REFERENCE.getValue(), shareProductId,
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue());
|
||||
|
||||
// income
|
||||
this.shareProductToGLAccountMappingHelper.saveSharesToIncomeAccountMapping(element,
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), shareProductId,
|
||||
CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES.getValue());
|
||||
|
||||
// expenses
|
||||
this.shareProductToGLAccountMappingHelper.saveSharesToEquityAccountMapping(element,
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_EQUITY.getValue(), shareProductId,
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY.getValue());
|
||||
|
||||
// liability
|
||||
this.shareProductToGLAccountMappingHelper.saveSharesToLiabilityAccountMapping(element,
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_SUSPENSE.getValue(), shareProductId,
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue());
|
||||
|
||||
// advanced accounting mappings
|
||||
this.savingsProductToGLAccountMappingHelper.savePaymentChannelToFundSourceMappings(command, element, shareProductId, null);
|
||||
this.savingsProductToGLAccountMappingHelper.saveChargesToIncomeAccountMappings(command, element, shareProductId, null);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Map<String, Object> updateLoanProductToGLAccountMapping(final Long loanProductId, final JsonCommand command,
|
||||
@@ -293,4 +342,34 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> updateShareProductToGLAccountMapping(final Long shareProductId, final JsonCommand command,
|
||||
final boolean accountingRuleChanged, final int accountingRuleTypeId) {
|
||||
/***
|
||||
* Variable tracks all accounting mapping properties that have been
|
||||
* updated
|
||||
***/
|
||||
Map<String, Object> changes = new HashMap<>();
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(command.json());
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId);
|
||||
|
||||
/***
|
||||
* If the accounting rule has been changed, delete all existing mapping
|
||||
* for the product and recreate a new set of mappings
|
||||
***/
|
||||
if (accountingRuleChanged) {
|
||||
this.shareProductToGLAccountMappingHelper.deleteSharesProductToGLAccountMapping(shareProductId);
|
||||
createShareProductToGLAccountMapping(shareProductId, command);
|
||||
changes = this.shareProductToGLAccountMappingHelper.populateChangesForNewSharesProductToGLAccountMappingCreation(element,
|
||||
accountingRuleType);
|
||||
}/*** else examine and update individual changes ***/
|
||||
else {
|
||||
this.shareProductToGLAccountMappingHelper.handleChangesToSharesProductToGLAccountMappings(shareProductId, changes, element,
|
||||
accountingRuleType);
|
||||
this.shareProductToGLAccountMappingHelper.updatePaymentChannelToFundSourceMappings(command, element, shareProductId, changes);
|
||||
this.shareProductToGLAccountMappingHelper.updateChargesToIncomeAccountMappings(command, element, shareProductId, changes);
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
}
|
||||
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.accounting.producttoaccountmapping.service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SHARES;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SHARES_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepository;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioProductType;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.paymenttype.domain.PaymentTypeRepositoryWrapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
@Component
|
||||
public class ShareProductToGLAccountMappingHelper extends ProductToGLAccountMappingHelper {
|
||||
|
||||
@Autowired
|
||||
public ShareProductToGLAccountMappingHelper(final GLAccountRepository glAccountRepository,
|
||||
final ProductToGLAccountMappingRepository glAccountMappingRepository, final FromJsonHelper fromApiJsonHelper,
|
||||
final ChargeRepositoryWrapper chargeRepositoryWrapper, final GLAccountRepositoryWrapper accountRepositoryWrapper,
|
||||
final PaymentTypeRepositoryWrapper paymentTypeRepositoryWrapper) {
|
||||
super(glAccountRepository, glAccountMappingRepository, fromApiJsonHelper, chargeRepositoryWrapper, accountRepositoryWrapper,
|
||||
paymentTypeRepositoryWrapper);
|
||||
}
|
||||
|
||||
/*** Set of abstractions for saving Share Products to GL Account Mappings ***/
|
||||
|
||||
public void saveSharesToAssetAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.ASSET, PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void saveSharesToIncomeAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.INCOME, PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void saveSharesToEquityAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.EQUITY, PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void saveSharesToLiabilityAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.LIABILITY, PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
/*** Set of abstractions for merging Shares Products to GL Account Mappings ***/
|
||||
|
||||
public void mergeSharesToAssetAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.ASSET,
|
||||
PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void mergeSharesToIncomeAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.INCOME,
|
||||
PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void mergeSharesToEquityAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.EQUITY,
|
||||
PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void mergeSharesToLiabilityAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes,
|
||||
GLAccountType.LIABILITY, PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
/*** Abstractions for payments channel related to Shares products ***/
|
||||
|
||||
public void savePaymentChannelToFundSourceMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
savePaymentChannelToFundSourceMappings(command, element, productId, changes, PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void updatePaymentChannelToFundSourceMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
updatePaymentChannelToFundSourceMappings(command, element, productId, changes, PortfolioProductType.SHARES);
|
||||
}
|
||||
|
||||
public void saveChargesToIncomeAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
saveChargesToIncomeOrLiabilityAccountMappings(command, element, productId, changes, PortfolioProductType.SHARES, true);
|
||||
saveChargesToIncomeOrLiabilityAccountMappings(command, element, productId, changes, PortfolioProductType.SHARES, false);
|
||||
}
|
||||
|
||||
public void updateChargesToIncomeAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
updateChargeToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SHARES, true);
|
||||
updateChargeToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SHARES, false);
|
||||
}
|
||||
|
||||
public Map<String, Object> populateChangesForNewSharesProductToGLAccountMappingCreation(final JsonElement element,
|
||||
final AccountingRuleType accountingRuleType) {
|
||||
final Map<String, Object> changes = new HashMap<>();
|
||||
|
||||
final Long shareReferenceId = this.fromApiJsonHelper.extractLongNamed(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_REFERENCE.getValue(),
|
||||
element);
|
||||
final Long incomeFromFeeAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SHARES_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), element);
|
||||
final Long shareSuspenseId = this.fromApiJsonHelper.extractLongNamed(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_SUSPENSE.getValue(),
|
||||
element);
|
||||
final Long shareEquityId = this.fromApiJsonHelper.extractLongNamed(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_EQUITY.getValue(),
|
||||
element);
|
||||
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
changes.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_REFERENCE.getValue(), shareReferenceId);
|
||||
changes.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), incomeFromFeeAccountId);
|
||||
changes.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_SUSPENSE.getValue(), shareSuspenseId);
|
||||
changes.put(SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_EQUITY.getValue(), shareEquityId);
|
||||
break;
|
||||
case ACCRUAL_PERIODIC:
|
||||
break;
|
||||
case ACCRUAL_UPFRONT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines and updates each account mapping for given loan product with
|
||||
* changes passed in from the Json element
|
||||
*
|
||||
* @param sharesProductId
|
||||
* @param changes
|
||||
* @param element
|
||||
* @param accountingRuleType
|
||||
*/
|
||||
public void handleChangesToSharesProductToGLAccountMappings(final Long sharesProductId, final Map<String, Object> changes,
|
||||
final JsonElement element, final AccountingRuleType accountingRuleType) {
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
// asset
|
||||
mergeSharesToAssetAccountMappingChanges(element, SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_REFERENCE.getValue(),
|
||||
sharesProductId, CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.toString(), changes);
|
||||
|
||||
// income
|
||||
mergeSharesToIncomeAccountMappingChanges(element, SHARES_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
sharesProductId, CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES.toString(), changes);
|
||||
|
||||
// liability
|
||||
mergeSharesToLiabilityAccountMappingChanges(element, SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_SUSPENSE.getValue(),
|
||||
sharesProductId, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.toString(), changes);
|
||||
|
||||
// equity
|
||||
mergeSharesToEquityAccountMappingChanges(element, SHARES_PRODUCT_ACCOUNTING_PARAMS.SHARES_EQUITY.getValue(),
|
||||
sharesProductId, CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY.toString(), changes);
|
||||
break;
|
||||
case ACCRUAL_PERIODIC:
|
||||
break;
|
||||
case ACCRUAL_UPFRONT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteSharesProductToGLAccountMapping(final Long sharesProductId) {
|
||||
deleteProductToGLAccountMapping(sharesProductId, PortfolioProductType.SHARES);
|
||||
}
|
||||
}
|
||||
+59
-13
@@ -830,7 +830,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/loans/" + loanId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder undoLastDisbursalLoanApplication(final Long loanId) {
|
||||
this.actionName = "DISBURSALLASTUNDO";
|
||||
this.entityName = "LOAN";
|
||||
@@ -2584,36 +2584,82 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/loans/" + loanId + "/schedule";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder createProduct(String productType) {
|
||||
this.entityName = productType.toUpperCase()+"PRODUCT" ; //To Support different type of products
|
||||
this.entityName = productType.toUpperCase() + "PRODUCT"; // To Support
|
||||
// different
|
||||
// type of
|
||||
// products
|
||||
this.actionName = "CREATE";
|
||||
this.entityId = null;
|
||||
this.href = "/products/"+productType;
|
||||
this.href = "/products/" + productType;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder updateProduct(String productType, final Long productId) {
|
||||
this.entityName = productType.toUpperCase()+"PRODUCT" ;
|
||||
this.entityName = productType.toUpperCase() + "PRODUCT";
|
||||
this.actionName = "UPDATE";
|
||||
this.entityId = productId;
|
||||
this.href = "/products/" + productType+"/"+productId;
|
||||
this.href = "/products/" + productType + "/" + productId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder createAccount(String accountType) {
|
||||
this.entityName = accountType.toUpperCase()+"ACCOUNT" ; //To Support different type of Accounts
|
||||
this.entityName = accountType.toUpperCase() + "ACCOUNT"; // To Support
|
||||
// different
|
||||
// type of
|
||||
// Accounts
|
||||
this.actionName = "CREATE";
|
||||
this.entityId = null;
|
||||
this.href = "/accounts/"+accountType;
|
||||
this.href = "/accounts/" + accountType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateAccount(String accountType, final Long accountId) {
|
||||
this.entityName = accountType.toUpperCase() + "ACCOUNT";
|
||||
this.actionName = "UPDATE";
|
||||
this.entityId = accountId;
|
||||
this.href = "/accounts/" + accountType + "/" + accountId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createProductCommand(String productType, String command, final Long productId) {
|
||||
this.entityName = productType.toUpperCase() + "PRODUCT";
|
||||
this.actionName = "CREATE" + "_" + command.toUpperCase();
|
||||
this.entityId = productId;
|
||||
this.href = "/products/" + productType + "/" + productId + "?command=" + command;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createShareProductDividendPayoutCommand(final Long productId) {
|
||||
this.entityName = "SHAREPRODUCT";
|
||||
this.actionName = "CREATE_DIVIDEND";
|
||||
this.entityId = productId;
|
||||
this.href = "/shareproduct/" + productId + "/dividend";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder approveShareProductDividendPayoutCommand(final Long productId, final Long dividendId) {
|
||||
this.entityName = "SHAREPRODUCT";
|
||||
this.actionName = "APPROVE_DIVIDEND";
|
||||
this.entityId = dividendId;
|
||||
this.href = "/shareproduct/" + productId + "/dividend/" + dividendId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateAccount(String accountType, final Long accountId) {
|
||||
public CommandWrapperBuilder deleteShareProductDividendPayoutCommand(final Long productId, final Long dividendId) {
|
||||
this.entityName = "SHAREPRODUCT";
|
||||
this.actionName = "DELETE_DIVIDEND";
|
||||
this.entityId = dividendId;
|
||||
this.href = "/shareproduct/" + productId + "/dividend/" + dividendId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createAccountCommand(String accountType, final Long accountId, String command) {
|
||||
this.entityName = accountType.toUpperCase()+"ACCOUNT" ;
|
||||
this.actionName = "UPDATE";
|
||||
this.actionName = command.toUpperCase();
|
||||
this.entityId = accountId;
|
||||
this.href = "/accounts/" + accountType+"/"+accountId;
|
||||
this.href = "/accounts/" + accountType+"/"+accountId+"?command="+command;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import java.util.Map;
|
||||
|
||||
public enum EntityAccountType {
|
||||
CLIENT(1, "accountType.client"), LOAN(2, "accountType.loan"), SAVINGS(3, "accountType.savings"), CENTER(4, "accountType.center"),
|
||||
GROUP(5, "accountType.group");
|
||||
GROUP(5, "accountType.group"), SHARES(6, "accountType.shares");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
+50
-35
@@ -43,13 +43,13 @@ public final class SearchParameters {
|
||||
private final Long savingsId;
|
||||
private final Boolean orphansOnly;
|
||||
|
||||
//Provisning Entries Search Params
|
||||
private final Long provisioningEntryId ;
|
||||
private final Long productId ;
|
||||
private final Long categoryId ;
|
||||
private final boolean isSelfUser;
|
||||
|
||||
public static SearchParameters from(final String sqlSearch, final Long officeId, final String externalId, final String name,
|
||||
// Provisning Entries Search Params
|
||||
private final Long provisioningEntryId;
|
||||
private final Long productId;
|
||||
private final Long categoryId;
|
||||
private final boolean isSelfUser;
|
||||
|
||||
public static SearchParameters from(final String sqlSearch, final Long officeId, final String externalId, final String name,
|
||||
final String hierarchy) {
|
||||
final Long staffId = null;
|
||||
final String accountNo = null;
|
||||
@@ -145,6 +145,20 @@ public final class SearchParameters {
|
||||
loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forPaginationAndAccountNumberSearch(final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder, final String accountNumber) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
final Long staffId = null;
|
||||
final Long loanId = null;
|
||||
final Long savingsId = null;
|
||||
final Boolean orphansOnly = false;
|
||||
final boolean isSelfUser = false;
|
||||
|
||||
return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy, sortOrder, staffId,
|
||||
accountNumber, loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public static SearchParameters forPagination(final Integer offset, final Integer limit) {
|
||||
|
||||
final Integer maxLimitAllowed = getCheckedLimit(limit);
|
||||
@@ -160,11 +174,11 @@ public final class SearchParameters {
|
||||
loanId, savingsId, orphansOnly, isSelfUser);
|
||||
}
|
||||
|
||||
public final static SearchParameters forProvisioningEntries(final Long provisioningEntryId, final Long officeId, final Long productId,
|
||||
public final static SearchParameters forProvisioningEntries(final Long provisioningEntryId, final Long officeId, final Long productId,
|
||||
final Long categoryId, final Integer offset, final Integer limit) {
|
||||
return new SearchParameters(provisioningEntryId, officeId, productId, categoryId, offset, limit) ;
|
||||
return new SearchParameters(provisioningEntryId, officeId, productId, categoryId, offset, limit);
|
||||
}
|
||||
|
||||
|
||||
public static SearchParameters forSavings(final String sqlSearch, final String externalId, final Integer offset, final Integer limit,
|
||||
final String orderBy, final String sortOrder) {
|
||||
|
||||
@@ -216,11 +230,11 @@ public final class SearchParameters {
|
||||
this.savingsId = savingsId;
|
||||
this.orphansOnly = orphansOnly;
|
||||
this.currencyCode = null;
|
||||
this.provisioningEntryId = null ;
|
||||
this.productId = null ;
|
||||
this.categoryId = null ;
|
||||
this.provisioningEntryId = null;
|
||||
this.productId = null;
|
||||
this.categoryId = null;
|
||||
this.isSelfUser = isSelfUser;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private SearchParameters(final Long provisioningEntryId, final Long officeId, final Long productId, final Long categoryId,
|
||||
@@ -242,17 +256,17 @@ public final class SearchParameters {
|
||||
this.officeId = officeId;
|
||||
this.offset = offset;
|
||||
this.limit = limit;
|
||||
this.provisioningEntryId = provisioningEntryId ;
|
||||
this.productId = productId ;
|
||||
this.categoryId = categoryId ;
|
||||
this.provisioningEntryId = provisioningEntryId;
|
||||
this.productId = productId;
|
||||
this.categoryId = categoryId;
|
||||
this.isSelfUser = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, final String hierarchy,
|
||||
final String firstname, final String lastname, final Integer offset, final Integer limit, final String orderBy,
|
||||
final String sortOrder, final Long staffId, final String accountNo, final Long loanId, final Long savingsId,
|
||||
final Boolean orphansOnly, final String currencyCode) {
|
||||
|
||||
public SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name,
|
||||
final String hierarchy, final String firstname, final String lastname, final Integer offset, final Integer limit,
|
||||
final String orderBy, final String sortOrder, final Long staffId, final String accountNo, final Long loanId,
|
||||
final Long savingsId, final Boolean orphansOnly, final String currencyCode) {
|
||||
this.sqlSearch = sqlSearch;
|
||||
this.officeId = officeId;
|
||||
this.externalId = externalId;
|
||||
@@ -270,9 +284,9 @@ public final class SearchParameters {
|
||||
this.savingsId = savingsId;
|
||||
this.orphansOnly = orphansOnly;
|
||||
this.currencyCode = currencyCode;
|
||||
this.provisioningEntryId = null ;
|
||||
this.productId = null ;
|
||||
this.categoryId = null ;
|
||||
this.provisioningEntryId = null;
|
||||
this.productId = null;
|
||||
this.categoryId = null;
|
||||
this.isSelfUser = false;
|
||||
}
|
||||
|
||||
@@ -400,32 +414,33 @@ public final class SearchParameters {
|
||||
if (this.orphansOnly != null) { return this.orphansOnly; }
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public Long getProvisioningEntryId() {
|
||||
return this.provisioningEntryId;
|
||||
}
|
||||
|
||||
|
||||
public boolean isProvisioningEntryIdPassed() {
|
||||
return this.provisioningEntryId != null && this.provisioningEntryId != 0 ;
|
||||
return this.provisioningEntryId != null && this.provisioningEntryId != 0;
|
||||
}
|
||||
|
||||
|
||||
public Long getProductId() {
|
||||
return this.productId;
|
||||
}
|
||||
|
||||
public boolean isProductIdPassed() {
|
||||
return this.productId != null && this.productId != 0 ;
|
||||
return this.productId != null && this.productId != 0;
|
||||
}
|
||||
|
||||
public Long getCategoryId() {
|
||||
return this.categoryId;
|
||||
}
|
||||
|
||||
|
||||
public boolean isCategoryIdPassed() {
|
||||
return this.categoryId != null && this.categoryId != 0 ;
|
||||
return this.categoryId != null && this.categoryId != 0;
|
||||
}
|
||||
|
||||
public boolean isSelfUser() {
|
||||
return this.isSelfUser;
|
||||
}
|
||||
return this.isSelfUser;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ public class FineractEntityAccessType {
|
||||
public static final FineractEntityAccessType OFFICE_ACCESS_TO_LOAN_PRODUCTS = new FineractEntityAccessType("Office Access to Loan Products");
|
||||
public static final FineractEntityAccessType OFFICE_ACCESS_TO_SAVINGS_PRODUCTS = new FineractEntityAccessType("Office Access to Savings Products");
|
||||
public static final FineractEntityAccessType OFFICE_ACCESS_TO_CHARGES = new FineractEntityAccessType("Office Access to Fees/Charges");
|
||||
|
||||
|
||||
private FineractEntityAccessType (String str) {
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
+7
-4
@@ -27,7 +27,8 @@ public class FineractEntityType {
|
||||
public static FineractEntityType LOAN_PRODUCT = new FineractEntityType ("loan_product", "Loan Products", "m_product_loan");
|
||||
public static FineractEntityType SAVINGS_PRODUCT = new FineractEntityType ("savings_product", "Savings Products", "m_savings_product");
|
||||
public static FineractEntityType CHARGE = new FineractEntityType ("charge", "Fees/Charges", "m_charge");
|
||||
|
||||
public static FineractEntityType SHARE_PRODUCT = new FineractEntityType("shares_product", "Shares Products", "m_share_product") ;
|
||||
|
||||
private FineractEntityType (String type, String description, String table_name) {
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
@@ -56,9 +57,11 @@ public class FineractEntityType {
|
||||
retType = LOAN_PRODUCT;
|
||||
} else if (type.equals(SAVINGS_PRODUCT)) {
|
||||
retType = SAVINGS_PRODUCT;
|
||||
} else if (type.equals(CHARGE))
|
||||
retType = CHARGE;
|
||||
|
||||
} else if (type.equals(CHARGE)) {
|
||||
retType = CHARGE;
|
||||
}else if(type.equals(SHARE_PRODUCT)) {
|
||||
retType = SHARE_PRODUCT ;
|
||||
}
|
||||
return retType;
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -29,17 +29,18 @@ public enum JobName {
|
||||
TRANSFER_FEE_CHARGE_FOR_LOANS("Transfer Fee For Loans From Savings"), //
|
||||
ACCOUNTING_RUNNING_BALANCE_UPDATE("Update Accounting Running Balances"), //
|
||||
PAY_DUE_SAVINGS_CHARGES("Pay Due Savings Charges"), //
|
||||
APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue loans"),
|
||||
EXECUTE_STANDING_INSTRUCTIONS("Execute Standing Instruction"),
|
||||
ADD_ACCRUAL_ENTRIES("Add Accrual Transactions"),
|
||||
UPDATE_NPA("Update Non Performing Assets"),
|
||||
UPDATE_DEPOSITS_ACCOUNT_MATURITY_DETAILS("Update Deposit Accounts Maturity details"),
|
||||
TRANSFER_INTEREST_TO_SAVINGS("Transfer Interest To Savings"),
|
||||
ADD_PERIODIC_ACCRUAL_ENTRIES("Add Periodic Accrual Transactions"),
|
||||
RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"),
|
||||
GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"),
|
||||
GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning");
|
||||
|
||||
APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue loans"), //
|
||||
EXECUTE_STANDING_INSTRUCTIONS("Execute Standing Instruction"), //
|
||||
ADD_ACCRUAL_ENTRIES("Add Accrual Transactions"), //
|
||||
UPDATE_NPA("Update Non Performing Assets"), //
|
||||
UPDATE_DEPOSITS_ACCOUNT_MATURITY_DETAILS("Update Deposit Accounts Maturity details"), //
|
||||
TRANSFER_INTEREST_TO_SAVINGS("Transfer Interest To Savings"), //
|
||||
ADD_PERIODIC_ACCRUAL_ENTRIES("Add Periodic Accrual Transactions"), //
|
||||
RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"), //
|
||||
GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"), //
|
||||
GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"), //
|
||||
POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares");
|
||||
|
||||
private final String name;
|
||||
|
||||
private JobName(final String name) {
|
||||
|
||||
+3
-2
@@ -422,6 +422,7 @@ public class TellerWritePlatformServiceJpaImpl implements TellerWritePlatformSer
|
||||
final String uniqueVal = String.valueOf(time) + currentUser.getId() + cashierOffice.getId();
|
||||
final String transactionId = Long.toHexString(Long.parseLong(uniqueVal));
|
||||
ClientTransaction clientTransaction = null;
|
||||
final Long shareTransactionId = null;
|
||||
|
||||
final JournalEntry debitJournalEntry = JournalEntry.createNew(cashierOffice, null, // payment
|
||||
// detail
|
||||
@@ -430,7 +431,7 @@ public class TellerWritePlatformServiceJpaImpl implements TellerWritePlatformSer
|
||||
transactionId, false, // manual entry
|
||||
cashierTxn.getTxnDate(), JournalEntryType.DEBIT, cashierTxn.getTxnAmount(), cashierTxn.getTxnNote(), // Description
|
||||
null, null, null, // entity Type, entityId, reference number
|
||||
null, null, clientTransaction); // Loan and Savings Txn
|
||||
null, null, clientTransaction, shareTransactionId); // Loan and Savings Txn
|
||||
|
||||
final JournalEntry creditJournalEntry = JournalEntry.createNew(cashierOffice, null, // payment
|
||||
// detail
|
||||
@@ -439,7 +440,7 @@ public class TellerWritePlatformServiceJpaImpl implements TellerWritePlatformSer
|
||||
transactionId, false, // manual entry
|
||||
cashierTxn.getTxnDate(), JournalEntryType.CREDIT, cashierTxn.getTxnAmount(), cashierTxn.getTxnNote(), // Description
|
||||
null, null, null, // entity Type, entityId, reference number
|
||||
null, null, clientTransaction); // Loan and Savings Txn
|
||||
null, null, clientTransaction, shareTransactionId); // Loan and Savings Txn
|
||||
|
||||
this.glJournalEntryRepository.saveAndFlush(debitJournalEntry);
|
||||
this.glJournalEntryRepository.saveAndFlush(creditJournalEntry);
|
||||
|
||||
+15
-6
@@ -23,30 +23,31 @@ import java.util.Collection;
|
||||
/**
|
||||
* Immutable data object representing a summary of various accounts.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class AccountSummaryCollectionData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<LoanAccountSummaryData> loanAccounts;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<SavingsAccountSummaryData> savingsAccounts;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<ShareAccountSummaryData> shareAccounts ;
|
||||
|
||||
private final Collection<LoanAccountSummaryData> memberLoanAccounts;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<SavingsAccountSummaryData> memberSavingsAccounts;
|
||||
|
||||
public AccountSummaryCollectionData(final Collection<LoanAccountSummaryData> loanAccounts,
|
||||
final Collection<SavingsAccountSummaryData> savingsAccounts) {
|
||||
final Collection<SavingsAccountSummaryData> savingsAccounts, final Collection<ShareAccountSummaryData> shareAccounts) {
|
||||
this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts);
|
||||
this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts);
|
||||
this.shareAccounts = defaultShareAccountsIfEmpty(shareAccounts) ;
|
||||
this.memberLoanAccounts = null;
|
||||
this.memberSavingsAccounts = null;
|
||||
}
|
||||
|
||||
|
||||
public AccountSummaryCollectionData(final Collection<LoanAccountSummaryData> loanAccounts,
|
||||
final Collection<SavingsAccountSummaryData> savingsAccounts, final Collection<LoanAccountSummaryData> memberLoanAccounts,
|
||||
final Collection<SavingsAccountSummaryData> memberSavingsAccounts) {
|
||||
this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts);
|
||||
this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts);
|
||||
this.shareAccounts = null ;
|
||||
this.memberLoanAccounts = defaultLoanAccountsIfEmpty(memberLoanAccounts);
|
||||
this.memberSavingsAccounts = defaultSavingsAccountsIfEmpty(memberSavingsAccounts);
|
||||
}
|
||||
@@ -66,5 +67,13 @@ public class AccountSummaryCollectionData {
|
||||
}
|
||||
return returnCollection;
|
||||
}
|
||||
|
||||
private Collection<ShareAccountSummaryData> defaultShareAccountsIfEmpty(final Collection<ShareAccountSummaryData> collection) {
|
||||
Collection<ShareAccountSummaryData> returnCollection = null;
|
||||
if (collection != null && !collection.isEmpty()) {
|
||||
returnCollection = collection;
|
||||
}
|
||||
return returnCollection;
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accountdetails.data;
|
||||
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountApplicationTimelineData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountStatusEnumData;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ShareAccountSummaryData {
|
||||
|
||||
private final Long id;
|
||||
private final String accountNo;
|
||||
private final Long totalApprovedShares;
|
||||
private final Long totalPendingForApprovalShares;
|
||||
private final String externalId;
|
||||
private final Long productId;
|
||||
private final String productName;
|
||||
private final String shortProductName;
|
||||
private final ShareAccountStatusEnumData status;
|
||||
private final CurrencyData currency;
|
||||
private final ShareAccountApplicationTimelineData timeline;
|
||||
|
||||
public ShareAccountSummaryData(final Long id, final String accountNo,
|
||||
final String externalId, final Long productId,
|
||||
final String productName, final String shortProductName,
|
||||
final ShareAccountStatusEnumData status,
|
||||
final CurrencyData currency, final Long approvedShares,
|
||||
final Long pendingForApprovalShares,
|
||||
final ShareAccountApplicationTimelineData timeline) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
if(approvedShares == null) {
|
||||
this.totalApprovedShares = new Long(0) ;
|
||||
}else {
|
||||
this.totalApprovedShares = approvedShares;
|
||||
}
|
||||
if(pendingForApprovalShares == null) {
|
||||
this.totalPendingForApprovalShares = new Long(0) ;
|
||||
}else {
|
||||
this.totalPendingForApprovalShares = pendingForApprovalShares;
|
||||
}
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
this.shortProductName = shortProductName;
|
||||
this.status = status;
|
||||
this.currency = currency;
|
||||
this.timeline = timeline;
|
||||
}
|
||||
|
||||
|
||||
public String getAccountNo() {
|
||||
return this.accountNo;
|
||||
}
|
||||
|
||||
}
|
||||
+108
-1
@@ -31,6 +31,7 @@ import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData;
|
||||
import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData;
|
||||
import org.apache.fineract.portfolio.accountdetails.data.SavingsAccountSummaryData;
|
||||
import org.apache.fineract.portfolio.accountdetails.data.ShareAccountSummaryData;
|
||||
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.apache.fineract.portfolio.group.service.GroupReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanApplicationTimelineData;
|
||||
@@ -39,6 +40,9 @@ import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountApplicationTimelineData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountStatusEnumData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.SharesEnumerations;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -68,7 +72,8 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
||||
final String savingswhereClause = " where sa.client_id = ? order by sa.status_enum ASC, sa.account_no ASC";
|
||||
final List<LoanAccountSummaryData> loanAccounts = retrieveLoanAccountDetails(loanwhereClause, new Object[] { clientId });
|
||||
final List<SavingsAccountSummaryData> savingsAccounts = retrieveAccountDetails(savingswhereClause, new Object[] { clientId });
|
||||
return new AccountSummaryCollectionData(loanAccounts, savingsAccounts);
|
||||
final List<ShareAccountSummaryData> shareAccounts = retrieveShareAccountDetails(clientId) ;
|
||||
return new AccountSummaryCollectionData(loanAccounts, savingsAccounts, shareAccounts);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,6 +126,108 @@ public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements Accou
|
||||
return this.jdbcTemplate.query(savingsSql, savingsAccountSummaryDataMapper, inputs);
|
||||
}
|
||||
|
||||
private List<ShareAccountSummaryData> retrieveShareAccountDetails(final Long clientId) {
|
||||
final ShareAccountSummaryDataMapper mapper = new ShareAccountSummaryDataMapper() ;
|
||||
final String query = "select " + mapper.schema() + " where sa.client_id = ?" ;
|
||||
return this.jdbcTemplate.query(query, mapper, new Object [] {clientId});
|
||||
}
|
||||
|
||||
private final static class ShareAccountSummaryDataMapper implements RowMapper<ShareAccountSummaryData> {
|
||||
|
||||
private final String schema ;
|
||||
|
||||
ShareAccountSummaryDataMapper() {
|
||||
final StringBuffer buff = new StringBuffer()
|
||||
.append("sa.id as id, sa.external_id as externalId, sa.status_enum as statusEnum, ")
|
||||
.append("sa.account_no as accountNo, sa.total_approved_shares as approvedShares, sa.total_pending_shares as pendingShares, ")
|
||||
.append("sa.savings_account_id as savingsAccountNo, sa.minimum_active_period_frequency as minimumactivePeriod,")
|
||||
.append("sa.minimum_active_period_frequency_enum as minimumactivePeriodEnum,")
|
||||
.append("sa.lockin_period_frequency as lockinPeriod, sa.lockin_period_frequency_enum as lockinPeriodEnum, ")
|
||||
.append("sa.submitted_date as submittedDate, sbu.username as submittedByUsername, ")
|
||||
.append("sbu.firstname as submittedByFirstname, sbu.lastname as submittedByLastname, ")
|
||||
.append("sa.rejected_date as rejectedDate, rbu.username as rejectedByUsername, ")
|
||||
.append("rbu.firstname as rejectedByFirstname, rbu.lastname as rejectedByLastname, ")
|
||||
.append("sa.approved_date as approvedDate, abu.username as approvedByUsername, ")
|
||||
.append("abu.firstname as approvedByFirstname, abu.lastname as approvedByLastname, ")
|
||||
.append("sa.activated_date as activatedDate, avbu.username as activatedByUsername, ")
|
||||
.append("avbu.firstname as activatedByFirstname, avbu.lastname as activatedByLastname, ")
|
||||
.append("sa.closed_date as closedDate, cbu.username as closedByUsername, ")
|
||||
.append("cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname, ")
|
||||
.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, sa.currency_multiplesof as inMultiplesOf, ")
|
||||
.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ")
|
||||
.append("curr.display_symbol as currencyDisplaySymbol, sa.product_id as productId, p.name as productName, p.short_name as shortProductName ")
|
||||
.append("from m_share_account sa ")
|
||||
.append("join m_share_product as p on p.id = sa.product_id ")
|
||||
.append("join m_currency curr on curr.code = sa.currency_code ")
|
||||
.append("left join m_appuser sbu on sbu.id = sa.submitted_userid ")
|
||||
.append("left join m_appuser rbu on rbu.id = sa.rejected_userid ")
|
||||
.append("left join m_appuser abu on abu.id = sa.approved_userid ")
|
||||
.append("left join m_appuser avbu on rbu.id = sa.activated_userid ")
|
||||
.append("left join m_appuser cbu on cbu.id = sa.closed_userid ") ;
|
||||
schema = buff.toString() ;
|
||||
}
|
||||
@Override
|
||||
public ShareAccountSummaryData mapRow(ResultSet rs, int rowNum)
|
||||
throws SQLException {
|
||||
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final Long approvedShares = JdbcSupport.getLong(rs, "approvedShares");
|
||||
final Long pendingShares = JdbcSupport.getLong(rs, "pendingShares");
|
||||
final String externalId = rs.getString("externalId");
|
||||
final Long productId = JdbcSupport.getLong(rs, "productId");
|
||||
final String productName = rs.getString("productName");
|
||||
final String shortProductName = rs.getString("shortProductName");
|
||||
final Integer statusId = JdbcSupport.getInteger(rs, "statusEnum");
|
||||
final ShareAccountStatusEnumData status = SharesEnumerations.status(statusId) ;
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
final String currencyName = rs.getString("currencyName");
|
||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf,
|
||||
currencyDisplaySymbol, currencyNameCode);
|
||||
|
||||
final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedDate");
|
||||
final String submittedByUsername = rs.getString("submittedByUsername");
|
||||
final String submittedByFirstname = rs.getString("submittedByFirstname");
|
||||
final String submittedByLastname = rs.getString("submittedByLastname");
|
||||
|
||||
final LocalDate rejectedOnDate = JdbcSupport.getLocalDate(rs, "rejectedDate");
|
||||
final String rejectedByUsername = rs.getString("rejectedByUsername");
|
||||
final String rejectedByFirstname = rs.getString("rejectedByFirstname");
|
||||
final String rejectedByLastname = rs.getString("rejectedByLastname");
|
||||
|
||||
final LocalDate approvedOnDate = JdbcSupport.getLocalDate(rs, "approvedDate");
|
||||
final String approvedByUsername = rs.getString("approvedByUsername");
|
||||
final String approvedByFirstname = rs.getString("approvedByFirstname");
|
||||
final String approvedByLastname = rs.getString("approvedByLastname");
|
||||
|
||||
final LocalDate activatedOnDate = JdbcSupport.getLocalDate(rs, "activatedDate");
|
||||
final String activatedByUsername = rs.getString("activatedByUsername");
|
||||
final String activatedByFirstname = rs.getString("activatedByFirstname");
|
||||
final String activatedByLastname = rs.getString("activatedByLastname");
|
||||
|
||||
final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedDate");
|
||||
final String closedByUsername = rs.getString("closedByUsername");
|
||||
final String closedByFirstname = rs.getString("closedByFirstname");
|
||||
final String closedByLastname = rs.getString("closedByLastname");
|
||||
|
||||
final ShareAccountApplicationTimelineData timeline = new ShareAccountApplicationTimelineData(submittedOnDate,
|
||||
submittedByUsername, submittedByFirstname, submittedByLastname, rejectedOnDate, rejectedByUsername,
|
||||
rejectedByFirstname, rejectedByLastname, approvedOnDate, approvedByUsername, approvedByFirstname, approvedByLastname, activatedOnDate,
|
||||
activatedByUsername, activatedByFirstname, activatedByLastname, closedOnDate, closedByUsername, closedByFirstname,
|
||||
closedByLastname);
|
||||
|
||||
return new ShareAccountSummaryData(id, accountNo, externalId, productId, productName, shortProductName, status, currency,
|
||||
approvedShares, pendingShares, timeline);
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schema ;
|
||||
}
|
||||
}
|
||||
private static final class SavingsAccountSummaryDataMapper implements RowMapper<SavingsAccountSummaryData> {
|
||||
|
||||
final String schemaSql;
|
||||
|
||||
+23
-10
@@ -19,7 +19,6 @@
|
||||
package org.apache.fineract.portfolio.accounts.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -44,7 +43,6 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
|
||||
import org.apache.fineract.portfolio.accounts.constants.AccountsApiConstants;
|
||||
import org.apache.fineract.portfolio.accounts.data.AccountData;
|
||||
import org.apache.fineract.portfolio.accounts.service.AccountReadPlatformService;
|
||||
import org.apache.fineract.portfolio.accounts.service.AccountsCommandsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@@ -78,6 +76,21 @@ public class AccountsApiResource {
|
||||
this.toApiObjectJsonSerializer = toApiObjectJsonSerializer ;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String template(@PathParam("type") final String accountType, @QueryParam("clientId") final Long clientId,
|
||||
@QueryParam("productId") final Long productId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
this.platformSecurityContext.authenticatedUser() ;
|
||||
String serviceName = accountType+AccountsApiConstants.READPLATFORM_NAME ;
|
||||
AccountReadPlatformService service = (AccountReadPlatformService) this.applicationContext.getBean(serviceName) ;
|
||||
final AccountData accountData = service.retrieveTemplate(clientId, productId);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, accountData, service.getResponseDataParams());
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{accountId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -85,9 +98,9 @@ public class AccountsApiResource {
|
||||
public String retrieveAccount(@PathParam("accountId") final Long accountId, @PathParam("type") final String accountType,
|
||||
@Context final UriInfo uriInfo) {
|
||||
String serviceName = accountType+AccountsApiConstants.READPLATFORM_NAME ;
|
||||
AccountReadPlatformService service = (AccountReadPlatformService) this.applicationContext.getBean(serviceName) ;
|
||||
AccountData data = service.retrieveOne(accountId) ;
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
AccountReadPlatformService service = (AccountReadPlatformService) this.applicationContext.getBean(serviceName) ;
|
||||
AccountData data = service.retrieveOne(accountId, settings.isTemplate()) ;
|
||||
return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams());
|
||||
}
|
||||
|
||||
@@ -118,12 +131,12 @@ public class AccountsApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String handleCommands(@PathParam("type") final String accountType, @PathParam("accountId") final Long accountId, @QueryParam("command") final String commandParam,
|
||||
@Context final UriInfo uriInfo, final String apiRequestBodyAsJson) {
|
||||
String serviceName = accountType.toUpperCase()+AccountsApiConstants.ACCOUNT_COMMANDSERVICE ;
|
||||
AccountsCommandsService service = (AccountsCommandsService) this.applicationContext.getBean(serviceName) ;
|
||||
final Object obj = service.handleCommand(accountId, commandParam, apiRequestBodyAsJson) ;
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiObjectJsonSerializer.serialize(settings, obj, new HashSet<String>());
|
||||
final String apiRequestBodyAsJson) {
|
||||
CommandWrapper commandWrapper = null;
|
||||
this.platformSecurityContext.authenticatedUser();
|
||||
commandWrapper = new CommandWrapperBuilder().createAccountCommand(accountType, accountId, commandParam).withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
|
||||
return this.toApiJsonSerializer.serialize(commandProcessingResult);
|
||||
}
|
||||
|
||||
@PUT
|
||||
|
||||
+90
-53
@@ -18,60 +18,97 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.constants;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ShareAccountApiConstants {
|
||||
|
||||
//Command Strings
|
||||
String APPROVE_COMMAND = "approve" ;
|
||||
String REJECT_COMMAND = "reject" ;
|
||||
String APPLY_ADDITIONALSHARES_COMMAND = "applyadditionalshares" ;
|
||||
String APPROVE_ADDITIONSHARES_COMMAND = "approveadditionalshares" ;
|
||||
String REJECT_ADDITIONSHARES_COMMAND = "rejectadditionalshares" ;
|
||||
|
||||
//
|
||||
String id_paramname = "id" ;
|
||||
|
||||
String clientid_paramname = "clientId" ;
|
||||
|
||||
String productid_paramname = "productId" ;
|
||||
|
||||
String submitteddate_paramname = "submittedDate" ;
|
||||
|
||||
String approveddate_paramname = "approvedDate" ;
|
||||
|
||||
String fieldofferid_paramname = "fieldOfficerId" ;
|
||||
|
||||
String externalid_paramname = "externalId" ;
|
||||
|
||||
String currency_paramname = "currencyCode" ;
|
||||
|
||||
String digitsafterdecimal_paramname = "digitsAfterDecimal" ;
|
||||
|
||||
String inmultiplesof_paramname = "inMultiplesOf" ;
|
||||
|
||||
String purchasedshares_paramname = "purchasedShares" ;
|
||||
|
||||
String additionalshares_paramname = "additionalShares" ;
|
||||
|
||||
String suspenseaccount_paramname = "suspenseAccount" ;
|
||||
|
||||
String equityaccount_paramname = "equityAccount" ;
|
||||
|
||||
String savingsaccountid_paramname = "savingsAccountId" ;
|
||||
|
||||
String lockperiod_paramname = "lockPeriod" ;
|
||||
|
||||
String minimumactiveperiodfordividends_paramname = "minimumActivePeriodForDividends" ;
|
||||
|
||||
String allowdividendcalculationforinactiveclients_paramname = "allowDividendCalculationForInactiveClients" ;
|
||||
|
||||
String charges_paramname = "charges" ;
|
||||
|
||||
String purchaseddate_paramname = "purchasedDate" ;
|
||||
|
||||
String numberofshares_paramname = "numberOfShares" ;
|
||||
|
||||
String purchasedprice_paramname = "purchasedPrice" ;
|
||||
|
||||
public static final String amountParamName = "amount";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
public static final String dueAsOfDateParamName = "dueDate";
|
||||
public static final String feeIntervalParamName = "feeInterval";
|
||||
public static final String feeOnMonthDayParamName = "feeOnMonthDay";
|
||||
public static final String localeParamName = "locale";
|
||||
|
||||
// Command Strings
|
||||
String APPROVE_COMMAND = "approve";
|
||||
String REJECT_COMMAND = "reject";
|
||||
String APPLY_ADDITIONALSHARES_COMMAND = "applyadditionalshares";
|
||||
String APPROVE_ADDITIONSHARES_COMMAND = "approveadditionalshares";
|
||||
String REJECT_ADDITIONSHARES_COMMAND = "rejectadditionalshares";
|
||||
|
||||
//
|
||||
String locale_paramname = "locale" ;
|
||||
|
||||
String dateformat_paramname = "dateFormat" ;
|
||||
|
||||
String id_paramname = "id";
|
||||
|
||||
String clientid_paramname = "clientId";
|
||||
|
||||
String productid_paramname = "productId";
|
||||
|
||||
String submitteddate_paramname = "submittedDate";
|
||||
|
||||
String approveddate_paramname = "approvedDate";
|
||||
|
||||
String activatedate_paramname = "activatedDate" ;
|
||||
|
||||
String fieldofferid_paramname = "fieldOfficerId";
|
||||
|
||||
String externalid_paramname = "externalId";
|
||||
|
||||
String currency_paramname = "currencyCode";
|
||||
|
||||
String digitsafterdecimal_paramname = "digitsAfterDecimal";
|
||||
|
||||
String inmultiplesof_paramname = "inMultiplesOf";
|
||||
|
||||
String requestedshares_paramname = "requestedShares";
|
||||
|
||||
String savingsaccountid_paramname = "savingsAccountId";
|
||||
|
||||
String lockinperiod_paramname = "lockinPeriodFrequency";
|
||||
|
||||
String lockperiodfrequencytype_paramname = "lockinPeriodFrequencyType";
|
||||
|
||||
String minimumactiveperiod_paramname = "minimumActivePeriod";
|
||||
|
||||
String minimumactiveperiodfrequencytype_paramname = "minimumActivePeriodFrequencyType";
|
||||
|
||||
String allowdividendcalculationforinactiveclients_paramname = "allowDividendCalculationForInactiveClients";
|
||||
|
||||
String charges_paramname = "charges";
|
||||
|
||||
String applicationdate_param = "applicationDate";
|
||||
|
||||
String purchaseddate_paramname = "purchasedDate";
|
||||
|
||||
String numberofshares_paramname = "numberOfShares";
|
||||
|
||||
String purchasedprice_paramname = "unitPrice";
|
||||
|
||||
String note_paramname = "note" ;
|
||||
|
||||
public String requesteddate_paramname = "requestedDate" ;
|
||||
|
||||
public String additionalshares_paramname = "additionalshares" ;
|
||||
|
||||
public String closeddate_paramname = "closedDate" ;
|
||||
|
||||
Set<String> supportedParameters = new HashSet<>(Arrays.asList(locale_paramname, dateformat_paramname, id_paramname,clientid_paramname, productid_paramname,
|
||||
submitteddate_paramname,approveddate_paramname, externalid_paramname, currency_paramname, digitsafterdecimal_paramname,
|
||||
inmultiplesof_paramname, requestedshares_paramname,savingsaccountid_paramname,lockinperiod_paramname,
|
||||
lockperiodfrequencytype_paramname,minimumactiveperiod_paramname, minimumactiveperiodfrequencytype_paramname,
|
||||
allowdividendcalculationforinactiveclients_paramname, charges_paramname, applicationdate_param,
|
||||
purchaseddate_paramname,numberofshares_paramname,purchasedprice_paramname));
|
||||
|
||||
Set<String> approvalParameters = new HashSet<>(Arrays.asList(locale_paramname, dateformat_paramname, approveddate_paramname, note_paramname));
|
||||
|
||||
Set<String> activateParameters = new HashSet<>(Arrays.asList(locale_paramname, dateformat_paramname, activatedate_paramname));
|
||||
|
||||
Set<String> closeParameters = new HashSet<>(Arrays.asList(locale_paramname, dateformat_paramname, closeddate_paramname, note_paramname));
|
||||
|
||||
Set<String> addtionalSharesParameters = new HashSet<>(Arrays.asList(locale_paramname, requesteddate_paramname, requestedshares_paramname, purchasedprice_paramname, dateformat_paramname));
|
||||
}
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
public class PurchasedSharesData {
|
||||
|
||||
private final Date purchasedDate ;
|
||||
|
||||
private final Long numberOfShares ;
|
||||
|
||||
private final BigDecimal purchasedPrice ;
|
||||
|
||||
private final String status ;
|
||||
|
||||
public PurchasedSharesData(final Date purchasedDate, final Long numberOfShares, final BigDecimal purchasedPrice, final String status) {
|
||||
this.purchasedDate = purchasedDate ;
|
||||
this.numberOfShares = numberOfShares ;
|
||||
this.purchasedPrice = purchasedPrice ;
|
||||
this.status = status ;
|
||||
}
|
||||
|
||||
|
||||
public Date getPurchasedDate() {
|
||||
return this.purchasedDate;
|
||||
}
|
||||
|
||||
|
||||
public Long getNumberOfShares() {
|
||||
return this.numberOfShares;
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal getPurchasedPrice() {
|
||||
return this.purchasedPrice;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return this.status ;
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.data;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
|
||||
public class ShareAccountData implements AccountData{
|
||||
|
||||
private Long id;
|
||||
|
||||
private String accountNo;
|
||||
|
||||
private String externalId;
|
||||
|
||||
private Long productId;
|
||||
|
||||
private String productName;
|
||||
|
||||
private String loanProductDescription;
|
||||
|
||||
private Long fieldOfficerId;
|
||||
|
||||
private String fieldOfficerName;
|
||||
|
||||
private Long clientId;
|
||||
|
||||
private String clientName;
|
||||
|
||||
private Long clientOfficeId;
|
||||
|
||||
private CurrencyData currency;
|
||||
|
||||
private Date submittedDate;
|
||||
|
||||
private Date approvedDate;
|
||||
|
||||
private Collection<PurchasedSharesData> purchasedShares;
|
||||
|
||||
private GLAccountData suspenseAccount;
|
||||
|
||||
private GLAccountData equityAccount;
|
||||
|
||||
private Long savingsAccountId;
|
||||
|
||||
private EnumOptionData lockPeriod;
|
||||
|
||||
private EnumOptionData minimumActivePeriodForDividends;
|
||||
|
||||
private Boolean allowDividendCalculationForInactiveClients;
|
||||
|
||||
private Collection<ShareChargeData> charges ;
|
||||
|
||||
private String status ;
|
||||
|
||||
public ShareAccountData(final Long id, final String accountNo, final Long clientId, final String clientName, final Long productId, final String productName,
|
||||
final Long fieldOfficerId, final String externalId, final Date submittedDate, final Collection<PurchasedSharesData> purchasedShares, final GLAccountData suspenseAccount,
|
||||
final GLAccountData equityAccount, final EnumOptionData lockPeriod, final EnumOptionData minimumActivePeriodForDividends,
|
||||
final Boolean allowDividendCalculationForInactiveClients, final Collection<ShareChargeData> charges, final String status) {
|
||||
this.id = id ;
|
||||
this.accountNo = accountNo ;
|
||||
this.clientId = clientId ;
|
||||
this.clientName = clientName ;
|
||||
this.productId = productId ;
|
||||
this.productName = productName ;
|
||||
this.fieldOfficerId = fieldOfficerId ;
|
||||
this.externalId = externalId ;
|
||||
this.submittedDate = submittedDate ;
|
||||
this.purchasedShares = purchasedShares ;
|
||||
this.suspenseAccount = suspenseAccount ;
|
||||
this.equityAccount = equityAccount ;
|
||||
this.lockPeriod = lockPeriod ;
|
||||
this.minimumActivePeriodForDividends = minimumActivePeriodForDividends ;
|
||||
this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients ;
|
||||
this.charges = charges ;
|
||||
this.status = status ;
|
||||
|
||||
}
|
||||
}
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.fineract.portfolio.accounts.data.PurchasedSharesData;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_purchasedshares")
|
||||
public class PurchasedShares extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "account_id", referencedColumnName = "id", nullable = false)
|
||||
private ShareAccount shareAccount ;
|
||||
|
||||
@Column(name = "purchased_date")
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date purchasedDate ;
|
||||
|
||||
@Column(name = "share_count")
|
||||
private Long totalShares ;
|
||||
|
||||
@Column(name = "share_price")
|
||||
private BigDecimal shareValue ;
|
||||
|
||||
@Column(name ="status")
|
||||
private String status = "Submitted";
|
||||
|
||||
protected PurchasedShares() {
|
||||
|
||||
}
|
||||
|
||||
public void setShareAccount(final ShareAccount shareAccount) {
|
||||
this.shareAccount = shareAccount ;
|
||||
}
|
||||
|
||||
public PurchasedShares(final Date purchasedDate, final Long totalShares, final BigDecimal shareValue) {
|
||||
this.purchasedDate = purchasedDate ;
|
||||
this.totalShares = totalShares ;
|
||||
this.shareValue = shareValue ;
|
||||
}
|
||||
|
||||
public PurchasedSharesData toData() {
|
||||
return new PurchasedSharesData(this.purchasedDate, this.totalShares, this.shareValue, this.status) ;
|
||||
}
|
||||
|
||||
public Date getPurchasedDate() {
|
||||
return this.purchasedDate ;
|
||||
}
|
||||
|
||||
public Long getTotalShares() {
|
||||
return this.totalShares ;
|
||||
}
|
||||
|
||||
public BigDecimal getPurchasePrice() {
|
||||
return this.shareValue ;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return this.status ;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status ;
|
||||
}
|
||||
}
|
||||
-333
@@ -1,333 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.accounts.data.PurchasedSharesData;
|
||||
import org.apache.fineract.portfolio.accounts.data.ShareAccountData;
|
||||
import org.apache.fineract.portfolio.accounts.data.ShareChargeData;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.shares.domain.ShareProduct;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_shareaccounts")
|
||||
public class ShareAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "client_id", nullable = true)
|
||||
private Client client ;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "product_id", nullable = true)
|
||||
private ShareProduct shareProduct ;
|
||||
|
||||
@Column(name = "submitted_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date submittedDate ;
|
||||
|
||||
@Column(name = "approved_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date approvedDate ;
|
||||
|
||||
@Column(name = "field_officer")
|
||||
private Long fieldOfficerId ;
|
||||
|
||||
@Column(name = "external_id")
|
||||
private String externalId ;
|
||||
|
||||
@Embedded
|
||||
private MonetaryCurrency currency;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "suspense_account", nullable = true)
|
||||
private GLAccount suspenseAccount ;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "equity_account", nullable = true)
|
||||
private GLAccount equityAccount ;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "savings_id", nullable = true)
|
||||
private SavingsAccount savingsAccount ;
|
||||
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccount", orphanRemoval = true)
|
||||
private Set<PurchasedShares> purchasedShares ;
|
||||
|
||||
@Column(name = "allow_dividends_inactive_clients")
|
||||
private Boolean allowDividendCalculationForInactiveClients;
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "lock_period", nullable = true)
|
||||
private PeriodFrequencyType lockPeriod;
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "dividend_active_period", nullable = true)
|
||||
private PeriodFrequencyType minimumActivePeriodForDividends;
|
||||
|
||||
@Column(name = "status")
|
||||
private String status = "Submitted"; //change it to enum
|
||||
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccount", orphanRemoval = true)
|
||||
private Set<ShareAccountCharge> charges ;
|
||||
|
||||
protected ShareAccount() {
|
||||
|
||||
}
|
||||
|
||||
public ShareAccount(final Client client, final ShareProduct shareProduct, final Date submittedDate, final Date approvedDate,
|
||||
final Long fieldOfficerId , final String externalId, final MonetaryCurrency currency, GLAccount suspenseAccount,
|
||||
final GLAccount equityAccount, final SavingsAccount savingsAccount, final Set<PurchasedShares> purchasedShares,
|
||||
final Boolean allowDividendCalculationForInactiveClients, final PeriodFrequencyType lockPeriod,
|
||||
final PeriodFrequencyType minimumActivePeriodForDividends, Set<ShareAccountCharge> charges,
|
||||
AppUser createdBy, DateTime createdDate, AppUser lastModifiedBy, DateTime lastModifiedDate) {
|
||||
this.client = client ;
|
||||
this.shareProduct = shareProduct ;
|
||||
this.submittedDate = submittedDate ;
|
||||
this.approvedDate = approvedDate ;
|
||||
this.fieldOfficerId = fieldOfficerId ;
|
||||
this.externalId = externalId ;
|
||||
this.currency = currency ;
|
||||
this.suspenseAccount = suspenseAccount ;
|
||||
this.equityAccount = equityAccount ;
|
||||
this.savingsAccount = savingsAccount ;
|
||||
this.purchasedShares = purchasedShares ;
|
||||
this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients ;
|
||||
this.lockPeriod = lockPeriod ;
|
||||
this.minimumActivePeriodForDividends = minimumActivePeriodForDividends ;
|
||||
this.charges = charges ;
|
||||
setCreatedBy(createdBy) ;
|
||||
setCreatedDate(createdDate) ;
|
||||
setLastModifiedBy(lastModifiedBy) ;
|
||||
setLastModifiedDate(lastModifiedDate) ;
|
||||
}
|
||||
|
||||
public boolean setShareProduct(final ShareProduct shareProduct) {
|
||||
boolean toReturn = false ;
|
||||
if(!this.shareProduct.getId().equals(shareProduct.getId())) {
|
||||
this.shareProduct = shareProduct ;
|
||||
toReturn = true ;
|
||||
}
|
||||
return toReturn ;
|
||||
}
|
||||
|
||||
public ShareProduct getShareProduct() {
|
||||
return this.shareProduct ;
|
||||
}
|
||||
|
||||
public boolean setSubmittedDate(final Date submittedDate) {
|
||||
boolean toReturn = false ;
|
||||
if(!this.submittedDate.equals(submittedDate)) {
|
||||
this.submittedDate = submittedDate ;
|
||||
toReturn = true ;
|
||||
}
|
||||
return toReturn ;
|
||||
}
|
||||
|
||||
public boolean setApprovedDate(final Date approvedDate) {
|
||||
boolean toReturn = false ;
|
||||
if(!this.approvedDate.equals(approvedDate)) {
|
||||
this.approvedDate = approvedDate ;
|
||||
toReturn = true ;
|
||||
}
|
||||
return toReturn ;
|
||||
}
|
||||
|
||||
public boolean setFieldOfficer(final Long fieldOfficerId) {
|
||||
boolean toReturn = false ;
|
||||
if(!this.fieldOfficerId.equals(fieldOfficerId)) {
|
||||
this.fieldOfficerId = fieldOfficerId ;
|
||||
toReturn = true ;
|
||||
}
|
||||
return toReturn ;
|
||||
}
|
||||
|
||||
public boolean setExternalId(final String externalId) {
|
||||
boolean toReturn = false ;
|
||||
if(!this.externalId.equals(externalId)) {
|
||||
this.externalId = externalId ;
|
||||
toReturn = true ;
|
||||
}
|
||||
return toReturn ;
|
||||
}
|
||||
|
||||
public boolean setSuspenseAccount(GLAccount suspenseAccount) {
|
||||
boolean returnValue = false;
|
||||
if (!this.suspenseAccount.getId().equals(suspenseAccount.getId())) {
|
||||
this.suspenseAccount = suspenseAccount;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setEquityAccount(GLAccount equityAccount) {
|
||||
boolean returnValue = false;
|
||||
if (!this.equityAccount.getId().equals(equityAccount.getId())) {
|
||||
this.equityAccount = equityAccount;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setSavingsAccount(final SavingsAccount savingsAccount) {
|
||||
boolean returnValue = false;
|
||||
if (!this.savingsAccount.getId().equals(savingsAccount.getId())) {
|
||||
this.savingsAccount = savingsAccount;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setPurchasedShares(Set<PurchasedShares> purchasedShares) {
|
||||
this.purchasedShares = purchasedShares ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
public boolean setAllowDividendCalculationForInactiveClients(Boolean allowDividendCalculationForInactiveClients) {
|
||||
boolean returnValue = false;
|
||||
if (!this.allowDividendCalculationForInactiveClients.equals(allowDividendCalculationForInactiveClients)) {
|
||||
this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setLockPeriod(final PeriodFrequencyType lockPeriod) {
|
||||
boolean returnValue = false;
|
||||
if (!this.lockPeriod.equals(lockPeriod)) {
|
||||
this.lockPeriod = lockPeriod;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setminimumActivePeriodForDividends(final PeriodFrequencyType minimumActivePeriodForDividends) {
|
||||
boolean returnValue = false;
|
||||
if (!this.minimumActivePeriodForDividends.equals(minimumActivePeriodForDividends)) {
|
||||
this.minimumActivePeriodForDividends = minimumActivePeriodForDividends;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setCharges(final Set<ShareAccountCharge> charges) {
|
||||
this.charges = charges ;
|
||||
return true ;
|
||||
}
|
||||
//FIXME: Remove this
|
||||
public void setTempId(Long id) {
|
||||
setId(id) ;
|
||||
}
|
||||
|
||||
public ShareAccountData toData() {
|
||||
String accountNo = "000025900"+getId() ;
|
||||
Collection<PurchasedSharesData> purchasedSharesdata = new ArrayList<>();
|
||||
for(PurchasedShares val: purchasedShares) {
|
||||
purchasedSharesdata.add(new PurchasedSharesData(val.getPurchasedDate(), val.getTotalShares(), val.getPurchasePrice(), val.getStatus())) ;
|
||||
}
|
||||
Collection<ShareChargeData> chargesdata = new ArrayList<>();
|
||||
for(ShareAccountCharge charge: charges) {
|
||||
chargesdata.add(new ShareChargeData(charge.getAccountId(), charge.getChargeId())) ;
|
||||
}
|
||||
|
||||
GLAccountData suspenseAccount1 = new GLAccountData(suspenseAccount.getId(), suspenseAccount.getName(), suspenseAccount.getGlCode());
|
||||
GLAccountData equityAccount1 = new GLAccountData(equityAccount.getId(), equityAccount.getName(), equityAccount.getGlCode());
|
||||
EnumOptionData lock = new EnumOptionData(this.lockPeriod.getValue().longValue(), this.lockPeriod.getCode(),
|
||||
this.lockPeriod.toString());
|
||||
EnumOptionData mini = new EnumOptionData(this.minimumActivePeriodForDividends.getValue().longValue(), this.minimumActivePeriodForDividends.getCode(),
|
||||
this.minimumActivePeriodForDividends.toString());;
|
||||
|
||||
ShareAccountData data = new ShareAccountData(getId(), accountNo, this.client.getId(), this.client.getDisplayName(), this.shareProduct.getId(),
|
||||
this.shareProduct.getProductName(), fieldOfficerId, externalId,
|
||||
submittedDate, purchasedSharesdata, suspenseAccount1, equityAccount1, lock, mini,
|
||||
allowDividendCalculationForInactiveClients, chargesdata, status) ;
|
||||
return data ;
|
||||
}
|
||||
|
||||
public Long getClientId() {
|
||||
return this.client.getId() ;
|
||||
}
|
||||
|
||||
public String getClientName() {
|
||||
return this.client.getDisplayName() ;
|
||||
}
|
||||
|
||||
public Long getTotalShares() {
|
||||
long value = 0 ;
|
||||
for(PurchasedShares val: purchasedShares) {
|
||||
if(val.getStatus().equals("Approved")) {
|
||||
value += val.getTotalShares().longValue() ;
|
||||
}
|
||||
}
|
||||
return new Long(value) ;
|
||||
}
|
||||
|
||||
public String getShareAccountNo() {
|
||||
return "000025900"+getId() ;
|
||||
}
|
||||
|
||||
public String getSavingsAccountNo() {
|
||||
return this.savingsAccount.getAccountNumber() ;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status ;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return this.status ;
|
||||
}
|
||||
|
||||
public void addAddtionalShares(Set<PurchasedShares> additionalShares) {
|
||||
this.purchasedShares.addAll(additionalShares) ;
|
||||
}
|
||||
|
||||
public Set<PurchasedShares> getPurchasedShares() {
|
||||
return this.purchasedShares ;
|
||||
}
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.domain;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_shareaccounts_charges")
|
||||
public class ShareAccountCharge extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "account_id", referencedColumnName = "id", nullable = false)
|
||||
private ShareAccount shareAccount;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "charge_id", referencedColumnName = "id", nullable = false)
|
||||
private Charge charge;
|
||||
|
||||
protected ShareAccountCharge() {
|
||||
|
||||
}
|
||||
|
||||
public ShareAccountCharge(final ShareAccount shareAccount, final Charge charge) {
|
||||
this.shareAccount = shareAccount;
|
||||
this.charge = charge;
|
||||
}
|
||||
|
||||
public ShareAccountCharge(final Charge charge) {
|
||||
this.charge = charge;
|
||||
}
|
||||
|
||||
public void setShareAccount(ShareAccount shareAccount) {
|
||||
this.shareAccount = shareAccount;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return this.shareAccount.getId() ;
|
||||
}
|
||||
|
||||
public Long getChargeId() {
|
||||
return this.charge.getId() ;
|
||||
}
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.domain;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.fineract.portfolio.shares.domain.ShareProductTempRepository;
|
||||
|
||||
|
||||
public class ShareAccountTempRepository {
|
||||
|
||||
private final static ShareAccountTempRepository instance = new ShareAccountTempRepository() ;
|
||||
|
||||
private Map<Long, ShareAccount> cache = new HashMap<>() ;
|
||||
|
||||
private ShareAccountTempRepository() {
|
||||
|
||||
}
|
||||
|
||||
public static ShareAccountTempRepository getInstance() {
|
||||
return instance ;
|
||||
}
|
||||
|
||||
public void save(ShareAccount account) {
|
||||
Long id = new Long(cache.size()+1) ;
|
||||
account.setTempId(id) ;
|
||||
cache.put(id, account) ;
|
||||
ShareProductTempRepository.getInstance().addAccount(account.getShareProduct().getId(), account) ;
|
||||
}
|
||||
|
||||
public ShareAccount findOne(Long id) {
|
||||
return cache.get(id) ;
|
||||
}
|
||||
|
||||
public Collection<ShareAccount> findAll() {
|
||||
return cache.values() ;
|
||||
}
|
||||
}
|
||||
-333
@@ -1,333 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.serialization;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
|
||||
import org.apache.fineract.portfolio.accounts.domain.PurchasedShares;
|
||||
import org.apache.fineract.portfolio.accounts.domain.ShareAccount;
|
||||
import org.apache.fineract.portfolio.accounts.domain.ShareAccountCharge;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
|
||||
import org.apache.fineract.portfolio.products.exception.ProductNotFoundException;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.shares.domain.ShareProduct;
|
||||
import org.apache.fineract.portfolio.shares.domain.ShareProductTempRepository;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Service
|
||||
public class ShareAccountDataSerializer {
|
||||
|
||||
private final Set<String> supportedParameters = new HashSet<>(Arrays.asList(""));
|
||||
|
||||
private final PlatformSecurityContext platformSecurityContext;
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
|
||||
private final GLAccountRepositoryWrapper glAccountRepository;
|
||||
|
||||
private final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper;
|
||||
|
||||
private final ClientRepositoryWrapper clientRepositoryWrapper;
|
||||
|
||||
@Autowired
|
||||
public ShareAccountDataSerializer(final PlatformSecurityContext platformSecurityContext, final FromJsonHelper fromApiJsonHelper,
|
||||
final ChargeRepositoryWrapper chargeRepository, GLAccountRepositoryWrapper glAccountRepository,
|
||||
final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper, final ClientRepositoryWrapper clientRepositoryWrapper) {
|
||||
this.platformSecurityContext = platformSecurityContext;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.chargeRepository = chargeRepository;
|
||||
this.glAccountRepository = glAccountRepository;
|
||||
this.savingsAccountRepositoryWrapper = savingsAccountRepositoryWrapper;
|
||||
this.clientRepositoryWrapper = clientRepositoryWrapper;
|
||||
}
|
||||
|
||||
public ShareAccount validateAndCreate(JsonCommand jsonCommand) {
|
||||
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
//this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), supportedParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
|
||||
final Long clientId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.clientid_paramname, element);
|
||||
final Long productId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.productid_paramname, element);
|
||||
final Date submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname, element)
|
||||
.toDate();
|
||||
// On creation submitted date will not be there.
|
||||
final Long fieldOfficerId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.fieldofferid_paramname, element);
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element);
|
||||
|
||||
Long suspenseAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.suspenseaccount_paramname, element);
|
||||
Long equityAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.equityaccount_paramname, element);
|
||||
Long savingsAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.savingsaccountid_paramname, element);
|
||||
Set<PurchasedShares> sharesPurchased = asemblePurchasedShares(element);
|
||||
|
||||
Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element);
|
||||
PeriodFrequencyType lockPeriod = extractPeriodType(ShareAccountApiConstants.lockperiod_paramname, element);
|
||||
PeriodFrequencyType minimumActivePeriod = extractPeriodType(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname,
|
||||
element);
|
||||
|
||||
Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
|
||||
GLAccount suspenseAccount = glAccountRepository.findOneWithNotFoundDetection(suspenseAccountId);
|
||||
GLAccount equityAccount = glAccountRepository.findOneWithNotFoundDetection(equityAccountId);
|
||||
SavingsAccount savingsAccount = this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId);
|
||||
ShareProduct shareProduct = ShareProductTempRepository.getInstance().fineOne(productId);
|
||||
if(shareProduct == null) {
|
||||
throw new ProductNotFoundException(productId, "Share") ;
|
||||
}
|
||||
final MonetaryCurrency currency = shareProduct.getCurrency() ;
|
||||
Set<ShareAccountCharge> charges = assembleListOfAccountCharges(element, currency.getCode());
|
||||
AppUser modifiedBy = null;
|
||||
DateTime modifiedOn = null;
|
||||
Date approvedDate = null;
|
||||
AppUser createdBy = platformSecurityContext.authenticatedUser();
|
||||
DateTime createdDate = DateUtils.getLocalDateTimeOfTenant().toDateTime();
|
||||
ShareAccount account = new ShareAccount(client, shareProduct, submittedDate, approvedDate, fieldOfficerId, externalId, currency,
|
||||
suspenseAccount, equityAccount, savingsAccount, sharesPurchased, allowdividendsForInactiveClients, lockPeriod,
|
||||
minimumActivePeriod, charges, createdBy, createdDate, modifiedBy, modifiedOn);
|
||||
|
||||
for(PurchasedShares pur: sharesPurchased) {
|
||||
pur.setShareAccount(account) ;
|
||||
}
|
||||
|
||||
for(ShareAccountCharge charge: charges) {
|
||||
charge.setShareAccount(account) ;
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndUpdate(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
//this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), supportedParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.productid_paramname, element)) {
|
||||
final Long productId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.productid_paramname, element);
|
||||
ShareProduct shareProduct = ShareProductTempRepository.getInstance().fineOne(productId);
|
||||
if(account.setShareProduct(shareProduct)) {
|
||||
actualChanges.put(ShareAccountApiConstants.productid_paramname, shareProduct) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.submitteddate_paramname, element)) {
|
||||
final Date submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname, element)
|
||||
.toDate();
|
||||
if(account.setSubmittedDate(submittedDate)) {
|
||||
actualChanges.put(ShareAccountApiConstants.submitteddate_paramname, submittedDate) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.fieldofferid_paramname, element)) {
|
||||
final Long fieldOfficerId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.fieldofferid_paramname, element);
|
||||
if(account.setFieldOfficer(fieldOfficerId)){
|
||||
actualChanges.put(ShareAccountApiConstants.fieldofferid_paramname, fieldOfficerId) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.externalid_paramname, element)) {
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element);
|
||||
if(account.setExternalId(externalId)) {
|
||||
actualChanges.put(ShareAccountApiConstants.externalid_paramname, externalId) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.suspenseaccount_paramname, element)) {
|
||||
Long suspenseAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.suspenseaccount_paramname, element);
|
||||
GLAccount suspenseAccount = glAccountRepository.findOneWithNotFoundDetection(suspenseAccountId);
|
||||
if(account.setSuspenseAccount(suspenseAccount)) {
|
||||
actualChanges.put(ShareAccountApiConstants.suspenseaccount_paramname, suspenseAccount) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.equityaccount_paramname, element)) {
|
||||
Long equityAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.equityaccount_paramname, element);
|
||||
GLAccount equityAccount = glAccountRepository.findOneWithNotFoundDetection(equityAccountId);
|
||||
if(account.setEquityAccount(equityAccount)) {
|
||||
actualChanges.put(ShareAccountApiConstants.equityaccount_paramname, equityAccount) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.savingsaccountid_paramname, element)) {
|
||||
Long savingsAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.savingsaccountid_paramname, element);
|
||||
SavingsAccount savingsAccount = this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId);
|
||||
if(account.setSavingsAccount(savingsAccount)) {
|
||||
actualChanges.put(ShareAccountApiConstants.savingsaccountid_paramname, savingsAccount) ;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.purchasedshares_paramname, element)) {
|
||||
Set<PurchasedShares> sharesPurchased = asemblePurchasedShares(element);
|
||||
account.setPurchasedShares(sharesPurchased) ;
|
||||
actualChanges.put(ShareAccountApiConstants.purchasedshares_paramname, sharesPurchased) ;
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element)) {
|
||||
Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element);
|
||||
if (account.setAllowDividendCalculationForInactiveClients(allowdividendsForInactiveClients)) {
|
||||
actualChanges.put(ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname,
|
||||
allowdividendsForInactiveClients);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.lockperiod_paramname, element)) {
|
||||
PeriodFrequencyType lockPeriod = extractPeriodType(ShareAccountApiConstants.lockperiod_paramname, element);
|
||||
if (account.setLockPeriod(lockPeriod)) {
|
||||
actualChanges.put(ShareAccountApiConstants.lockperiod_paramname, lockPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname, element)) {
|
||||
PeriodFrequencyType minimumActivePeriod = extractPeriodType(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname,
|
||||
element);
|
||||
if (account.setminimumActivePeriodForDividends(minimumActivePeriod)) {
|
||||
actualChanges.put(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname, minimumActivePeriod);
|
||||
}
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) {
|
||||
ShareProduct shareProduct = account.getShareProduct() ;
|
||||
Set<ShareAccountCharge> charges = assembleListOfAccountCharges(element, shareProduct.getCurrency().getCode());
|
||||
if(account.setCharges(charges)) {
|
||||
actualChanges.put(ShareAccountApiConstants.charges_paramname, charges);
|
||||
}
|
||||
}
|
||||
AppUser modifiedBy = platformSecurityContext.authenticatedUser();
|
||||
DateTime modifiedOn = DateUtils.getLocalDateTimeOfTenant().toDateTime();
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private Set<ShareAccountCharge> assembleListOfAccountCharges(final JsonElement element, final String currencyCode) {
|
||||
final Set<ShareAccountCharge> charges = new HashSet<>();
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) {
|
||||
JsonArray chargesArray = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.charges_paramname, element);
|
||||
if (chargesArray != null) {
|
||||
for (int i = 0; i < chargesArray.size(); i++) {
|
||||
final JsonObject jsonObject = chargesArray.get(i).getAsJsonObject();
|
||||
if (jsonObject.has("id")) {
|
||||
final Long id = jsonObject.get("id").getAsLong();
|
||||
final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(id);
|
||||
if (!currencyCode.equals(charge.getCurrencyCode())) {
|
||||
final String errorMessage = "Charge and Share Account must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.share.account", errorMessage);
|
||||
}
|
||||
ShareAccountCharge accountCharge = new ShareAccountCharge(charge);
|
||||
charges.add(accountCharge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return charges;
|
||||
}
|
||||
|
||||
private PeriodFrequencyType extractPeriodType(String paramName, final JsonElement element) {
|
||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.INVALID;
|
||||
frequencyType = PeriodFrequencyType.fromInt(this.fromApiJsonHelper.extractIntegerWithLocaleNamed(paramName, element));
|
||||
return frequencyType;
|
||||
}
|
||||
|
||||
private Set<PurchasedShares> asemblePurchasedShares(final JsonElement element) {
|
||||
Set<PurchasedShares> set = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.purchasedshares_paramname, element)) {
|
||||
set = new HashSet<>();
|
||||
JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.purchasedshares_paramname, element);
|
||||
for (JsonElement arrayElement : array) {
|
||||
LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.purchaseddate_paramname,
|
||||
arrayElement);
|
||||
final Long shares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.numberofshares_paramname, arrayElement);
|
||||
final BigDecimal shareValue = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
ShareAccountApiConstants.purchasedprice_paramname, arrayElement);
|
||||
|
||||
PurchasedShares obj = new PurchasedShares(localDate.toDate(), shares, shareValue);
|
||||
set.add(obj);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
public Set<PurchasedShares> asembleAdditionalShares(final JsonElement element) {
|
||||
Set<PurchasedShares> set = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.additionalshares_paramname, element)) {
|
||||
set = new HashSet<>();
|
||||
JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.additionalshares_paramname, element);
|
||||
for (JsonElement arrayElement : array) {
|
||||
LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.purchaseddate_paramname,
|
||||
arrayElement);
|
||||
final Long shares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.numberofshares_paramname, arrayElement);
|
||||
final BigDecimal shareValue = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||
ShareAccountApiConstants.purchasedprice_paramname, arrayElement);
|
||||
|
||||
PurchasedShares obj = new PurchasedShares(localDate.toDate(), shares, shareValue);
|
||||
set.add(obj);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
}
|
||||
+7
-5
@@ -23,12 +23,14 @@ import java.util.Set;
|
||||
|
||||
import org.apache.fineract.portfolio.accounts.data.AccountData;
|
||||
|
||||
|
||||
public interface AccountReadPlatformService {
|
||||
|
||||
public AccountData retrieveOne(Long id) ;
|
||||
|
||||
public Collection<AccountData> retrieveAll() ;
|
||||
|
||||
public AccountData retrieveTemplate(final Long clientId, final Long productId);
|
||||
|
||||
public AccountData retrieveOne(Long id, boolean includeTemplate);
|
||||
|
||||
public Collection<AccountData> retrieveAll();
|
||||
|
||||
public Set<String> getResponseDataParams();
|
||||
|
||||
}
|
||||
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.fineract.portfolio.accounts.constants.AccountsApiConstants;
|
||||
import org.apache.fineract.portfolio.accounts.data.AccountData;
|
||||
import org.apache.fineract.portfolio.accounts.domain.ShareAccount;
|
||||
import org.apache.fineract.portfolio.accounts.domain.ShareAccountTempRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service(value = "share"+AccountsApiConstants.READPLATFORM_NAME)
|
||||
public class ShareAccountReadPlatformServiceImpl implements AccountReadPlatformService{
|
||||
|
||||
@Override
|
||||
public AccountData retrieveOne(Long id) {
|
||||
return ShareAccountTempRepository.getInstance().findOne(id).toData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AccountData> retrieveAll() {
|
||||
Collection<ShareAccount> collection = ShareAccountTempRepository.getInstance().findAll() ;
|
||||
Set<AccountData> set = new HashSet<>() ;
|
||||
for(ShareAccount data: collection) {
|
||||
set.add(data.toData()) ;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getResponseDataParams() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.accounts.domain.ShareAccount;
|
||||
import org.apache.fineract.portfolio.accounts.domain.ShareAccountTempRepository;
|
||||
import org.apache.fineract.portfolio.accounts.exceptions.ShareAccountNotFoundException;
|
||||
import org.apache.fineract.portfolio.accounts.serialization.ShareAccountDataSerializer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareAccountWritePlatformService {
|
||||
|
||||
private final ShareAccountDataSerializer accountDataSerializer;
|
||||
|
||||
@Autowired
|
||||
public ShareAccountWritePlatformServiceJpaRepositoryImpl(final ShareAccountDataSerializer accountDataSerializer) {
|
||||
this.accountDataSerializer = accountDataSerializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult createShareAccount(JsonCommand jsonCommand) {
|
||||
try {
|
||||
ShareAccount account = this.accountDataSerializer.validateAndCreate(jsonCommand);
|
||||
ShareAccountTempRepository.getInstance().save(account);
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(jsonCommand.commandId()) //
|
||||
.withEntityId(account.getId()) //
|
||||
.build();
|
||||
} catch (final DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(jsonCommand, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult updateShareAccount(Long accountId, JsonCommand jsonCommand) {
|
||||
try {
|
||||
ShareAccount account = ShareAccountTempRepository.getInstance().findOne(accountId);
|
||||
if (account == null) {
|
||||
throw new ShareAccountNotFoundException(accountId) ;
|
||||
}
|
||||
Map<String, Object> changes = this.accountDataSerializer.validateAndUpdate(jsonCommand, account);
|
||||
if (!changes.isEmpty()) {
|
||||
// Save the data here
|
||||
}
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(jsonCommand.commandId()) //
|
||||
.withEntityId(accountId) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
handleDataIntegrityIssues(jsonCommand, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+38
-7
@@ -31,6 +31,7 @@ import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountChargeData;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
|
||||
@@ -69,6 +70,9 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
private final List<EnumOptionData> savingsChargeTimeTypeOptions;
|
||||
private final List<EnumOptionData> clientChargeCalculationTypeOptions;
|
||||
private final List<EnumOptionData> clientChargeTimeTypeOptions;
|
||||
private final List<EnumOptionData> shareChargeCalculationTypeOptions;
|
||||
private final List<EnumOptionData> shareChargeTimeTypeOptions;
|
||||
|
||||
private final List<EnumOptionData> feeFrequencyOptions;
|
||||
|
||||
private final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions;
|
||||
@@ -81,14 +85,17 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final List<EnumOptionData> savingsChargeCalculationTypeOptions, final List<EnumOptionData> savingsChargeTimeTypeOptions,
|
||||
final List<EnumOptionData> clientChargeCalculationTypeOptions, final List<EnumOptionData> clientChargeTimeTypeOptions,
|
||||
final List<EnumOptionData> feeFrequencyOptions, final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions,
|
||||
final Collection<TaxGroupData> taxGroupOptions) {
|
||||
final Collection<TaxGroupData> taxGroupOptions, final List<EnumOptionData> shareChargeCalculationTypeOptions,
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions) {
|
||||
final GLAccountData account = null;
|
||||
final TaxGroupData taxGroupData = null;
|
||||
|
||||
return new ChargeData(null, null, null, null, null, null, null, null, false, false, taxGroupData, currencyOptions,
|
||||
chargeCalculationTypeOptions, chargeAppliesToOptions, chargeTimeTypeOptions, chargePaymentModeOptions,
|
||||
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
|
||||
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, null, null, null, null,
|
||||
null, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions);
|
||||
null, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions,
|
||||
shareChargeTimeTypeOptions);
|
||||
}
|
||||
|
||||
public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) {
|
||||
@@ -99,7 +106,8 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
template.loanChargeTimeTypeOptions, template.savingsChargeCalculationTypeOptions, template.savingsChargeTimeTypeOptions,
|
||||
template.clientChargeCalculationTypeOptions, template.clientChargeTimeTypeOptions, charge.feeOnMonthDay,
|
||||
charge.feeInterval, charge.minCap, charge.maxCap, charge.feeFrequency, template.feeFrequencyOptions,
|
||||
charge.incomeOrLiabilityAccount, template.incomeOrLiabilityAccountOptions, template.taxGroupOptions);
|
||||
charge.incomeOrLiabilityAccount, template.incomeOrLiabilityAccountOptions, template.taxGroupOptions,
|
||||
template.shareChargeCalculationTypeOptions, template.shareChargeTimeTypeOptions);
|
||||
}
|
||||
|
||||
public static ChargeData instance(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
|
||||
@@ -121,14 +129,15 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final List<EnumOptionData> clientChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> clientChargeTimeTypeOptions = null;
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions = null;
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions = null;
|
||||
final Collection<TaxGroupData> taxGroupOptions = null;
|
||||
|
||||
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
|
||||
penalty, active, taxGroupData, currencyOptions, chargeCalculationTypeOptions, chargeAppliesToOptions,
|
||||
chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions);
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions);
|
||||
}
|
||||
|
||||
public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) {
|
||||
@@ -159,6 +168,8 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final List<EnumOptionData> feeFrequencyOptions = null;
|
||||
final GLAccountData account = null;
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions = null;
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions = null;
|
||||
final TaxGroupData taxGroupData = null;
|
||||
final Collection<TaxGroupData> taxGroupOptions = null;
|
||||
return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode,
|
||||
@@ -166,7 +177,7 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
chargeTimeTypeOptions, chargePaymentModeOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, account,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions);
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions);
|
||||
}
|
||||
|
||||
private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency,
|
||||
@@ -180,7 +191,8 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
final List<EnumOptionData> clientChargeTimeTypeOptions, final MonthDay feeOnMonthDay, final Integer feeInterval,
|
||||
final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency,
|
||||
final List<EnumOptionData> feeFrequencyOptions, final GLAccountData account,
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions, final Collection<TaxGroupData> taxGroupOptions) {
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions, final Collection<TaxGroupData> taxGroupOptions,
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions, final List<EnumOptionData> shareChargeTimeTypeOptions) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.amount = amount;
|
||||
@@ -212,6 +224,8 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
this.incomeOrLiabilityAccountOptions = incomeOrLiabilityAccountOptions;
|
||||
this.taxGroup = taxGroupData;
|
||||
this.taxGroupOptions = taxGroupOptions;
|
||||
this.shareChargeCalculationTypeOptions = shareChargeCalculationTypeOptions;
|
||||
this.shareChargeTimeTypeOptions = shareChargeTimeTypeOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -264,6 +278,23 @@ public class ChargeData implements Comparable<ChargeData>, Serializable {
|
||||
this.feeInterval, isActive, inactivationDate);
|
||||
}
|
||||
|
||||
public ShareAccountChargeData toShareAccountChargeData() {
|
||||
|
||||
final Long shareChargeId = null;
|
||||
final Long shareAccountId = null;
|
||||
final BigDecimal amountPaid = BigDecimal.ZERO;
|
||||
final BigDecimal amountWaived = BigDecimal.ZERO;
|
||||
final BigDecimal amountWrittenOff = BigDecimal.ZERO;
|
||||
final BigDecimal amountOutstanding = BigDecimal.ZERO;
|
||||
final BigDecimal percentage = BigDecimal.ZERO;
|
||||
final BigDecimal amountPercentageAppliedTo = BigDecimal.ZERO;
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
final Boolean isActive = null;
|
||||
return new ShareAccountChargeData(shareChargeId, this.id, shareAccountId, this.name, this.currency, this.amount, amountPaid,
|
||||
amountWaived, amountWrittenOff, amountOutstanding, this.chargeTimeType, this.chargeCalculationType, percentage,
|
||||
amountPercentageAppliedTo, chargeOptions, isActive);
|
||||
}
|
||||
|
||||
public boolean isPenalty() {
|
||||
return this.penalty;
|
||||
}
|
||||
|
||||
+10
-3
@@ -23,8 +23,9 @@ public enum ChargeAppliesTo {
|
||||
INVALID(0, "chargeAppliesTo.invalid"), //
|
||||
LOAN(1, "chargeAppliesTo.loan"), //
|
||||
SAVINGS(2, "chargeAppliesTo.savings"), //
|
||||
CLIENT(3, "chargeAppliesTo.client");
|
||||
|
||||
CLIENT(3, "chargeAppliesTo.client"),
|
||||
SHARES(4, "chargeAppliesTo.shares");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
@@ -55,6 +56,9 @@ public enum ChargeAppliesTo {
|
||||
case 3:
|
||||
chargeAppliesToType = CLIENT;
|
||||
break;
|
||||
case 4:
|
||||
chargeAppliesToType = SHARES ;
|
||||
break ;
|
||||
default:
|
||||
chargeAppliesToType = INVALID;
|
||||
break;
|
||||
@@ -76,7 +80,10 @@ public enum ChargeAppliesTo {
|
||||
return this.value.equals(ChargeAppliesTo.CLIENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isSharesCharge() {
|
||||
return this.value.equals(SHARES.getValue()) ;
|
||||
}
|
||||
public static Object[] validValues() {
|
||||
return new Object[] { ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.getValue(), ChargeAppliesTo.CLIENT.getValue() };
|
||||
return new Object[] { ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.getValue(), ChargeAppliesTo.CLIENT.getValue(), ChargeAppliesTo.SHARES.getValue() };
|
||||
}
|
||||
}
|
||||
+8
@@ -53,10 +53,18 @@ public enum ChargeCalculationType {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForShares() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForClients() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForShareAccountActivation() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForTrancheDisbursement(){
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue()};
|
||||
}
|
||||
|
||||
+37
-9
@@ -19,7 +19,6 @@
|
||||
package org.apache.fineract.portfolio.charge.domain;
|
||||
|
||||
public enum ChargeTimeType {
|
||||
|
||||
INVALID(0, "chargeTimeType.invalid"), //
|
||||
DISBURSEMENT(1, "chargeTimeType.disbursement"), // only for loan charges
|
||||
SPECIFIED_DUE_DATE(2, "chargeTimeType.specifiedDueDate"), // for loan and
|
||||
@@ -30,9 +29,13 @@ public enum ChargeTimeType {
|
||||
MONTHLY_FEE(7, "chargeTimeType.monthlyFee"), // only for savings
|
||||
INSTALMENT_FEE(8, "chargeTimeType.instalmentFee"), // only for loan charges
|
||||
OVERDUE_INSTALLMENT(9, "chargeTimeType.overdueInstallment"), // only for
|
||||
OVERDRAFT_FEE(10, "chargeTimeType.overdraftFee"),// only for savings
|
||||
OVERDRAFT_FEE(10, "chargeTimeType.overdraftFee"), // only for savings
|
||||
WEEKLY_FEE(11, "chargeTimeType.weeklyFee"), // only for savings
|
||||
TRANCHE_DISBURSEMENT(12,"chargeTimeType.tranchedisbursement"); // only for loan
|
||||
TRANCHE_DISBURSEMENT(12, "chargeTimeType.tranchedisbursement"), // only for
|
||||
// loan
|
||||
SHAREACCOUNT_ACTIVATION(13, "chargeTimeType.activation"), // only for loan
|
||||
SHARE_PURCHASE(14, "chargeTimeType.sharespurchase"),
|
||||
SHARE_REDEEM(15, "chargeTimeType.sharesredeem");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -52,7 +55,8 @@ public enum ChargeTimeType {
|
||||
|
||||
public static Object[] validLoanValues() {
|
||||
return new Integer[] { ChargeTimeType.DISBURSEMENT.getValue(), ChargeTimeType.SPECIFIED_DUE_DATE.getValue(),
|
||||
ChargeTimeType.INSTALMENT_FEE.getValue(), ChargeTimeType.OVERDUE_INSTALLMENT.getValue(), ChargeTimeType.TRANCHE_DISBURSEMENT.getValue() };
|
||||
ChargeTimeType.INSTALMENT_FEE.getValue(), ChargeTimeType.OVERDUE_INSTALLMENT.getValue(),
|
||||
ChargeTimeType.TRANCHE_DISBURSEMENT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validLoanChargeValues() {
|
||||
@@ -70,6 +74,10 @@ public enum ChargeTimeType {
|
||||
return new Integer[] { ChargeTimeType.SPECIFIED_DUE_DATE.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validShareValues() {
|
||||
return new Integer[] { ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue(), ChargeTimeType.SHARE_PURCHASE.getValue(), ChargeTimeType.SHARE_REDEEM.getValue() };
|
||||
}
|
||||
|
||||
public static ChargeTimeType fromInt(final Integer chargeTime) {
|
||||
ChargeTimeType chargeTimeType = ChargeTimeType.INVALID;
|
||||
if (chargeTime != null) {
|
||||
@@ -110,6 +118,15 @@ public enum ChargeTimeType {
|
||||
case 12:
|
||||
chargeTimeType = TRANCHE_DISBURSEMENT;
|
||||
break;
|
||||
case 13:
|
||||
chargeTimeType = SHAREACCOUNT_ACTIVATION;
|
||||
break;
|
||||
case 14:
|
||||
chargeTimeType = SHARE_PURCHASE;
|
||||
break;
|
||||
case 15:
|
||||
chargeTimeType = SHARE_REDEEM;
|
||||
break;
|
||||
default:
|
||||
chargeTimeType = INVALID;
|
||||
break;
|
||||
@@ -167,16 +184,27 @@ public enum ChargeTimeType {
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeTime() {
|
||||
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee() || isMonthlyFee()
|
||||
|| isWeeklyFee() || isOverdraftFee();
|
||||
return isOnSpecifiedDueDate() || isSavingsActivation() || isSavingsClosure() || isWithdrawalFee() || isAnnualFee()
|
||||
|| isMonthlyFee() || isWeeklyFee() || isOverdraftFee();
|
||||
}
|
||||
|
||||
public boolean isOverdraftFee() {
|
||||
return this.value.equals(ChargeTimeType.OVERDRAFT_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isTrancheDisbursement(){
|
||||
return this.value.equals(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue());
|
||||
|
||||
public boolean isTrancheDisbursement() {
|
||||
return this.value.equals(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isShareAccountActivation() {
|
||||
return this.value.equals(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue());
|
||||
}
|
||||
|
||||
public boolean isSharesPurchase() {
|
||||
return this.value.equals(ChargeTimeType.SHARE_PURCHASE.getValue());
|
||||
}
|
||||
|
||||
public boolean isSharesRedeem() {
|
||||
return this.value.equals(ChargeTimeType.SHARE_REDEEM.getValue());
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when currency mismatch
|
||||
* occurs
|
||||
*/
|
||||
public class ShareAccountChargeWithoutMandatoryFieldException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ShareAccountChargeWithoutMandatoryFieldException(final String entity, final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg." + entity + "." + postFix + ".cannot.be.blank", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+28
-4
@@ -176,6 +176,25 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
.longGreaterThanZero();
|
||||
}
|
||||
|
||||
}else if(appliesTo.isSharesCharge()) {
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeTimeType", element);
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull();
|
||||
if (chargeTimeType != null) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType)
|
||||
.isOneOfTheseValues(ChargeTimeType.validShareValues());
|
||||
}
|
||||
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForShares());
|
||||
}
|
||||
|
||||
if(chargeTimeType != null && chargeTimeType.equals(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue())) {
|
||||
if(chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForShareAccountActivation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
|
||||
@@ -263,11 +282,11 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
final Collection<Object> validLoanValues = Arrays.asList(ChargeTimeType.validLoanValues());
|
||||
final Collection<Object> validSavingsValues = Arrays.asList(ChargeTimeType.validSavingsValues());
|
||||
final Collection<Object> validClientValues = Arrays.asList(ChargeTimeType.validClientValues());
|
||||
|
||||
final Collection<Object> validShareValues = Arrays.asList(ChargeTimeType.validShareValues()) ;
|
||||
final Collection<Object> allValidValues = new ArrayList<>(validLoanValues);
|
||||
allValidValues.addAll(validSavingsValues);
|
||||
allValidValues.addAll(validClientValues);
|
||||
|
||||
allValidValues.addAll(validShareValues) ;
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull()
|
||||
.isOneOfTheseValues(allValidValues.toArray(new Object[allValidValues.size()]));
|
||||
}
|
||||
@@ -281,13 +300,13 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
final Integer feeInterval = this.fromApiJsonHelper.extractIntegerNamed("feeInterval", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("feeInterval").value(feeInterval).integerGreaterThanZero();
|
||||
}
|
||||
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists("chargeCalculationType", element)) {
|
||||
final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerNamed("chargeCalculationType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull().inMinMaxRange(1, 5);
|
||||
}
|
||||
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists("chargePaymentMode", element)) {
|
||||
final Integer chargePaymentMode = this.fromApiJsonHelper.extractIntegerNamed("chargePaymentMode", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("chargePaymentMode").value(chargePaymentMode).notNull().inMinMaxRange(0, 1);
|
||||
@@ -338,6 +357,11 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
|
||||
private void performChargeTimeNCalculationTypeValidation(DataValidatorBuilder baseDataValidator, final Integer chargeTimeType,
|
||||
final Integer chargeCalculationType) {
|
||||
if(chargeTimeType.equals(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue())){
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForShareAccountActivation());
|
||||
}
|
||||
|
||||
if (chargeTimeType.equals(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue())) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForTrancheDisbursement());
|
||||
|
||||
+4
@@ -42,4 +42,8 @@ public interface ChargeDropdownReadPlatformService {
|
||||
List<EnumOptionData> retrieveClientCalculationTypes();
|
||||
|
||||
List<EnumOptionData> retrieveClientCollectionTimeTypes();
|
||||
|
||||
List<EnumOptionData> retrieveSharesCalculationTypes() ;
|
||||
List<EnumOptionData> retrieveSharesCollectionTimeTypes() ;
|
||||
|
||||
}
|
||||
|
||||
+12
@@ -114,4 +114,16 @@ public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownRead
|
||||
public List<EnumOptionData> retrieveClientCollectionTimeTypes() {
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSharesCalculationTypes() {
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSharesCollectionTimeTypes() {
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SHAREACCOUNT_ACTIVATION),
|
||||
chargeTimeType(ChargeTimeType.SHARE_PURCHASE), chargeTimeType(ChargeTimeType.SHARE_REDEEM));
|
||||
}
|
||||
}
|
||||
+13
@@ -81,6 +81,16 @@ public class ChargeEnumerations {
|
||||
optionData = new EnumOptionData(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue().longValue(),
|
||||
ChargeTimeType.TRANCHE_DISBURSEMENT.getCode(), "Tranche Disbursement");
|
||||
break;
|
||||
case SHAREACCOUNT_ACTIVATION:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue().longValue(), ChargeTimeType.SHAREACCOUNT_ACTIVATION.getCode(), "Share Account Activate") ;
|
||||
break ;
|
||||
|
||||
case SHARE_PURCHASE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHARE_PURCHASE.getValue().longValue(), ChargeTimeType.SHARE_PURCHASE.getCode(), "Share Purchase") ;
|
||||
break ;
|
||||
case SHARE_REDEEM:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHARE_REDEEM.getValue().longValue(), ChargeTimeType.SHARE_REDEEM.getCode(), "Share Redeem") ;
|
||||
break ;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
@@ -105,6 +115,9 @@ public class ChargeEnumerations {
|
||||
case CLIENT:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.CLIENT.getValue().longValue(), ChargeAppliesTo.CLIENT.getCode(), "Client");
|
||||
break;
|
||||
case SHARES:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.SHARES.getValue().longValue(), ChargeAppliesTo.SHARES.getCode(), "Shares") ;
|
||||
break ;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.INVALID.getValue().longValue(), ChargeAppliesTo.INVALID.getCode(),
|
||||
"Invalid");
|
||||
|
||||
+6
@@ -116,5 +116,11 @@ public interface ChargeReadPlatformService {
|
||||
|
||||
/** Retrieve savings account charges **/
|
||||
Collection<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsId);
|
||||
|
||||
/**
|
||||
* Returns charge definitions which are applicable for shares
|
||||
*/
|
||||
Collection<ChargeData> retrieveSharesApplicableCharges();
|
||||
|
||||
public Collection<ChargeData> retrieveShareProductCharges(final Long shareProductId) ;
|
||||
}
|
||||
|
||||
+28
-1
@@ -147,11 +147,15 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions = this.accountingDropdownReadPlatformService
|
||||
.retrieveAccountMappingOptionsForCharges();
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions = this.chargeDropdownReadPlatformService
|
||||
.retrieveSharesCalculationTypes();
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions = this.chargeDropdownReadPlatformService.retrieveSharesCollectionTimeTypes();
|
||||
final Collection<TaxGroupData> taxGroupOptions = this.taxReadPlatformService.retrieveTaxGroupsForLookUp();
|
||||
return ChargeData.template(currencyOptions, allowedChargeCalculationTypeOptions, allowedChargeAppliesToOptions,
|
||||
allowedChargeTimeOptions, chargePaymentOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions,
|
||||
savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions,
|
||||
clientChargeTimeTypeOptions, feeFrequencyOptions, incomeOrLiabilityAccountOptions, taxGroupOptions);
|
||||
clientChargeTimeTypeOptions, feeFrequencyOptions, incomeOrLiabilityAccountOptions, taxGroupOptions,
|
||||
shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -292,6 +296,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
return chargeSchema() + " join m_savings_product_charge spc on spc.charge_id = c.id";
|
||||
}
|
||||
|
||||
public String shareProductChargeSchema() {
|
||||
return chargeSchema() + " join m_share_product_charge mspc on mspc.charge_id = c.id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = rs.getLong("id");
|
||||
@@ -396,6 +404,16 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { savingsProductId });
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChargeData> retrieveShareProductCharges(final Long shareProductId) {
|
||||
final ChargeMapper rm = new ChargeMapper();
|
||||
|
||||
String sql = "select " + rm.shareProductChargeSchema() + " where c.is_deleted=0 and c.is_active=1 and mspc.product_id=? ";
|
||||
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
|
||||
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { shareProductId });
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsAccountId) {
|
||||
|
||||
@@ -419,4 +437,13 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.CLIENT.getValue() });
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChargeData> retrieveSharesApplicableCharges() {
|
||||
final ChargeMapper rm = new ChargeMapper();
|
||||
String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? ";
|
||||
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
|
||||
sql += " order by c.name ";
|
||||
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SHARES.getValue() });
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -299,7 +299,7 @@ public class ClientsApiResource {
|
||||
|
||||
final AccountSummaryCollectionData clientAccount = this.accountDetailsReadPlatformService.retrieveClientAccountDetails(clientId);
|
||||
|
||||
final Set<String> CLIENT_ACCOUNTS_DATA_PARAMETERS = new HashSet<>(Arrays.asList("loanAccounts", "savingsAccounts"));
|
||||
final Set<String> CLIENT_ACCOUNTS_DATA_PARAMETERS = new HashSet<>(Arrays.asList("loanAccounts", "savingsAccounts", "shareAccounts"));
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.clientAccountSummaryToApiJsonSerializer.serialize(settings, clientAccount, CLIENT_ACCOUNTS_DATA_PARAMETERS);
|
||||
|
||||
+10
-1
@@ -28,6 +28,7 @@ import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,8 @@ public class AccountNumberGenerator {
|
||||
private final static String OFFICE_NAME = "officeName";
|
||||
private final static String LOAN_PRODUCT_SHORT_NAME = "loanProductShortName";
|
||||
private final static String SAVINGS_PRODUCT_SHORT_NAME = "savingsProductShortName";
|
||||
|
||||
private final static String SHARE_PRODUCT_SHORT_NAME = "sharesProductShortName" ;
|
||||
|
||||
public String generate(Client client, AccountNumberFormat accountNumberFormat) {
|
||||
Map<String, String> propertyMap = new HashMap<>();
|
||||
propertyMap.put(ID, client.getId().toString());
|
||||
@@ -73,6 +75,13 @@ public class AccountNumberGenerator {
|
||||
return generateAccountNumber(propertyMap, accountNumberFormat);
|
||||
}
|
||||
|
||||
public String generate(ShareAccount shareaccount, AccountNumberFormat accountNumberFormat) {
|
||||
Map<String, String> propertyMap = new HashMap<>();
|
||||
propertyMap.put(ID, shareaccount.getId().toString());
|
||||
propertyMap.put(SHARE_PRODUCT_SHORT_NAME, shareaccount.getShareProduct().getShortName());
|
||||
return generateAccountNumber(propertyMap, accountNumberFormat) ;
|
||||
}
|
||||
|
||||
private String generateAccountNumber(Map<String, String> propertyMap, AccountNumberFormat accountNumberFormat) {
|
||||
String accountNumber = StringUtils.leftPad(propertyMap.get(ID), AccountNumberGenerator.maxLength, '0');
|
||||
if (accountNumberFormat != null && accountNumberFormat.getPrefixEnum() != null) {
|
||||
|
||||
+3
-2
@@ -157,12 +157,13 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
|
||||
final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
|
||||
// this field is applicable only for client charges
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions = null;
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions = null ;
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions = null ;
|
||||
final Collection<TaxGroupData> taxGroupOptions = null;
|
||||
|
||||
return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null,
|
||||
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
|
||||
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions);
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+46
-44
@@ -18,9 +18,6 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.products.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
@@ -41,80 +38,85 @@ import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.products.constants.ProductsApiConstants;
|
||||
import org.apache.fineract.portfolio.products.data.ProductData;
|
||||
import org.apache.fineract.portfolio.products.service.ProductCommandsService;
|
||||
import org.apache.fineract.portfolio.products.service.ProductReadPlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@Path("/products/{type}")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class ProductsApiResource {
|
||||
|
||||
private final ApplicationContext applicationContext ;
|
||||
private final ApplicationContext applicationContext;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final DefaultToApiJsonSerializer<ProductData> toApiJsonSerializer;
|
||||
private final DefaultToApiJsonSerializer<Object> toApiObjectJsonSerializer ;
|
||||
private final DefaultToApiJsonSerializer<Object> toApiObjectJsonSerializer;
|
||||
private final PlatformSecurityContext platformSecurityContext;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
|
||||
|
||||
@Autowired
|
||||
public ProductsApiResource(final ApplicationContext applicationContext,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final DefaultToApiJsonSerializer<ProductData> toApiJsonSerializer,
|
||||
final PlatformSecurityContext platformSecurityContext,
|
||||
public ProductsApiResource(final ApplicationContext applicationContext, final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final DefaultToApiJsonSerializer<ProductData> toApiJsonSerializer, final PlatformSecurityContext platformSecurityContext,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
final DefaultToApiJsonSerializer<Object> toApiDividendsJsonSerializer) {
|
||||
this.applicationContext = applicationContext ;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper ;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer ;
|
||||
this.platformSecurityContext = platformSecurityContext ;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService ;
|
||||
this.toApiObjectJsonSerializer = toApiDividendsJsonSerializer ;
|
||||
this.applicationContext = applicationContext;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.platformSecurityContext = platformSecurityContext;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.toApiObjectJsonSerializer = toApiDividendsJsonSerializer;
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveTemplate(@PathParam("type") final String productType, @Context final UriInfo uriInfo) {
|
||||
String serviceName = productType+ProductsApiConstants.READPLATFORM_NAME ;
|
||||
ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName) ;
|
||||
ProductData data = service.retrieveTemplate() ;
|
||||
String serviceName = productType + ProductsApiConstants.READPLATFORM_NAME;
|
||||
ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName);
|
||||
ProductData data = service.retrieveTemplate();
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams());
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("{productId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveProduct(@PathParam("productId") final Long productId, @PathParam("type") final String productType,
|
||||
@Context final UriInfo uriInfo) {
|
||||
String serviceName = productType+ProductsApiConstants.READPLATFORM_NAME ;
|
||||
ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName) ;
|
||||
ProductData data = service.retrieveOne(productId) ;
|
||||
String serviceName = productType + ProductsApiConstants.READPLATFORM_NAME;
|
||||
ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
|
||||
ProductData data = service.retrieveOne(productId, settings.isTemplate());
|
||||
|
||||
return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams());
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveAllProducts(@PathParam("type") final String productType, @Context final UriInfo uriInfo) {
|
||||
String serviceName = productType+ProductsApiConstants.READPLATFORM_NAME ;
|
||||
ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName) ;
|
||||
Collection<ProductData> data = service.retrieveAllProducts() ;
|
||||
public String retrieveAllProducts(/*
|
||||
* @PathParam("type") final String
|
||||
* productType, @Context final UriInfo
|
||||
* uriInfo
|
||||
*/
|
||||
@PathParam("type") final String productType, @QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
|
||||
@Context final UriInfo uriInfo) {
|
||||
String serviceName = productType + ProductsApiConstants.READPLATFORM_NAME;
|
||||
ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName);
|
||||
Page<ProductData> data = service.retrieveAllProducts(offset, limit);
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams());
|
||||
return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams());
|
||||
}
|
||||
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@@ -125,32 +127,32 @@ public class ProductsApiResource {
|
||||
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
|
||||
return this.toApiJsonSerializer.serialize(commandProcessingResult);
|
||||
}
|
||||
|
||||
|
||||
@POST
|
||||
@Path("{productId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String handleCommands(@PathParam("type") final String productType, @PathParam("productId") final Long productId, @QueryParam("command") final String commandParam,
|
||||
@Context final UriInfo uriInfo, final String apiRequestBodyAsJson) {
|
||||
String serviceName = productType.toUpperCase()+ProductsApiConstants.PRODUCT_COMMANDSERVICE ;
|
||||
ProductCommandsService service = (ProductCommandsService) this.applicationContext.getBean(serviceName) ;
|
||||
final Object obj = service.handleCommand(productId, commandParam, apiRequestBodyAsJson) ;
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiObjectJsonSerializer.serialize(settings, obj, new HashSet<String>());
|
||||
public String handleCommands(@PathParam("type") final String productType, @PathParam("productId") final Long productId,
|
||||
@QueryParam("command") final String commandParam, @SuppressWarnings("unused") @Context final UriInfo uriInfo, final String apiRequestBodyAsJson) {
|
||||
CommandWrapper commandWrapper = new CommandWrapperBuilder().createProductCommand(productType, commandParam, productId)
|
||||
.withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
|
||||
return this.toApiJsonSerializer.serialize(commandProcessingResult);
|
||||
}
|
||||
|
||||
|
||||
@PUT
|
||||
@Path("{productId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String updateProduct(@PathParam("type") final String productType, @PathParam("productId") final Long productId, final String apiRequestBodyAsJson) {
|
||||
public String updateProduct(@PathParam("type") final String productType, @PathParam("productId") final Long productId,
|
||||
final String apiRequestBodyAsJson) {
|
||||
this.platformSecurityContext.authenticatedUser();
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateProduct(productType, productId)
|
||||
.withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
|
||||
private boolean is(final String commandParam, final String commandValue) {
|
||||
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
|
||||
}
|
||||
|
||||
+5
-2
@@ -21,15 +21,18 @@ package org.apache.fineract.portfolio.products.service;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.portfolio.products.data.ProductData;
|
||||
|
||||
public interface ProductReadPlatformService {
|
||||
|
||||
public Collection<ProductData> retrieveAllProducts();
|
||||
public Page<ProductData> retrieveAllProducts(Integer offSet, Integer limit);
|
||||
|
||||
public ProductData retrieveOne(final Long productId);
|
||||
public ProductData retrieveOne(final Long productId, boolean includeTemplate);
|
||||
|
||||
public ProductData retrieveTemplate();
|
||||
|
||||
public Set<String> getResponseDataParams();
|
||||
|
||||
public Collection<ProductData> retrieveAllForLookup() ;
|
||||
}
|
||||
|
||||
+9
-1
@@ -34,6 +34,7 @@ public enum SavingsAccountTransactionType {
|
||||
ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), //
|
||||
WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharge"), //
|
||||
PAY_CHARGE(7, "savingsAccountTransactionType.payCharge"), //
|
||||
DIVIDEND_PAYOUT(8, "savingsAccountTransactionType.dividendPayout"), //
|
||||
INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), //
|
||||
APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
|
||||
WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
|
||||
@@ -84,6 +85,9 @@ public enum SavingsAccountTransactionType {
|
||||
case 7:
|
||||
savingsAccountTransactionType = SavingsAccountTransactionType.PAY_CHARGE;
|
||||
break;
|
||||
case 8:
|
||||
savingsAccountTransactionType = SavingsAccountTransactionType.DIVIDEND_PAYOUT;
|
||||
break;
|
||||
case 12:
|
||||
savingsAccountTransactionType = SavingsAccountTransactionType.INITIATE_TRANSFER;
|
||||
break;
|
||||
@@ -165,6 +169,10 @@ public enum SavingsAccountTransactionType {
|
||||
return this.value.equals(SavingsAccountTransactionType.WRITTEN_OFF.getValue());
|
||||
}
|
||||
|
||||
public boolean isDividendPayout() {
|
||||
return this.value.equals(SavingsAccountTransactionType.DIVIDEND_PAYOUT.getValue());
|
||||
}
|
||||
|
||||
public boolean isIncomeFromInterest() {
|
||||
return this.value.equals(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue());
|
||||
}
|
||||
@@ -174,6 +182,6 @@ public enum SavingsAccountTransactionType {
|
||||
}
|
||||
|
||||
public boolean isCredit() {
|
||||
return isDeposit() || isInterestPosting();
|
||||
return isDeposit() || isInterestPosting() || isDividendPayout();
|
||||
}
|
||||
}
|
||||
+6
@@ -31,6 +31,7 @@ public class SavingsAccountTransactionEnumData {
|
||||
private final String value;
|
||||
|
||||
private final boolean deposit;
|
||||
private final boolean dividendPayout;
|
||||
private final boolean withdrawal;
|
||||
private final boolean interestPosting;
|
||||
private final boolean feeDeduction;
|
||||
@@ -48,6 +49,7 @@ public class SavingsAccountTransactionEnumData {
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
this.deposit = Long.valueOf(SavingsAccountTransactionType.DEPOSIT.getValue()).equals(this.id);
|
||||
this.dividendPayout = Long.valueOf(SavingsAccountTransactionType.DIVIDEND_PAYOUT.getValue()).equals(this.id);
|
||||
this.withdrawal = Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL.getValue()).equals(this.id);
|
||||
this.interestPosting = Long.valueOf(SavingsAccountTransactionType.INTEREST_POSTING.getValue()).equals(this.id);
|
||||
this.feeDeduction = Long.valueOf(SavingsAccountTransactionType.ANNUAL_FEE.getValue()).equals(this.id)
|
||||
@@ -127,5 +129,9 @@ public class SavingsAccountTransactionEnumData {
|
||||
public boolean isWithholdTax() {
|
||||
return this.withholdTax;
|
||||
}
|
||||
|
||||
public boolean isDividendPayout() {
|
||||
return this.dividendPayout;
|
||||
}
|
||||
|
||||
}
|
||||
+12
-1
@@ -88,6 +88,7 @@ import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
@@ -844,6 +845,15 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public SavingsAccountTransaction deposit(final SavingsAccountTransactionDTO transactionDTO) {
|
||||
return deposit(transactionDTO, SavingsAccountTransactionType.DEPOSIT);
|
||||
}
|
||||
|
||||
public SavingsAccountTransaction dividendPayout(final SavingsAccountTransactionDTO transactionDTO) {
|
||||
return deposit(transactionDTO, SavingsAccountTransactionType.DIVIDEND_PAYOUT);
|
||||
}
|
||||
|
||||
public SavingsAccountTransaction deposit(final SavingsAccountTransactionDTO transactionDTO,
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType) {
|
||||
final String resourceTypeName = depositAccountType().resourceName();
|
||||
if (isNotActive()) {
|
||||
final String defaultUserMessage = "Transaction is not allowed. Account is not active.";
|
||||
@@ -886,7 +896,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final Money amount = Money.of(this.currency, transactionDTO.getTransactionAmount());
|
||||
|
||||
final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(this, office(), transactionDTO.getPaymentDetail(),
|
||||
transactionDTO.getTransactionDate(), amount, transactionDTO.getCreatedDate(), transactionDTO.getAppUser());
|
||||
transactionDTO.getTransactionDate(), amount, transactionDTO.getCreatedDate(), transactionDTO.getAppUser(),
|
||||
savingsAccountTransactionType);
|
||||
this.transactions.add(transaction);
|
||||
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
|
||||
+2
@@ -35,4 +35,6 @@ public interface SavingsAccountDomainService {
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, boolean isAccountTransfer, boolean isRegularTransaction);
|
||||
|
||||
void postJournalEntries(SavingsAccount savingsAccount, Set<Long> existingTransactionIds, Set<Long> existingReversedTransactionIds);
|
||||
|
||||
SavingsAccountTransaction handleDividendPayout(SavingsAccount account, LocalDate transactionDate, BigDecimal transactionAmount);
|
||||
}
|
||||
+27
-4
@@ -26,6 +26,7 @@ import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDTO;
|
||||
import org.apache.fineract.portfolio.savings.exception.DepositAccountTransactionNotAllowedException;
|
||||
@@ -102,10 +103,12 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions = null;
|
||||
if(account.getOnHoldFunds().compareTo(BigDecimal.ZERO) == 1){
|
||||
depositAccountOnHoldTransactions = this.depositAccountOnHoldTransactionRepository.findBySavingsAccountAndReversedFalseOrderByCreatedDateAsc(account);
|
||||
if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) == 1) {
|
||||
depositAccountOnHoldTransactions = this.depositAccountOnHoldTransactionRepository
|
||||
.findBySavingsAccountAndReversedFalseOrderByCreatedDateAsc(account);
|
||||
}
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(transactionAmount, transactionBooleanValues.isExceptionForBalanceCheck(), depositAccountOnHoldTransactions);
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(transactionAmount, transactionBooleanValues.isExceptionForBalanceCheck(),
|
||||
depositAccountOnHoldTransactions);
|
||||
saveTransactionToGenerateTransactionId(withdrawal);
|
||||
this.savingsAccountRepository.save(account);
|
||||
|
||||
@@ -127,7 +130,15 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
public SavingsAccountTransaction handleDeposit(final SavingsAccount account, final DateTimeFormatter fmt,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
|
||||
final boolean isAccountTransfer, final boolean isRegularTransaction) {
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType = SavingsAccountTransactionType.DEPOSIT;
|
||||
return handleDeposit(account, fmt, transactionDate, transactionAmount, paymentDetail, isAccountTransfer, isRegularTransaction,
|
||||
savingsAccountTransactionType);
|
||||
}
|
||||
|
||||
private SavingsAccountTransaction handleDeposit(final SavingsAccount account, final DateTimeFormatter fmt,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
|
||||
final boolean isAccountTransfer, final boolean isRegularTransaction,
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType) {
|
||||
AppUser user = getAppUserIfPresent();
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
@@ -142,7 +153,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
|
||||
paymentDetail, new Date(), user);
|
||||
final SavingsAccountTransaction deposit = account.deposit(transactionDTO);
|
||||
final SavingsAccountTransaction deposit = account.deposit(transactionDTO, savingsAccountTransactionType);
|
||||
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(transactionDate)) {
|
||||
@@ -163,6 +174,18 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
return deposit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsAccountTransaction handleDividendPayout(final SavingsAccount account, final LocalDate transactionDate,
|
||||
final BigDecimal transactionAmount) {
|
||||
final DateTimeFormatter fmt = null;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final boolean isAccountTransfer = false;
|
||||
final boolean isRegularTransaction = true;
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType = SavingsAccountTransactionType.DIVIDEND_PAYOUT;
|
||||
return handleDeposit(account, fmt, transactionDate, transactionAmount, paymentDetail, isAccountTransfer, isRegularTransaction,
|
||||
savingsAccountTransactionType);
|
||||
}
|
||||
|
||||
private Long saveTransactionToGenerateTransactionId(final SavingsAccountTransaction transaction) {
|
||||
this.savingsAccountTransactionRepository.save(transaction);
|
||||
return transaction.getId();
|
||||
|
||||
+21
-5
@@ -135,6 +135,14 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
createdDate, amount, isReversed, appUser);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction deposit(final SavingsAccount savingsAccount, final Office office,
|
||||
final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate, final AppUser appUser,
|
||||
final SavingsAccountTransactionType savingsAccountTransactionType) {
|
||||
final boolean isReversed = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, savingsAccountTransactionType.getValue(), date,
|
||||
createdDate, amount, isReversed, appUser);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction withdrawal(final SavingsAccount savingsAccount, final Office office,
|
||||
final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate, final AppUser appUser) {
|
||||
final boolean isReversed = false;
|
||||
@@ -283,12 +291,20 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isDeposit() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isDividendPayout() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isDividendPayout();
|
||||
}
|
||||
|
||||
public boolean isDividendPayoutAndNotReversed() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isDividendPayout() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isWithdrawal() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawal();
|
||||
}
|
||||
|
||||
public boolean isPostInterestCalculationRequired() {
|
||||
return this.isDeposit() || this.isChargeTransaction();
|
||||
return this.isDeposit() || this.isChargeTransaction() || this.isDividendPayout();
|
||||
}
|
||||
|
||||
public boolean isInterestPostingAndNotReversed() {
|
||||
@@ -470,7 +486,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
|
||||
final MonetaryCurrency currency = openingBalance.getCurrency();
|
||||
Money endOfDayBalance = openingBalance.copy();
|
||||
if (isDeposit()) {
|
||||
if (isDeposit() || isDividendPayoutAndNotReversed()) {
|
||||
endOfDayBalance = openingBalance.plus(getAmount(currency));
|
||||
} else if (isWithdrawal() || isChargeTransactionAndNotReversed()) {
|
||||
endOfDayBalance = openingBalance.minus(getAmount(currency));
|
||||
@@ -486,7 +502,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
public EndOfDayBalance toEndOfDayBalance(final Money openingBalance) {
|
||||
final MonetaryCurrency currency = openingBalance.getCurrency();
|
||||
Money endOfDayBalance = openingBalance.copy();
|
||||
if (isDeposit()) {
|
||||
if (isDeposit() || isDividendPayoutAndNotReversed()) {
|
||||
endOfDayBalance = openingBalance.plus(getAmount(currency));
|
||||
} else if (isWithdrawal() || isChargeTransactionAndNotReversed()) {
|
||||
|
||||
@@ -515,7 +531,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate);
|
||||
numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate();
|
||||
} else {
|
||||
if (isDeposit()) {
|
||||
if (isDeposit() || isDividendPayoutAndNotReversed()) {
|
||||
// endOfDayBalance = openingBalance.plus(getAmount(currency));
|
||||
// if (endOfDayBalance.isLessThanZero()) {
|
||||
endOfDayBalance = endOfDayBalance.plus(getAmount(currency));
|
||||
@@ -558,7 +574,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public boolean isCredit() {
|
||||
return isDeposit() || isInterestPostingAndNotReversed();
|
||||
return isDeposit() || isInterestPostingAndNotReversed() || isDividendPayoutAndNotReversed();
|
||||
}
|
||||
|
||||
public boolean isDebit() {
|
||||
|
||||
+1
-3
@@ -35,7 +35,7 @@ public final class SavingsAccountTransactionSummaryWrapper {
|
||||
public BigDecimal calculateTotalDeposits(final MonetaryCurrency currency, final List<SavingsAccountTransaction> transactions) {
|
||||
Money total = Money.zero(currency);
|
||||
for (final SavingsAccountTransaction transaction : transactions) {
|
||||
if (transaction.isDeposit() && transaction.isNotReversed()) {
|
||||
if (transaction.isDepositAndNotReversed() || transaction.isDividendPayoutAndNotReversed()) {
|
||||
total = total.plus(transaction.getAmount(currency));
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,6 @@ public final class SavingsAccountTransactionSummaryWrapper {
|
||||
}
|
||||
return total.getAmountDefaultedToNullIfZero();
|
||||
}
|
||||
|
||||
public BigDecimal calculateTotalWithholdTaxWithdrawal(MonetaryCurrency currency, List<SavingsAccountTransaction> transactions) {
|
||||
Money total = Money.zero(currency);
|
||||
for (final SavingsAccountTransaction transaction : transactions) {
|
||||
@@ -141,5 +140,4 @@ public final class SavingsAccountTransactionSummaryWrapper {
|
||||
}
|
||||
return total.getAmountDefaultedToNullIfZero();
|
||||
}
|
||||
|
||||
}
|
||||
+16
-9
@@ -74,12 +74,18 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
private static final class SavingsAccountChargeMapper implements RowMapper<SavingsAccountChargeData> {
|
||||
|
||||
public String schema() {
|
||||
return "sc.id as id, c.id as chargeId, sc.savings_account_id as accountId, c.name as name, " + "sc.amount as amountDue, "
|
||||
+ "sc.amount_paid_derived as amountPaid, " + "sc.amount_waived_derived as amountWaived, "
|
||||
+ "sc.amount_writtenoff_derived as amountWrittenOff, " + "sc.amount_outstanding_derived as amountOutstanding, "
|
||||
return "sc.id as id, c.id as chargeId, sc.savings_account_id as accountId, c.name as name, "
|
||||
+ "sc.amount as amountDue, "
|
||||
+ "sc.amount_paid_derived as amountPaid, "
|
||||
+ "sc.amount_waived_derived as amountWaived, "
|
||||
+ "sc.amount_writtenoff_derived as amountWrittenOff, "
|
||||
+ "sc.amount_outstanding_derived as amountOutstanding, "
|
||||
+ "sc.calculation_percentage as percentageOf, sc.calculation_on_amount as amountPercentageAppliedTo, "
|
||||
+ "sc.charge_time_enum as chargeTime, " + "sc.is_penalty as penalty, " + "sc.charge_due_date as dueAsOfDate, "
|
||||
+ "sc.fee_on_month as feeOnMonth, " + "sc.fee_on_day as feeOnDay, sc.fee_interval as feeInterval, "
|
||||
+ "sc.charge_time_enum as chargeTime, "
|
||||
+ "sc.is_penalty as penalty, "
|
||||
+ "sc.charge_due_date as dueAsOfDate, "
|
||||
+ "sc.fee_on_month as feeOnMonth, "
|
||||
+ "sc.fee_on_day as feeOnDay, sc.fee_interval as feeInterval, "
|
||||
+ "sc.charge_calculation_enum as chargeCalculation, "
|
||||
+ "sc.is_active as isActive, sc.inactivated_on_date as inactivationDate, "
|
||||
+ "c.currency_code as currencyCode, oc.name as currencyName, "
|
||||
@@ -160,14 +166,14 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
final List<EnumOptionData> feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
|
||||
// this field is applicable only for client charges
|
||||
final Map<String, List<GLAccountData>> incomeOrLiabilityAccountOptions = null;
|
||||
|
||||
final List<EnumOptionData> shareChargeCalculationTypeOptions = null;
|
||||
final List<EnumOptionData> shareChargeTimeTypeOptions = null;
|
||||
final Collection<TaxGroupData> taxGroupOptions = null;
|
||||
|
||||
// TODO AA : revisit for merge conflict - Not sure method signature
|
||||
return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions, null,
|
||||
loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions,
|
||||
savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions,
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions);
|
||||
incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -244,7 +250,8 @@ public class SavingsAccountChargeReadPlatformServiceImpl implements SavingsAccou
|
||||
|
||||
@Override
|
||||
public Collection<SavingsAccountAnnualFeeData> retrieveChargesWithDue() {
|
||||
final String sql = "select " + this.chargeDueMapper.schema()
|
||||
final String sql = "select "
|
||||
+ this.chargeDueMapper.schema()
|
||||
+ " where sac.charge_due_date is not null and sac.charge_due_date <= NOW() and sac.waived = 0 and sac.is_paid_derived=0 and sac.is_active=1 and sa.status_enum = "
|
||||
+ SavingsAccountStatusType.ACTIVE.getValue() + " order by sac.charge_due_date ";
|
||||
|
||||
|
||||
+4
@@ -183,6 +183,10 @@ public class SavingsEnumerations {
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WITHHOLD_TAX.getValue().longValue(),
|
||||
SavingsAccountTransactionType.WITHHOLD_TAX.getCode(), "Withhold Tax");
|
||||
break;
|
||||
case DIVIDEND_PAYOUT:
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.DIVIDEND_PAYOUT.getValue().longValue(),
|
||||
SavingsAccountTransactionType.DIVIDEND_PAYOUT.getCode(), "Dividend Payout");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
public class PurchasedSharesData {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final Long accountId;
|
||||
|
||||
private final LocalDate purchasedDate;
|
||||
|
||||
private final Long numberOfShares;
|
||||
|
||||
private final BigDecimal purchasedPrice;
|
||||
|
||||
private final EnumOptionData status;
|
||||
|
||||
private final EnumOptionData type;
|
||||
|
||||
private final BigDecimal amount ;
|
||||
|
||||
private final BigDecimal chargeAmount ;
|
||||
|
||||
public PurchasedSharesData(final Long id, final Long accountId, final LocalDate purchasedDate, final Long numberOfShares,
|
||||
final BigDecimal purchasedPrice, final EnumOptionData status, final EnumOptionData type, final BigDecimal amount, final BigDecimal chargeAmount) {
|
||||
this.id = id;
|
||||
this.accountId = accountId;
|
||||
this.purchasedDate = purchasedDate;
|
||||
this.numberOfShares = numberOfShares;
|
||||
this.purchasedPrice = purchasedPrice;
|
||||
this.status = status;
|
||||
this.type = type;
|
||||
this.amount = amount ;
|
||||
this.chargeAmount = chargeAmount ;
|
||||
}
|
||||
|
||||
public LocalDate getPurchasedDate() {
|
||||
return this.purchasedDate;
|
||||
}
|
||||
|
||||
public Long getNumberOfShares() {
|
||||
return this.numberOfShares;
|
||||
}
|
||||
|
||||
public BigDecimal getPurchasedPrice() {
|
||||
return this.purchasedPrice;
|
||||
}
|
||||
|
||||
public EnumOptionData getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public EnumOptionData getType() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ShareAccountApplicationTimelineData {
|
||||
|
||||
private final LocalDate submittedOnDate;
|
||||
private final String submittedByUsername;
|
||||
private final String submittedByFirstname;
|
||||
private final String submittedByLastname;
|
||||
|
||||
private final LocalDate rejectedDate;
|
||||
private final String rejectedByUsername;
|
||||
private final String rejectedByFirstname;
|
||||
private final String rejectedByLastname;
|
||||
|
||||
private final LocalDate approvedDate;
|
||||
private final String approvedByUsername;
|
||||
private final String approvedByFirstname;
|
||||
private final String approvedByLastname;
|
||||
|
||||
private final LocalDate activatedDate;
|
||||
private final String activatedByUsername;
|
||||
private final String activatedByFirstname;
|
||||
private final String activatedByLastname;
|
||||
|
||||
private final LocalDate closedDate;
|
||||
private final String closedByUsername;
|
||||
private final String closedByFirstname;
|
||||
private final String closedByLastname;
|
||||
|
||||
public static ShareAccountApplicationTimelineData templateDefault() {
|
||||
|
||||
final LocalDate submittedOnDate = null;
|
||||
final String submittedByUsername = null;
|
||||
final String submittedByFirstname = null;
|
||||
final String submittedByLastname = null;
|
||||
final LocalDate rejectedOnDate = null;
|
||||
final String rejectedByUsername = null;
|
||||
final String rejectedByFirstname = null;
|
||||
final String rejectedByLastname = null;
|
||||
final LocalDate approvedOnDate = null;
|
||||
final String approvedByUsername = null;
|
||||
final String approvedByFirstname = null;
|
||||
final String approvedByLastname = null;
|
||||
final LocalDate activatedOnDate = null;
|
||||
final String activatedByUsername = null;
|
||||
final String activatedByFirstname = null;
|
||||
final String activatedByLastname = null;
|
||||
final LocalDate closedOnDate = null;
|
||||
final String closedByUsername = null;
|
||||
final String closedByFirstname = null;
|
||||
final String closedByLastname = null;
|
||||
|
||||
return new ShareAccountApplicationTimelineData(submittedOnDate, submittedByUsername, submittedByFirstname, submittedByLastname,
|
||||
rejectedOnDate, rejectedByUsername, rejectedByFirstname, rejectedByLastname, approvedOnDate, approvedByUsername,
|
||||
approvedByFirstname, approvedByLastname, activatedOnDate, activatedByUsername, activatedByFirstname, activatedByLastname,
|
||||
closedOnDate, closedByUsername, closedByFirstname, closedByLastname);
|
||||
}
|
||||
|
||||
public ShareAccountApplicationTimelineData(final LocalDate submittedOnDate, final String submittedByUsername,
|
||||
final String submittedByFirstname, final String submittedByLastname, final LocalDate rejectedOnDate,
|
||||
final String rejectedByUsername, final String rejectedByFirstname, final String rejectedByLastname,
|
||||
final LocalDate approvedOnDate, final String approvedByUsername,
|
||||
final String approvedByFirstname, final String approvedByLastname, final LocalDate activatedOnDate,
|
||||
final String activatedByUsername, final String activatedByFirstname, final String activatedByLastname,
|
||||
final LocalDate closedOnDate, final String closedByUsername, final String closedByFirstname, final String closedByLastname) {
|
||||
this.submittedOnDate = submittedOnDate;
|
||||
this.submittedByUsername = submittedByUsername;
|
||||
this.submittedByFirstname = submittedByFirstname;
|
||||
this.submittedByLastname = submittedByLastname;
|
||||
this.rejectedDate = rejectedOnDate;
|
||||
this.rejectedByUsername = rejectedByUsername;
|
||||
this.rejectedByFirstname = rejectedByFirstname;
|
||||
this.rejectedByLastname = rejectedByLastname;
|
||||
this.approvedDate = approvedOnDate;
|
||||
this.approvedByUsername = approvedByUsername;
|
||||
this.approvedByFirstname = approvedByFirstname;
|
||||
this.approvedByLastname = approvedByLastname;
|
||||
this.activatedDate = activatedOnDate;
|
||||
this.activatedByUsername = activatedByUsername;
|
||||
this.activatedByFirstname = activatedByFirstname;
|
||||
this.activatedByLastname = activatedByLastname;
|
||||
this.closedDate = closedOnDate;
|
||||
this.closedByUsername = closedByUsername;
|
||||
this.closedByFirstname = closedByFirstname;
|
||||
this.closedByLastname = closedByLastname;
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ShareAccountChargeData {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final Long chargeId;
|
||||
|
||||
private final Long accountId;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final EnumOptionData chargeTimeType;
|
||||
|
||||
private final EnumOptionData chargeCalculationType;
|
||||
|
||||
private final BigDecimal percentage;
|
||||
|
||||
private final BigDecimal amountPercentageAppliedTo;
|
||||
|
||||
private final CurrencyData currency;
|
||||
|
||||
private final BigDecimal amount;
|
||||
|
||||
private final BigDecimal amountPaid;
|
||||
|
||||
private final BigDecimal amountWaived;
|
||||
|
||||
private final BigDecimal amountWrittenOff;
|
||||
|
||||
private final BigDecimal amountOutstanding;
|
||||
|
||||
private final BigDecimal amountOrPercentage;
|
||||
|
||||
private final Boolean isActive;
|
||||
|
||||
private final Collection<ChargeData> chargeOptions;
|
||||
|
||||
public ShareAccountChargeData(final Long id, final Long chargeId, final Long accountId, final String name,
|
||||
final CurrencyData currency, final BigDecimal amount, final BigDecimal amountPaid, final BigDecimal amountWaived,
|
||||
final BigDecimal amountWrittenOff, final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType,
|
||||
final EnumOptionData chargeCalculationType, final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo,
|
||||
final Collection<ChargeData> chargeOptions, final Boolean isActive) {
|
||||
this.id = id;
|
||||
this.chargeId = chargeId;
|
||||
this.accountId = accountId;
|
||||
this.name = name;
|
||||
this.chargeTimeType = chargeTimeType;
|
||||
this.chargeCalculationType = chargeCalculationType;
|
||||
this.percentage = percentage;
|
||||
this.amountPercentageAppliedTo = amountPercentageAppliedTo;
|
||||
this.currency = currency;
|
||||
this.amount = amount;
|
||||
this.amountPaid = amountPaid;
|
||||
this.amountWaived = amountWaived;
|
||||
this.amountWrittenOff = amountWrittenOff;
|
||||
this.amountOutstanding = amountOutstanding;
|
||||
this.amountOrPercentage = getAmountOrPercentage();
|
||||
this.chargeOptions = chargeOptions;
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
private BigDecimal getAmountOrPercentage() {
|
||||
return (this.chargeCalculationType != null) && (this.chargeCalculationType.getId().intValue() > 1) ? this.percentage : this.amount;
|
||||
}
|
||||
}
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.accountdetails.data.ShareAccountSummaryData;
|
||||
import org.apache.fineract.portfolio.accounts.data.AccountData;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.products.data.ProductData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||
import org.apache.fineract.portfolio.shareproducts.data.ShareProductData;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ShareAccountData implements AccountData {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String accountNo;
|
||||
|
||||
private String externalId;
|
||||
|
||||
private String savingsAccountNumber;
|
||||
|
||||
private Long clientId;
|
||||
|
||||
private String clientName;
|
||||
|
||||
private Long defaultShares ;
|
||||
|
||||
private Long productId;
|
||||
|
||||
private String productName;
|
||||
|
||||
private ShareAccountStatusEnumData status;
|
||||
|
||||
ShareAccountApplicationTimelineData timeline;
|
||||
|
||||
private CurrencyData currency;
|
||||
|
||||
private ShareAccountSummaryData summary;
|
||||
|
||||
private Collection<PurchasedSharesData> purchasedShares;
|
||||
|
||||
private Long savingsAccountId;
|
||||
|
||||
private BigDecimal currentMarketPrice;
|
||||
|
||||
private Integer lockinPeriod;
|
||||
|
||||
private EnumOptionData lockPeriodTypeEnum;
|
||||
|
||||
private Integer minimumActivePeriod;
|
||||
|
||||
private EnumOptionData minimumActivePeriodTypeEnum;
|
||||
|
||||
private Boolean allowDividendCalculationForInactiveClients;
|
||||
|
||||
private Collection<ShareAccountChargeData> charges;
|
||||
|
||||
private Collection<ShareAccountDividendData> dividends ;
|
||||
|
||||
// Data for template
|
||||
private Collection<ProductData> productOptions;
|
||||
private Collection<ChargeData> chargeOptions;
|
||||
private Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions;
|
||||
private Collection<EnumOptionData> minimumActivePeriodFrequencyTypeOptions;
|
||||
private Collection<SavingsAccountData> clientSavingsAccounts;
|
||||
|
||||
public ShareAccountData(final Long id, final String accountNo, final String externalId, final Long savingsAccountId,
|
||||
final String savingsAccountNumber, final Long clientId, final String clientName, final Long productId,
|
||||
final String productName, final ShareAccountStatusEnumData status, final ShareAccountApplicationTimelineData timeline,
|
||||
final CurrencyData currency, final ShareAccountSummaryData summaryData, final Collection<ShareAccountChargeData> charges,
|
||||
final Collection<PurchasedSharesData> purchasedSharesData, final Integer lockinPeriod, final EnumOptionData lockPeriodTypeEnum,
|
||||
final Integer minimumActivePeriod, final EnumOptionData minimumActivePeriodTypeEnum, Boolean allowdividendsforinactiveclients) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
this.savingsAccountId = savingsAccountId;
|
||||
this.savingsAccountNumber = savingsAccountNumber;
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
this.status = status;
|
||||
this.timeline = timeline;
|
||||
this.currency = currency;
|
||||
this.summary = summaryData;
|
||||
this.charges = charges;
|
||||
this.purchasedShares = purchasedSharesData;
|
||||
this.lockinPeriod = lockinPeriod;
|
||||
this.lockPeriodTypeEnum = lockPeriodTypeEnum;
|
||||
this.minimumActivePeriod = minimumActivePeriod;
|
||||
this.minimumActivePeriodTypeEnum = minimumActivePeriodTypeEnum;
|
||||
this.allowDividendCalculationForInactiveClients = allowdividendsforinactiveclients;
|
||||
}
|
||||
|
||||
public ShareAccountData(final Long clientId, final String clientName, final Collection<ProductData> productOptions,
|
||||
final Collection<ChargeData> chargeOptions) {
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
this.productOptions = productOptions;
|
||||
this.chargeOptions = chargeOptions;
|
||||
}
|
||||
|
||||
public ShareAccountData(final Long clientId, final String clientName, final CurrencyData currency,
|
||||
final Collection<ShareAccountChargeData> charges, final BigDecimal currentMarketPrice,
|
||||
final Collection<EnumOptionData> minimumActivePeriodFrequencyTypeOptions,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountData> clientSavingsAccounts,
|
||||
final Long defaultShares) {
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
this.charges = charges;
|
||||
this.currency = currency;
|
||||
this.currentMarketPrice = currentMarketPrice;
|
||||
// template
|
||||
this.minimumActivePeriodFrequencyTypeOptions = minimumActivePeriodFrequencyTypeOptions;
|
||||
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions;
|
||||
this.clientSavingsAccounts = clientSavingsAccounts;
|
||||
this.defaultShares = defaultShares ;
|
||||
}
|
||||
|
||||
private ShareAccountData(final Long id, final String accountNo, final String externalId, final Long savingsAccountId,
|
||||
final String savingsAccountNumber, final Long clientId, final String clientName, final Long productId,
|
||||
final String productName, final ShareAccountStatusEnumData status, final ShareAccountApplicationTimelineData timeline,
|
||||
final CurrencyData currency, final ShareAccountSummaryData summaryData, final Collection<ShareAccountChargeData> charges,
|
||||
final Collection<PurchasedSharesData> purchasedSharesData, final Integer lockinPeriod, final EnumOptionData lockPeriodTypeEnum,
|
||||
final Integer minimumActivePeriod, final EnumOptionData minimumActivePeriodTypeEnum,
|
||||
final Boolean allowDividendCalculationForInactiveClients, final Collection<ProductData> productOptions,
|
||||
final Collection<ChargeData> chargeOptions, final Collection<SavingsAccountData> clientSavingsAccounts,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions,
|
||||
final Collection<EnumOptionData> minimumActivePeriodFrequencyTypeOption, final BigDecimal currenMarketPrice) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
this.savingsAccountId = savingsAccountId;
|
||||
this.savingsAccountNumber = savingsAccountNumber;
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
this.status = status;
|
||||
this.timeline = timeline;
|
||||
this.currency = currency;
|
||||
this.summary = summaryData;
|
||||
this.charges = charges;
|
||||
this.purchasedShares = purchasedSharesData;
|
||||
this.lockinPeriod = lockinPeriod;
|
||||
this.lockPeriodTypeEnum = lockPeriodTypeEnum;
|
||||
this.minimumActivePeriod = minimumActivePeriod;
|
||||
this.minimumActivePeriodTypeEnum = minimumActivePeriodTypeEnum;
|
||||
this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients;
|
||||
this.productOptions = productOptions;
|
||||
this.chargeOptions = chargeOptions;
|
||||
this.clientSavingsAccounts = clientSavingsAccounts;
|
||||
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions;
|
||||
this.minimumActivePeriodFrequencyTypeOptions = minimumActivePeriodFrequencyTypeOption;
|
||||
this.currentMarketPrice = currenMarketPrice;
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return this.productId;
|
||||
}
|
||||
|
||||
public Long getClientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
public static ShareAccountData template(ShareAccountData data, Collection<ProductData> productOptions,
|
||||
Collection<ChargeData> chargeOptions, Collection<SavingsAccountData> clientSavingsAccounts,
|
||||
Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, Collection<EnumOptionData> minimumActivePeriodFrequencyTypeOptions) {
|
||||
return new ShareAccountData(data.id, data.accountNo, data.externalId, data.savingsAccountId, data.savingsAccountNumber,
|
||||
data.clientId, data.clientName, data.productId, data.productName, data.status, data.timeline, data.currency, data.summary,
|
||||
data.charges, data.purchasedShares, data.lockinPeriod, data.lockPeriodTypeEnum, data.minimumActivePeriod,
|
||||
data.minimumActivePeriodTypeEnum, data.allowDividendCalculationForInactiveClients, productOptions, chargeOptions,
|
||||
clientSavingsAccounts, lockinPeriodFrequencyTypeOptions, minimumActivePeriodFrequencyTypeOptions, data.currentMarketPrice);
|
||||
}
|
||||
|
||||
public static ShareAccountData lookup(final Long id, final String accountNo, final Long clientId, final String clientName) {
|
||||
String externalId = null;
|
||||
ShareAccountSummaryData summaryData = null;
|
||||
Collection<PurchasedSharesData> purchasedSharesData = null;
|
||||
GLAccountData suspenseAccount = null;
|
||||
Integer lockinPeriod = null;
|
||||
EnumOptionData lockPeriodTypeEnum = null;
|
||||
Integer minimumActivePeriod = null;
|
||||
EnumOptionData minimumActivePeriodTypeEnum = null;
|
||||
Collection<ShareAccountChargeData> charges = null;
|
||||
ShareAccountStatusEnumData status = null;
|
||||
ShareAccountApplicationTimelineData timeline = null;
|
||||
CurrencyData currency = null;
|
||||
Boolean allowDividendCalculationForInactiveClients = null;
|
||||
final Long savingsAccountId = null;
|
||||
final String savingsAccountNumber = null;
|
||||
final String productName = null;
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
final Collection<SavingsAccountData> clientSavingsAccounts = null;
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<EnumOptionData> minimumActivePeriodFrequencyTypeOption = null;
|
||||
final BigDecimal currenMarketPrice = null;
|
||||
final Long productId = null;
|
||||
final Collection<ProductData> productOptions = null;
|
||||
|
||||
return new ShareAccountData(id, accountNo, externalId, savingsAccountId, savingsAccountNumber, clientId, clientName, productId,
|
||||
productName, status, timeline, currency, summaryData, charges, purchasedSharesData, lockinPeriod, lockPeriodTypeEnum,
|
||||
minimumActivePeriod, minimumActivePeriodTypeEnum, allowDividendCalculationForInactiveClients, productOptions,
|
||||
chargeOptions, clientSavingsAccounts, lockinPeriodFrequencyTypeOptions, minimumActivePeriodFrequencyTypeOption,
|
||||
currenMarketPrice);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public Collection<PurchasedSharesData> getPurchasedShares() {
|
||||
return this.purchasedShares;
|
||||
}
|
||||
|
||||
public void setCurrentMarketPrice(final BigDecimal currentMarketPrice) {
|
||||
this.currentMarketPrice = currentMarketPrice;
|
||||
}
|
||||
|
||||
public void setDividends(Collection<ShareAccountDividendData> dividends) {
|
||||
this.dividends = dividends ;
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ShareAccountDividendData {
|
||||
|
||||
private final Long id;
|
||||
private final Date postedDate ;
|
||||
private final ShareAccountData accountData;
|
||||
private final BigDecimal amount;
|
||||
private final EnumOptionData status;
|
||||
private final Long savingsTransactionId;
|
||||
|
||||
public ShareAccountDividendData(final Long id, final ShareAccountData accountData, final BigDecimal amount) {
|
||||
this.id = id;
|
||||
this.accountData = accountData;
|
||||
this.amount = amount;
|
||||
this.status = null;
|
||||
this.savingsTransactionId = null;
|
||||
this.postedDate = null ;
|
||||
}
|
||||
|
||||
public ShareAccountDividendData(final Long id, final ShareAccountData accountData, final BigDecimal amount,
|
||||
final EnumOptionData status, final Long savingsTransactionId) {
|
||||
this.id = id;
|
||||
this.accountData = accountData;
|
||||
this.amount = amount;
|
||||
this.status = status;
|
||||
this.savingsTransactionId = savingsTransactionId;
|
||||
this.postedDate = null ;
|
||||
}
|
||||
|
||||
public ShareAccountDividendData(final Long id, final Date postedDate, final ShareAccountData accountData, final BigDecimal amount,
|
||||
final EnumOptionData status, final Long savingsTransactionId) {
|
||||
this.id = id;
|
||||
this.accountData = accountData;
|
||||
this.amount = amount;
|
||||
this.status = status;
|
||||
this.savingsTransactionId = savingsTransactionId;
|
||||
this.postedDate = postedDate ;
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
/**
|
||||
* Immutable data object represent savings account status enumerations.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ShareAccountStatusEnumData {
|
||||
|
||||
private final Long id;
|
||||
|
||||
private final String code;
|
||||
private final String value;
|
||||
private final boolean submittedAndPendingApproval;
|
||||
private final boolean approved;
|
||||
private final boolean rejected;
|
||||
private final boolean active;
|
||||
private final boolean closed;
|
||||
|
||||
public ShareAccountStatusEnumData(final Long id, final String code, final String value, final boolean submittedAndPendingApproval,
|
||||
final boolean approved, final boolean rejected, final boolean active, final boolean closed) {
|
||||
this.id = id;
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
this.submittedAndPendingApproval = submittedAndPendingApproval;
|
||||
this.approved = approved;
|
||||
this.rejected = rejected;
|
||||
this.active = active;
|
||||
this.closed = closed;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
public class ShareAccountTransactionEnumData {
|
||||
|
||||
private final Long id;
|
||||
private final String code;
|
||||
private final String value;
|
||||
|
||||
private final boolean isApplied;
|
||||
private final boolean isApproved;
|
||||
private final boolean isRejected;
|
||||
private final boolean isPurchased;
|
||||
private final boolean isRedeemed;
|
||||
private final boolean isChargePayment;
|
||||
|
||||
public ShareAccountTransactionEnumData(final Long id, final String code, final String value) {
|
||||
this.id = id;
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
this.isApplied = Long.valueOf(100).equals(this.id);
|
||||
this.isApproved = Long.valueOf(300).equals(this.id);
|
||||
this.isRejected = Long.valueOf(400).equals(this.id);
|
||||
this.isPurchased = Long.valueOf(500).equals(this.id);
|
||||
this.isRedeemed = Long.valueOf(600).equals(this.id);
|
||||
this.isChargePayment = Long.valueOf(700).equals(this.id);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public boolean isApplied() {
|
||||
return this.isApplied;
|
||||
}
|
||||
|
||||
public boolean isApproved() {
|
||||
return this.isApproved;
|
||||
}
|
||||
|
||||
public boolean isRejected() {
|
||||
return this.isRejected;
|
||||
}
|
||||
|
||||
public boolean isPurchased() {
|
||||
return this.isPurchased;
|
||||
}
|
||||
|
||||
public boolean isRedeemed() {
|
||||
return this.isRedeemed;
|
||||
}
|
||||
|
||||
|
||||
public boolean isChargePayment() {
|
||||
return this.isChargePayment;
|
||||
}
|
||||
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
public enum PurchasedSharesStatusType {
|
||||
INVALID(0, "purchasedSharesStatusType.invalid"), APPLIED(100, "purchasedSharesStatusType.applied"), APPROVED(300,
|
||||
"purchasedSharesStatusType.approved"), REJECTED(400, "purchasedSharesStatusType.rejected"), PURCHASED(500,
|
||||
"purchasedSharesType.purchased"), REDEEMED(600, "purchasedSharesType.redeemed"),
|
||||
CHARGE_PAYMENT(700, "charge.payment");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private PurchasedSharesStatusType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static PurchasedSharesStatusType fromInt(final Integer type) {
|
||||
|
||||
PurchasedSharesStatusType enumeration = PurchasedSharesStatusType.INVALID;
|
||||
switch (type) {
|
||||
case 100:
|
||||
enumeration = PurchasedSharesStatusType.APPLIED;
|
||||
break;
|
||||
case 300:
|
||||
enumeration = PurchasedSharesStatusType.APPROVED;
|
||||
break;
|
||||
case 400:
|
||||
enumeration = PurchasedSharesStatusType.REJECTED;
|
||||
break;
|
||||
case 500:
|
||||
enumeration = PurchasedSharesStatusType.PURCHASED;
|
||||
break;
|
||||
case 600:
|
||||
enumeration = PurchasedSharesStatusType.REDEEMED;
|
||||
break;
|
||||
case 700:
|
||||
enumeration = PurchasedSharesStatusType.CHARGE_PAYMENT;
|
||||
break ;
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public boolean isApproved() {
|
||||
return this.value.equals(PurchasedSharesStatusType.APPROVED.getValue());
|
||||
}
|
||||
|
||||
public boolean isPurchased() {
|
||||
return this.value.equals(PurchasedSharesStatusType.PURCHASED.getValue());
|
||||
}
|
||||
|
||||
public boolean isChargePayment() {
|
||||
return this.value.equals(PurchasedSharesStatusType.CHARGE_PAYMENT.getValue());
|
||||
}
|
||||
}
|
||||
+526
@@ -0,0 +1,526 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_share_account")
|
||||
public class ShareAccount extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "client_id", nullable = true)
|
||||
private Client client;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "product_id", nullable = true)
|
||||
private ShareProduct shareProduct;
|
||||
|
||||
@Column(name = "status_enum", nullable = false)
|
||||
protected Integer status;
|
||||
|
||||
@Column(name = "submitted_date")
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date submittedDate;
|
||||
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "submitted_userid", nullable = true)
|
||||
protected AppUser submittedBy;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "approved_date")
|
||||
protected Date approvedDate;
|
||||
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "approved_userid", nullable = true)
|
||||
protected AppUser approvedBy;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "rejected_date")
|
||||
protected Date rejectedDate;
|
||||
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "rejected_userid", nullable = true)
|
||||
protected AppUser rejectedBy;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "activated_date", nullable = true)
|
||||
protected Date activatedDate;
|
||||
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "activated_userid", nullable = true)
|
||||
protected AppUser activatedBy;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "closed_date")
|
||||
protected Date closedDate;
|
||||
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "closed_userid", nullable = true)
|
||||
protected AppUser closedBy;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "lastmodified_date")
|
||||
protected Date modifiedDate;
|
||||
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "lastmodifiedby_id", nullable = true)
|
||||
protected AppUser modifiedBy;
|
||||
|
||||
@Column(name = "external_id")
|
||||
private String externalId;
|
||||
|
||||
@Column(name = "account_no", length = 20, unique = true, nullable = false)
|
||||
private String accountNumber;
|
||||
|
||||
@Column(name = "total_approved_shares")
|
||||
private Long totalSharesApproved;
|
||||
|
||||
@Column(name = "total_pending_shares")
|
||||
private Long totalSharesPending;
|
||||
|
||||
@Embedded
|
||||
private MonetaryCurrency currency;
|
||||
|
||||
@Column(name = "allow_dividends_inactive_clients")
|
||||
private Boolean allowDividendCalculationForInactiveClients;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "savings_account_id", nullable = true)
|
||||
private SavingsAccount savingsAccount;
|
||||
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccount", orphanRemoval = true)
|
||||
private Set<ShareAccountTransaction> shareAccountTransactions;
|
||||
|
||||
@Column(name = "lockin_period_frequency")
|
||||
private Integer lockinPeriodFrequency;
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "lockin_period_frequency_enum", nullable = true)
|
||||
private PeriodFrequencyType lockinPeriodFrequencyType;
|
||||
|
||||
@Column(name = "minimum_active_period_frequency")
|
||||
private Integer minimumActivePeriodFrequency;
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "minimum_active_period_frequency_enum", nullable = true)
|
||||
private PeriodFrequencyType minimumActivePeriodFrequencyType;
|
||||
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccount", orphanRemoval = true)
|
||||
private Set<ShareAccountCharge> charges;
|
||||
|
||||
@Transient
|
||||
protected boolean accountNumberRequiresAutoGeneration = false;
|
||||
|
||||
protected ShareAccount() {
|
||||
|
||||
}
|
||||
|
||||
public ShareAccount(final Client client, final ShareProduct shareProduct, final String externalId, final MonetaryCurrency currency,
|
||||
final SavingsAccount savingsAccount, final String accountNo, final Long totalSharesApproved, final Long totalSharesPending,
|
||||
final Set<ShareAccountTransaction> purchasedShares, final Boolean allowDividendCalculationForInactiveClients,
|
||||
final Integer lockinPeriodFrequency, final PeriodFrequencyType lockPeriodType, final Integer minimumActivePeriodFrequency,
|
||||
final PeriodFrequencyType minimumActivePeriodType, Set<ShareAccountCharge> charges, AppUser submittedBy,
|
||||
final Date submittedDate, AppUser approvedBy, Date approvedDate, AppUser rejectedBy, Date rejectedDate, AppUser activatedBy,
|
||||
Date activatedDate, AppUser closedBy, Date closedDate, AppUser modifiedBy, Date modifiedDate) {
|
||||
|
||||
this.client = client;
|
||||
this.shareProduct = shareProduct;
|
||||
this.externalId = externalId;
|
||||
this.currency = currency;
|
||||
this.savingsAccount = savingsAccount;
|
||||
if (StringUtils.isBlank(accountNo)) {
|
||||
this.accountNumber = new RandomPasswordGenerator(19).generate();
|
||||
this.accountNumberRequiresAutoGeneration = true;
|
||||
} else {
|
||||
this.accountNumber = accountNo;
|
||||
}
|
||||
this.totalSharesApproved = totalSharesApproved;
|
||||
this.totalSharesPending = totalSharesPending;
|
||||
this.shareAccountTransactions = purchasedShares;
|
||||
this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients;
|
||||
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
||||
this.lockinPeriodFrequencyType = lockPeriodType;
|
||||
this.minimumActivePeriodFrequency = minimumActivePeriodFrequency;
|
||||
this.minimumActivePeriodFrequencyType = minimumActivePeriodType;
|
||||
this.charges = charges;
|
||||
this.submittedDate = submittedDate;
|
||||
this.submittedBy = submittedBy;
|
||||
this.approvedDate = approvedDate;
|
||||
this.approvedBy = approvedBy;
|
||||
this.rejectedDate = rejectedDate;
|
||||
this.rejectedBy = rejectedBy;
|
||||
this.activatedDate = activatedDate;
|
||||
this.activatedBy = activatedBy;
|
||||
this.closedDate = closedDate;
|
||||
this.closedBy = closedBy;
|
||||
this.modifiedBy = modifiedBy;
|
||||
this.modifiedDate = modifiedDate;
|
||||
this.status = ShareAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue();
|
||||
}
|
||||
|
||||
public boolean setShareProduct(final ShareProduct shareProduct) {
|
||||
boolean toReturn = false;
|
||||
if (!this.shareProduct.getId().equals(shareProduct.getId())) {
|
||||
this.shareProduct = shareProduct;
|
||||
toReturn = true;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public ShareProduct getShareProduct() {
|
||||
return this.shareProduct;
|
||||
}
|
||||
|
||||
public boolean setSubmittedDate(final Date submittedDate) {
|
||||
boolean toReturn = false;
|
||||
if (!this.submittedDate.equals(submittedDate)) {
|
||||
this.submittedDate = submittedDate;
|
||||
toReturn = true;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public boolean setApprovedDate(final Date approvedDate) {
|
||||
boolean toReturn = false;
|
||||
if (!this.approvedDate.equals(approvedDate)) {
|
||||
this.approvedDate = approvedDate;
|
||||
toReturn = true;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public boolean setExternalId(final String externalId) {
|
||||
boolean toReturn = false;
|
||||
if (!this.externalId.equals(externalId)) {
|
||||
this.externalId = externalId;
|
||||
toReturn = true;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public boolean setSavingsAccount(final SavingsAccount savingsAccount) {
|
||||
boolean returnValue = false;
|
||||
if (!this.savingsAccount.getId().equals(savingsAccount.getId())) {
|
||||
this.savingsAccount = savingsAccount;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setPurchasedShares(Set<ShareAccountTransaction> purchasedShares) {
|
||||
this.shareAccountTransactions = purchasedShares;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setAllowDividendCalculationForInactiveClients(Boolean allowDividendCalculationForInactiveClients) {
|
||||
boolean returnValue = false;
|
||||
if (this.allowDividendCalculationForInactiveClients == null) {
|
||||
this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients;
|
||||
returnValue = true;
|
||||
} else if (!this.allowDividendCalculationForInactiveClients.equals(allowDividendCalculationForInactiveClients)) {
|
||||
this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setLockPeriod(final Integer lockinPeriod) {
|
||||
boolean returnValue = false;
|
||||
if (this.lockinPeriodFrequency == null || !this.lockinPeriodFrequency.equals(lockinPeriod)) {
|
||||
this.lockinPeriodFrequency = lockinPeriod;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setLockPeriodFrequencyEnum(final PeriodFrequencyType lockinPeriodFrequencyType) {
|
||||
boolean returnValue = false;
|
||||
if (!this.lockinPeriodFrequencyType.getValue().equals(lockinPeriodFrequencyType.getValue())) {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setminimumActivePeriod(final Integer minimumActivePeriodFrequency) {
|
||||
boolean returnValue = false;
|
||||
if (this.minimumActivePeriodFrequency == null || !this.minimumActivePeriodFrequency.equals(minimumActivePeriodFrequency)) {
|
||||
this.minimumActivePeriodFrequency = minimumActivePeriodFrequency;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setminimumActivePeriodTypeEnum(final PeriodFrequencyType minimumActivePeriodForDividends) {
|
||||
boolean returnValue = false;
|
||||
if (!this.minimumActivePeriodFrequencyType.getValue().equals(minimumActivePeriodForDividends.getValue())) {
|
||||
this.minimumActivePeriodFrequencyType = minimumActivePeriodForDividends;
|
||||
returnValue = true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean setCharges(final Set<ShareAccountCharge> charges) {
|
||||
this.charges = charges;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateAccountNumber(String accountNo) {
|
||||
this.accountNumber = accountNo;
|
||||
this.accountNumberRequiresAutoGeneration = false;
|
||||
}
|
||||
|
||||
public boolean isAccountNumberRequiresAutoGeneration() {
|
||||
return this.accountNumberRequiresAutoGeneration;
|
||||
}
|
||||
|
||||
public Long getClientId() {
|
||||
return this.client.getId();
|
||||
}
|
||||
|
||||
public String getClientName() {
|
||||
return this.client.getDisplayName();
|
||||
}
|
||||
|
||||
public String getSavingsAccountNo() {
|
||||
return this.savingsAccount.getAccountNumber();
|
||||
}
|
||||
|
||||
public void addAddtionalShares(Set<ShareAccountTransaction> additionalShares) {
|
||||
this.shareAccountTransactions.addAll(additionalShares);
|
||||
}
|
||||
|
||||
public Set<ShareAccountTransaction> getShareAccountTransactions() {
|
||||
return this.shareAccountTransactions;
|
||||
}
|
||||
|
||||
public Set<ShareAccountTransaction> getChargeTransactions() {
|
||||
Set<ShareAccountTransaction> chargeTransactions = new HashSet<>();
|
||||
for (ShareAccountTransaction transaction : this.shareAccountTransactions) {
|
||||
if (transaction.isChargeTransaction()) {
|
||||
chargeTransactions.add(transaction);
|
||||
}
|
||||
}
|
||||
return chargeTransactions;
|
||||
}
|
||||
|
||||
public void updateRequestedShares(ShareAccountTransaction purchased) {
|
||||
if (!this.shareAccountTransactions.isEmpty()) {
|
||||
Iterator<ShareAccountTransaction> iter = this.shareAccountTransactions.iterator();
|
||||
ShareAccountTransaction existing = iter.next();
|
||||
existing.update(purchased.getPurchasedDate(), purchased.getTotalShares(), purchased.getPurchasePrice());
|
||||
}
|
||||
}
|
||||
|
||||
public void addAdditionalPurchasedShares(ShareAccountTransaction purchased) {
|
||||
purchased.setShareAccount(this);
|
||||
if (purchased.isRedeemTransaction()) {
|
||||
this.totalSharesApproved -= purchased.getTotalShares();
|
||||
} else {
|
||||
if (this.totalSharesPending == null) {
|
||||
this.totalSharesPending = purchased.getTotalShares();
|
||||
} else {
|
||||
this.totalSharesPending += purchased.getTotalShares();
|
||||
}
|
||||
}
|
||||
this.shareAccountTransactions.add(purchased);
|
||||
}
|
||||
|
||||
public void addShareAccountCharge(ShareAccountCharge charge) {
|
||||
charge.update(this);
|
||||
this.charges.add(charge);
|
||||
}
|
||||
|
||||
public ShareAccountCharge updateShareCharge(final Long id, final Long chargeId, final BigDecimal amount) {
|
||||
ShareAccountCharge updatedCharge = null;
|
||||
for (ShareAccountCharge charge : this.charges) {
|
||||
if (charge.getId() == id && charge.getChargeId() == chargeId) {
|
||||
updatedCharge = charge;
|
||||
charge.update(amount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return updatedCharge;
|
||||
}
|
||||
|
||||
public void approve(final Date approvedDate, final AppUser approvedUser) {
|
||||
this.approvedDate = approvedDate;
|
||||
this.approvedBy = approvedUser;
|
||||
for (ShareAccountTransaction transaction : this.shareAccountTransactions) {
|
||||
transaction.approve();
|
||||
}
|
||||
this.status = ShareAccountStatusType.APPROVED.getValue();
|
||||
this.totalSharesApproved = this.totalSharesPending;
|
||||
this.totalSharesPending = null;
|
||||
}
|
||||
|
||||
public void activate(final Date approvedDate, final AppUser approvedUser) {
|
||||
this.activatedDate = approvedDate;
|
||||
this.activatedBy = approvedUser;
|
||||
this.status = ShareAccountStatusType.ACTIVE.getValue();
|
||||
}
|
||||
|
||||
public void undoApprove() {
|
||||
this.status = ShareAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue();
|
||||
this.approvedDate = null;
|
||||
this.approvedBy = null;
|
||||
this.rejectedDate = null;
|
||||
this.rejectedBy = null;
|
||||
this.closedDate = null;
|
||||
this.closedBy = null;
|
||||
this.totalSharesApproved = null;
|
||||
Iterator<ShareAccountTransaction> iter = this.shareAccountTransactions.iterator();
|
||||
ShareAccountTransaction share = iter.next();
|
||||
share.undoApprove();
|
||||
this.totalSharesPending = share.getTotalShares();
|
||||
}
|
||||
|
||||
public void reject(final Date rejectedDate, final AppUser rejectedUser) {
|
||||
this.rejectedDate = rejectedDate;
|
||||
this.rejectedBy = rejectedUser;
|
||||
this.status = ShareAccountStatusType.REJECTED.getValue();
|
||||
this.totalSharesPending = null;
|
||||
this.totalSharesApproved = null;
|
||||
Iterator<ShareAccountTransaction> iter = this.shareAccountTransactions.iterator();
|
||||
ShareAccountTransaction share = iter.next();
|
||||
share.reject();
|
||||
}
|
||||
|
||||
public void close(final Date closedDate, final AppUser closedBy) {
|
||||
this.closedDate = closedDate ;
|
||||
this.closedBy = closedBy ;
|
||||
this.status = ShareAccountStatusType.CLOSED.getValue() ;
|
||||
this.totalSharesPending = null;
|
||||
this.totalSharesApproved = null;
|
||||
}
|
||||
public String getAccountNumber() {
|
||||
return this.accountNumber;
|
||||
}
|
||||
|
||||
public ShareAccountTransaction retrievePurchasedShares(final Long id) {
|
||||
ShareAccountTransaction toReturn = null;
|
||||
for (ShareAccountTransaction share : this.shareAccountTransactions) {
|
||||
if (share.getId().equals(id)) {
|
||||
toReturn = share;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public Set<ShareAccountCharge> getCharges() {
|
||||
return this.charges;
|
||||
}
|
||||
|
||||
public void addChargeTransaction(ShareAccountTransaction chargeTransaction) {
|
||||
chargeTransaction.setShareAccount(this);
|
||||
this.shareAccountTransactions.add(chargeTransaction);
|
||||
}
|
||||
|
||||
public Set<ShareAccountTransaction> getPendingForApprovalSharePurchaseTransactions() {
|
||||
Set<ShareAccountTransaction> purchaseTransactions = new HashSet<>();
|
||||
for (ShareAccountTransaction transaction : this.shareAccountTransactions) {
|
||||
if (transaction.isPendingForApprovalTransaction()) {
|
||||
purchaseTransactions.add(transaction);
|
||||
}
|
||||
}
|
||||
return purchaseTransactions;
|
||||
}
|
||||
|
||||
public MonetaryCurrency getCurrency() {
|
||||
return this.currency;
|
||||
}
|
||||
|
||||
public void updateApprovedShares(Long shares) {
|
||||
if (this.totalSharesApproved == null) {
|
||||
this.totalSharesApproved = shares;
|
||||
} else {
|
||||
this.totalSharesApproved += shares;
|
||||
this.totalSharesPending -= shares;
|
||||
}
|
||||
}
|
||||
|
||||
public Long getTotalApprovedShares() {
|
||||
return this.totalSharesApproved ;
|
||||
}
|
||||
|
||||
public void removePendingShares(Long totalShares) {
|
||||
this.totalSharesPending -= totalShares;
|
||||
}
|
||||
|
||||
public Long getOfficeId() {
|
||||
return this.client.getOffice().getId();
|
||||
}
|
||||
|
||||
public ShareAccountTransaction getShareAccountTransaction(final ShareAccountTransaction transaction) {
|
||||
ShareAccountTransaction returnTrans = null;
|
||||
for (ShareAccountTransaction tran : this.shareAccountTransactions) {
|
||||
if (tran.getPurchasedDate().equals(transaction.getPurchasedDate())
|
||||
&& tran.getTotalShares().equals(transaction.getTotalShares())
|
||||
&& tran.getPurchasePrice().equals(transaction.getPurchasePrice())
|
||||
&& tran.getTransactionStatus().equals(transaction.getTransactionStatus())
|
||||
&& tran.getTransactionType().equals(transaction.getTransactionType())) {
|
||||
returnTrans = tran;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnTrans;
|
||||
}
|
||||
|
||||
public Date getSubmittedDate(){
|
||||
return this.submittedDate ;
|
||||
}
|
||||
|
||||
public Date getApprovedDate() {
|
||||
return this.approvedDate ;
|
||||
}
|
||||
}
|
||||
+444
@@ -0,0 +1,444 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_share_account_charge")
|
||||
public class ShareAccountCharge extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "account_id", referencedColumnName = "id", nullable = false)
|
||||
private ShareAccount shareAccount;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "charge_id", referencedColumnName = "id", nullable = false)
|
||||
private Charge charge;
|
||||
|
||||
@Column(name = "charge_time_enum", nullable = false)
|
||||
private Integer chargeTime;
|
||||
|
||||
@Column(name = "charge_calculation_enum")
|
||||
private Integer chargeCalculation;
|
||||
|
||||
@Column(name = "calculation_percentage", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal percentage;
|
||||
|
||||
@Column(name = "calculation_on_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountPercentageAppliedTo;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "amount_paid_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountPaid;
|
||||
|
||||
@Column(name = "amount_waived_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountWaived;
|
||||
|
||||
@Column(name = "amount_writtenoff_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountWrittenOff;
|
||||
|
||||
@Column(name = "amount_outstanding_derived", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amountOutstanding;
|
||||
|
||||
@Column(name = "is_paid_derived", nullable = false)
|
||||
private boolean paid = false;
|
||||
|
||||
@Column(name = "waived", nullable = false)
|
||||
private boolean waived = false;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private boolean status = true;
|
||||
|
||||
@Column(name = "charge_amount_or_percentage")
|
||||
private BigDecimal amountOrPercentage;
|
||||
|
||||
public static ShareAccountCharge createNewWithoutShareAccount(final Charge chargeDefinition, final BigDecimal amountPayable,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final boolean status) {
|
||||
return new ShareAccountCharge(null, chargeDefinition, amountPayable, chargeTime, chargeCalculation, status);
|
||||
}
|
||||
|
||||
protected ShareAccountCharge() {
|
||||
//
|
||||
}
|
||||
|
||||
private ShareAccountCharge(final ShareAccount shareAccount, final Charge chargeDefinition, final BigDecimal amount,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final boolean status) {
|
||||
|
||||
this.shareAccount = shareAccount;
|
||||
this.charge = chargeDefinition;
|
||||
this.chargeTime = (chargeTime == null) ? chargeDefinition.getChargeTimeType() : chargeTime.getValue();
|
||||
|
||||
this.chargeCalculation = chargeDefinition.getChargeCalculation();
|
||||
if (chargeCalculation != null) {
|
||||
this.chargeCalculation = chargeCalculation.getValue();
|
||||
}
|
||||
|
||||
BigDecimal chargeAmount = chargeDefinition.getAmount();
|
||||
if (amount != null) {
|
||||
chargeAmount = amount;
|
||||
}
|
||||
|
||||
final BigDecimal transactionAmount = new BigDecimal(0);
|
||||
|
||||
populateDerivedFields(transactionAmount, chargeAmount);
|
||||
this.paid = determineIfFullyPaid();
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public void populateDerivedFields(final BigDecimal transactionAmount, final BigDecimal chargeAmount) {
|
||||
if (this.chargeCalculation.equals(ChargeCalculationType.FLAT.getValue())) {
|
||||
this.percentage = null;
|
||||
this.amountOrPercentage = chargeAmount ;
|
||||
this.amount = BigDecimal.ZERO;
|
||||
this.amountPercentageAppliedTo = null;
|
||||
this.amountPaid = null;
|
||||
this.amountOutstanding = BigDecimal.ZERO;
|
||||
this.amountWaived = null;
|
||||
this.amountWrittenOff = null;
|
||||
} else if (this.chargeCalculation.equals(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue())) {
|
||||
this.percentage = chargeAmount;
|
||||
this.amountPercentageAppliedTo = transactionAmount;
|
||||
this.amount = percentageOf(this.amountPercentageAppliedTo, this.percentage);
|
||||
this.amountPaid = null;
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
this.amountWaived = null;
|
||||
this.amountWrittenOff = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void markAsFullyPaid() {
|
||||
this.amountPaid = this.amount;
|
||||
this.amountOutstanding = BigDecimal.ZERO;
|
||||
this.paid = true;
|
||||
}
|
||||
|
||||
public void resetToOriginal(final MonetaryCurrency currency) {
|
||||
this.amountPaid = BigDecimal.ZERO;
|
||||
this.amountWaived = BigDecimal.ZERO;
|
||||
this.amountWrittenOff = BigDecimal.ZERO;
|
||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||
this.paid = false;
|
||||
this.waived = false;
|
||||
}
|
||||
|
||||
public void undoPayment(final MonetaryCurrency currency, final Money transactionAmount) {
|
||||
Money amountPaid = getAmountPaid(currency);
|
||||
amountPaid = amountPaid.minus(transactionAmount);
|
||||
this.amountPaid = amountPaid.getAmount();
|
||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||
this.paid = false;
|
||||
this.status = true;
|
||||
}
|
||||
|
||||
public Money waive(final MonetaryCurrency currency) {
|
||||
Money amountWaivedToDate = Money.of(currency, this.amountWaived);
|
||||
Money amountOutstanding = Money.of(currency, this.amountOutstanding);
|
||||
this.amountWaived = amountWaivedToDate.plus(amountOutstanding).getAmount();
|
||||
this.amountOutstanding = BigDecimal.ZERO;
|
||||
this.waived = true;
|
||||
return amountOutstanding;
|
||||
}
|
||||
|
||||
public void undoWaiver(final MonetaryCurrency currency, final Money transactionAmount) {
|
||||
Money amountWaived = getAmountWaived(currency);
|
||||
amountWaived = amountWaived.minus(transactionAmount);
|
||||
this.amountWaived = amountWaived.getAmount();
|
||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||
this.waived = false;
|
||||
this.status = true;
|
||||
}
|
||||
|
||||
public Money pay(final MonetaryCurrency currency, final Money amountPaid) {
|
||||
Money amountPaidToDate = Money.of(currency, this.amountPaid);
|
||||
Money amountOutstanding = Money.of(currency, this.amountOutstanding);
|
||||
amountPaidToDate = amountPaidToDate.plus(amountPaid);
|
||||
amountOutstanding = amountOutstanding.minus(amountPaid);
|
||||
this.amountPaid = amountPaidToDate.getAmount();
|
||||
this.amountOutstanding = amountOutstanding.getAmount();
|
||||
this.paid = determineIfFullyPaid();
|
||||
return Money.of(currency, this.amountOutstanding);
|
||||
}
|
||||
|
||||
private BigDecimal calculateAmountOutstanding(final MonetaryCurrency currency) {
|
||||
return getAmount(currency).minus(getAmountWaived(currency)).minus(getAmountPaid(currency)).getAmount();
|
||||
}
|
||||
|
||||
public void update(final ShareAccount shareAccount) {
|
||||
this.shareAccount = shareAccount;
|
||||
}
|
||||
|
||||
public void update(final BigDecimal amount) {
|
||||
final BigDecimal transactionAmount = BigDecimal.ZERO;
|
||||
if (this.chargeCalculation.equals(ChargeCalculationType.FLAT.getValue())) {
|
||||
this.amountOrPercentage = amount;
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
} else if (this.chargeCalculation.equals(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue())) {
|
||||
this.percentage = amount;
|
||||
this.amountPercentageAppliedTo = transactionAmount;
|
||||
this.amount = percentageOf(this.amountPercentageAppliedTo, this.percentage);
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isGreaterThanZero(final BigDecimal value) {
|
||||
return value.compareTo(BigDecimal.ZERO) == 1;
|
||||
}
|
||||
|
||||
private boolean determineIfFullyPaid() {
|
||||
return BigDecimal.ZERO.compareTo(calculateOutstanding()) == 0;
|
||||
}
|
||||
|
||||
private BigDecimal calculateOutstanding() {
|
||||
|
||||
BigDecimal amountPaidLocal = BigDecimal.ZERO;
|
||||
if (this.amountPaid != null) {
|
||||
amountPaidLocal = this.amountPaid;
|
||||
}
|
||||
|
||||
BigDecimal amountWaivedLocal = BigDecimal.ZERO;
|
||||
if (this.amountWaived != null) {
|
||||
amountWaivedLocal = this.amountWaived;
|
||||
}
|
||||
|
||||
BigDecimal amountWrittenOffLocal = BigDecimal.ZERO;
|
||||
if (this.amountWrittenOff != null) {
|
||||
amountWrittenOffLocal = this.amountWrittenOff;
|
||||
}
|
||||
|
||||
final BigDecimal totalAccountedFor = amountPaidLocal.add(amountWaivedLocal).add(amountWrittenOffLocal);
|
||||
|
||||
return this.amount.subtract(totalAccountedFor);
|
||||
}
|
||||
|
||||
private BigDecimal percentageOf(final BigDecimal value, final BigDecimal percentage) {
|
||||
BigDecimal percentageOf = BigDecimal.ZERO;
|
||||
if (isGreaterThanZero(value)) {
|
||||
final MathContext mc = new MathContext(8, MoneyHelper.getRoundingMode());
|
||||
final BigDecimal multiplicand = percentage.divide(BigDecimal.valueOf(100l), mc);
|
||||
percentageOf = value.multiply(multiplicand, mc);
|
||||
}
|
||||
return percentageOf;
|
||||
}
|
||||
|
||||
public BigDecimal percentageOrAmount() {
|
||||
return this.amountOrPercentage;
|
||||
}
|
||||
|
||||
public BigDecimal amoutOutstanding() {
|
||||
return this.amountOutstanding;
|
||||
}
|
||||
|
||||
public boolean isNotFullyPaid() {
|
||||
return !isPaid();
|
||||
}
|
||||
|
||||
public boolean isPaid() {
|
||||
return this.paid;
|
||||
}
|
||||
|
||||
public boolean isWaived() {
|
||||
return this.waived;
|
||||
}
|
||||
|
||||
public boolean isPaidOrPartiallyPaid(final MonetaryCurrency currency) {
|
||||
|
||||
final Money amountWaivedOrWrittenOff = getAmountWaived(currency).plus(getAmountWrittenOff(currency));
|
||||
return Money.of(currency, this.amountPaid).plus(amountWaivedOrWrittenOff).isGreaterThanZero();
|
||||
}
|
||||
|
||||
public Money getAmount(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.amount);
|
||||
}
|
||||
|
||||
private Money getAmountPaid(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.amountPaid);
|
||||
}
|
||||
|
||||
public Money getAmountWaived(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.amountWaived);
|
||||
}
|
||||
|
||||
public Money getAmountWrittenOff(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.amountWrittenOff);
|
||||
}
|
||||
|
||||
public Money getAmountOutstanding(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.amountOutstanding);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param incrementBy
|
||||
* Amount used to pay off this charge
|
||||
* @return Actual amount paid on this charge
|
||||
*/
|
||||
public Money updatePaidAmountBy(final Money incrementBy) {
|
||||
Money amountPaidToDate = Money.of(incrementBy.getCurrency(), this.amountPaid);
|
||||
Money amountPaidOnThisCharge = Money.zero(incrementBy.getCurrency());
|
||||
amountPaidOnThisCharge = incrementBy;
|
||||
amountPaidToDate = amountPaidToDate.plus(incrementBy);
|
||||
this.amountPaid = amountPaidToDate.getAmount();
|
||||
final Money amountExpected = Money.of(incrementBy.getCurrency(), this.amountPaid);
|
||||
this.amountOutstanding = amountExpected.minus(amountPaidToDate).getAmount();
|
||||
this.paid = determineIfFullyPaid();
|
||||
return amountPaidOnThisCharge;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.charge.getName();
|
||||
}
|
||||
|
||||
public String currencyCode() {
|
||||
return this.charge.getCurrencyCode();
|
||||
}
|
||||
|
||||
public Charge getCharge() {
|
||||
return this.charge;
|
||||
}
|
||||
|
||||
public ShareAccount shareAccount() {
|
||||
return this.shareAccount;
|
||||
}
|
||||
|
||||
public boolean isShareAccountActivation() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isShareAccountActivation();
|
||||
}
|
||||
|
||||
public boolean isShareAccountClosure() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isSavingsClosure();
|
||||
}
|
||||
|
||||
public boolean hasCurrencyCodeOf(final String matchingCurrencyCode) {
|
||||
if (this.currencyCode() == null || matchingCurrencyCode == null) { return false; }
|
||||
return this.currencyCode().equalsIgnoreCase(matchingCurrencyCode);
|
||||
}
|
||||
|
||||
public BigDecimal updateWithdralFeeAmount(final BigDecimal transactionAmount) {
|
||||
BigDecimal amountPaybale = BigDecimal.ZERO;
|
||||
if (ChargeCalculationType.fromInt(this.chargeCalculation).isFlat()) {
|
||||
amountPaybale = this.amount;
|
||||
} else if (ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfAmount()) {
|
||||
amountPaybale = transactionAmount.multiply(this.percentage).divide(BigDecimal.valueOf(100l));
|
||||
}
|
||||
this.amountOutstanding = amountPaybale;
|
||||
return amountPaybale;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public boolean isNotActive() {
|
||||
return !isActive();
|
||||
}
|
||||
|
||||
public Long getChargeId() {
|
||||
return this.charge.getId();
|
||||
}
|
||||
|
||||
public boolean isSharesPurchaseCharge() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isSharesPurchase();
|
||||
}
|
||||
|
||||
public boolean isSharesRedeemCharge() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).isSharesRedeem();
|
||||
}
|
||||
|
||||
public Integer getChargeTimeType() {
|
||||
return this.chargeTime;
|
||||
}
|
||||
|
||||
public BigDecimal deriveChargeAmount(BigDecimal transactionAmount) {
|
||||
BigDecimal toReturnAmount = amountOrPercentage;
|
||||
if (ChargeCalculationType.fromInt(this.chargeCalculation) == ChargeCalculationType.PERCENT_OF_AMOUNT) {
|
||||
toReturnAmount = percentageOf(transactionAmount, this.percentage);
|
||||
this.amountPercentageAppliedTo = transactionAmount;
|
||||
this.amount = percentageOf(this.amountPercentageAppliedTo, this.percentage);
|
||||
this.amountPaid = null;
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
this.amountWaived = null;
|
||||
this.amountWrittenOff = null;
|
||||
}else {
|
||||
this.amount = this.amountOrPercentage;
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
this.amountWaived = null;
|
||||
this.amountWrittenOff = null;
|
||||
}
|
||||
return toReturnAmount;
|
||||
}
|
||||
|
||||
public BigDecimal updateChargeDetailsForAdditionalSharesRequest(final BigDecimal transactionAmount) {
|
||||
BigDecimal toReturnAmount = amountOrPercentage;
|
||||
if (ChargeCalculationType.fromInt(this.chargeCalculation) == ChargeCalculationType.PERCENT_OF_AMOUNT) {
|
||||
toReturnAmount = percentageOf(transactionAmount, this.percentage);
|
||||
this.amountPercentageAppliedTo = this.amountPercentageAppliedTo.add(transactionAmount);
|
||||
this.amount = percentageOf(this.amountPercentageAppliedTo, this.percentage);
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
this.amountWaived = null;
|
||||
this.amountWrittenOff = null;
|
||||
} else {
|
||||
this.amount = this.amount.add(this.amountOrPercentage);
|
||||
this.amountOutstanding = calculateOutstanding();
|
||||
this.amountWaived = null;
|
||||
this.amountWrittenOff = null;
|
||||
}
|
||||
return toReturnAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == null) { return false; }
|
||||
if (obj == this) { return true; }
|
||||
if (obj.getClass() != getClass()) { return false; }
|
||||
final ShareAccountCharge rhs = (ShareAccountCharge) obj;
|
||||
return new EqualsBuilder().appendSuper(super.equals(obj)) //
|
||||
.append(getId(), rhs.getId()) //
|
||||
.append(this.charge.getId(), rhs.charge.getId()) //
|
||||
.append(this.amount, rhs.amount) //
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(3, 5) //
|
||||
.append(getId()) //
|
||||
.append(this.charge.getId()) //
|
||||
.append(this.amount)//
|
||||
.toHashCode();
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_share_account_charge_paid_by")
|
||||
public class ShareAccountChargePaidBy extends AbstractPersistable<Long>{
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "share_transaction_id", referencedColumnName = "id", nullable = false)
|
||||
private ShareAccountTransaction shareAccountTransaction;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "charge_transaction_id", referencedColumnName = "id", nullable = false)
|
||||
private ShareAccountCharge shareAccountCharge;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amount ;
|
||||
|
||||
protected ShareAccountChargePaidBy() {
|
||||
|
||||
}
|
||||
|
||||
public ShareAccountChargePaidBy(final ShareAccountTransaction shareAccountTransaction,
|
||||
final ShareAccountCharge shareAccountCharge, final BigDecimal amount) {
|
||||
this.shareAccountTransaction = shareAccountTransaction ;
|
||||
this.shareAccountCharge = shareAccountCharge ;
|
||||
this.amount = amount ;
|
||||
}
|
||||
|
||||
public ShareAccountCharge getCharge() {
|
||||
return this.shareAccountCharge ;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount ;
|
||||
}
|
||||
|
||||
public ShareAccountTransaction getShareAccountTransaction() {
|
||||
return this.shareAccountTransaction ;
|
||||
}
|
||||
|
||||
public Long getChargeId() {
|
||||
return this.shareAccountCharge.getChargeId() ;
|
||||
}
|
||||
|
||||
public Long getShareChargeId() {
|
||||
return this.shareAccountCharge.getId() ;
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_share_account_dividend_details")
|
||||
public class ShareAccountDividendDetails extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "account_id", nullable = false)
|
||||
private Long shareAccountId;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "status")
|
||||
private Integer status;
|
||||
|
||||
@Column(name = "savings_transaction_id")
|
||||
private Long savingsTransactionId;
|
||||
|
||||
protected ShareAccountDividendDetails() {
|
||||
|
||||
}
|
||||
|
||||
public ShareAccountDividendDetails(final Long shareAccountId, final BigDecimal amount) {
|
||||
this.shareAccountId = shareAccountId;
|
||||
this.amount = amount;
|
||||
this.status = ShareAccountDividendStatusType.INITIATED.getValue();
|
||||
}
|
||||
|
||||
public void update(final Integer status, final Long savingsTransactionId) {
|
||||
this.status = status;
|
||||
this.savingsTransactionId = savingsTransactionId;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface ShareAccountDividendRepository extends JpaRepository<ShareAccountDividendDetails, Long>,
|
||||
JpaSpecificationExecutor<ShareAccountDividendDetails> {
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
public enum ShareAccountDividendStatusType {
|
||||
|
||||
INVALID(0, "shareAccountDividendStatusType.invalid"), INITIATED(100, "shareAccountDividendStatusType.initiated"), POSTED(300,
|
||||
"shareAccountDividendStatusType.posted");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private ShareAccountDividendStatusType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static ShareAccountDividendStatusType fromInt(final Integer type) {
|
||||
|
||||
ShareAccountDividendStatusType enumeration = ShareAccountDividendStatusType.INVALID;
|
||||
switch (type) {
|
||||
case 100:
|
||||
enumeration = ShareAccountDividendStatusType.INITIATED;
|
||||
break;
|
||||
case 300:
|
||||
enumeration = ShareAccountDividendStatusType.POSTED;
|
||||
break;
|
||||
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.domain;
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import org.apache.fineract.portfolio.accounts.exceptions.ShareAccountNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ShareAccountRepositoryWrapper {
|
||||
|
||||
private final ShareAccountRepository shareAccountRepository ;
|
||||
|
||||
@Autowired
|
||||
public ShareAccountRepositoryWrapper(final ShareAccountRepository shareAccountRepository) {
|
||||
this.shareAccountRepository = shareAccountRepository ;
|
||||
}
|
||||
|
||||
public ShareAccount findOneWithNotFoundDetection(final Long accountId) {
|
||||
ShareAccount account = this.shareAccountRepository.findOne(accountId) ;
|
||||
if(account == null) {
|
||||
throw new ShareAccountNotFoundException(accountId) ;
|
||||
}
|
||||
return account ;
|
||||
}
|
||||
public void save(final ShareAccount shareAccount) {
|
||||
this.shareAccountRepository.save(shareAccount) ;
|
||||
}
|
||||
|
||||
public void saveAndFlush(final ShareAccount shareAccount) {
|
||||
this.shareAccountRepository.saveAndFlush(shareAccount) ;
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
/**
|
||||
* Enum representation of {@link ShareAccount} status states.
|
||||
*/
|
||||
public enum ShareAccountStatusType {
|
||||
|
||||
INVALID(0, "shareAccountStatusType.invalid"), //
|
||||
SUBMITTED_AND_PENDING_APPROVAL(100, "shareAccountStatusType.submitted.and.pending.approval"), //
|
||||
APPROVED(200, "shareAccountStatusType.approved"), //
|
||||
ACTIVE(300, "shareAccountStatusType.active"), //
|
||||
REJECTED(500, "shareAccountStatusType.rejected"), //
|
||||
CLOSED(600, "shareAccountStatusType.closed");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
public static ShareAccountStatusType fromInt(final Integer type) {
|
||||
|
||||
ShareAccountStatusType enumeration = ShareAccountStatusType.INVALID;
|
||||
switch (type) {
|
||||
case 100:
|
||||
enumeration = ShareAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL;
|
||||
break;
|
||||
case 200:
|
||||
enumeration = ShareAccountStatusType.APPROVED;
|
||||
break;
|
||||
case 300:
|
||||
enumeration = ShareAccountStatusType.ACTIVE;
|
||||
break;
|
||||
case 500:
|
||||
enumeration = ShareAccountStatusType.REJECTED;
|
||||
break;
|
||||
case 600:
|
||||
enumeration = ShareAccountStatusType.CLOSED;
|
||||
break;
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
private ShareAccountStatusType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public boolean hasStateOf(final ShareAccountStatusType state) {
|
||||
return this.value.equals(state.getValue());
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public boolean isSubmittedAndPendingApproval() {
|
||||
return this.value.equals(ShareAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue());
|
||||
}
|
||||
|
||||
public boolean isApproved() {
|
||||
return this.value.equals(ShareAccountStatusType.APPROVED.getValue());
|
||||
}
|
||||
|
||||
public boolean isRejected() {
|
||||
return this.value.equals(ShareAccountStatusType.REJECTED.getValue());
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.value.equals(ShareAccountStatusType.ACTIVE.getValue());
|
||||
}
|
||||
|
||||
public boolean isActiveOrAwaitingApprovalOrDisbursal() {
|
||||
return isApproved() || isSubmittedAndPendingApproval() || isActive();
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return this.value.equals(ShareAccountStatusType.CLOSED.getValue()) || isRejected();
|
||||
}
|
||||
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_share_account_transactions")
|
||||
public class ShareAccountTransaction extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "account_id", referencedColumnName = "id", nullable = false)
|
||||
private ShareAccount shareAccount;
|
||||
|
||||
@Column(name = "transaction_date")
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date transactionDate;
|
||||
|
||||
@Column(name = "total_shares")
|
||||
private Long totalShares;
|
||||
|
||||
@Column(name = "unit_price")
|
||||
private BigDecimal shareValue;
|
||||
|
||||
@Column(name = "amount")
|
||||
private BigDecimal amount ;
|
||||
|
||||
@Column(name = "charge_amount")
|
||||
private BigDecimal totalChargeAmount ;
|
||||
|
||||
@Column(name = "status_enum", nullable = true)
|
||||
private Integer status;
|
||||
|
||||
@Column(name = "type_enum", nullable = true)
|
||||
private Integer type ;
|
||||
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccountTransaction", orphanRemoval = true)
|
||||
private final Set<ShareAccountChargePaidBy> shareAccountChargesPaid = new HashSet<>();
|
||||
|
||||
protected ShareAccountTransaction() {
|
||||
|
||||
}
|
||||
|
||||
public void setShareAccount(final ShareAccount shareAccount) {
|
||||
this.shareAccount = shareAccount;
|
||||
}
|
||||
|
||||
public ShareAccountTransaction(final Date transactionDate, final Long totalShares, final BigDecimal shareValue) {
|
||||
this.transactionDate = transactionDate;
|
||||
this.totalShares = totalShares;
|
||||
this.shareValue = shareValue;
|
||||
this.status = PurchasedSharesStatusType.APPLIED.getValue();
|
||||
this.type = PurchasedSharesStatusType.PURCHASED.getValue() ;
|
||||
this.amount = shareValue.multiply(BigDecimal.valueOf(totalShares)) ;
|
||||
}
|
||||
|
||||
private ShareAccountTransaction(final Date transactionDate, final Long totalShares, final BigDecimal shareValue,
|
||||
final Integer status, final Integer type, final BigDecimal amount, final BigDecimal chargeAmount) {
|
||||
this.transactionDate = transactionDate;
|
||||
this.totalShares = totalShares;
|
||||
this.shareValue = shareValue;
|
||||
this.status = status ;
|
||||
this.type = type ;
|
||||
this.amount = amount ;
|
||||
this.totalChargeAmount = chargeAmount ;
|
||||
}
|
||||
|
||||
public static ShareAccountTransaction createRedeemTransaction(final Date transactionDate, final Long totalShares, final BigDecimal shareValue) {
|
||||
final Integer status = PurchasedSharesStatusType.APPROVED.getValue() ;
|
||||
final Integer type = PurchasedSharesStatusType.REDEEMED.getValue() ;
|
||||
final BigDecimal amount = shareValue.multiply(BigDecimal.valueOf(totalShares)) ;
|
||||
return new ShareAccountTransaction(transactionDate, totalShares, shareValue, status, type, amount, null) ;
|
||||
}
|
||||
|
||||
public static ShareAccountTransaction createChargeTransaction(final Date transactionDate, final ShareAccountCharge charge) {
|
||||
final Long totalShares = null ;
|
||||
final BigDecimal unitPrice = null ;
|
||||
final Integer status = PurchasedSharesStatusType.APPROVED.getValue() ;
|
||||
final Integer type = PurchasedSharesStatusType.CHARGE_PAYMENT.getValue() ;
|
||||
BigDecimal amount = charge.percentageOrAmount() ;
|
||||
BigDecimal chargeAmount = amount ;
|
||||
return new ShareAccountTransaction(transactionDate, totalShares, unitPrice, status, type, amount, chargeAmount) ;
|
||||
}
|
||||
|
||||
public Date getPurchasedDate() {
|
||||
return this.transactionDate;
|
||||
}
|
||||
|
||||
public Long getTotalShares() {
|
||||
return this.totalShares;
|
||||
}
|
||||
|
||||
public BigDecimal getPurchasePrice() {
|
||||
return this.shareValue;
|
||||
}
|
||||
|
||||
public void update(final Date purchasedDate, final Long totalShares, final BigDecimal shareValue) {
|
||||
this.transactionDate = purchasedDate;
|
||||
this.totalShares = totalShares;
|
||||
this.shareValue = shareValue;
|
||||
this.amount = shareValue.multiply(BigDecimal.valueOf(totalShares)) ;
|
||||
this.status = PurchasedSharesStatusType.APPLIED.getValue();
|
||||
}
|
||||
|
||||
public void approve() {
|
||||
this.status = PurchasedSharesStatusType.APPROVED.getValue() ;
|
||||
}
|
||||
|
||||
public void undoApprove() {
|
||||
this.status = PurchasedSharesStatusType.APPLIED.getValue() ;
|
||||
}
|
||||
|
||||
public void reject() {
|
||||
this.status = PurchasedSharesStatusType.REJECTED.getValue() ;
|
||||
if(this.totalChargeAmount != null) {
|
||||
this.amount = this.amount.subtract(totalChargeAmount) ;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPendingForApprovalTransaction() {
|
||||
return this.status.equals(PurchasedSharesStatusType.APPLIED.getValue()) && this.type.equals(PurchasedSharesStatusType.PURCHASED.getValue()) ;
|
||||
}
|
||||
|
||||
public boolean isPurchasTransaction() {
|
||||
return this.status.equals(PurchasedSharesStatusType.APPROVED.getValue()) && this.type.equals(PurchasedSharesStatusType.PURCHASED.getValue()) ;
|
||||
}
|
||||
|
||||
public boolean isRedeemTransaction() {
|
||||
return this.status.equals(PurchasedSharesStatusType.APPROVED.getValue()) && this.type.equals(PurchasedSharesStatusType.REDEEMED.getValue()) ;
|
||||
}
|
||||
|
||||
public boolean isChargeTransaction() {
|
||||
return this.status.equals(PurchasedSharesStatusType.APPROVED.getValue()) && this.type.equals(PurchasedSharesStatusType.CHARGE_PAYMENT.getValue()) ;
|
||||
}
|
||||
|
||||
public void addShareAccountChargePaidBy(final ShareAccountChargePaidBy chargePaidBy) {
|
||||
this.shareAccountChargesPaid.add(chargePaidBy) ;
|
||||
}
|
||||
|
||||
public BigDecimal amount() {
|
||||
return this.amount ;
|
||||
}
|
||||
|
||||
public BigDecimal chargeAmount() {
|
||||
return this.totalChargeAmount ;
|
||||
}
|
||||
|
||||
public void updateChargeAmount(BigDecimal totalChargeAmount) {
|
||||
this.amount = this.amount.add(totalChargeAmount);
|
||||
this.totalChargeAmount = totalChargeAmount ;
|
||||
}
|
||||
|
||||
public void deductChargesFromTotalAmount(BigDecimal totalChargeAmount) {
|
||||
this.amount = this.amount.subtract(totalChargeAmount);
|
||||
this.totalChargeAmount = totalChargeAmount ;
|
||||
}
|
||||
|
||||
public Set<ShareAccountChargePaidBy> getChargesPaidBy() {
|
||||
return this.shareAccountChargesPaid ;
|
||||
}
|
||||
|
||||
public Integer getTransactionStatus() {
|
||||
return this.status ;
|
||||
}
|
||||
|
||||
public Integer getTransactionType() {
|
||||
return this.type ;
|
||||
}
|
||||
|
||||
public void adjustRedeemAmount() {
|
||||
if(this.totalChargeAmount != null) {
|
||||
this.amount = this.amount.subtract(totalChargeAmount) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.exceptions;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException}
|
||||
*/
|
||||
public class IssueableSharesExceededException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public IssueableSharesExceededException() {
|
||||
super("error.msg.shares.issuable.shares.exceeded", "Issueable Shares exceeded than product definition");
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "ACTIVATE")
|
||||
public class ActivateShareAccountCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public ActivateShareAccountCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.activateShareAccount(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "APPLYADDITIONALSHARES")
|
||||
public class ApplyAddtionalSharesCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public ApplyAddtionalSharesCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.applyAddtionalShares(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "APPROVEADDITIONALSHARES")
|
||||
public class ApproveAddtionalSharesCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public ApproveAddtionalSharesCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.approveAdditionalShares(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "APPROVE")
|
||||
public class ApproveShareAccountCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public ApproveShareAccountCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.approveShareAccount(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "CLOSE")
|
||||
public class CloseShareAccountCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public CloseShareAccountCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.closeShareAccount(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -16,13 +16,13 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.handler;
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.accounts.service.ShareAccountWritePlatformService;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "REDEEMSHARES")
|
||||
public class RedeemSharesCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public RedeemSharesCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.redeemShares(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "REJECTADDITIONALSHARES")
|
||||
public class RejectAddtionalSharesCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public RejectAddtionalSharesCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.rejectAdditionalShares(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "REJECT")
|
||||
public class RejectShareAccountCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public RejectShareAccountCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.rejectShareAccount(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SHAREACCOUNT", action = "UNDOAPPROVAL")
|
||||
public class UndoApproveShareAccountCommandHandler implements NewCommandSourceHandler{
|
||||
|
||||
|
||||
private final ShareAccountWritePlatformService shareAccountWritePlatformService ;
|
||||
|
||||
@Autowired
|
||||
public UndoApproveShareAccountCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) {
|
||||
this.shareAccountWritePlatformService = shareAccountWritePlatformService ;
|
||||
}
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
|
||||
return this.shareAccountWritePlatformService.undoApproveShareAccount(jsonCommand.entityId(), jsonCommand);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -16,13 +16,13 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.accounts.handler;
|
||||
package org.apache.fineract.portfolio.shareaccounts.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.accounts.service.ShareAccountWritePlatformService;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
+741
@@ -0,0 +1,741 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.serialization;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
|
||||
import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountCharge;
|
||||
import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountChargePaidBy;
|
||||
import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountTransaction;
|
||||
import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
|
||||
import org.apache.fineract.portfolio.shareproducts.domain.ShareProductRepositoryWrapper;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Service
|
||||
public class ShareAccountDataSerializer {
|
||||
|
||||
private final PlatformSecurityContext platformSecurityContext;
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
|
||||
private final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper;
|
||||
|
||||
private final ClientRepositoryWrapper clientRepositoryWrapper;
|
||||
|
||||
private final ShareProductRepositoryWrapper shareProductRepository;
|
||||
|
||||
@Autowired
|
||||
public ShareAccountDataSerializer(final PlatformSecurityContext platformSecurityContext, final FromJsonHelper fromApiJsonHelper,
|
||||
final ChargeRepositoryWrapper chargeRepository,
|
||||
final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper, final ClientRepositoryWrapper clientRepositoryWrapper,
|
||||
final ShareProductRepositoryWrapper shareProductRepository) {
|
||||
this.platformSecurityContext = platformSecurityContext;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.chargeRepository = chargeRepository;
|
||||
this.savingsAccountRepositoryWrapper = savingsAccountRepositoryWrapper;
|
||||
this.clientRepositoryWrapper = clientRepositoryWrapper;
|
||||
this.shareProductRepository = shareProductRepository;
|
||||
}
|
||||
|
||||
public ShareAccount validateAndCreate(JsonCommand jsonCommand) {
|
||||
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), ShareAccountApiConstants.supportedParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
|
||||
final Long clientId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.clientid_paramname, element);
|
||||
final Long productId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.productid_paramname, element);
|
||||
ShareProduct shareProduct = this.shareProductRepository.findOneWithNotFoundDetection(productId);
|
||||
final LocalDate submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.submitteddate_paramname).value(submittedDate).notNull();
|
||||
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.externalid_paramname).value(externalId).notNull();
|
||||
|
||||
Long savingsAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.savingsaccountid_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.savingsaccountid_paramname).value(savingsAccountId).notNull()
|
||||
.longGreaterThanZero();
|
||||
|
||||
final Long requestedShares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares).notNull()
|
||||
.longGreaterThanZero();
|
||||
boolean allowed = shareProduct.isSharesAllowed(requestedShares) ;
|
||||
if(!allowed) {
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares).failWithCode("differ.from.productdefinition", "Out of range");;
|
||||
}
|
||||
|
||||
/*Long subscribedShares = shareProduct.getSubscribedShares() ;
|
||||
if(subscribedShares == null) subscribedShares = new Long(0) ;
|
||||
Long totalShares = shareProduct.getTotalShares() ;
|
||||
Long issuedShares = shareProduct.getSharesIssued() ;
|
||||
if(issuedShares == null) issuedShares = totalShares ;
|
||||
if((subscribedShares+requestedShares) > issuedShares) {
|
||||
throw new IssueableSharesExceededException() ;
|
||||
}
|
||||
shareProduct.addSubscribedShares(requestedShares);*/
|
||||
|
||||
/*BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareAccountApiConstants.purchasedprice_paramname, element,
|
||||
locale);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.purchasedprice_paramname).value(unitPrice).notNull().positiveAmount();*/
|
||||
|
||||
LocalDate applicationDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.applicationdate_param, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.applicationdate_param).value(applicationDate).notNull();
|
||||
|
||||
Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element);
|
||||
|
||||
Integer minimumActivePeriod = this.fromApiJsonHelper.extractIntegerNamed(ShareAccountApiConstants.minimumactiveperiod_paramname,
|
||||
element, locale);
|
||||
PeriodFrequencyType minimumActivePeriodEnum = extractPeriodType(
|
||||
ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, element);
|
||||
|
||||
if (minimumActivePeriod != null) {
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname)
|
||||
.value(minimumActivePeriodEnum.getValue()).integerSameAsNumber(PeriodFrequencyType.DAYS.getValue());
|
||||
}
|
||||
|
||||
Integer lockinPeriod = this.fromApiJsonHelper.extractIntegerNamed(ShareAccountApiConstants.lockinperiod_paramname, element, locale);
|
||||
PeriodFrequencyType lockPeriodEnum = extractPeriodType(ShareAccountApiConstants.lockperiodfrequencytype_paramname, element);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
|
||||
SavingsAccount savingsAccount = this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId);
|
||||
final MonetaryCurrency currency = shareProduct.getCurrency();
|
||||
Set<ShareAccountCharge> charges = assembleListOfAccountCharges(element, currency.getCode());
|
||||
|
||||
AppUser submittedBy = platformSecurityContext.authenticatedUser();
|
||||
AppUser approvedBy = null;
|
||||
Date approvedDate = null;
|
||||
AppUser rejectedBy = null;
|
||||
Date rejectedDate = null;
|
||||
AppUser activatedBy = null;
|
||||
Date activatedDate = null;
|
||||
AppUser closedBy = null;
|
||||
Date closedDate = null;
|
||||
AppUser modifiedBy = null;
|
||||
Date modifiedDate = null;
|
||||
String accountNo = null;
|
||||
Long approvedShares = null;
|
||||
Long pendingShares = requestedShares;
|
||||
BigDecimal unitPrice = shareProduct.deriveMarketPrice(applicationDate.toDate()) ;
|
||||
ShareAccountTransaction transaction = new ShareAccountTransaction(applicationDate.toDate(), requestedShares, unitPrice);
|
||||
Set<ShareAccountTransaction> sharesPurchased = new HashSet<>();
|
||||
sharesPurchased.add(transaction);
|
||||
|
||||
ShareAccount account = new ShareAccount(client, shareProduct, externalId, currency, savingsAccount, accountNo, approvedShares,
|
||||
pendingShares, sharesPurchased, allowdividendsForInactiveClients, lockinPeriod, lockPeriodEnum, minimumActivePeriod,
|
||||
minimumActivePeriodEnum, charges, submittedBy, submittedDate.toDate(), approvedBy, approvedDate, rejectedBy, rejectedDate,
|
||||
activatedBy, activatedDate, closedBy, closedDate, modifiedBy, modifiedDate);
|
||||
|
||||
for (ShareAccountTransaction pur : sharesPurchased) {
|
||||
pur.setShareAccount(account);
|
||||
}
|
||||
|
||||
if (charges != null) {
|
||||
for (ShareAccountCharge charge : charges) {
|
||||
charge.update(account);
|
||||
}
|
||||
}
|
||||
createChargeTransaction(account, transaction);
|
||||
return account;
|
||||
}
|
||||
|
||||
private void createChargeTransaction(ShareAccount account, final ShareAccountTransaction transaction) {
|
||||
BigDecimal totalChargeAmount = BigDecimal.ZERO;
|
||||
Set<ShareAccountCharge> charges = account.getCharges();
|
||||
Date currentDate = DateUtils.getLocalDateOfTenant().toDate();
|
||||
for (ShareAccountCharge charge : charges) {
|
||||
if (charge.isShareAccountActivation()) {
|
||||
charge.deriveChargeAmount(totalChargeAmount) ;
|
||||
ShareAccountTransaction chargeTransaction = ShareAccountTransaction.createChargeTransaction(currentDate, charge);
|
||||
ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(chargeTransaction, charge, charge.percentageOrAmount());
|
||||
chargeTransaction.addShareAccountChargePaidBy(paidBy);
|
||||
account.addChargeTransaction(chargeTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
Set<ShareAccountTransaction> pendingApprovalTransaction = account.getPendingForApprovalSharePurchaseTransactions();
|
||||
for (ShareAccountTransaction pending : pendingApprovalTransaction) {
|
||||
for (ShareAccountCharge charge : charges) {
|
||||
if (charge.isSharesPurchaseCharge()) {
|
||||
BigDecimal amount = charge.deriveChargeAmount(pending.amount());
|
||||
ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(pending, charge, amount);
|
||||
pending.addShareAccountChargePaidBy(paidBy);
|
||||
totalChargeAmount = totalChargeAmount.add(amount);
|
||||
}
|
||||
}
|
||||
pending.updateChargeAmount(totalChargeAmount);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndUpdate(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), ShareAccountApiConstants.supportedParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
ShareProduct shareProduct = account.getShareProduct() ;
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.productid_paramname, element)) {
|
||||
final Long productId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.productid_paramname, element);
|
||||
shareProduct = this.shareProductRepository.findOneWithNotFoundDetection(productId);
|
||||
if (account.setShareProduct(shareProduct)) {
|
||||
actualChanges.put(ShareAccountApiConstants.productid_paramname, productId);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.submitteddate_paramname, element)) {
|
||||
final Date submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname,
|
||||
element).toDate();
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.submitteddate_paramname).value(submittedDate).notNull();
|
||||
if (account.setSubmittedDate(submittedDate)) {
|
||||
actualChanges.put(ShareAccountApiConstants.submitteddate_paramname, submittedDate);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.externalid_paramname, element)) {
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.externalid_paramname).value(externalId).notNull();
|
||||
if (account.setExternalId(externalId)) {
|
||||
actualChanges.put(ShareAccountApiConstants.externalid_paramname, externalId);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.savingsaccountid_paramname, element)) {
|
||||
Long savingsAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.savingsaccountid_paramname, element);
|
||||
SavingsAccount savingsAccount = this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId);
|
||||
if (account.setSavingsAccount(savingsAccount)) {
|
||||
actualChanges.put(ShareAccountApiConstants.savingsaccountid_paramname, savingsAccount);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.requestedshares_paramname, element)) {
|
||||
Long requestedShares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
|
||||
/*BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareAccountApiConstants.purchasedprice_paramname,
|
||||
element, locale);*/
|
||||
Date applicationDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.applicationdate_param, element)
|
||||
.toDate();
|
||||
BigDecimal unitPrice = shareProduct.deriveMarketPrice(applicationDate) ;
|
||||
ShareAccountTransaction purchased = new ShareAccountTransaction(applicationDate, requestedShares, unitPrice);
|
||||
account.updateRequestedShares(purchased);
|
||||
actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, purchased);
|
||||
boolean allowed = shareProduct.isSharesAllowed(requestedShares) ;
|
||||
if(!allowed) {
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares).failWithCode("differ.from.productdefinition", "Out of range");;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element)) {
|
||||
Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element);
|
||||
if (account.setAllowDividendCalculationForInactiveClients(allowdividendsForInactiveClients)) {
|
||||
actualChanges.put(ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname,
|
||||
allowdividendsForInactiveClients);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.lockinperiod_paramname, element)) {
|
||||
final Integer lockinperiod = this.fromApiJsonHelper.extractIntegerNamed(ShareAccountApiConstants.lockinperiod_paramname,
|
||||
element, locale);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.lockinperiod_paramname).value(lockinperiod).notNull();
|
||||
if (account.setLockPeriod(lockinperiod)) {
|
||||
actualChanges.put(ShareAccountApiConstants.lockinperiod_paramname, lockinperiod);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.lockperiodfrequencytype_paramname, element)) {
|
||||
PeriodFrequencyType lockPeriod = extractPeriodType(ShareAccountApiConstants.lockperiodfrequencytype_paramname, element);
|
||||
if (account.setLockPeriodFrequencyEnum(lockPeriod)) {
|
||||
actualChanges.put(ShareAccountApiConstants.lockperiodfrequencytype_paramname, lockPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.minimumactiveperiod_paramname, element)) {
|
||||
final Integer minimumActivePeriod = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
ShareAccountApiConstants.minimumactiveperiod_paramname, element, locale);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.minimumactiveperiod_paramname).value(minimumActivePeriod)
|
||||
.notNull();
|
||||
if (account.setminimumActivePeriod(minimumActivePeriod)) {
|
||||
actualChanges.put(ShareAccountApiConstants.minimumactiveperiod_paramname, minimumActivePeriod);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, element)) {
|
||||
PeriodFrequencyType minimumActivePeriod = extractPeriodType(
|
||||
ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, element);
|
||||
if (account.setminimumActivePeriodTypeEnum(minimumActivePeriod)) {
|
||||
actualChanges.put(ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, minimumActivePeriod);
|
||||
}
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) {
|
||||
shareProduct = account.getShareProduct();
|
||||
Set<ShareAccountCharge> updatedCharges = assembleListOfAccountChargesforUpdate(account, element, shareProduct.getCurrency()
|
||||
.getCode());
|
||||
if (!updatedCharges.isEmpty()) {
|
||||
actualChanges.put(ShareAccountApiConstants.charges_paramname, new HashSet<ShareAccountCharge>());
|
||||
}
|
||||
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public Map<String, Object> validateAndApprove(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), ShareAccountApiConstants.approvalParameters);
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
LocalDate approvedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.approveddate_paramname, element);
|
||||
final LocalDate submittalDate = new LocalDate(account.getSubmittedDate());
|
||||
if (approvedDate != null && approvedDate.isBefore(submittalDate)) {
|
||||
final DateTimeFormatter formatter = DateTimeFormat.forPattern(jsonCommand.dateFormat()).withLocale(jsonCommand.extractLocale());
|
||||
final String submittalDateAsString = formatter.print(submittalDate);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.approveddate_paramname).value(submittalDateAsString)
|
||||
.failWithCodeNoParameterAddedToErrorCode("cannot.be.before.submittal.date");
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
|
||||
account.approve(approvedDate.toDate(), approvedUser);
|
||||
actualChanges.put(ShareAccountApiConstants.id_paramname, account.getId());
|
||||
updateTotalChargeDerived(account);
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void updateTotalChargeDerived(final ShareAccount shareAccount) {
|
||||
// Set<ShareAccountCharge> charges = shareAccount.getCharges() ;
|
||||
Set<ShareAccountTransaction> transactions = shareAccount.getShareAccountTransactions();
|
||||
for (ShareAccountTransaction transaction : transactions) {
|
||||
Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
|
||||
if (paidBySet != null && !paidBySet.isEmpty()) {
|
||||
for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
|
||||
ShareAccountCharge charge = chargePaidBy.getCharge();
|
||||
if (charge.isSharesPurchaseCharge()) {
|
||||
Money money = Money.of(shareAccount.getCurrency(), chargePaidBy.getAmount());
|
||||
charge.updatePaidAmountBy(money);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndUndoApprove(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
//final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
//this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), ShareAccountApiConstants.activateParameters);
|
||||
//final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
//final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
//JsonElement element = jsonCommand.parsedJson();
|
||||
//String notes = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.note_paramname, element);
|
||||
// baseDataValidator.reset().parameter(ShareAccountApiConstants.approveddate_paramname).validateDateAfter(account.get)
|
||||
//AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
|
||||
account.undoApprove();
|
||||
actualChanges.put(ShareAccountApiConstants.charges_paramname, Boolean.TRUE);
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public Map<String, Object> validateAndReject(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
AppUser rejectedUser = this.platformSecurityContext.authenticatedUser();
|
||||
Date rejectedDate = DateUtils.getDateOfTenant();
|
||||
account.reject(rejectedDate, rejectedUser);
|
||||
actualChanges.put(ShareAccountApiConstants.charges_paramname, Boolean.TRUE);
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public Map<String, Object> validateAndActivate(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), ShareAccountApiConstants.activateParameters);
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
LocalDate activatedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.activatedate_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.activatedate_paramname).value(activatedDate).notNull();
|
||||
final LocalDate approvedDate = new LocalDate(account.getApprovedDate());
|
||||
if (activatedDate != null && activatedDate.isBefore(approvedDate)) {
|
||||
final DateTimeFormatter formatter = DateTimeFormat.forPattern(jsonCommand.dateFormat()).withLocale(jsonCommand.extractLocale());
|
||||
final String submittalDateAsString = formatter.print(approvedDate);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.activatedate_paramname).value(submittalDateAsString)
|
||||
.failWithCodeNoParameterAddedToErrorCode("cannot.be.before.approved.date");
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
|
||||
account.activate(activatedDate.toDate(), approvedUser);
|
||||
handlechargesOnActivation(account);
|
||||
actualChanges.put(ShareAccountApiConstants.charges_paramname, activatedDate.toDate());
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void handlechargesOnActivation(final ShareAccount account) {
|
||||
Set<ShareAccountCharge> charges = account.getCharges();
|
||||
for (ShareAccountCharge charge : charges) {
|
||||
if (charge.isShareAccountActivation()) {
|
||||
charge.markAsFullyPaid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<ShareAccountCharge> assembleListOfAccountCharges(final JsonElement element, final String currencyCode) {
|
||||
final Set<ShareAccountCharge> charges = new HashSet<>();
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) {
|
||||
JsonArray chargesArray = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.charges_paramname, element);
|
||||
if (chargesArray != null) {
|
||||
for (int i = 0; i < chargesArray.size(); i++) {
|
||||
final JsonObject jsonObject = chargesArray.get(i).getAsJsonObject();
|
||||
if (jsonObject.has("chargeId")) {
|
||||
final Long id = jsonObject.get("chargeId").getAsLong();
|
||||
BigDecimal amount = jsonObject.get("amount").getAsBigDecimal();
|
||||
final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(id);
|
||||
if (!currencyCode.equals(charge.getCurrencyCode())) {
|
||||
final String errorMessage = "Charge and Share Account must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.share.account", errorMessage);
|
||||
}
|
||||
|
||||
ChargeTimeType chargeTime = null;
|
||||
ChargeCalculationType chargeCalculation = null;
|
||||
Boolean status = Boolean.TRUE;
|
||||
ShareAccountCharge accountCharge = ShareAccountCharge.createNewWithoutShareAccount(charge, amount, chargeTime,
|
||||
chargeCalculation, status);
|
||||
charges.add(accountCharge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return charges;
|
||||
}
|
||||
|
||||
private Set<ShareAccountCharge> assembleListOfAccountChargesforUpdate(final ShareAccount account, final JsonElement element,
|
||||
final String currencyCode) {
|
||||
Set<ShareAccountCharge> updated = new HashSet<>();
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) {
|
||||
JsonArray chargesArray = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.charges_paramname, element);
|
||||
if (chargesArray != null) {
|
||||
for (int i = 0; i < chargesArray.size(); i++) {
|
||||
final JsonObject jsonObject = chargesArray.get(i).getAsJsonObject();
|
||||
if (jsonObject.has("id")) {
|
||||
final Long id = jsonObject.get("id").getAsLong();
|
||||
final Long chargeId = jsonObject.get("chargeId").getAsLong();
|
||||
BigDecimal amount = jsonObject.get("amount").getAsBigDecimal();
|
||||
final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(chargeId);
|
||||
if (!currencyCode.equals(charge.getCurrencyCode())) {
|
||||
final String errorMessage = "Charge and Share Account must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.share.account", errorMessage);
|
||||
}
|
||||
ShareAccountCharge updatedCharge = account.updateShareCharge(id, chargeId, amount);
|
||||
updated.add(updatedCharge);
|
||||
} else {
|
||||
if (jsonObject.has("chargeId")) {
|
||||
final Long id = jsonObject.get("chargeId").getAsLong();
|
||||
BigDecimal amount = jsonObject.get("amount").getAsBigDecimal();
|
||||
final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(id);
|
||||
if (!currencyCode.equals(charge.getCurrencyCode())) {
|
||||
final String errorMessage = "Charge and Share Account must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.share.account", errorMessage);
|
||||
}
|
||||
ChargeTimeType chargeTime = ChargeTimeType.fromInt(charge.getChargeTimeType());
|
||||
ChargeCalculationType chargeCalculation = ChargeCalculationType.fromInt(charge.getChargeCalculation());
|
||||
Boolean status = Boolean.TRUE;
|
||||
ShareAccountCharge accountCharge = ShareAccountCharge.createNewWithoutShareAccount(charge, amount, chargeTime,
|
||||
chargeCalculation, status);
|
||||
account.addShareAccountCharge(accountCharge);
|
||||
updated.add(accountCharge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
private PeriodFrequencyType extractPeriodType(String paramName, final JsonElement element) {
|
||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.INVALID;
|
||||
frequencyType = PeriodFrequencyType.fromInt(this.fromApiJsonHelper.extractIntegerWithLocaleNamed(paramName, element));
|
||||
return frequencyType;
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndApplyAddtionalShares(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(),
|
||||
ShareAccountApiConstants.addtionalSharesParameters);
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
LocalDate requestedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.requesteddate_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname).value(requestedDate).notNull();
|
||||
final Long sharesRequested = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested).notNull();
|
||||
ShareProduct shareProduct = account.getShareProduct() ;
|
||||
if(sharesRequested != null) {
|
||||
boolean allowed = shareProduct.isSharesAllowed(sharesRequested) ;
|
||||
if(!allowed) {
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested).failWithCode("differ.from.productdefinition", "Out of range");;
|
||||
}
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
final BigDecimal unitPrice = shareProduct.deriveMarketPrice(requestedDate.toDate()) ;
|
||||
ShareAccountTransaction purchaseTransaction = new ShareAccountTransaction(requestedDate.toDate(), sharesRequested, unitPrice);
|
||||
account.addAdditionalPurchasedShares(purchaseTransaction);
|
||||
handleAdditionalSharesChargeTransactions(account, purchaseTransaction);
|
||||
actualChanges.put(ShareAccountApiConstants.additionalshares_paramname, purchaseTransaction);
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void handleAdditionalSharesChargeTransactions(final ShareAccount account, final ShareAccountTransaction purchaseTransaction) {
|
||||
Set<ShareAccountCharge> charges = account.getCharges();
|
||||
BigDecimal totalChargeAmount = BigDecimal.ZERO;
|
||||
for (ShareAccountCharge charge : charges) {
|
||||
if (charge.isSharesPurchaseCharge()) {
|
||||
BigDecimal amount = charge.updateChargeDetailsForAdditionalSharesRequest(purchaseTransaction.amount());
|
||||
ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(purchaseTransaction, charge, amount);
|
||||
purchaseTransaction.addShareAccountChargePaidBy(paidBy);
|
||||
totalChargeAmount = totalChargeAmount.add(amount);
|
||||
}
|
||||
}
|
||||
purchaseTransaction.updateChargeAmount(totalChargeAmount);
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndApproveAddtionalShares(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(),
|
||||
ShareAccountApiConstants.addtionalSharesParameters);
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
final ArrayList<Long> purchasedShares = new ArrayList<>();
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.requestedshares_paramname, element)) {
|
||||
JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.requestedshares_paramname, element);
|
||||
long totalShares = 0 ;
|
||||
for (JsonElement arrayElement : array) {
|
||||
final Long purchasedSharesId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.id_paramname, arrayElement);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(purchasedSharesId).notBlank() ;
|
||||
ShareAccountTransaction transaction = account.retrievePurchasedShares(purchasedSharesId);
|
||||
if (transaction != null) {
|
||||
totalShares+=transaction.getTotalShares().longValue() ;
|
||||
transaction.approve();
|
||||
updateTotalChargeDerivedForAdditonalShares(account, transaction);
|
||||
}
|
||||
purchasedShares.add(purchasedSharesId);
|
||||
}
|
||||
if(totalShares > 0) {
|
||||
account.updateApprovedShares(new Long(totalShares)) ;
|
||||
}
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, purchasedShares);
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void updateTotalChargeDerivedForAdditonalShares(final ShareAccount shareAccount, final ShareAccountTransaction transaction) {
|
||||
Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
|
||||
if (paidBySet != null && !paidBySet.isEmpty()) {
|
||||
for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
|
||||
ShareAccountCharge charge = chargePaidBy.getCharge();
|
||||
if (charge.isSharesPurchaseCharge()) {
|
||||
Money money = Money.of(shareAccount.getCurrency(), chargePaidBy.getAmount());
|
||||
charge.updatePaidAmountBy(money);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndRejectAddtionalShares(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(),
|
||||
ShareAccountApiConstants.addtionalSharesParameters);
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
final ArrayList<Long> purchasedShares = new ArrayList<>();
|
||||
if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.requestedshares_paramname, element)) {
|
||||
long totalShares = 0 ;
|
||||
JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.requestedshares_paramname, element);
|
||||
for (JsonElement arrayElement : array) {
|
||||
final Long purchasedSharesId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.id_paramname, arrayElement);
|
||||
ShareAccountTransaction shares = account.retrievePurchasedShares(purchasedSharesId);
|
||||
if (shares != null) {
|
||||
shares.reject();
|
||||
updateTotalChargeDerivedForAdditonalSharesReject(account, shares) ;
|
||||
totalShares +=shares.getTotalShares().longValue() ;
|
||||
}
|
||||
purchasedShares.add(purchasedSharesId);
|
||||
}
|
||||
if(totalShares > 0) {
|
||||
account.removePendingShares(new Long(totalShares)) ;
|
||||
}
|
||||
}
|
||||
actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, purchasedShares);
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void updateTotalChargeDerivedForAdditonalSharesReject(final ShareAccount shareAccount, final ShareAccountTransaction transaction) {
|
||||
Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
|
||||
if (paidBySet != null && !paidBySet.isEmpty()) {
|
||||
for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
|
||||
ShareAccountCharge charge = chargePaidBy.getCharge();
|
||||
if (charge.isSharesPurchaseCharge()) {
|
||||
Money money = Money.of(shareAccount.getCurrency(), chargePaidBy.getAmount());
|
||||
charge.updatePaidAmountBy(money);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndRedeemShares(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(),
|
||||
ShareAccountApiConstants.addtionalSharesParameters);
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
LocalDate requestedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.requesteddate_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname).value(requestedDate).notNull();
|
||||
final Long sharesRequested = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested).notNull()
|
||||
.longGreaterThanZero();
|
||||
|
||||
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
|
||||
final BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareAccountApiConstants.purchasedprice_paramname,
|
||||
element, locale);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.purchasedprice_paramname).value(unitPrice).notNull().positiveAmount();
|
||||
ShareAccountTransaction transaction = ShareAccountTransaction.createRedeemTransaction(requestedDate.toDate(), sharesRequested,
|
||||
unitPrice);
|
||||
account.addAdditionalPurchasedShares(transaction);
|
||||
actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, transaction);
|
||||
handleRedeemSharesChargeTransactions(account, transaction);
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void handleRedeemSharesChargeTransactions(final ShareAccount account, final ShareAccountTransaction transaction) {
|
||||
Set<ShareAccountCharge> charges = account.getCharges();
|
||||
BigDecimal totalChargeAmount = BigDecimal.ZERO;
|
||||
for (ShareAccountCharge charge : charges) {
|
||||
if (charge.isSharesRedeemCharge()) {
|
||||
BigDecimal amount = charge.updateChargeDetailsForAdditionalSharesRequest(transaction.amount());
|
||||
ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(transaction, charge, amount);
|
||||
transaction.addShareAccountChargePaidBy(paidBy);
|
||||
totalChargeAmount = totalChargeAmount.add(amount);
|
||||
}
|
||||
}
|
||||
transaction.deductChargesFromTotalAmount(totalChargeAmount);
|
||||
Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
|
||||
if (paidBySet != null && !paidBySet.isEmpty()) {
|
||||
for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
|
||||
ShareAccountCharge charge = chargePaidBy.getCharge();
|
||||
if (charge.isSharesRedeemCharge()) {
|
||||
Money money = Money.of(account.getCurrency(), chargePaidBy.getAmount());
|
||||
charge.updatePaidAmountBy(money);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// transaction.adjustRedeemAmount();
|
||||
}
|
||||
|
||||
public Map<String, Object> validateAndClose(JsonCommand jsonCommand, ShareAccount account) {
|
||||
Map<String, Object> actualChanges = new HashMap<>();
|
||||
if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); }
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), ShareAccountApiConstants.closeParameters);
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
|
||||
JsonElement element = jsonCommand.parsedJson();
|
||||
LocalDate closedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.closeddate_paramname, element);
|
||||
baseDataValidator.reset().parameter(ShareAccountApiConstants.approveddate_paramname).value(closedDate).notNull();
|
||||
AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
|
||||
final BigDecimal unitPrice = account.getShareProduct().deriveMarketPrice(DateUtils.getDateOfTenant()) ;
|
||||
ShareAccountTransaction transaction = ShareAccountTransaction.createRedeemTransaction(closedDate.toDate(), account.getTotalApprovedShares(), unitPrice) ;
|
||||
account.addAdditionalPurchasedShares(transaction);
|
||||
account.close(closedDate.toDate(), approvedUser);
|
||||
handleRedeemSharesChargeTransactions(account, transaction) ;
|
||||
actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, transaction);
|
||||
updateTotalChargeDerived(account);
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
return actualChanges;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareaccounts.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.PurchasedSharesData;
|
||||
|
||||
public interface PurchasedSharesReadPlatformService {
|
||||
|
||||
public Collection<PurchasedSharesData> retrievePurchasedShares(final Long accountId) ;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user