[FINERACT-1859] Avro schema for LoanAccountsStayedLockedBusinessEvent

This commit is contained in:
taskain7
2023-01-20 14:47:22 +01:00
committed by Arnold Gálovics
parent e82c0cac52
commit ef153c2b69
14 changed files with 290 additions and 11 deletions
@@ -0,0 +1,27 @@
{
"name": "LoanAccountStayedLockedDataV1",
"namespace": "org.apache.fineract.avro.loan.v1",
"type": "record",
"fields": [
{
"name": "id",
"type": "long"
},
{
"default": null,
"name": "externalId",
"type": [
"null",
"string"
]
},
{
"default": null,
"name": "accountNo",
"type": [
"null",
"string"
]
}
]
}
@@ -0,0 +1,12 @@
{
"name": "LoanAccountsStayedLockedDataV1",
"namespace": "org.apache.fineract.avro.loan.v1",
"type": "record",
"fields": [{
"name": "loanAccounts",
"type": {
"type": "array",
"items": "org.apache.fineract.avro.loan.v1.LoanAccountStayedLockedDataV1"
}
}]
}
@@ -0,0 +1,32 @@
/**
* 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.cob.data;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
@Getter
@AllArgsConstructor
public class LoanAccountStayedLockedData {
private Long id;
private ExternalId externalId;
private String accountNo;
}
@@ -0,0 +1,30 @@
/**
* 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.cob.data;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class LoanAccountsStayedLockedData {
private List<LoanAccountStayedLockedData> loanAccounts;
}
@@ -0,0 +1,30 @@
/**
* 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.cob.data;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
public interface LoanIdAndExternalIdAndAccountNo {
Long getId();
ExternalId getExternalId();
String getAccountNo();
}
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.cob.domain;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -28,7 +29,9 @@ import javax.persistence.Table;
import javax.persistence.Version;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
@Entity
@Table(name = "m_loan_account_locks")
@@ -57,10 +60,14 @@ public class LoanAccountLock {
@Column(name = "stacktrace")
private String stacktrace;
@Column(name = "lock_placed_on_cob_business_date")
private LocalDate lockPlacedOnCobBusinessDate;
public LoanAccountLock(Long loanId, LockOwner lockOwner) {
this.loanId = loanId;
this.lockOwner = lockOwner;
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenant();
this.lockPlacedOnCobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE);
}
public void setError(String errorMessage, String stacktrace) {
@@ -71,5 +78,6 @@ public class LoanAccountLock {
public void setNewLockOwner(LockOwner newLockOwner) {
this.lockOwner = newLockOwner;
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenant();
this.lockPlacedOnCobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE);
}
}
@@ -18,15 +18,15 @@
*/
package org.apache.fineract.cob.loan;
import java.util.List;
import org.apache.fineract.cob.data.LoanAccountsStayedLockedData;
import org.apache.fineract.infrastructure.event.business.domain.AbstractBusinessEvent;
public class LoanAccountsStayedLockedBusinessEvent extends AbstractBusinessEvent<List<Long>> {
public class LoanAccountsStayedLockedBusinessEvent extends AbstractBusinessEvent<LoanAccountsStayedLockedData> {
private static final String CATEGORY = "Loan COB";
private static final String TYPE = "LoanAccountsStayedLockedBusinessEvent";
public LoanAccountsStayedLockedBusinessEvent(List<Long> value) {
public LoanAccountsStayedLockedBusinessEvent(LoanAccountsStayedLockedData value) {
super(value);
}
@@ -26,6 +26,7 @@ import org.apache.fineract.cob.listener.COBExecutionListenerRunner;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.infrastructure.springbatch.PropertyService;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
@@ -76,6 +77,8 @@ public class LoanCOBManagerConfiguration {
private BusinessEventNotifierService businessEventNotifierService;
@Autowired
private CustomJobParameterResolver customJobParameterResolver;
@Autowired
private LoanRepository loanRepository;
@Bean
@JobScope
@@ -120,7 +123,7 @@ public class LoanCOBManagerConfiguration {
@Bean
@JobScope
public StayedLockedLoansTasklet stayedLockedTasklet() {
return new StayedLockedLoansTasklet(accountLockRepository, businessEventNotifierService);
return new StayedLockedLoansTasklet(businessEventNotifierService, loanRepository);
}
@Bean(name = "loanCOBJob")
@@ -18,12 +18,18 @@
*/
package org.apache.fineract.cob.loan;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.cob.domain.LoanAccountLock;
import org.apache.fineract.cob.domain.LoanAccountLockRepository;
import org.apache.fineract.cob.data.LoanAccountStayedLockedData;
import org.apache.fineract.cob.data.LoanAccountsStayedLockedData;
import org.apache.fineract.cob.data.LoanIdAndExternalIdAndAccountNo;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -33,16 +39,25 @@ import org.springframework.batch.repeat.RepeatStatus;
@RequiredArgsConstructor
public class StayedLockedLoansTasklet implements Tasklet {
private final LoanAccountLockRepository loanAccountLockRepository;
private final BusinessEventNotifierService businessEventNotifierService;
private final LoanRepository loanRepository;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
List<LoanAccountLock> loanAccountLocks = loanAccountLockRepository.findAll();
if (!loanAccountLocks.isEmpty()) {
List<Long> loanIds = loanAccountLocks.stream().map(LoanAccountLock::getLoanId).toList();
businessEventNotifierService.notifyPostBusinessEvent(new LoanAccountsStayedLockedBusinessEvent(loanIds));
LoanAccountsStayedLockedData lockedLoanAccounts = buildLoanAccountData();
if (!lockedLoanAccounts.getLoanAccounts().isEmpty()) {
businessEventNotifierService.notifyPostBusinessEvent(new LoanAccountsStayedLockedBusinessEvent(lockedLoanAccounts));
}
return RepeatStatus.FINISHED;
}
private LoanAccountsStayedLockedData buildLoanAccountData() {
LocalDate cobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE);
List<LoanIdAndExternalIdAndAccountNo> stayedLockedLoanAccounts = loanRepository.findAllStayedLockedByLoanIds(cobBusinessDate);
List<LoanAccountStayedLockedData> loanAccounts = new ArrayList<>();
stayedLockedLoanAccounts.forEach(loanAccount -> {
loanAccounts.add(new LoanAccountStayedLockedData(loanAccount.getId(), loanAccount.getExternalId(), loanAccount.getAccountNo()));
});
return new LoanAccountsStayedLockedData(loanAccounts);
}
}
@@ -0,0 +1,30 @@
/**
* 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.infrastructure.event.external.service.serialization.mapper.loan;
import org.apache.fineract.avro.loan.v1.LoanAccountsStayedLockedDataV1;
import org.apache.fineract.cob.data.LoanAccountsStayedLockedData;
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroMapperConfig;
import org.mapstruct.Mapper;
@Mapper(config = AvroMapperConfig.class)
public interface LoanAccountsStayedLockedDataMapper {
LoanAccountsStayedLockedDataV1 map(LoanAccountsStayedLockedData loanAccountStayedLockedData);
}
@@ -0,0 +1,54 @@
/**
* 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.infrastructure.event.external.service.serialization.serializer.loan;
import lombok.RequiredArgsConstructor;
import org.apache.avro.generic.GenericContainer;
import org.apache.fineract.avro.generator.ByteBufferSerializable;
import org.apache.fineract.avro.loan.v1.LoanAccountsStayedLockedDataV1;
import org.apache.fineract.cob.data.LoanAccountsStayedLockedData;
import org.apache.fineract.cob.loan.LoanAccountsStayedLockedBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanAccountsStayedLockedDataMapper;
import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class LoanAccountsStayedLockedBusinessEventSerializer extends AbstractBusinessEventSerializer {
private final LoanAccountsStayedLockedDataMapper mapper;
@Override
public <T> boolean canSerialize(BusinessEvent<T> event) {
return event instanceof LoanAccountsStayedLockedBusinessEvent;
}
@Override
protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
LoanAccountsStayedLockedBusinessEvent event = (LoanAccountsStayedLockedBusinessEvent) rawEvent;
LoanAccountsStayedLockedData loanAccounts = event.get();
return mapper.map(loanAccounts);
}
@Override
public Class<? extends GenericContainer> getSupportedSchema() {
return LoanAccountsStayedLockedDataV1.class;
}
}
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.cob.data.LoanIdAndExternalIdAndAccountNo;
import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -88,6 +89,8 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
String FIND_ALL_NON_CLOSED_LOANS_BEHIND_BY_LOAN_IDS = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in (100,200,300,303,304) and (loan.lastClosedBusinessDate <> :cobBusinessDate or "
+ "loan.lastClosedBusinessDate is null)";
String FIND_ALL_STAYED_LOCKED_BY_LOAN_IDS = "select loan.id, loan.externalId, loan.accountNumber from LoanAccountLock lock left join Loan loan on lock.loanId = loan.id where lock.lockPlacedOnCobBusinessDate = :cobBusinessDate";
@Query(FIND_GROUP_LOANS_DISBURSED_AFTER)
List<Loan> getGroupLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("groupId") Long groupId,
@Param("loanType") Integer loanType);
@@ -194,4 +197,7 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
@Query(FIND_OLDEST_COB_PROCESSED_LOAN)
List<LoanIdAndLastClosedBusinessDate> findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate);
@Query(FIND_ALL_STAYED_LOCKED_BY_LOAN_IDS)
List<LoanIdAndExternalIdAndAccountNo> findAllStayedLockedByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate);
}
@@ -105,4 +105,5 @@
<include file="parts/0083_add_loan_transaction_enum_values.xml" relativeToChangelogFile="true" />
<include file="parts/0084_add_general_accounting_table_reports.xml" relativeToChangelogFile="true" />
<include file="parts/0085_add_aggregate_root_id_external_events.xml" relativeToChangelogFile="true" />
<include file="parts/0086_add_cob_business_date_to_loan_account_locks.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="1">
<addColumn tableName="m_loan_account_locks">
<column name="lock_placed_on_cob_business_date" type="DATE">
</column>
</addColumn>
</changeSet>
</databaseChangeLog>