FINERACT-1932: Fineract modularization - custom modules

This commit is contained in:
Marta Jankovics
2024-06-10 15:39:13 +02:00
committed by Adam Saghy
parent 92e291a9e4
commit 655466785c
101 changed files with 239 additions and 194 deletions
@@ -1,24 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.interoperation.domain;
public enum InteropIdentifierType {
MSISDN, EMAIL, PERSONAL_ID, BUSINESS, DEVICE, ACCOUNT_ID, IBAN, ALIAS
}
@@ -0,0 +1,73 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.savings.domain;
import jakarta.persistence.LockModeType;
import java.util.List;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
//Use SavingsAccountRepositoryWrapper.
public interface SavingsAccountRepository extends JpaRepository<SavingsAccount, Long>, JpaSpecificationExecutor<SavingsAccount> {
@Query("select s_acc from SavingsAccount s_acc where s_acc.client.id = :clientId")
List<SavingsAccount> findSavingAccountByClientId(@Param("clientId") Long clientId);
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("select sa from SavingsAccount sa where sa.id = :savingsId")
SavingsAccount findOneLocked(@Param("savingsId") Long id);
@Query("select s_acc from SavingsAccount s_acc where s_acc.gsim.id = :gsimId")
List<SavingsAccount> findSavingAccountByGsimId(@Param("gsimId") Long gsimId);
@Query("select s_acc from SavingsAccount s_acc where s_acc.status = :status")
List<SavingsAccount> findSavingAccountByStatus(@Param("status") Integer status);
@Query("select sa from SavingsAccount sa where sa.client.id = :clientId and sa.group.id = :groupId")
List<SavingsAccount> findByClientIdAndGroupId(@Param("clientId") Long clientId, @Param("groupId") Long groupId);
@Query("select case when (count (saving) > 0) then 'true' else 'false' end from SavingsAccount saving where saving.client.id = :clientId and saving.status in (100,200,300,303,304)")
boolean doNonClosedSavingAccountsExistForClient(@Param("clientId") Long clientId);
@Query("select sa from SavingsAccount sa where sa.client.id is null and sa.group.id = :groupId")
List<SavingsAccount> findByGroupId(@Param("groupId") Long groupId);
@Query("select sa from SavingsAccount sa where sa.id = :accountId and sa.depositType = :depositAccountTypeId")
SavingsAccount findByIdAndDepositAccountType(@Param("accountId") Long accountId,
@Param("depositAccountTypeId") Integer depositAccountTypeId);
@Query("select sa from SavingsAccount sa where sa.accountNumber = :accountNumber and sa.status in (100, 200, 300, 303, 304) ")
SavingsAccount findNonClosedAccountByAccountNumber(@Param("accountNumber") String accountNumber);
@Query("select sa from SavingsAccount sa where sa.accountNumber = :accountNumber ")
SavingsAccount findSavingsAccountByAccountNumber(@Param("accountNumber") String accountNumber);
Page<SavingsAccount> findByStatus(Integer status, Pageable pageable);
SavingsAccount findByExternalId(ExternalId externalId);
@Query("SELECT sa.id FROM SavingsAccount sa WHERE sa.externalId = :externalId")
Long findIdByExternalId(@Param("externalId") ExternalId externalId);
}
@@ -0,0 +1,182 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.savings.domain;
import java.time.LocalDate;
import java.util.List;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.portfolio.savings.DepositAccountType;
import org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* <p>
* Wrapper for {@link SavingsAccountRepository} that is responsible for checking if {@link SavingsAccount} is returned
* when using <code>findOne</code> repository method and throwing an appropriate not found exception.
* </p>
*
* <p>
* This is to avoid need for checking and throwing in multiple areas of code base where {@link SavingsAccountRepository}
* is required.
* </p>
*/
@Service
public class SavingsAccountRepositoryWrapper {
private final SavingsAccountRepository repository;
private final SavingsAccountTransactionRepository savingsAccountTransactionRepository;
private final JdbcTemplate jdbcTemplate;
@Autowired
public SavingsAccountRepositoryWrapper(final SavingsAccountRepository repository,
final SavingsAccountTransactionRepository savingsAccountTransactionRepository, final JdbcTemplate jdbcTemplate) {
this.repository = repository;
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
this.jdbcTemplate = jdbcTemplate;
}
@Transactional(readOnly = true)
public SavingsAccount findOneWithNotFoundDetection(final Long savingsId) {
final SavingsAccount account = this.repository.findById(savingsId)
.orElseThrow(() -> new SavingsAccountNotFoundException(savingsId));
account.loadLazyCollections();
return account;
}
@Transactional
public SavingsAccount findSavingsWithNotFoundDetection(final Long savingsId, final boolean backdatedTxnsAllowedTill) {
SavingsAccount account = null;
if (!backdatedTxnsAllowedTill) {
account = findOneWithNotFoundDetection(savingsId);
} else {
account = this.repository.findOneLocked(savingsId);
if (account == null) {
throw new SavingsAccountNotFoundException(savingsId);
}
}
return account;
}
@Transactional(readOnly = true)
public SavingsAccount findOneWithNotFoundDetection(final Long savingsId, final DepositAccountType depositAccountType) {
final SavingsAccount account = this.repository.findByIdAndDepositAccountType(savingsId, depositAccountType.getValue());
if (account == null) {
throw new SavingsAccountNotFoundException(savingsId);
}
account.loadLazyCollections();
return account;
}
@Transactional(readOnly = true)
public List<SavingsAccount> findSavingAccountByClientId(@Param("clientId") Long clientId) {
List<SavingsAccount> accounts = this.repository.findSavingAccountByClientId(clientId);
loadLazyCollections(accounts);
return accounts;
}
@Transactional(readOnly = true)
public List<SavingsAccount> findSavingAccountByStatus(@Param("status") Integer status) {
List<SavingsAccount> accounts = this.repository.findSavingAccountByStatus(status);
loadLazyCollections(accounts);
return accounts;
}
@Transactional(readOnly = true)
public Page<SavingsAccount> findByStatus(Integer status, Pageable pageable) {
Page<SavingsAccount> accounts = this.repository.findByStatus(status, pageable);
loadLazyCollections(accounts);
return accounts;
}
// Root Entities are enough
public List<SavingsAccount> findByClientIdAndGroupId(@Param("clientId") Long clientId, @Param("groupId") Long groupId) {
return this.repository.findByClientIdAndGroupId(clientId, groupId);
}
public boolean doNonClosedSavingAccountsExistForClient(@Param("clientId") Long clientId) {
return this.repository.doNonClosedSavingAccountsExistForClient(clientId);
}
// Root Entities are enough
public List<SavingsAccount> findByGroupId(@Param("groupId") Long groupId) {
return this.repository.findByGroupId(groupId);
}
public List<SavingsAccount> findByGsimId(@Param("gsimId") Long gsimId) {
return this.repository.findSavingAccountByGsimId(gsimId);
}
@Transactional
public List<SavingsAccountTransaction> findTransactionsAfterPivotDate(@Param("savingsAccount") SavingsAccount savingsAccount,
@Param("date") LocalDate transactionDate) {
return this.savingsAccountTransactionRepository.findTransactionsAfterPivotDate(savingsAccount, transactionDate);
}
public List<SavingsAccountTransaction> findTransactionRunningBalanceBeforePivotDate(
@Param("savingsAccount") SavingsAccount savingsAccount, @Param("date") LocalDate date) {
return this.savingsAccountTransactionRepository.findTransactionRunningBalanceBeforePivotDate(savingsAccount, date);
}
@Transactional
public List<SavingsAccountTransaction> findAllTransactions(@Param("savingsAccount") SavingsAccount savingsAccount) {
return this.savingsAccountTransactionRepository.findBySavingsAccount(savingsAccount);
}
// Root Entity is enough
public SavingsAccount findNonClosedAccountByAccountNumber(@Param("accountNumber") String accountNumber) {
return this.repository.findNonClosedAccountByAccountNumber(accountNumber);
}
public SavingsAccount save(final SavingsAccount account) {
return this.repository.save(account);
}
public void delete(final SavingsAccount account) {
this.repository.delete(account);
}
public SavingsAccount saveAndFlush(final SavingsAccount account) {
return this.repository.saveAndFlush(account);
}
private void loadLazyCollections(final List<SavingsAccount> accounts) {
if (accounts != null && accounts.size() > 0) {
for (SavingsAccount account : accounts) {
account.loadLazyCollections();
}
}
}
private void loadLazyCollections(Page<SavingsAccount> accounts) {
for (SavingsAccount account : accounts) {
account.loadLazyCollections();
}
}
public Long findIdByExternalId(final ExternalId externalId) {
return this.repository.findIdByExternalId(externalId);
}
}
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.savings.domain;
package org.apache.fineract.portfolio.savings.service;
import java.math.BigDecimal;
import java.time.LocalDate;
@@ -25,6 +25,8 @@ import java.util.List;
import java.util.Set;
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
public interface SavingsAccountDomainService {