Issue fixes on shares and dividends reported by QA
Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/60588a78 Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/60588a78 Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/60588a78 Branch: refs/heads/develop Commit: 60588a78e0c23cf492371e38c6c4d15ced89d628 Parents: fe6e1e8 Author: Nazeer Hussain Shaik <nazeer.sh...@confluxtechnologies.com> Authored: Tue Apr 19 17:55:23 2016 +0530 Committer: Nazeer Hussain Shaik <nazeer.sh...@confluxtechnologies.com> Committed: Tue Apr 19 17:55:23 2016 +0530 ---------------------------------------------------------------------- .../domain/JournalEntryRepository.java | 4 + .../service/AccountingProcessorHelper.java | 31 ++ .../CashBasedAccountingProcessorForShares.java | 2 + .../JournalEntryWritePlatformService.java | 3 + ...ryWritePlatformServiceJpaRepositoryImpl.java | 40 ++ .../portfolio/charge/data/ChargeData.java | 4 +- .../SavingsAccountReadPlatformService.java | 2 + .../SavingsAccountReadPlatformServiceImpl.java | 9 + .../shareaccounts/data/PurchasedSharesData.java | 78 ---- .../data/ShareAccountChargeData.java | 5 +- .../shareaccounts/data/ShareAccountData.java | 10 +- .../data/ShareAccountTransactionData.java | 83 ++++ .../shareaccounts/domain/ShareAccount.java | 75 ++- .../domain/ShareAccountCharge.java | 32 +- .../domain/ShareAccountChargePaidBy.java | 5 + .../domain/ShareAccountTransaction.java | 64 ++- .../ShareAccountDataSerializer.java | 464 +++++++++++++------ .../PurchasedSharesReadPlatformService.java | 4 +- .../PurchasedSharesReadPlatformServiceImpl.java | 17 +- ...areAccountChargeReadPlatformServiceImpl.java | 6 +- .../ShareAccountReadPlatformServiceImpl.java | 30 +- ...ntWritePlatformServiceJpaRepositoryImpl.java | 104 ++++- .../shareproducts/domain/ShareProduct.java | 16 +- .../ShareAccountsNotFoundException.java | 29 ++ .../ShareProductDataSerializer.java | 30 +- .../service/ShareProductDividendAssembler.java | 16 +- .../ShareProductReadPlatformServiceImpl.java | 2 +- .../migrations/core_db/V299__share_products.sql | 6 +- 28 files changed, 839 insertions(+), 332 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java index 73714e0..ab61a70 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java @@ -39,4 +39,8 @@ public interface JournalEntryRepository extends JpaRepository<JournalEntry, Long @Query("from JournalEntry journalEntry where journalEntry.entityId= :entityId and journalEntry.entityType = :entityType") List<JournalEntry> findProvisioningJournalEntriesByEntityId(@Param("entityId") Long entityId, @Param("entityType") Integer entityType) ; + + @Query("from JournalEntry journalEntry where journalEntry.transactionId= :transactionId and journalEntry.reversed is false and journalEntry.entityType = :entityType") + List<JournalEntry> findJournalEntries(@Param("transactionId") String transactionId, @Param("entityType") Integer entityType) ; + } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java index ec2c0dd..3d64581 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java @@ -1001,6 +1001,37 @@ public class AccountingProcessorHelper { "Recent Portfolio changes w.r.t Charges for shares have Broken the accounting code"); } } + public void revertCashBasedJournalEntryForSharesCharges(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); + createDebitJournalEntryForShares(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; http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForShares.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForShares.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForShares.java index f379ed1..3b71474 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForShares.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForShares.java @@ -119,6 +119,8 @@ public class CashBasedAccountingProcessorForShares implements AccountingProcesso BigDecimal amountForJE = amount; if (chargeAmount != null && chargeAmount.compareTo(BigDecimal.ZERO) == 1) { amountForJE = amount.subtract(chargeAmount); + /*this.helper.revertCashBasedJournalEntryForSharesCharges(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES, + shareProductId, shareAccountId, transactionId, transactionDate, chargeAmount, feePayments);*/ } this.helper.createJournalEntriesForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(), CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId, http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java index 4428daa..89c9364 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformService.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.accounting.journalentry.service; +import java.util.ArrayList; import java.util.Date; import java.util.Map; @@ -44,4 +45,6 @@ public interface JournalEntryWritePlatformService { public String createProvisioningJournalEntries(ProvisioningEntry entry) ; void createJournalEntriesForShares(Map<String, Object> accountingBridgeData); + + void revertShareAccountJournalEntries(final ArrayList<Long> transactionId, final Date transactionDate); } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java index aed5f7f..205cb1a 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/JournalEntryWritePlatformServiceJpaRepositoryImpl.java @@ -53,6 +53,7 @@ import org.apache.fineract.accounting.journalentry.exception.JournalEntriesNotFo import org.apache.fineract.accounting.journalentry.exception.JournalEntryInvalidException; import org.apache.fineract.accounting.journalentry.exception.JournalEntryInvalidException.GL_JOURNAL_ENTRY_INVALID_REASON; import org.apache.fineract.accounting.journalentry.serialization.JournalEntryCommandFromApiJsonDeserializer; +import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioProductType; import org.apache.fineract.accounting.provisioning.domain.LoanProductProvisioningEntry; import org.apache.fineract.accounting.provisioning.domain.ProvisioningEntry; import org.apache.fineract.accounting.rule.domain.AccountingRule; @@ -383,6 +384,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa // save the reversal entry this.glJournalEntryRepository.save(reversalJournalEntry); journalEntry.setReversalJournalEntry(reversalJournalEntry); + journalEntry.setReversed(true); // save the updated journal entry this.glJournalEntryRepository.save(journalEntry); } @@ -516,6 +518,44 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa } + @Override + public void revertShareAccountJournalEntries(final ArrayList<Long> transactionIds, final Date transactionDate) { + for (Long shareTransactionId : transactionIds) { + String transactionId = AccountingProcessorHelper.SHARE_TRANSACTION_IDENTIFIER + shareTransactionId.longValue(); + List<JournalEntry> journalEntries = this.glJournalEntryRepository.findJournalEntries(transactionId, + PortfolioProductType.SHARES.getValue()); + if (journalEntries == null || journalEntries.isEmpty()) continue; + final Long officeId = journalEntries.get(0).getOffice().getId(); + final String reversalTransactionId = generateTransactionId(officeId); + for (final JournalEntry journalEntry : journalEntries) { + JournalEntry reversalJournalEntry; + String reversalComment = "Reversal entry for Journal Entry with id :" + journalEntry.getId() + " and transaction Id " + + journalEntry.getTransactionId(); + if (journalEntry.isDebitEntry()) { + reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getPaymentDetails(), + journalEntry.getGlAccount(), journalEntry.getCurrencyCode(), reversalTransactionId, Boolean.FALSE, + transactionDate, JournalEntryType.CREDIT, journalEntry.getAmount(), reversalComment, + journalEntry.getEntityType(), journalEntry.getEntityId(), journalEntry.getReferenceNumber(), + journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(), journalEntry.getClientTransaction(), + journalEntry.getShareTransactionId()); + } else { + reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getPaymentDetails(), + journalEntry.getGlAccount(), journalEntry.getCurrencyCode(), reversalTransactionId, Boolean.FALSE, + transactionDate, JournalEntryType.DEBIT, journalEntry.getAmount(), reversalComment, + journalEntry.getEntityType(), journalEntry.getEntityId(), journalEntry.getReferenceNumber(), + journalEntry.getLoanTransaction(), journalEntry.getSavingsTransaction(), journalEntry.getClientTransaction(), + journalEntry.getShareTransactionId()); + } + // save the reversal entry + this.glJournalEntryRepository.save(reversalJournalEntry); + journalEntry.setReversalJournalEntry(reversalJournalEntry); + journalEntry.setReversed(true); + // save the updated journal entry + this.glJournalEntryRepository.save(journalEntry); + } + } + } + private void validateBusinessRulesForJournalEntries(final JournalEntryCommand command) { /** check if date of Journal entry is valid ***/ final LocalDate entryLocalDate = command.getTransactionDate(); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java index 627eaf9..9828962 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java @@ -290,9 +290,11 @@ public class ChargeData implements Comparable<ChargeData>, Serializable { final BigDecimal amountPercentageAppliedTo = BigDecimal.ZERO; final Collection<ChargeData> chargeOptions = null; final Boolean isActive = null; + final BigDecimal chargeAmountOrPercentage = BigDecimal.ZERO ; + 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); + amountPercentageAppliedTo, chargeOptions, isActive, chargeAmountOrPercentage); } public boolean isPenalty() { http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java index bcc165c..b9835f1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java @@ -34,6 +34,8 @@ public interface SavingsAccountReadPlatformService { Collection<SavingsAccountData> retrieveActiveForLookup(Long clientId, DepositAccountType depositAccountType); + public Collection<SavingsAccountData> retrieveActiveForLookup(final Long clientId, DepositAccountType depositAccountType, String currencyCode) ; + SavingsAccountData retrieveOne(Long savingsId); SavingsAccountData retrieveTemplate(Long clientId, Long groupId, Long productId, boolean staffInSelectedOfficeOnly); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java index 4865fa4..022f61e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java @@ -133,6 +133,15 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead } @Override + public Collection<SavingsAccountData> retrieveActiveForLookup(final Long clientId, DepositAccountType depositAccountType, String currencyCode) { + final StringBuilder sqlBuilder = new StringBuilder("select " + this.savingAccountMapper.schema()); + sqlBuilder.append(" where sa.client_id = ? and sa.status_enum = 300 and sa.deposit_type_enum = ? and sa.currency_code = ? "); + + final Object[] queryParameters = new Object[] { clientId, depositAccountType.getValue(), currencyCode }; + return this.jdbcTemplate.query(sqlBuilder.toString(), this.savingAccountMapper, queryParameters); + } + + @Override public Page<SavingsAccountData> retrieveAll(final SearchParameters searchParameters) { final AppUser currentUser = this.context.authenticatedUser(); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/PurchasedSharesData.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/PurchasedSharesData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/PurchasedSharesData.java deleted file mode 100644 index 95048c6..0000000 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/PurchasedSharesData.java +++ /dev/null @@ -1,78 +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.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; - } -} http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountChargeData.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountChargeData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountChargeData.java index 497db0e..41eaf74 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountChargeData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountChargeData.java @@ -69,7 +69,7 @@ public class ShareAccountChargeData { 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) { + final Collection<ChargeData> chargeOptions, final Boolean isActive, final BigDecimal chargeamountorpercentage) { this.id = id; this.chargeId = chargeId; this.accountId = accountId; @@ -84,11 +84,12 @@ public class ShareAccountChargeData { this.amountWaived = amountWaived; this.amountWrittenOff = amountWrittenOff; this.amountOutstanding = amountOutstanding; - this.amountOrPercentage = getAmountOrPercentage(); + this.amountOrPercentage = chargeamountorpercentage; this.chargeOptions = chargeOptions; this.isActive = isActive; } + private BigDecimal getAmountOrPercentage() { return (this.chargeCalculationType != null) && (this.chargeCalculationType.getId().intValue() > 1) ? this.percentage : this.amount; } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountData.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountData.java index 36d3e9b..d0e1f84 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountData.java @@ -61,7 +61,7 @@ public class ShareAccountData implements AccountData { private ShareAccountSummaryData summary; - private Collection<PurchasedSharesData> purchasedShares; + private Collection<ShareAccountTransactionData> purchasedShares; private Long savingsAccountId; @@ -92,7 +92,7 @@ public class ShareAccountData implements AccountData { 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 Collection<ShareAccountTransactionData> purchasedSharesData, final Integer lockinPeriod, final EnumOptionData lockPeriodTypeEnum, final Integer minimumActivePeriod, final EnumOptionData minimumActivePeriodTypeEnum, Boolean allowdividendsforinactiveclients) { this.id = id; this.accountNo = accountNo; @@ -145,7 +145,7 @@ public class ShareAccountData implements AccountData { 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 Collection<ShareAccountTransactionData> 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, @@ -200,7 +200,7 @@ public class ShareAccountData implements AccountData { 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; + Collection<ShareAccountTransactionData> purchasedSharesData = null; GLAccountData suspenseAccount = null; Integer lockinPeriod = null; EnumOptionData lockPeriodTypeEnum = null; @@ -233,7 +233,7 @@ public class ShareAccountData implements AccountData { return this.id; } - public Collection<PurchasedSharesData> getPurchasedShares() { + public Collection<ShareAccountTransactionData> getPurchasedShares() { return this.purchasedShares; } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountTransactionData.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountTransactionData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountTransactionData.java new file mode 100644 index 0000000..dcb192e --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/data/ShareAccountTransactionData.java @@ -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; + +import java.math.BigDecimal; + +import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.joda.time.LocalDate; + +@SuppressWarnings("unused") +public class ShareAccountTransactionData { + + 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 ; + + private final BigDecimal amountPaid ; + + public ShareAccountTransactionData(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, + final BigDecimal amountPaid) { + 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 ; + this.amountPaid = amountPaid ; + } + + 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; + } +} http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java index 9cd21cf..6494383 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccount.java @@ -18,10 +18,8 @@ */ 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; @@ -261,6 +259,17 @@ public class ShareAccount extends AbstractPersistable<Long> { return true; } + public void addTransaction(final ShareAccountTransaction transaction) { + transaction.setShareAccount(this); + if(transaction.isPendingForApprovalTransaction()) { + this.totalSharesPending += transaction.getTotalShares() ; + }else if(transaction.isPurchasTransaction()) { + this.totalSharesApproved += transaction.getTotalShares() ; + } + + this.shareAccountTransactions.add(transaction); + } + public boolean setAllowDividendCalculationForInactiveClients(Boolean allowDividendCalculationForInactiveClients) { boolean returnValue = false; if (this.allowDividendCalculationForInactiveClients == null) { @@ -346,7 +355,7 @@ public class ShareAccount extends AbstractPersistable<Long> { public Set<ShareAccountTransaction> getChargeTransactions() { Set<ShareAccountTransaction> chargeTransactions = new HashSet<>(); for (ShareAccountTransaction transaction : this.shareAccountTransactions) { - if (transaction.isChargeTransaction()) { + if (transaction.isActive() && transaction.isChargeTransaction()) { chargeTransactions.add(transaction); } } @@ -380,18 +389,6 @@ public class ShareAccount extends AbstractPersistable<Long> { 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; @@ -418,10 +415,14 @@ public class ShareAccount extends AbstractPersistable<Long> { 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(); + Long tempTotalShares = new Long(0); + for (ShareAccountTransaction transaction : this.shareAccountTransactions) { + if(transaction.isPurchasTransaction()) { + transaction.undoApprove(); + tempTotalShares += transaction.getTotalShares() ; + } + } + this.totalSharesPending = tempTotalShares; } public void reject(final Date rejectedDate, final AppUser rejectedUser) { @@ -430,9 +431,11 @@ public class ShareAccount extends AbstractPersistable<Long> { this.status = ShareAccountStatusType.REJECTED.getValue(); this.totalSharesPending = null; this.totalSharesApproved = null; - Iterator<ShareAccountTransaction> iter = this.shareAccountTransactions.iterator(); - ShareAccountTransaction share = iter.next(); - share.reject(); + for (ShareAccountTransaction transaction : this.shareAccountTransactions) { + if(transaction.isPurchasTransaction()) { + transaction.reject(); + } + } } public void close(final Date closedDate, final AppUser closedBy) { @@ -469,7 +472,7 @@ public class ShareAccount extends AbstractPersistable<Long> { public Set<ShareAccountTransaction> getPendingForApprovalSharePurchaseTransactions() { Set<ShareAccountTransaction> purchaseTransactions = new HashSet<>(); for (ShareAccountTransaction transaction : this.shareAccountTransactions) { - if (transaction.isPendingForApprovalTransaction()) { + if (transaction.isActive() && transaction.isPendingForApprovalTransaction()) { purchaseTransactions.add(transaction); } } @@ -523,4 +526,30 @@ public class ShareAccount extends AbstractPersistable<Long> { public Date getApprovedDate() { return this.approvedDate ; } + + public void removeTransactions() { + for(ShareAccountTransaction transaction: this.shareAccountTransactions) { + transaction.setActive(false); + } + this.totalSharesApproved = new Long(0) ; + this.totalSharesPending = new Long(0) ; + } + + public void removeCharges() { + for(ShareAccountCharge charge: this.charges) { + charge.setActive(false); + } + } + + public void addCharges(Set<ShareAccountCharge> charges) { + this.charges.addAll(charges) ; + } + + public Integer getLockinPeriodFrequency() { + return this.lockinPeriodFrequency ; + } + + public PeriodFrequencyType getLockinPeriodFrequencyType() { + return this.lockinPeriodFrequencyType ; + } } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountCharge.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountCharge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountCharge.java index a415c36..2587dd6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountCharge.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountCharge.java @@ -83,7 +83,7 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { private boolean waived = false; @Column(name = "is_active", nullable = false) - private boolean status = true; + private boolean active = true; @Column(name = "charge_amount_or_percentage") private BigDecimal amountOrPercentage; @@ -118,13 +118,13 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { populateDerivedFields(transactionAmount, chargeAmount); this.paid = determineIfFullyPaid(); - this.status = status; + this.active = status; } - public void populateDerivedFields(final BigDecimal transactionAmount, final BigDecimal chargeAmount) { + private void populateDerivedFields(final BigDecimal transactionAmount, final BigDecimal chargeAmount) { + this.amountOrPercentage = chargeAmount ; if (this.chargeCalculation.equals(ChargeCalculationType.FLAT.getValue())) { this.percentage = null; - this.amountOrPercentage = chargeAmount ; this.amount = BigDecimal.ZERO; this.amountPercentageAppliedTo = null; this.amountPaid = null; @@ -149,6 +149,7 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { } public void resetToOriginal(final MonetaryCurrency currency) { + this.amount = BigDecimal.ZERO ; this.amountPaid = BigDecimal.ZERO; this.amountWaived = BigDecimal.ZERO; this.amountWrittenOff = BigDecimal.ZERO; @@ -163,7 +164,7 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { this.amountPaid = amountPaid.getAmount(); this.amountOutstanding = calculateAmountOutstanding(currency); this.paid = false; - this.status = true; + this.active = true; } public Money waive(final MonetaryCurrency currency) { @@ -181,7 +182,7 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { this.amountWaived = amountWaived.getAmount(); this.amountOutstanding = calculateAmountOutstanding(currency); this.waived = false; - this.status = true; + this.active = true; } public Money pay(final MonetaryCurrency currency, final Money amountPaid) { @@ -203,17 +204,8 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { 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(); - } + public void update(final BigDecimal transactionAmount, final BigDecimal amount) { + populateDerivedFields(transactionAmount, amount); } private boolean isGreaterThanZero(final BigDecimal value) { @@ -360,7 +352,7 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { } public boolean isActive() { - return this.status; + return this.active; } public boolean isNotActive() { @@ -420,6 +412,10 @@ public class ShareAccountCharge extends AbstractPersistable<Long> { return toReturnAmount; } + public void setActive(boolean active) { + this.active = active ; + } + @Override public boolean equals(final Object obj) { if (obj == null) { return false; } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountChargePaidBy.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountChargePaidBy.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountChargePaidBy.java index 97f1ce3..d9843eb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountChargePaidBy.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountChargePaidBy.java @@ -74,4 +74,9 @@ public class ShareAccountChargePaidBy extends AbstractPersistable<Long>{ public Long getShareChargeId() { return this.shareAccountCharge.getId() ; } + + public void reset() { + this.shareAccountTransaction = null ; + this.shareAccountCharge = null ; + } } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountTransaction.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountTransaction.java index 662b2cd..af2225e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/domain/ShareAccountTransaction.java @@ -58,8 +58,11 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { @Column(name = "amount") private BigDecimal amount ; + @Column(name = "amount_paid") + private BigDecimal amountPaid ; + @Column(name = "charge_amount") - private BigDecimal totalChargeAmount ; + private BigDecimal chargeAmount ; @Column(name = "status_enum", nullable = true) private Integer status; @@ -67,6 +70,9 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { @Column(name = "type_enum", nullable = true) private Integer type ; + @Column(name = "is_active", nullable = false) + private boolean active = true ; + @LazyCollection(LazyCollectionOption.FALSE) @OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccountTransaction", orphanRemoval = true) private final Set<ShareAccountChargePaidBy> shareAccountChargesPaid = new HashSet<>(); @@ -86,24 +92,27 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { this.status = PurchasedSharesStatusType.APPLIED.getValue(); this.type = PurchasedSharesStatusType.PURCHASED.getValue() ; this.amount = shareValue.multiply(BigDecimal.valueOf(totalShares)) ; + this.amountPaid = new BigDecimal(this.amount.doubleValue()) ; } private ShareAccountTransaction(final Date transactionDate, final Long totalShares, final BigDecimal shareValue, - final Integer status, final Integer type, final BigDecimal amount, final BigDecimal chargeAmount) { + final Integer status, final Integer type, final BigDecimal amount, final BigDecimal chargeAmount, final BigDecimal amountPaid) { this.transactionDate = transactionDate; this.totalShares = totalShares; this.shareValue = shareValue; this.status = status ; this.type = type ; this.amount = amount ; - this.totalChargeAmount = chargeAmount ; + this.chargeAmount = chargeAmount ; + this.amountPaid = amountPaid ; } 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) ; + BigDecimal amountPaid = new BigDecimal(amount.doubleValue()) ; + return new ShareAccountTransaction(transactionDate, totalShares, shareValue, status, type, amount, null, amountPaid) ; } public static ShareAccountTransaction createChargeTransaction(final Date transactionDate, final ShareAccountCharge charge) { @@ -113,7 +122,8 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { final Integer type = PurchasedSharesStatusType.CHARGE_PAYMENT.getValue() ; BigDecimal amount = charge.percentageOrAmount() ; BigDecimal chargeAmount = null ; - return new ShareAccountTransaction(transactionDate, totalShares, unitPrice, status, type, amount, chargeAmount) ; + BigDecimal amountPaid = null ; + return new ShareAccountTransaction(transactionDate, totalShares, unitPrice, status, type, amount, chargeAmount, amountPaid) ; } public Date getPurchasedDate() { @@ -133,6 +143,7 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { this.totalShares = totalShares; this.shareValue = shareValue; this.amount = shareValue.multiply(BigDecimal.valueOf(totalShares)) ; + this.chargeAmount = BigDecimal.ZERO ; this.status = PurchasedSharesStatusType.APPLIED.getValue(); } @@ -146,8 +157,8 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { public void reject() { this.status = PurchasedSharesStatusType.REJECTED.getValue() ; - if(this.totalChargeAmount != null) { - this.amount = this.amount.subtract(totalChargeAmount) ; + if(this.chargeAmount != null) { + this.amount = this.amount.subtract(chargeAmount) ; } } @@ -167,6 +178,10 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { return this.status.equals(PurchasedSharesStatusType.APPROVED.getValue()) && this.type.equals(PurchasedSharesStatusType.CHARGE_PAYMENT.getValue()) ; } + public boolean isPurchaseRejectedTransaction() { + return this.status.equals(PurchasedSharesStatusType.REJECTED.getValue()) && this.type.equals(PurchasedSharesStatusType.PURCHASED.getValue()) ; + } + public void addShareAccountChargePaidBy(final ShareAccountChargePaidBy chargePaidBy) { this.shareAccountChargesPaid.add(chargePaidBy) ; } @@ -176,17 +191,17 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { } public BigDecimal chargeAmount() { - return this.totalChargeAmount ; + return this.chargeAmount ; } public void updateChargeAmount(BigDecimal totalChargeAmount) { this.amount = this.amount.add(totalChargeAmount); - this.totalChargeAmount = totalChargeAmount ; + this.chargeAmount = totalChargeAmount ; } public void deductChargesFromTotalAmount(BigDecimal totalChargeAmount) { this.amount = this.amount.subtract(totalChargeAmount); - this.totalChargeAmount = totalChargeAmount ; + this.chargeAmount = totalChargeAmount ; } public Set<ShareAccountChargePaidBy> getChargesPaidBy() { @@ -201,9 +216,32 @@ public class ShareAccountTransaction extends AbstractPersistable<Long> { return this.type ; } - public void adjustRedeemAmount() { - if(this.totalChargeAmount != null) { - this.amount = this.amount.subtract(totalChargeAmount) ; + public void updateAmountPaid(final BigDecimal amountPaid) { + this.amountPaid = amountPaid ; + } + + public void addAmountPaid(final BigDecimal amountPaid) { + if(isRedeemTransaction()) { + this.amountPaid = this.amountPaid.subtract(amountPaid) ; + }else if(isPurchasTransaction() /*|| isPurchaseRejectedTransaction()*/) { + this.amountPaid = this.amountPaid.add(amountPaid) ; } } + + public void resetAmountPaid() { + this.amountPaid = BigDecimal.ZERO ; + } + + public void setActive(boolean active) { + this.active = active ; + if(!this.active) { + //this.shareAccountChargesPaid.clear(); + } + } + + public boolean isActive() { + return this.active ; + } + + }