From ef153c2b69b5427e2045a57fa8d01ffc83490eb5 Mon Sep 17 00:00:00 2001 From: taskain7 Date: Wed, 18 Jan 2023 12:49:47 +0100 Subject: [PATCH] [FINERACT-1859] Avro schema for LoanAccountsStayedLockedBusinessEvent --- .../v1/LoanAccountStayedLockedDataV1.avsc | 27 ++++++++++ .../v1/LoanAccountsStayedLockedDataV1.avsc | 12 +++++ .../cob/data/LoanAccountStayedLockedData.java | 32 +++++++++++ .../data/LoanAccountsStayedLockedData.java | 30 +++++++++++ .../data/LoanIdAndExternalIdAndAccountNo.java | 30 +++++++++++ .../fineract/cob/domain/LoanAccountLock.java | 8 +++ ...LoanAccountsStayedLockedBusinessEvent.java | 6 +-- .../cob/loan/LoanCOBManagerConfiguration.java | 5 +- .../cob/loan/StayedLockedLoansTasklet.java | 29 +++++++--- .../LoanAccountsStayedLockedDataMapper.java | 30 +++++++++++ ...tsStayedLockedBusinessEventSerializer.java | 54 +++++++++++++++++++ .../loanaccount/domain/LoanRepository.java | 6 +++ .../db/changelog/tenant/changelog-tenant.xml | 1 + ...ob_business_date_to_loan_account_locks.xml | 31 +++++++++++ 14 files changed, 290 insertions(+), 11 deletions(-) create mode 100644 fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountStayedLockedDataV1.avsc create mode 100644 fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountsStayedLockedDataV1.avsc create mode 100644 fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountStayedLockedData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountsStayedLockedData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanIdAndExternalIdAndAccountNo.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountsStayedLockedDataMapper.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/0086_add_cob_business_date_to_loan_account_locks.xml diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountStayedLockedDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountStayedLockedDataV1.avsc new file mode 100644 index 000000000..172fceae3 --- /dev/null +++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountStayedLockedDataV1.avsc @@ -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" + ] + } + ] +} diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountsStayedLockedDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountsStayedLockedDataV1.avsc new file mode 100644 index 000000000..2f9db112f --- /dev/null +++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountsStayedLockedDataV1.avsc @@ -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" + } + }] +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountStayedLockedData.java b/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountStayedLockedData.java new file mode 100644 index 000000000..c37ac5647 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountStayedLockedData.java @@ -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; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountsStayedLockedData.java b/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountsStayedLockedData.java new file mode 100644 index 000000000..9b171663c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanAccountsStayedLockedData.java @@ -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 loanAccounts; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanIdAndExternalIdAndAccountNo.java b/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanIdAndExternalIdAndAccountNo.java new file mode 100644 index 000000000..b7a94b13f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/data/LoanIdAndExternalIdAndAccountNo.java @@ -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(); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java index e490bde89..7d6266b3d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLock.java @@ -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); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanAccountsStayedLockedBusinessEvent.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanAccountsStayedLockedBusinessEvent.java index d9280ae56..d14038c6b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanAccountsStayedLockedBusinessEvent.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanAccountsStayedLockedBusinessEvent.java @@ -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> { +public class LoanAccountsStayedLockedBusinessEvent extends AbstractBusinessEvent { private static final String CATEGORY = "Loan COB"; private static final String TYPE = "LoanAccountsStayedLockedBusinessEvent"; - public LoanAccountsStayedLockedBusinessEvent(List value) { + public LoanAccountsStayedLockedBusinessEvent(LoanAccountsStayedLockedData value) { super(value); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java index 1990bbdd5..4fa8ca2e3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java @@ -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") diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java index f3ea0a6b9..f34d80739 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/StayedLockedLoansTasklet.java @@ -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 loanAccountLocks = loanAccountLockRepository.findAll(); - if (!loanAccountLocks.isEmpty()) { - List 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 stayedLockedLoanAccounts = loanRepository.findAllStayedLockedByLoanIds(cobBusinessDate); + List loanAccounts = new ArrayList<>(); + stayedLockedLoanAccounts.forEach(loanAccount -> { + loanAccounts.add(new LoanAccountStayedLockedData(loanAccount.getId(), loanAccount.getExternalId(), loanAccount.getAccountNo())); + }); + return new LoanAccountsStayedLockedData(loanAccounts); + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountsStayedLockedDataMapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountsStayedLockedDataMapper.java new file mode 100644 index 000000000..d030632f9 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountsStayedLockedDataMapper.java @@ -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); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java new file mode 100644 index 000000000..8ff06cbd5 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java @@ -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 boolean canSerialize(BusinessEvent event) { + return event instanceof LoanAccountsStayedLockedBusinessEvent; + } + + @Override + protected ByteBufferSerializable toAvroDTO(BusinessEvent rawEvent) { + LoanAccountsStayedLockedBusinessEvent event = (LoanAccountsStayedLockedBusinessEvent) rawEvent; + LoanAccountsStayedLockedData loanAccounts = event.get(); + return mapper.map(loanAccounts); + } + + @Override + public Class getSupportedSchema() { + return LoanAccountsStayedLockedDataV1.class; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java index 605377861..4d20391d3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java @@ -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, 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 getGroupLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("groupId") Long groupId, @Param("loanType") Integer loanType); @@ -194,4 +197,7 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query(FIND_OLDEST_COB_PROCESSED_LOAN) List findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate); + @Query(FIND_ALL_STAYED_LOCKED_BY_LOAN_IDS) + List findAllStayedLockedByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate); + } diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index d81bba3f1..9c6ed1e14 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -105,4 +105,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0086_add_cob_business_date_to_loan_account_locks.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0086_add_cob_business_date_to_loan_account_locks.xml new file mode 100644 index 000000000..409fc273a --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0086_add_cob_business_date_to_loan_account_locks.xml @@ -0,0 +1,31 @@ + + + + + + + + + +