Shares And Dividends Implementation
Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/08c553f9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/08c553f9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/08c553f9 Branch: refs/heads/develop Commit: 08c553f9fcb47137464d7fb66a644aa8bf3ccdac Parents: 9fedac2 Author: Nazeer Hussain Shaik <nazeer.sh...@confluxtechnologies.com> Authored: Wed Apr 13 16:34:38 2016 +0530 Committer: Nazeer Hussain Shaik <nazeer.sh...@confluxtechnologies.com> Committed: Wed Apr 13 16:34:38 2016 +0530 ---------------------------------------------------------------------- .../accounting/common/AccountingConstants.java | 64 +- .../AccountingDropdownReadPlatformService.java | 2 + ...countingDropdownReadPlatformServiceImpl.java | 11 + .../FinancialActivityAccountDataValidator.java | 6 +- .../accounting/journalentry/data/SharesDTO.java | 101 +++ .../journalentry/data/SharesTransactionDTO.java | 94 +++ .../journalentry/domain/JournalEntry.java | 21 +- .../service/AccountingProcessorForShares.java | 27 + .../AccountingProcessorForSharesFactory.java | 48 ++ .../service/AccountingProcessorHelper.java | 220 +++++- .../CashBasedAccountingProcessorForSavings.java | 6 + .../CashBasedAccountingProcessorForShares.java | 129 ++++ .../JournalEntryWritePlatformService.java | 2 + ...ryWritePlatformServiceJpaRepositoryImpl.java | 59 +- .../domain/PortfolioProductType.java | 7 +- ...GLAccountMappingFromApiJsonDeserializer.java | 47 +- ...ctToGLAccountMappingReadPlatformService.java | 6 + ...GLAccountMappingReadPlatformServiceImpl.java | 48 ++ ...tToGLAccountMappingWritePlatformService.java | 5 + ...LAccountMappingWritePlatformServiceImpl.java | 81 +- .../ShareProductToGLAccountMappingHelper.java | 204 +++++ .../commands/service/CommandWrapperBuilder.java | 72 +- .../domain/EntityAccountType.java | 2 +- .../core/service/SearchParameters.java | 85 ++- .../domain/FineractEntityAccessType.java | 2 +- .../entityaccess/domain/FineractEntityType.java | 11 +- .../infrastructure/jobs/service/JobName.java | 23 +- .../TellerWritePlatformServiceJpaImpl.java | 5 +- .../data/AccountSummaryCollectionData.java | 21 +- .../data/ShareAccountSummaryData.java | 73 ++ ...ilsReadPlatformServiceJpaRepositoryImpl.java | 109 ++- .../accounts/api/AccountsApiResource.java | 33 +- .../constants/ShareAccountApiConstants.java | 143 ++-- .../accounts/data/PurchasedSharesData.java | 60 -- .../accounts/data/ShareAccountData.java | 99 --- .../accounts/data/ShareChargeData.java | 32 - .../accounts/domain/PurchasedShares.java | 93 --- .../portfolio/accounts/domain/ShareAccount.java | 333 --------- .../accounts/domain/ShareAccountCharge.java | 65 -- .../accounts/domain/ShareAccountRepository.java | 27 - .../domain/ShareAccountTempRepository.java | 56 -- .../CreateShareAccountCommandHandler.java | 47 -- .../UpdateShareAccountCommandHandler.java | 47 -- .../ShareAccountDataSerializer.java | 333 --------- .../service/AccountReadPlatformService.java | 12 +- .../ShareAccountCommandsServiceImpl.java | 136 ---- .../ShareAccountReadPlatformServiceImpl.java | 53 -- .../ShareAccountWritePlatformService.java | 30 - ...ntWritePlatformServiceJpaRepositoryImpl.java | 85 --- .../portfolio/charge/data/ChargeData.java | 45 +- .../charge/domain/ChargeAppliesTo.java | 13 +- .../charge/domain/ChargeCalculationType.java | 8 + .../portfolio/charge/domain/ChargeTimeType.java | 46 +- ...untChargeWithoutMandatoryFieldException.java | 34 + ...efinitionCommandFromApiJsonDeserializer.java | 32 +- .../ChargeDropdownReadPlatformService.java | 4 + .../ChargeDropdownReadPlatformServiceImpl.java | 12 + .../charge/service/ChargeEnumerations.java | 13 + .../service/ChargeReadPlatformService.java | 6 + .../service/ChargeReadPlatformServiceImpl.java | 29 +- .../client/api/ClientsApiResource.java | 2 +- .../client/domain/AccountNumberGenerator.java | 11 +- .../LoanChargeReadPlatformServiceImpl.java | 5 +- .../products/api/ProductsApiResource.java | 90 +-- .../service/ProductReadPlatformService.java | 7 +- .../savings/SavingsAccountTransactionType.java | 10 +- .../data/SavingsAccountTransactionEnumData.java | 6 + .../savings/domain/SavingsAccount.java | 13 +- .../domain/SavingsAccountDomainService.java | 2 + .../domain/SavingsAccountDomainServiceJpa.java | 31 +- .../domain/SavingsAccountTransaction.java | 26 +- ...SavingsAccountTransactionSummaryWrapper.java | 4 +- ...ngsAccountChargeReadPlatformServiceImpl.java | 25 +- .../savings/service/SavingsEnumerations.java | 4 + .../shareaccounts/data/PurchasedSharesData.java | 78 ++ .../ShareAccountApplicationTimelineData.java | 108 +++ .../data/ShareAccountChargeData.java | 95 +++ .../shareaccounts/data/ShareAccountData.java | 247 +++++++ .../data/ShareAccountDividendData.java | 64 ++ .../data/ShareAccountStatusEnumData.java | 52 ++ .../data/ShareAccountTransactionEnumData.java | 83 +++ .../domain/PurchasedSharesStatusType.java | 80 ++ .../shareaccounts/domain/ShareAccount.java | 526 +++++++++++++ .../domain/ShareAccountCharge.java | 444 +++++++++++ .../domain/ShareAccountChargePaidBy.java | 77 ++ .../domain/ShareAccountDividendDetails.java | 64 ++ .../domain/ShareAccountDividendRepository.java | 27 + .../domain/ShareAccountDividendStatusType.java | 57 ++ .../domain/ShareAccountRepository.java | 27 + .../domain/ShareAccountRepositoryWrapper.java | 49 ++ .../domain/ShareAccountStatusType.java | 100 +++ .../domain/ShareAccountTransaction.java | 209 ++++++ .../IssueableSharesExceededException.java | 31 + .../ActivateShareAccountCommandHandler.java | 47 ++ .../ApplyAddtionalSharesCommandHandler.java | 47 ++ .../ApproveAddtionalSharesCommandHandler.java | 47 ++ .../ApproveShareAccountCommandHandler.java | 47 ++ .../CloseShareAccountCommandHandler.java | 47 ++ .../CreateShareAccountCommandHandler.java | 47 ++ .../handler/RedeemSharesCommandHandler.java | 47 ++ .../RejectAddtionalSharesCommandHandler.java | 47 ++ .../RejectShareAccountCommandHandler.java | 47 ++ .../UndoApproveShareAccountCommandHandler.java | 47 ++ .../UpdateShareAccountCommandHandler.java | 47 ++ .../ShareAccountDataSerializer.java | 741 +++++++++++++++++++ .../PurchasedSharesReadPlatformService.java | 28 + .../PurchasedSharesReadPlatformServiceImpl.java | 86 +++ .../ShareAccountChargeReadPlatformService.java | 28 + ...areAccountChargeReadPlatformServiceImpl.java | 148 ++++ .../ShareAccountCommandsServiceImpl.java | 85 +++ ...ShareAccountDividendReadPlatformService.java | 34 + ...eAccountDividendReadPlatformServiceImpl.java | 140 ++++ .../ShareAccountReadPlatformService.java | 41 + .../ShareAccountReadPlatformServiceImpl.java | 482 ++++++++++++ .../service/ShareAccountSchedularService.java | 27 + .../ShareAccountSchedularServiceImpl.java | 61 ++ .../ShareAccountWritePlatformService.java | 49 ++ ...ntWritePlatformServiceJpaRepositoryImpl.java | 404 ++++++++++ .../service/SharesEnumerations.java | 196 +++++ .../shareproducts/SharePeriodFrequencyType.java | 85 +++ .../api/ShareDividendApiResource.java | 153 ++++ .../constants/ShareProductApiConstants.java | 83 +++ .../shareproducts/data/ShareProductData.java | 339 +++++++++ .../data/ShareProductDividendPayOutData.java | 56 ++ .../data/ShareProductMarketPriceData.java | 49 ++ .../shareproducts/domain/ShareProduct.java | 434 +++++++++++ .../ShareProductDividendPayOutDetails.java | 101 +++ .../domain/ShareProductDividendStatusType.java | 62 ++ ...eProductDividentPayOutDetailsRepository.java | 27 + ...tDividentPayOutDetailsRepositoryWrapper.java | 51 ++ .../domain/ShareProductMarketPrice.java | 77 ++ .../domain/ShareProductRepository.java | 27 + .../domain/ShareProductRepositoryWrapper.java | 50 ++ .../exception/DividendNotFoundException.java | 28 + .../exception/DividentProcessingException.java | 29 + ...proveShareProductDividendCommandHandler.java | 47 ++ .../CreateShareProductCommandHandler.java | 47 ++ ...reateShareProductDividendCommandHandler.java | 47 ++ ...eleteShareProductDividendCommandHandler.java | 47 ++ .../UpdateShareProductCommandHandler.java | 47 ++ .../ShareProductDataSerializer.java | 460 ++++++++++++ .../ShareProductCommandsServiceImpl.java | 59 ++ .../service/ShareProductDividendAssembler.java | 131 ++++ ...ShareProductDividendReadPlatformService.java | 29 + ...eProductDividendReadPlatformServiceImpl.java | 128 ++++ ...ShareProductDropdownReadPlatformService.java | 30 + ...eProductDropdownReadPlatformServiceImpl.java | 53 ++ .../ShareProductReadPlatformServiceImpl.java | 283 +++++++ .../ShareProductWritePlatformService.java | 35 + ...ctWritePlatformServiceJpaRepositoryImpl.java | 190 +++++ .../constants/ShareProductApiConstants.java | 52 -- .../portfolio/shares/data/DividendsData.java | 49 -- .../shares/data/ProductDividendsData.java | 65 -- .../shares/data/ShareMarketPriceData.java | 42 -- .../portfolio/shares/data/ShareProductData.java | 160 ---- .../shares/domain/ShareMarketPrice.java | 65 -- .../portfolio/shares/domain/ShareProduct.java | 363 --------- .../shares/domain/ShareProductRepository.java | 27 - .../domain/ShareProductTempRepository.java | 79 -- .../CreateShareProductCommandHandler.java | 47 -- .../UpdateShareProductCommandHandler.java | 47 -- .../ShareProductDataSerializer.java | 341 --------- .../ShareProductCommandsServiceImpl.java | 105 --- .../ShareProductReadPlatformServiceImpl.java | 64 -- .../ShareProductWritePlatformService.java | 30 - ...ctWritePlatformServiceJpaRepositoryImpl.java | 90 --- .../service/ScheduledJobRunnerService.java | 2 + .../service/ScheduledJobRunnerServiceImpl.java | 40 +- .../migrations/core_db/V299__share_products.sql | 194 +++++ 169 files changed, 10980 insertions(+), 3404 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingConstants.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingConstants.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingConstants.java index 03ca3c6..01a6510 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingConstants.java @@ -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"; http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformService.java index a8ce5d1..8c9aa31 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformService.java @@ -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(); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformServiceImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformServiceImpl.java index 87c6b28..66ce192 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/common/AccountingDropdownReadPlatformServiceImpl.java @@ -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); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/serialization/FinancialActivityAccountDataValidator.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/serialization/FinancialActivityAccountDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/serialization/FinancialActivityAccountDataValidator.java index 104b3c8..810de31 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/serialization/FinancialActivityAccountDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/financialactivityaccount/serialization/FinancialActivityAccountDataValidator.java @@ -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)) { http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesDTO.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesDTO.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesDTO.java new file mode 100644 index 0000000..28cbb7f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesDTO.java @@ -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; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesTransactionDTO.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesTransactionDTO.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesTransactionDTO.java new file mode 100644 index 0000000..a4871bd --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/SharesTransactionDTO.java @@ -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; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java index 341baf2..3e499d1 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java @@ -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; + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForShares.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForShares.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForShares.java new file mode 100644 index 0000000..a8f5e83 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForShares.java @@ -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.accounting.journalentry.service; + +import org.apache.fineract.accounting.journalentry.data.SharesDTO; + +public interface AccountingProcessorForShares { + + void createJournalEntriesForShares(SharesDTO sharesDTO); + +} http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForSharesFactory.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForSharesFactory.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForSharesFactory.java new file mode 100644 index 0000000..a59fd40 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorForSharesFactory.java @@ -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; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/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 fb9c799..ec2c0dd 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 @@ -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) { http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java index 27eb9e8..474f321 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java @@ -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()) { http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/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 new file mode 100644 index 0000000..f379ed1 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForShares.java @@ -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); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/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 480e722..4428daa 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 @@ -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); } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/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 4ac3dc2..aed5f7f 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 @@ -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; http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/PortfolioProductType.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/PortfolioProductType.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/PortfolioProductType.java index 786699c..f43f7e1 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/PortfolioProductType.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/PortfolioProductType.java @@ -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()); + } + }