Skip to content

Commit

Permalink
FINERACT-2022: remove @transactional(propagation = Propagation.REQUIR…
Browse files Browse the repository at this point in the history
…ES_NEW), add custom repositories
  • Loading branch information
mariiaKraievska committed Apr 30, 2024
1 parent 6b376c1 commit c267bfd
Show file tree
Hide file tree
Showing 16 changed files with 316 additions and 133 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.account.domain;

import java.util.Collection;
import org.apache.fineract.portfolio.account.data.AccountAssociationsData;

public interface AccountAssociationsCustomRepository {

AccountAssociationsData retrieveLoanLinkedAssociation(Long loanId);

AccountAssociationsData retrieveSavingsLinkedAssociation(Long savingsId);

Collection<AccountAssociationsData> retrieveLoanAssociations(Long loanId, Integer associationType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* 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.account.domain;

import static java.util.stream.Collectors.toList;

import com.querydsl.core.Tuple;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.SimpleExpression;
import com.querydsl.jpa.impl.JPAQuery;
import jakarta.persistence.EntityManager;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.portfolio.account.data.AccountAssociationsData;
import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
import org.apache.fineract.portfolio.loanaccount.domain.QLoan;
import org.apache.fineract.portfolio.savings.domain.QSavingsAccount;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class AccountAssociationsCustomRepositoryImpl implements AccountAssociationsCustomRepository {

private final EntityManager entityManager;

@Override
public AccountAssociationsData retrieveLoanLinkedAssociation(final Long loanId) {
final QAccountAssociations qAccountAssociations = QAccountAssociations.accountAssociations;
final JPAQuery<Tuple> query = getAccountAssociationsSelectQuery();
final Tuple queryResult = query
.where(eq(qAccountAssociations.loanAccount.id, loanId)
.and(qAccountAssociations.associationType.eq(AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue())))
.fetchOne();

return queryResult != null ? mapQueryResultToAccountAssociationsData(queryResult) : null;
}

@Override
public AccountAssociationsData retrieveSavingsLinkedAssociation(final Long savingsId) {
final QAccountAssociations qAccountAssociations = QAccountAssociations.accountAssociations;
final JPAQuery<Tuple> query = getAccountAssociationsSelectQuery();
final Tuple queryResult = query
.where(eq(qAccountAssociations.savingsAccount.id, savingsId)
.and(qAccountAssociations.associationType.eq(AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue())))
.fetchOne();

return queryResult != null ? mapQueryResultToAccountAssociationsData(queryResult) : null;
}

@Override
public Collection<AccountAssociationsData> retrieveLoanAssociations(final Long loanId, final Integer associationType) {
final QAccountAssociations qAccountAssociations = QAccountAssociations.accountAssociations;
final JPAQuery<Tuple> query = getAccountAssociationsSelectQuery();
final List<Tuple> queryResult = query
.where(eq(qAccountAssociations.loanAccount.id, loanId).and(eq(qAccountAssociations.associationType, associationType)))
.fetch();
return queryResult.isEmpty() ? Collections.emptyList() : mapQueryResultToAccountAssociationsDataList(queryResult);
}

private JPAQuery<Tuple> getAccountAssociationsSelectQuery() {
final QAccountAssociations qAccountAssociations = QAccountAssociations.accountAssociations;
final QLoan qLoan = QLoan.loan;
final QSavingsAccount qSavingsAccount = QSavingsAccount.savingsAccount;

final JPAQuery<Tuple> query = new JPAQuery<>(entityManager);
query.select(qAccountAssociations.id, qLoan.id.as("loanAccountId"), qLoan.accountNumber.as("loanAccountNo"),
qSavingsAccount.id.as("linkSavingsAccountId"), qSavingsAccount.accountNumber.as("linkSavingsAccountNo"))
.from(qAccountAssociations).leftJoin(qAccountAssociations.loanAccount, qLoan)
.on(qLoan.id.eq(qAccountAssociations.loanAccount.id)).leftJoin(qAccountAssociations.linkedSavingsAccount, qSavingsAccount)
.on(qSavingsAccount.id.eq(qAccountAssociations.linkedSavingsAccount.id));

return query;
}

private AccountAssociationsData mapQueryResultToAccountAssociationsData(final Tuple queryResult) {
final QAccountAssociations qAccountAssociations = QAccountAssociations.accountAssociations;
final QLoan qLoan = QLoan.loan;
final QSavingsAccount qSavingsAccount = QSavingsAccount.savingsAccount;

final PortfolioAccountData account = PortfolioAccountData.lookup(queryResult.get(qLoan.id.as("loanAccountId")),
queryResult.get(qLoan.accountNumber.as("loanAccountNo")));
final PortfolioAccountData linkedAccount = PortfolioAccountData.lookup(
queryResult.get(qSavingsAccount.id.as("linkSavingsAccountId")),
queryResult.get(qSavingsAccount.accountNumber.as("linkSavingsAccountNo")));

return new AccountAssociationsData(queryResult.get(qAccountAssociations.id), account, linkedAccount);
}

private List<AccountAssociationsData> mapQueryResultToAccountAssociationsDataList(final List<Tuple> queryResult) {
return queryResult.stream().map(this::mapQueryResultToAccountAssociationsData).collect(toList());
}

private <T> BooleanExpression eq(final SimpleExpression<T> expression, final T value) {
return value == null ? expression.isNull() : expression.eq(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;

public interface AccountAssociationsRepository extends JpaRepository<AccountAssociations, Long>,
JpaSpecificationExecutor<AccountAssociations>, QuerydslPredicateExecutor<AccountAssociations> {}
public interface AccountAssociationsRepository
extends JpaRepository<AccountAssociations, Long>, JpaSpecificationExecutor<AccountAssociations> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* 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.account.domain;

import java.time.LocalDate;

public interface AccountTransferStandingInstructionCustomRepository {

void updateLastRunDateById(long id, LocalDate lastRunDate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* 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.account.domain;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import java.time.LocalDate;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class AccountTransferStandingInstructionCustomRepositoryImpl implements AccountTransferStandingInstructionCustomRepository {

private final EntityManager entityManager;

@Override
public void updateLastRunDateById(final long id, final LocalDate lastRunDate) {
final JPAQueryFactory queryFactory = new JPAQueryFactory(this.entityManager);
final QAccountTransferStandingInstruction qAccountTransferStandingInstruction = QAccountTransferStandingInstruction.accountTransferStandingInstruction;

queryFactory.update(qAccountTransferStandingInstruction).set(qAccountTransferStandingInstruction.latsRunDate, lastRunDate)
.where(qAccountTransferStandingInstruction.id.eq(id)).execute();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* 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.account.domain;

import java.math.BigDecimal;

public interface AccountTransferStandingInstructionsHistoryCustomRepository {

void createNewHistory(long instructionId, BigDecimal transactionAmount, boolean transferCompleted, String errorLog);
}
Original file line number Diff line number Diff line change
@@ -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.portfolio.account.domain;

import jakarta.persistence.EntityManager;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class AccountTransferStandingInstructionsHistoryCustomRepositoryImpl
implements AccountTransferStandingInstructionsHistoryCustomRepository {

private final EntityManager entityManager;
private final StandingInstructionRepository standingInstructionRepository;

@Override
public void createNewHistory(final long instructionId, final BigDecimal transactionAmount, final boolean transferCompleted,
final String errorLog) {
final AccountTransferStandingInstructionsHistory newHistory = new AccountTransferStandingInstructionsHistory();
newHistory.setAccountTransferStandingInstruction(standingInstructionRepository.getReferenceById(instructionId));
newHistory.setStatus(transferCompleted ? "success" : "failed");
newHistory.setAmount(transactionAmount);
newHistory.setExecutionTime(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
newHistory.setErrorLog(errorLog);

entityManager.persist(newHistory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;

public interface StandingInstructionRepository extends JpaRepository<AccountTransferStandingInstruction, Long>,
JpaSpecificationExecutor<AccountTransferStandingInstruction>, QuerydslPredicateExecutor<AccountTransferStandingInstruction> {}
public interface StandingInstructionRepository
extends JpaRepository<AccountTransferStandingInstruction, Long>, JpaSpecificationExecutor<AccountTransferStandingInstruction> {

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
*/
package org.apache.fineract.portfolio.account.jobs.executestandinginstructions;

import jakarta.persistence.EntityManager;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.portfolio.account.domain.StandingInstructionRepository;
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstructionCustomRepositoryImpl;
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstructionsHistoryCustomRepositoryImpl;
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformService;
import org.springframework.batch.core.Job;
Expand All @@ -46,9 +46,9 @@ public class ExecuteStandingInstructionsConfig {
@Autowired
private AccountTransfersWritePlatformService accountTransfersWritePlatformService;
@Autowired
private EntityManager entityManager;
private AccountTransferStandingInstructionCustomRepositoryImpl accountTransferStandingInstructionCustomRepositoryImpl;
@Autowired
private StandingInstructionRepository standingInstructionRepository;
private AccountTransferStandingInstructionsHistoryCustomRepositoryImpl accountTransferStandingInstructionsHistoryCustomRepositoryImpl;

@Bean
protected Step executeStandingInstructionsStep() {
Expand All @@ -65,6 +65,6 @@ public Job executeStandingInstructionsJob() {
@Bean
public ExecuteStandingInstructionsTasklet executeStandingInstructionsTasklet() {
return new ExecuteStandingInstructionsTasklet(standingInstructionReadPlatformService, accountTransfersWritePlatformService,
entityManager, standingInstructionRepository);
accountTransferStandingInstructionCustomRepositoryImpl, accountTransferStandingInstructionsHistoryCustomRepositoryImpl);
}
}
Loading

0 comments on commit c267bfd

Please sign in to comment.