FINERACT-2198: Extend Manual Journal entry to support Asset Externalization
This commit is contained in:
committed by
Adam Saghy
parent
4feee70a7a
commit
0c1ca2baba
+1
@@ -71,6 +71,7 @@ public interface JournalEntryMapper {
|
||||
@Mapping(target = "debits", ignore = true)
|
||||
@Mapping(target = "transactionDetails", ignore = true)
|
||||
@Mapping(target = "savingTransactionId", ignore = true)
|
||||
@Mapping(target = "externalAssetOwner", ignore = true)
|
||||
JournalEntryData map(JournalEntry journalEntry);
|
||||
|
||||
@Named("entityType")
|
||||
|
||||
+2
-1
@@ -43,7 +43,8 @@ public enum JournalEntryJsonInputParams {
|
||||
CHECK_NUMBER("checkNumber"), //
|
||||
ROUTING_CODE("routingCode"), //
|
||||
RECEIPT_NUMBER("receiptNumber"), //
|
||||
BANK_NUMBER("bankNumber"); //
|
||||
BANK_NUMBER("bankNumber"), //
|
||||
EXTERNAL_ASSET_OWNER("externalAssetOwner"); //
|
||||
|
||||
private final String value;
|
||||
|
||||
|
||||
+4
@@ -54,6 +54,7 @@ public class JournalEntryCommand {
|
||||
private final SingleDebitOrCreditEntryCommand[] debits;
|
||||
private final String locale;
|
||||
private final String dateFormat;
|
||||
private final String externalAssetOwner;
|
||||
|
||||
public void validateForCreate() {
|
||||
|
||||
@@ -75,6 +76,9 @@ public class JournalEntryCommand {
|
||||
|
||||
baseDataValidator.reset().parameter("paymentTypeId").value(this.paymentTypeId).ignoreIfNull().longGreaterThanZero();
|
||||
|
||||
baseDataValidator.reset().parameter(JournalEntryJsonInputParams.EXTERNAL_ASSET_OWNER.getValue()).value(this.externalAssetOwner)
|
||||
.ignoreIfNull().notExceedingLengthOf(100);
|
||||
|
||||
// validation for credit array elements
|
||||
if (this.credits != null) {
|
||||
if (this.credits.length == 0) {
|
||||
|
||||
+5
-3
@@ -94,6 +94,7 @@ public class JournalEntryData {
|
||||
private String routingCode;
|
||||
private String receiptNumber;
|
||||
private String bankNumber;
|
||||
private String externalAssetOwner;
|
||||
private transient Long savingTransactionId;
|
||||
|
||||
public JournalEntryData() {}
|
||||
@@ -191,7 +192,7 @@ public class JournalEntryData {
|
||||
final EnumOptionData entityType, final Long entityId, final Long createdByUserId, final LocalDate submittedOnDate,
|
||||
final String createdByUserName, final String comments, final Boolean reversed, final String referenceNumber,
|
||||
final BigDecimal officeRunningBalance, final BigDecimal organizationRunningBalance, final Boolean runningBalanceComputed,
|
||||
final TransactionDetailData transactionDetailData, final CurrencyData currency) {
|
||||
final TransactionDetailData transactionDetailData, final CurrencyData currency, final String externalAssetOwner) {
|
||||
this.id = id;
|
||||
this.officeId = officeId;
|
||||
this.officeName = officeName;
|
||||
@@ -218,6 +219,7 @@ public class JournalEntryData {
|
||||
this.runningBalanceComputed = runningBalanceComputed;
|
||||
this.transactionDetails = transactionDetailData;
|
||||
this.currency = currency;
|
||||
this.externalAssetOwner = externalAssetOwner;
|
||||
}
|
||||
|
||||
public static JournalEntryData importInstance(Long officeId, LocalDate transactionDate, String currencyCode, Long paymentTypeId,
|
||||
@@ -259,10 +261,11 @@ public class JournalEntryData {
|
||||
final Boolean runningBalanceComputed = null;
|
||||
final TransactionDetailData transactionDetailData = null;
|
||||
final CurrencyData currency = null;
|
||||
final String externalAssetOwner = null;
|
||||
return new JournalEntryData(id, officeId, officeName, glAccountName, glAccountId, glAccountCode, glAccountClassification,
|
||||
transactionDate, entryType, amount, transactionId, manualEntry, entityType, entityId, createdByUserId, submittedOnDate,
|
||||
createdByUserName, comments, reversed, referenceNumber, officeRunningBalance, organizationRunningBalance,
|
||||
runningBalanceComputed, transactionDetailData, currency);
|
||||
runningBalanceComputed, transactionDetailData, currency, externalAssetOwner);
|
||||
}
|
||||
|
||||
public Integer getRowIndex() {
|
||||
@@ -274,7 +277,6 @@ public class JournalEntryData {
|
||||
}
|
||||
|
||||
public void addDebits(CreditDebit debit) {
|
||||
|
||||
this.debits.add(debit);
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -84,6 +84,8 @@ public final class JournalEntryCommandFromApiJsonDeserializer extends AbstractFr
|
||||
element);
|
||||
final String bankNumber = this.fromApiJsonHelper.extractStringNamed(JournalEntryJsonInputParams.BANK_NUMBER.getValue(), element);
|
||||
final String routingCode = this.fromApiJsonHelper.extractStringNamed(JournalEntryJsonInputParams.ROUTING_CODE.getValue(), element);
|
||||
final String externalAssetOwner = this.fromApiJsonHelper
|
||||
.extractStringNamed(JournalEntryJsonInputParams.EXTERNAL_ASSET_OWNER.getValue(), element);
|
||||
|
||||
SingleDebitOrCreditEntryCommand[] credits = null;
|
||||
SingleDebitOrCreditEntryCommand[] debits = null;
|
||||
@@ -99,7 +101,8 @@ public final class JournalEntryCommandFromApiJsonDeserializer extends AbstractFr
|
||||
}
|
||||
String dateFormat = this.fromApiJsonHelper.extractStringNamed(JournalEntryJsonInputParams.DATE_FORMAT.getValue(), element);
|
||||
return new JournalEntryCommand(officeId, currencyCode, transactionDate, comments, referenceNumber, accountingRuleId, amount,
|
||||
paymentTypeId, accountNumber, checkNumber, receiptNumber, bankNumber, routingCode, credits, debits, localeStr, dateFormat);
|
||||
paymentTypeId, accountNumber, checkNumber, receiptNumber, bankNumber, routingCode, credits, debits, localeStr, dateFormat,
|
||||
externalAssetOwner);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.investor.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class ExternalAssetOwnerNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public ExternalAssetOwnerNotFoundException(ExternalId externalId) {
|
||||
super("error.msg.external.asset.owner.external.id",
|
||||
String.format("External asset owner with external id: %s does not found", externalId.getValue()), externalId.getValue());
|
||||
}
|
||||
|
||||
public ExternalAssetOwnerNotFoundException(Long id) {
|
||||
super("error.msg.external.asset.owner.id", String.format("External asset owner with id: %s does not found", id), id);
|
||||
}
|
||||
}
|
||||
+3
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.investor.service;
|
||||
|
||||
import org.apache.fineract.accounting.journalentry.domain.JournalEntry;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwner;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
@@ -27,4 +28,6 @@ public interface AccountingService {
|
||||
void createJournalEntriesForSaleAssetTransfer(Loan loan, ExternalAssetOwnerTransfer transfer, ExternalAssetOwner previousOwner);
|
||||
|
||||
void createJournalEntriesForBuybackAssetTransfer(Loan loan, ExternalAssetOwnerTransfer transfer);
|
||||
|
||||
void createMappingToOwner(ExternalAssetOwner owner, JournalEntry journalEntry);
|
||||
}
|
||||
|
||||
+2
-1
@@ -120,7 +120,8 @@ public class AccountingServiceImpl implements AccountingService {
|
||||
return journalEntryList;
|
||||
}
|
||||
|
||||
private void createMappingToOwner(final ExternalAssetOwner owner, final JournalEntry journalEntry) {
|
||||
@Override
|
||||
public void createMappingToOwner(final ExternalAssetOwner owner, final JournalEntry journalEntry) {
|
||||
if (owner == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+2
@@ -177,6 +177,8 @@ final class JournalEntriesApiResourceSwagger {
|
||||
public String createdByUserName;
|
||||
@Schema(example = "[2022, 07, 01]")
|
||||
public LocalDate createdDate;
|
||||
@Schema(example = "qwerty1234")
|
||||
public String externalAssetOwner;
|
||||
|
||||
public CurrencyItem currency;
|
||||
public EnumOptionType glAccountType;
|
||||
|
||||
+8
-4
@@ -99,7 +99,8 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
|
||||
.append(" creatingUser.username as createdByUserName, journalEntry.description as comments, ")
|
||||
.append(" journalEntry.submitted_on_date as submittedOnDate, journalEntry.reversed as reversed, ")
|
||||
.append(" journalEntry.currency_code as currencyCode, curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ")
|
||||
.append(" curr.display_symbol as currencyDisplaySymbol, curr.decimal_places as currencyDigits, curr.currency_multiplesof as inMultiplesOf ");
|
||||
.append(" curr.display_symbol as currencyDisplaySymbol, curr.decimal_places as currencyDigits, curr.currency_multiplesof as inMultiplesOf, ")
|
||||
.append(" eao.external_id as externalAssetOwner ");
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
sb.append(" ,journalEntry.is_running_balance_calculated as runningBalanceComputed, ")
|
||||
.append(" journalEntry.office_running_balance as officeRunningBalance, ")
|
||||
@@ -117,7 +118,9 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
|
||||
.append(" left join acc_gl_account as glAccount on glAccount.id = journalEntry.account_id")
|
||||
.append(" left join m_office as office on office.id = journalEntry.office_id")
|
||||
.append(" left join m_appuser as creatingUser on creatingUser.id = journalEntry.created_by ")
|
||||
.append(" join m_currency curr on curr.code = journalEntry.currency_code ");
|
||||
.append(" join m_currency curr on curr.code = journalEntry.currency_code ")
|
||||
.append(" left join m_external_asset_owner_journal_entry_mapping eajem on eajem.journal_entry_id = journalEntry.id ")
|
||||
.append(" left join m_external_asset_owner eao on eao.id = eajem.owner_id ");
|
||||
if (associationParametersData.isTransactionDetailsRequired()) {
|
||||
sb.append(" left join m_loan_transaction as lt on journalEntry.loan_transaction_id = lt.id ")
|
||||
.append(" left join m_savings_account_transaction as st on journalEntry.savings_transaction_id = st.id ")
|
||||
@@ -150,7 +153,6 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
|
||||
EnumOptionData entityType = null;
|
||||
if (entityTypeId != null) {
|
||||
entityType = AccountingEnumerations.portfolioProductType(entityTypeId);
|
||||
|
||||
}
|
||||
|
||||
final Long entityId = JdbcSupport.getLong(rs, "entityId");
|
||||
@@ -224,10 +226,12 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
|
||||
|
||||
transactionDetailData = new TransactionDetailData(transaction, paymentDetailData, noteData, transactionTypeEnumData);
|
||||
}
|
||||
final String externalAssetOwner = rs.getString("externalAssetOwner");
|
||||
|
||||
return new JournalEntryData(id, officeId, officeName, glAccountName, glAccountId, glCode, accountType, transactionDate,
|
||||
entryType, amount, transactionId, manualEntry, entityType, entityId, createdByUserId, submittedOnDate,
|
||||
createdByUserName, comments, reversed, referenceNumber, officeRunningBalance, organizationRunningBalance,
|
||||
runningBalanceComputed, transactionDetailData, currency);
|
||||
runningBalanceComputed, transactionDetailData, currency, externalAssetOwner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -278,7 +278,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry
|
||||
final EnumOptionData entryType = AccountingEnumerations.journalEntryType(entryTypeId);
|
||||
|
||||
return new JournalEntryData(id, officeId, null, null, glAccountId, null, accountType, null, entryType, amount, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null);
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+37
-7
@@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -60,17 +61,25 @@ import org.apache.fineract.accounting.provisioning.domain.ProvisioningEntry;
|
||||
import org.apache.fineract.accounting.rule.domain.AccountingRule;
|
||||
import org.apache.fineract.accounting.rule.domain.AccountingRuleRepository;
|
||||
import org.apache.fineract.accounting.rule.exception.AccountingRuleNotFoundException;
|
||||
import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants;
|
||||
import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwner;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerRepository;
|
||||
import org.apache.fineract.investor.exception.ExternalAssetOwnerNotFoundException;
|
||||
import org.apache.fineract.investor.service.AccountingService;
|
||||
import org.apache.fineract.organisation.monetary.domain.OrganisationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
|
||||
@@ -105,6 +114,9 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||
private final FinancialActivityAccountRepositoryWrapper financialActivityAccountRepositoryWrapper;
|
||||
private final CashBasedAccountingProcessorForClientTransactions accountingProcessorForClientTransactions;
|
||||
private final ConfigurationReadPlatformService configurationReadPlatformService;
|
||||
private final AccountingService accountingService;
|
||||
private final ExternalAssetOwnerRepository externalAssetOwnerRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -131,6 +143,22 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
final String transactionId = generateTransactionId(officeId);
|
||||
final String referenceNumber = command.stringValueOfParameterNamed(JournalEntryJsonInputParams.REFERENCE_NUMBER.getValue());
|
||||
|
||||
ExternalAssetOwner externalAssetOwner = null;
|
||||
final ExternalId externalId = ExternalIdFactory
|
||||
.produce(command.stringValueOfParameterNamed(JournalEntryJsonInputParams.EXTERNAL_ASSET_OWNER.getValue()));
|
||||
if (!externalId.isEmpty()) {
|
||||
if (!configurationReadPlatformService
|
||||
.retrieveGlobalConfiguration(GlobalConfigurationConstants.ASSET_EXTERNALIZATION_OF_NON_ACTIVE_LOANS).isEnabled()) {
|
||||
throw new JournalEntryRuntimeException("error.msg.glJournalEntry.asset.externalization.not.enabled",
|
||||
"GL Journal Entry with Asset Externalization not enabled");
|
||||
}
|
||||
final Optional<ExternalAssetOwner> optExternalAssetOwner = externalAssetOwnerRepository.findByExternalId(externalId);
|
||||
if (!optExternalAssetOwner.isPresent()) {
|
||||
throw new ExternalAssetOwnerNotFoundException(externalId);
|
||||
}
|
||||
externalAssetOwner = optExternalAssetOwner.get();
|
||||
}
|
||||
|
||||
if (accountRuleId != null) {
|
||||
|
||||
final AccountingRule accountingRule = this.accountingRuleRepository.findById(accountRuleId)
|
||||
@@ -147,13 +175,13 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
}
|
||||
|
||||
saveAllDebitOrCreditEntries(journalEntryCommand, office, paymentDetail, currencyCode, transactionDate,
|
||||
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber);
|
||||
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber, externalAssetOwner);
|
||||
} else {
|
||||
final GLAccount creditAccountHead = accountingRule.getAccountToCredit();
|
||||
validateGLAccountForTransaction(creditAccountHead);
|
||||
validateDebitOrCreditArrayForExistingGLAccount(creditAccountHead, journalEntryCommand.getCredits());
|
||||
saveAllDebitOrCreditEntries(journalEntryCommand, office, paymentDetail, currencyCode, transactionDate,
|
||||
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber);
|
||||
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber, externalAssetOwner);
|
||||
}
|
||||
|
||||
if (accountingRule.getAccountToDebit() == null) {
|
||||
@@ -167,21 +195,21 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
}
|
||||
|
||||
saveAllDebitOrCreditEntries(journalEntryCommand, office, paymentDetail, currencyCode, transactionDate,
|
||||
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber);
|
||||
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber, externalAssetOwner);
|
||||
} else {
|
||||
final GLAccount debitAccountHead = accountingRule.getAccountToDebit();
|
||||
validateGLAccountForTransaction(debitAccountHead);
|
||||
validateDebitOrCreditArrayForExistingGLAccount(debitAccountHead, journalEntryCommand.getDebits());
|
||||
saveAllDebitOrCreditEntries(journalEntryCommand, office, paymentDetail, currencyCode, transactionDate,
|
||||
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber);
|
||||
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber, externalAssetOwner);
|
||||
}
|
||||
} else {
|
||||
|
||||
saveAllDebitOrCreditEntries(journalEntryCommand, office, paymentDetail, currencyCode, transactionDate,
|
||||
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber);
|
||||
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber, externalAssetOwner);
|
||||
|
||||
saveAllDebitOrCreditEntries(journalEntryCommand, office, paymentDetail, currencyCode, transactionDate,
|
||||
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber);
|
||||
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber, externalAssetOwner);
|
||||
|
||||
}
|
||||
|
||||
@@ -598,7 +626,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
private void saveAllDebitOrCreditEntries(final JournalEntryCommand command, final Office office, final PaymentDetail paymentDetail,
|
||||
final String currencyCode, final LocalDate transactionDate,
|
||||
final SingleDebitOrCreditEntryCommand[] singleDebitOrCreditEntryCommands, final String transactionId,
|
||||
final JournalEntryType type, final String referenceNumber) {
|
||||
final JournalEntryType type, final String referenceNumber, final ExternalAssetOwner externalAssetOwner) {
|
||||
final boolean manualEntry = true;
|
||||
for (final SingleDebitOrCreditEntryCommand singleDebitOrCreditEntryCommand : singleDebitOrCreditEntryCommands) {
|
||||
final GLAccount glAccount = this.glAccountRepository.findById(singleDebitOrCreditEntryCommand.getGlAccountId())
|
||||
@@ -618,6 +646,8 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
|
||||
manualEntry, transactionDate, type, singleDebitOrCreditEntryCommand.getAmount(), comments, null, null, referenceNumber,
|
||||
null, null, null, null);
|
||||
helper.persistJournalEntry(glJournalEntry);
|
||||
|
||||
accountingService.createMappingToOwner(externalAssetOwner, glJournalEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -35,11 +35,14 @@ import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlat
|
||||
import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformServiceJpaRepositoryImpl;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||
import org.apache.fineract.accounting.rule.domain.AccountingRuleRepository;
|
||||
import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService;
|
||||
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
|
||||
import org.apache.fineract.investor.domain.ExternalAssetOwnerRepository;
|
||||
import org.apache.fineract.investor.service.AccountingService;
|
||||
import org.apache.fineract.organisation.monetary.domain.OrganisationCurrencyRepositoryWrapper;
|
||||
import org.apache.fineract.organisation.office.domain.OfficeRepository;
|
||||
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
|
||||
@@ -89,11 +92,14 @@ public class AccountingJournalEntryConfiguration {
|
||||
GLAccountReadPlatformService glAccountReadPlatformService, OrganisationCurrencyRepositoryWrapper organisationCurrencyRepository,
|
||||
PlatformSecurityContext context, PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
||||
FinancialActivityAccountRepositoryWrapper financialActivityAccountRepositoryWrapper,
|
||||
CashBasedAccountingProcessorForClientTransactions accountingProcessorForClientTransactions) {
|
||||
CashBasedAccountingProcessorForClientTransactions accountingProcessorForClientTransactions,
|
||||
ConfigurationReadPlatformService configurationReadPlatformService, AccountingService accountingService,
|
||||
ExternalAssetOwnerRepository externalAssetOwnerRepository) {
|
||||
return new JournalEntryWritePlatformServiceJpaRepositoryImpl(glClosureRepository, glAccountRepository, glJournalEntryRepository,
|
||||
officeRepositoryWrapper, accountingProcessorForLoanFactory, accountingProcessorForSavingsFactory,
|
||||
accountingProcessorForSharesFactory, helper, fromApiJsonDeserializer, accountingRuleRepository,
|
||||
glAccountReadPlatformService, organisationCurrencyRepository, context, paymentDetailWritePlatformService,
|
||||
financialActivityAccountRepositoryWrapper, accountingProcessorForClientTransactions);
|
||||
financialActivityAccountRepositoryWrapper, accountingProcessorForClientTransactions, configurationReadPlatformService,
|
||||
accountingService, externalAssetOwnerRepository);
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -1301,5 +1301,4 @@ public class AccountingScenarioIntegrationTest {
|
||||
.withSubmittedDate("01 Jan 2016").withApplicationDate("01 Jan 2016").withRequestedShares("100").build();
|
||||
return ShareAccountTransactionHelper.createShareAccount(shareAccountJSON, requestSpec, responseSpec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
@@ -192,4 +192,10 @@ public class JournalEntryHelper {
|
||||
public static PostJournalEntriesResponse createJournalEntry(String command, JournalEntryCommand request) {
|
||||
return Calls.ok(FineractClientHelper.getFineractClient().journalEntries.createGLJournalEntry(command, request));
|
||||
}
|
||||
|
||||
public static GetJournalEntriesTransactionIdResponse retrieveJournalEntryByTransactionId(final String transactionId) {
|
||||
return Calls.ok(FineractClientHelper.getFineractClient().journalEntries.retrieveAll1(//
|
||||
null, null, null, null, null, null, null, transactionId, null, //
|
||||
null, null, null, null, null, null, null, null, null, true));
|
||||
}
|
||||
}
|
||||
|
||||
+73
@@ -60,11 +60,20 @@ import org.apache.fineract.client.models.ExternalOwnerJournalEntryData;
|
||||
import org.apache.fineract.client.models.ExternalOwnerTransferJournalEntryData;
|
||||
import org.apache.fineract.client.models.ExternalTransferData;
|
||||
import org.apache.fineract.client.models.GetFinancialActivityAccountsResponse;
|
||||
import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
|
||||
import org.apache.fineract.client.models.JournalEntryCommand;
|
||||
import org.apache.fineract.client.models.JournalEntryTransactionItem;
|
||||
import org.apache.fineract.client.models.PageExternalTransferData;
|
||||
import org.apache.fineract.client.models.PostFinancialActivityAccountsRequest;
|
||||
import org.apache.fineract.client.models.PostInitiateTransferResponse;
|
||||
import org.apache.fineract.client.models.PostJournalEntriesResponse;
|
||||
import org.apache.fineract.client.models.PostLoanProductsResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||
import org.apache.fineract.client.models.PostLoansRequest;
|
||||
import org.apache.fineract.client.models.PostLoansResponse;
|
||||
import org.apache.fineract.client.models.PutGlobalConfigurationsRequest;
|
||||
import org.apache.fineract.client.models.SingleDebitOrCreditEntryCommand;
|
||||
import org.apache.fineract.client.util.CallFailedRuntimeException;
|
||||
import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants;
|
||||
import org.apache.fineract.infrastructure.event.external.data.ExternalEventResponse;
|
||||
@@ -80,6 +89,7 @@ import org.apache.fineract.integrationtests.common.Utils;
|
||||
import org.apache.fineract.integrationtests.common.accounting.Account;
|
||||
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
|
||||
import org.apache.fineract.integrationtests.common.accounting.FinancialActivityAccountHelper;
|
||||
import org.apache.fineract.integrationtests.common.accounting.JournalEntryHelper;
|
||||
import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
|
||||
import org.apache.fineract.integrationtests.common.externalevents.ExternalEventHelper;
|
||||
import org.apache.fineract.integrationtests.common.externalevents.ExternalEventsExtension;
|
||||
@@ -1178,6 +1188,69 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addManualJournalEntriesWithAssetExternalization() {
|
||||
runAt("10 April 2025", () -> {
|
||||
|
||||
final Account glAccountDebit = accountHelper.createAssetAccount();
|
||||
final Account glAccountCredit = accountHelper.createLiabilityAccount();
|
||||
final String externalAssetOwner = Utils.uniqueRandomStringGenerator("ASSET_EXTERNAL_", 5);
|
||||
|
||||
CallFailedRuntimeException callFailedRuntimeException = Assertions.assertThrows(CallFailedRuntimeException.class,
|
||||
() -> JournalEntryHelper.createJournalEntry("", new JournalEntryCommand().amount(BigDecimal.TEN).officeId(1L)
|
||||
.currencyCode("USD").locale("en").dateFormat("uuuu-MM-dd").transactionDate(LocalDate.of(2024, 1, 1))
|
||||
.addCreditsItem(new SingleDebitOrCreditEntryCommand().glAccountId(glAccountDebit.getAccountID().longValue())
|
||||
.amount(BigDecimal.TEN))
|
||||
.addDebitsItem(new SingleDebitOrCreditEntryCommand().glAccountId(glAccountCredit.getAccountID().longValue())
|
||||
.amount(BigDecimal.TEN))
|
||||
.externalAssetOwner(externalAssetOwner)));
|
||||
Assertions.assertTrue(callFailedRuntimeException.getMessage().contains("External asset owner with external id:"));
|
||||
|
||||
final Integer clientId = ClientHelper.createClient(requestSpec, responseSpec);
|
||||
final String operationDate = "10 April 2025";
|
||||
|
||||
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(
|
||||
createOnePeriod30DaysPeriodicAccrualProductWithAdvancedPaymentAllocationAndInterestRecalculation(12.0, 4));
|
||||
|
||||
final PostLoansRequest applicationRequest = applyLoanRequest(clientId.longValue(), loanProductResponse.getResourceId(),
|
||||
operationDate, 1000.0, 4).transactionProcessingStrategyCode("advanced-payment-allocation-strategy")//
|
||||
.interestRatePerPeriod(BigDecimal.valueOf(12.0));
|
||||
|
||||
final PostLoansResponse loanResponse = loanTransactionHelper.applyLoan(applicationRequest);
|
||||
final Long loanId = loanResponse.getLoanId();
|
||||
|
||||
loanTransactionHelper.approveLoan(loanId, new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000.0))
|
||||
.dateFormat(DATETIME_PATTERN).approvedOnDate(operationDate).locale("en"));
|
||||
|
||||
loanTransactionHelper.disburseLoan(loanId, new PostLoansLoanIdRequest().actualDisbursementDate(operationDate)
|
||||
.dateFormat(DATETIME_PATTERN).transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
|
||||
|
||||
PostInitiateTransferResponse transferResponse = EXTERNAL_ASSET_OWNER_HELPER.initiateTransferByLoanId(loanId, "sale",
|
||||
new ExternalAssetOwnerRequest().settlementDate("2025-04-20").dateFormat("yyyy-MM-dd").locale("en")
|
||||
.transferExternalId(externalAssetOwner).transferExternalGroupId(null).ownerExternalId(externalAssetOwner)
|
||||
.purchasePriceRatio("0.90"));
|
||||
assertEquals(externalAssetOwner, transferResponse.getResourceExternalId());
|
||||
|
||||
final PostJournalEntriesResponse journalEntriesResponse = JournalEntryHelper.createJournalEntry("",
|
||||
new JournalEntryCommand().amount(BigDecimal.TEN).officeId(1L).currencyCode("USD").locale("en").dateFormat("uuuu-MM-dd")
|
||||
.transactionDate(LocalDate.of(2024, 1, 1))
|
||||
.addCreditsItem(new SingleDebitOrCreditEntryCommand().glAccountId(glAccountDebit.getAccountID().longValue())
|
||||
.amount(BigDecimal.TEN))
|
||||
.addDebitsItem(new SingleDebitOrCreditEntryCommand().glAccountId(glAccountCredit.getAccountID().longValue())
|
||||
.amount(BigDecimal.TEN))
|
||||
.externalAssetOwner(externalAssetOwner));
|
||||
|
||||
final GetJournalEntriesTransactionIdResponse journalEntriesTransactionIdResponse = JournalEntryHelper
|
||||
.retrieveJournalEntryByTransactionId(journalEntriesResponse.getTransactionId());
|
||||
Assertions.assertNotNull(journalEntriesTransactionIdResponse);
|
||||
assertEquals(2, journalEntriesTransactionIdResponse.getPageItems().size());
|
||||
JournalEntryTransactionItem journalEntryItem = journalEntriesTransactionIdResponse.getPageItems().get(0);
|
||||
assertEquals(externalAssetOwner, journalEntryItem.getExternalAssetOwner());
|
||||
journalEntryItem = journalEntriesTransactionIdResponse.getPageItems().get(1);
|
||||
assertEquals(externalAssetOwner, journalEntryItem.getExternalAssetOwner());
|
||||
});
|
||||
}
|
||||
|
||||
private void updateBusinessDateAndExecuteCOBJob(String date) {
|
||||
BusinessDateHelper.updateBusinessDate(REQUEST_SPEC, RESPONSE_SPEC, BUSINESS_DATE, LocalDate.parse(date));
|
||||
SCHEDULER_JOB_HELPER.executeAndAwaitJob("Loan COB");
|
||||
|
||||
Reference in New Issue
Block a user