FINERACT-1734: New business events and refactorings
This commit is contained in:
committed by
Arnold Gálovics
parent
d06c3655af
commit
130d9c0c3d
@@ -524,17 +524,6 @@
|
|||||||
"org.apache.fineract.avro.portfolio.v1.PortfolioAccountDataV1"
|
"org.apache.fineract.avro.portfolio.v1.PortfolioAccountDataV1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": null,
|
|
||||||
"name": "accountLinkingOptions",
|
|
||||||
"type": [
|
|
||||||
"null",
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"items": "org.apache.fineract.avro.portfolio.v1.PortfolioAccountDataV1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": null,
|
"default": null,
|
||||||
"name": "multiDisburseLoan",
|
"name": "multiDisburseLoan",
|
||||||
@@ -637,6 +626,14 @@
|
|||||||
"bigdecimal"
|
"bigdecimal"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"default": null,
|
||||||
|
"name": "product",
|
||||||
|
"type": [
|
||||||
|
"null",
|
||||||
|
"org.apache.fineract.avro.loan.v1.LoanProductDataV1"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"default": null,
|
"default": null,
|
||||||
"name": "inArrears",
|
"name": "inArrears",
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "LoanChargeDeletedV1",
|
||||||
|
"namespace": "org.apache.fineract.avro.loan.v1",
|
||||||
|
"type": "record",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"default": null,
|
||||||
|
"name": "id",
|
||||||
|
"type": [
|
||||||
|
"null",
|
||||||
|
"long"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": null,
|
||||||
|
"name": "chargeId",
|
||||||
|
"type": [
|
||||||
|
"null",
|
||||||
|
"long"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "LoanTransactionWithLoanV1",
|
||||||
|
"namespace": "org.apache.fineract.avro.loan.v1",
|
||||||
|
"type": "record",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"default": null,
|
||||||
|
"name": "loan",
|
||||||
|
"type": [
|
||||||
|
"null",
|
||||||
|
"org.apache.fineract.avro.loan.v1.LoanAccountDataV1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": null,
|
||||||
|
"name": "loanTransaction",
|
||||||
|
"type": [
|
||||||
|
"null",
|
||||||
|
"org.apache.fineract.avro.loan.v1.LoanTransactionDataV1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -29,3 +29,5 @@ include::technology.adoc[leveloffset=+1]
|
|||||||
include::modules.adoc[leveloffset=+1]
|
include::modules.adoc[leveloffset=+1]
|
||||||
|
|
||||||
include::business-date.adoc[leveloffset=+1]
|
include::business-date.adoc[leveloffset=+1]
|
||||||
|
|
||||||
|
include::reliable-event-framework.adoc[leveloffset=+1]
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.business.domain.loan;
|
||||||
|
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
|
||||||
|
public class LoanRescheduledDueCalendarChangeBusinessEvent extends LoanBusinessEvent {
|
||||||
|
|
||||||
|
public LoanRescheduledDueCalendarChangeBusinessEvent(Loan value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "LoanRescheduledDueCalendarChangeBusinessEvent";
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.business.domain.loan;
|
||||||
|
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
|
||||||
|
public class LoanRescheduledDueHolidayBusinessEvent extends LoanBusinessEvent {
|
||||||
|
|
||||||
|
public LoanRescheduledDueHolidayBusinessEvent(Loan value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "LoanRescheduledDueHolidayBusinessEvent";
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.business.domain.loan;
|
||||||
|
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
|
||||||
|
public class LoanScheduleVariationsAddedBusinessEvent extends LoanBusinessEvent {
|
||||||
|
|
||||||
|
public LoanScheduleVariationsAddedBusinessEvent(Loan value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "LoanScheduleVariationsAddedBusinessEvent";
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.business.domain.loan;
|
||||||
|
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
|
||||||
|
public class LoanScheduleVariationsDeletedBusinessEvent extends LoanBusinessEvent {
|
||||||
|
|
||||||
|
public LoanScheduleVariationsDeletedBusinessEvent(Loan value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "LoanScheduleVariationsDeletedBusinessEvent";
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.business.domain.loan;
|
||||||
|
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
|
||||||
|
public class LoanStatusChangedBusinessEvent extends LoanBusinessEvent {
|
||||||
|
|
||||||
|
public LoanStatusChangedBusinessEvent(Loan value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "LoanStatusChangedBusinessEvent";
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.business.domain.loan;
|
||||||
|
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
|
||||||
|
public class LoanUpdateDisbursementDataBusinessEvent extends LoanBusinessEvent {
|
||||||
|
|
||||||
|
public LoanUpdateDisbursementDataBusinessEvent(Loan value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "LoanUpdateDisbursementDataBusinessEvent";
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -19,6 +19,8 @@
|
|||||||
package org.apache.fineract.infrastructure.event.external.service;
|
package org.apache.fineract.infrastructure.event.external.service;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventRepository;
|
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventRepository;
|
||||||
@@ -38,6 +40,8 @@ public class ExternalEventService {
|
|||||||
private final ExternalEventIdempotencyKeyGenerator idempotencyKeyGenerator;
|
private final ExternalEventIdempotencyKeyGenerator idempotencyKeyGenerator;
|
||||||
private final BusinessEventSerializerFactory serializerFactory;
|
private final BusinessEventSerializerFactory serializerFactory;
|
||||||
|
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
public <T> void postEvent(BusinessEvent<T> event) {
|
public <T> void postEvent(BusinessEvent<T> event) {
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
throw new IllegalArgumentException("event cannot be null");
|
throw new IllegalArgumentException("event cannot be null");
|
||||||
@@ -48,6 +52,7 @@ public class ExternalEventService {
|
|||||||
try {
|
try {
|
||||||
BusinessEventSerializer serializer = serializerFactory.create(event);
|
BusinessEventSerializer serializer = serializerFactory.create(event);
|
||||||
String schema = serializer.getSupportedSchema().getName();
|
String schema = serializer.getSupportedSchema().getName();
|
||||||
|
flushChangesBeforeSerialization();
|
||||||
byte[] data = serializer.serialize(event);
|
byte[] data = serializer.serialize(event);
|
||||||
ExternalEvent externalEvent = new ExternalEvent(eventType, schema, data, idempotencyKey);
|
ExternalEvent externalEvent = new ExternalEvent(eventType, schema, data, idempotencyKey);
|
||||||
|
|
||||||
@@ -57,4 +62,13 @@ public class ExternalEventService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void flushChangesBeforeSerialization() {
|
||||||
|
entityManager.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
public void setEntityManager(EntityManager entityManager) {
|
||||||
|
this.entityManager = entityManager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* 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 java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.avro.generic.GenericContainer;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanChargeDeletedV1;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanDeleteChargeBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
|
||||||
|
import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Order(Ordered.LOWEST_PRECEDENCE - 1)
|
||||||
|
public class LoanChargeDeletedBusinessEventSerializer implements BusinessEventSerializer {
|
||||||
|
|
||||||
|
private final ByteBufferConverter byteBufferConverter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> boolean canSerialize(BusinessEvent<T> event) {
|
||||||
|
return event instanceof LoanDeleteChargeBusinessEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException {
|
||||||
|
LoanDeleteChargeBusinessEvent event = (LoanDeleteChargeBusinessEvent) rawEvent;
|
||||||
|
LoanCharge loanCharge = event.get();
|
||||||
|
Long id = loanCharge.getId();
|
||||||
|
Long chargeId = loanCharge.getCharge().getId();
|
||||||
|
LoanChargeDeletedV1 avroDto = new LoanChargeDeletedV1(id, chargeId);
|
||||||
|
ByteBuffer buffer = avroDto.toByteBuffer();
|
||||||
|
return byteBufferConverter.convert(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends GenericContainer> getSupportedSchema() {
|
||||||
|
return LoanChargeDeletedV1.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-3
@@ -22,12 +22,16 @@ import java.io.IOException;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.avro.generic.GenericContainer;
|
import org.apache.avro.generic.GenericContainer;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
|
||||||
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
|
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanTransactionWithLoanV1;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanAccountDataMapper;
|
||||||
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanTransactionDataMapper;
|
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanTransactionDataMapper;
|
||||||
import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
|
import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
|
||||||
import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
|
import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -37,7 +41,8 @@ import org.springframework.stereotype.Component;
|
|||||||
public class LoanTransactionBusinessEventSerializer implements BusinessEventSerializer {
|
public class LoanTransactionBusinessEventSerializer implements BusinessEventSerializer {
|
||||||
|
|
||||||
private final LoanReadPlatformService service;
|
private final LoanReadPlatformService service;
|
||||||
private final LoanTransactionDataMapper mapper;
|
private final LoanAccountDataMapper loanMapper;
|
||||||
|
private final LoanTransactionDataMapper loanTransactionMapper;
|
||||||
private final ByteBufferConverter byteBufferConverter;
|
private final ByteBufferConverter byteBufferConverter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -48,8 +53,13 @@ public class LoanTransactionBusinessEventSerializer implements BusinessEventSeri
|
|||||||
@Override
|
@Override
|
||||||
public <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException {
|
public <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException {
|
||||||
LoanTransactionBusinessEvent event = (LoanTransactionBusinessEvent) rawEvent;
|
LoanTransactionBusinessEvent event = (LoanTransactionBusinessEvent) rawEvent;
|
||||||
LoanTransactionData data = service.retrieveLoanTransaction(event.get().getLoan().getId(), event.get().getId());
|
Long loanId = event.get().getLoan().getId();
|
||||||
LoanTransactionDataV1 avroDto = mapper.map(data);
|
LoanAccountData loanData = service.retrieveOne(loanId);
|
||||||
|
LoanAccountDataV1 loanAvroDto = loanMapper.map(loanData);
|
||||||
|
Long loanTransactionId = event.get().getId();
|
||||||
|
LoanTransactionData transactionData = service.retrieveLoanTransaction(loanId, loanTransactionId);
|
||||||
|
LoanTransactionDataV1 loanTransactionAvroDto = loanTransactionMapper.map(transactionData);
|
||||||
|
LoanTransactionWithLoanV1 avroDto = new LoanTransactionWithLoanV1(loanAvroDto, loanTransactionAvroDto);
|
||||||
ByteBuffer buffer = avroDto.toByteBuffer();
|
ByteBuffer buffer = avroDto.toByteBuffer();
|
||||||
return byteBufferConverter.convert(buffer);
|
return byteBufferConverter.convert(buffer);
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -18,13 +18,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanStatusChangedBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
|
|
||||||
|
// TODO: introduce tests for the state machine
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachine {
|
public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachine {
|
||||||
|
|
||||||
private final List<LoanStatus> allowedLoanStatuses;
|
private final List<LoanStatus> allowedLoanStatuses;
|
||||||
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
|
|
||||||
|
public DefaultLoanLifecycleStateMachine(LoanStatus[] allowedLoanStatuses, BusinessEventNotifierService businessEventNotifierService) {
|
||||||
|
this(Arrays.asList(allowedLoanStatuses), businessEventNotifierService);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanStatus dryTransition(final LoanEvent loanEvent, final Loan loan) {
|
public LoanStatus dryTransition(final LoanEvent loanEvent, final Loan loan) {
|
||||||
@@ -35,6 +44,15 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi
|
|||||||
public void transition(final LoanEvent loanEvent, final Loan loan) {
|
public void transition(final LoanEvent loanEvent, final Loan loan) {
|
||||||
LoanStatus newState = getNextState(loanEvent, loan);
|
LoanStatus newState = getNextState(loanEvent, loan);
|
||||||
loan.setLoanStatus(newState.getValue());
|
loan.setLoanStatus(newState.getValue());
|
||||||
|
|
||||||
|
if (isNotLoanCreation(loanEvent)) {
|
||||||
|
// in case of Loan creation, a LoanCreatedBusinessEvent is also raised, no need to send a status change
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanStatusChangedBusinessEvent(loan));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNotLoanCreation(LoanEvent loanEvent) {
|
||||||
|
return !LoanEvent.LOAN_CREATED.equals(loanEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanStatus getNextState(LoanEvent loanEvent, Loan loan) {
|
private LoanStatus getNextState(LoanEvent loanEvent, Loan loan) {
|
||||||
|
|||||||
+4
-83
@@ -122,12 +122,10 @@ import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementData
|
|||||||
import org.apache.fineract.portfolio.loanaccount.exception.UndoLastTrancheDisbursementException;
|
import org.apache.fineract.portfolio.loanaccount.exception.UndoLastTrancheDisbursementException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
|
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
|
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
|
||||||
@@ -2406,12 +2404,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
public ChangedTransactionDetail disburse(final AppUser currentUser, final JsonCommand command, final Map<String, Object> actualChanges,
|
public ChangedTransactionDetail disburse(final AppUser currentUser, final JsonCommand command, final Map<String, Object> actualChanges,
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final PaymentDetail paymentDetail) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO, final PaymentDetail paymentDetail) {
|
||||||
|
|
||||||
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, this);
|
|
||||||
|
|
||||||
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||||
|
|
||||||
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
|
||||||
|
|
||||||
this.disbursedBy = currentUser;
|
this.disbursedBy = currentUser;
|
||||||
updateLoanScheduleDependentDerivedFields();
|
updateLoanScheduleDependentDerivedFields();
|
||||||
|
|
||||||
@@ -2446,7 +2440,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
addLoanTransaction(interestAppliedTransaction);
|
addLoanTransaction(interestAppliedTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
return reprocessTransactionForDisbursement();
|
ChangedTransactionDetail result = reprocessTransactionForDisbursement();
|
||||||
|
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, this);
|
||||||
|
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4597,82 +4594,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
|||||||
// startDate
|
// startDate
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyHolidayToRepaymentScheduleDates(final Holiday holiday, final LoanUtilService loanUtilService) {
|
|
||||||
final DefaultScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
|
||||||
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(this, holiday.getFromDateLocalDate());
|
|
||||||
final LoanApplicationTerms loanApplicationTerms = this.constructLoanApplicationTerms(scheduleGeneratorDTO);
|
|
||||||
|
|
||||||
// LocalDate rescheduleFromDate = holiday.getFromDateLocalDate();
|
|
||||||
LocalDate adjustedRescheduleToDate = null;
|
|
||||||
|
|
||||||
if (holiday.getReScheduleType().isResheduleToNextRepaymentDate()) {
|
|
||||||
final LocalDate rescheduleToDate = holiday.getToDateLocalDate();
|
|
||||||
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.getRepaymentScheduleInstallments()) {
|
|
||||||
if (rescheduleToDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) {
|
|
||||||
adjustedRescheduleToDate = rescheduleToDate;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// Account for a Bimonthly Loan Product
|
|
||||||
// if (loanApplicationTerms.getRepaymentPeriodFrequencyType().isSemiMonthly()) {
|
|
||||||
// if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())
|
|
||||||
// && rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(15))) {
|
|
||||||
// adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate();
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// // Once Bimonthly product implemented, Replace the `Standard Monthly Loan Holiday check` below
|
|
||||||
// HERE
|
|
||||||
// if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())
|
|
||||||
// && rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) {
|
|
||||||
// adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate();
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Standard Monthly Loan Holiday check
|
|
||||||
if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())
|
|
||||||
&& rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) {
|
|
||||||
adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
adjustedRescheduleToDate = holiday.getRepaymentsRescheduledToLocalDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// first repayment's from date is same as disbursement date.
|
|
||||||
LocalDate tmpFromDate = getDisbursementDate();
|
|
||||||
|
|
||||||
// Loop through all loanRepayments
|
|
||||||
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
|
||||||
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) {
|
|
||||||
|
|
||||||
if (adjustedRescheduleToDate == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
|
||||||
|
|
||||||
// update from date if it's not same as previous installament's due
|
|
||||||
// date.
|
|
||||||
if (!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)) {
|
|
||||||
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldDueDate.equals(holiday.getFromDateLocalDate()) || oldDueDate.isAfter(holiday.getFromDateLocalDate())) {
|
|
||||||
// FIXME: AA do we need to apply non-working days.
|
|
||||||
// Assuming holiday's repayment reschedule to date cannot be
|
|
||||||
// created on a non-working day.
|
|
||||||
|
|
||||||
adjustedRescheduleToDate = scheduledDateGenerator.generateNextRepaymentDate(adjustedRescheduleToDate, loanApplicationTerms,
|
|
||||||
false);
|
|
||||||
loanRepaymentScheduleInstallment.updateDueDate(adjustedRescheduleToDate);
|
|
||||||
}
|
|
||||||
tmpFromDate = loanRepaymentScheduleInstallment.getDueDate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateDisbursementDateIsOnNonWorkingDay(final WorkingDays workingDays, final boolean allowTransactionsOnNonWorkingDay) {
|
private void validateDisbursementDateIsOnNonWorkingDay(final WorkingDays workingDays, final boolean allowTransactionsOnNonWorkingDay) {
|
||||||
if (!allowTransactionsOnNonWorkingDay) {
|
if (!allowTransactionsOnNonWorkingDay) {
|
||||||
if (!WorkingDaysUtil.isWorkingDay(workingDays, getDisbursementDate())) {
|
if (!WorkingDaysUtil.isWorkingDay(workingDays, getDisbursementDate())) {
|
||||||
|
|||||||
+1
-3
@@ -21,7 +21,6 @@ package org.apache.fineract.portfolio.loanaccount.domain;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -425,8 +424,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||||
final List<LoanStatus> allowedLoanStatuses = Arrays.asList(LoanStatus.values());
|
return new DefaultLoanLifecycleStateMachine(LoanStatus.values(), businessEventNotifierService);
|
||||||
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkClientOrGroupActive(final Loan loan) {
|
private void checkClientOrGroupActive(final Loan loan) {
|
||||||
|
|||||||
+5
-22
@@ -18,11 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.jobs.applyholidaystoloans;
|
package org.apache.fineract.portfolio.loanaccount.jobs.applyholidaystoloans;
|
||||||
|
|
||||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
|
||||||
import org.apache.fineract.infrastructure.jobs.service.JobName;
|
import org.apache.fineract.infrastructure.jobs.service.JobName;
|
||||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
|
||||||
import org.springframework.batch.core.Job;
|
import org.springframework.batch.core.Job;
|
||||||
import org.springframework.batch.core.Step;
|
import org.springframework.batch.core.Step;
|
||||||
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
|
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
|
||||||
@@ -40,28 +36,15 @@ public class ApplyHolidaysToLoansConfig {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private StepBuilderFactory steps;
|
private StepBuilderFactory steps;
|
||||||
@Autowired
|
|
||||||
private ConfigurationDomainService configurationDomainService;
|
|
||||||
@Autowired
|
|
||||||
private HolidayRepositoryWrapper holidayRepository;
|
|
||||||
@Autowired
|
|
||||||
private LoanRepositoryWrapper loanRepositoryWrapper;
|
|
||||||
@Autowired
|
|
||||||
private LoanUtilService loanUtilService;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
protected Step applyHolidaysToLoansStep() {
|
protected Step applyHolidaysToLoansStep(ApplyHolidaysToLoansTasklet applyHolidaysToLoansTasklet) {
|
||||||
return steps.get(JobName.APPLY_HOLIDAYS_TO_LOANS.name()).tasklet(applyHolidaysToLoansTasklet()).build();
|
return steps.get(JobName.APPLY_HOLIDAYS_TO_LOANS.name()).tasklet(applyHolidaysToLoansTasklet).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Job applyHolidaysToLoansJob() {
|
public Job applyHolidaysToLoansJob(ApplyHolidaysToLoansTasklet applyHolidaysToLoansTasklet) {
|
||||||
return jobs.get(JobName.APPLY_HOLIDAYS_TO_LOANS.name()).start(applyHolidaysToLoansStep()).incrementer(new RunIdIncrementer())
|
return jobs.get(JobName.APPLY_HOLIDAYS_TO_LOANS.name()).start(applyHolidaysToLoansStep(applyHolidaysToLoansTasklet))
|
||||||
.build();
|
.incrementer(new RunIdIncrementer()).build();
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ApplyHolidaysToLoansTasklet applyHolidaysToLoansTasklet() {
|
|
||||||
return new ApplyHolidaysToLoansTasklet(configurationDomainService, holidayRepository, loanRepositoryWrapper, loanUtilService);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+87
-1
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.jobs.applyholidaystoloans;
|
package org.apache.fineract.portfolio.loanaccount.jobs.applyholidaystoloans;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -26,26 +27,35 @@ import java.util.Set;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRescheduledDueHolidayBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
|
import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
|
||||||
import org.apache.fineract.organisation.office.domain.Office;
|
import org.apache.fineract.organisation.office.domain.Office;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||||
import org.springframework.batch.core.StepContribution;
|
import org.springframework.batch.core.StepContribution;
|
||||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||||
import org.springframework.batch.repeat.RepeatStatus;
|
import org.springframework.batch.repeat.RepeatStatus;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@Component
|
||||||
public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
||||||
|
|
||||||
private final ConfigurationDomainService configurationDomainService;
|
private final ConfigurationDomainService configurationDomainService;
|
||||||
private final HolidayRepositoryWrapper holidayRepository;
|
private final HolidayRepositoryWrapper holidayRepository;
|
||||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||||
@@ -72,7 +82,7 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
|||||||
loans.addAll(loanRepositoryWrapper.findByGroupOfficeIdsAndLoanStatus(officeIds, loanStatuses));
|
loans.addAll(loanRepositoryWrapper.findByGroupOfficeIdsAndLoanStatus(officeIds, loanStatuses));
|
||||||
|
|
||||||
for (final Loan loan : loans) {
|
for (final Loan loan : loans) {
|
||||||
loan.applyHolidayToRepaymentScheduleDates(holiday, loanUtilService);
|
applyHolidayToRepaymentScheduleDates(loan, holiday);
|
||||||
}
|
}
|
||||||
loanRepositoryWrapper.save(loans);
|
loanRepositoryWrapper.save(loans);
|
||||||
holiday.processed();
|
holiday.processed();
|
||||||
@@ -80,4 +90,80 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet {
|
|||||||
holidayRepository.save(holidays);
|
holidayRepository.save(holidays);
|
||||||
return RepeatStatus.FINISHED;
|
return RepeatStatus.FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void applyHolidayToRepaymentScheduleDates(Loan loan, Holiday holiday) {
|
||||||
|
LocalDate adjustedRescheduleToDate = null;
|
||||||
|
if (holiday.getReScheduleType().isResheduleToNextRepaymentDate()) {
|
||||||
|
adjustedRescheduleToDate = getNextRepaymentDate(loan, holiday);
|
||||||
|
} else {
|
||||||
|
adjustedRescheduleToDate = holiday.getRepaymentsRescheduledToLocalDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRepaymentScheduleAdjustmentNeeded(adjustedRescheduleToDate)) {
|
||||||
|
adjustRepaymentSchedules(loan, holiday, adjustedRescheduleToDate);
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanRescheduledDueHolidayBusinessEvent(loan));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRepaymentScheduleAdjustmentNeeded(LocalDate adjustedRescheduleToDate) {
|
||||||
|
return adjustedRescheduleToDate != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adjustRepaymentSchedules(Loan loan, Holiday holiday, LocalDate adjustedRescheduleToDate) {
|
||||||
|
final DefaultScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
||||||
|
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, holiday.getFromDateLocalDate());
|
||||||
|
final LoanApplicationTerms loanApplicationTerms = loan.constructLoanApplicationTerms(scheduleGeneratorDTO);
|
||||||
|
|
||||||
|
// first repayment's from date is same as disbursement date.
|
||||||
|
LocalDate tmpFromDate = loan.getDisbursementDate();
|
||||||
|
|
||||||
|
// Loop through all loanRepayments
|
||||||
|
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||||
|
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : installments) {
|
||||||
|
|
||||||
|
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||||
|
|
||||||
|
// update from date if it's not same as previous installment's due
|
||||||
|
// date.
|
||||||
|
if (!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)) {
|
||||||
|
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldDueDate.equals(holiday.getFromDateLocalDate()) || oldDueDate.isAfter(holiday.getFromDateLocalDate())) {
|
||||||
|
// FIXME: AA do we need to apply non-working days.
|
||||||
|
// Assuming holiday's repayment reschedule to date cannot be
|
||||||
|
// created on a non-working day.
|
||||||
|
|
||||||
|
adjustedRescheduleToDate = scheduledDateGenerator.generateNextRepaymentDate(adjustedRescheduleToDate, loanApplicationTerms,
|
||||||
|
false);
|
||||||
|
loanRepaymentScheduleInstallment.updateDueDate(adjustedRescheduleToDate);
|
||||||
|
}
|
||||||
|
tmpFromDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDate getNextRepaymentDate(Loan loan, Holiday holiday) {
|
||||||
|
LocalDate adjustedRescheduleToDate = null;
|
||||||
|
final LocalDate rescheduleToDate = holiday.getToDateLocalDate();
|
||||||
|
for (final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : loan.getRepaymentScheduleInstallments()) {
|
||||||
|
if (rescheduleToDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) {
|
||||||
|
adjustedRescheduleToDate = rescheduleToDate;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
adjustedRescheduleToDate = doStandardMonthlyCheck(adjustedRescheduleToDate, rescheduleToDate,
|
||||||
|
loanRepaymentScheduleInstallment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return adjustedRescheduleToDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDate doStandardMonthlyCheck(LocalDate adjustedRescheduleToDate, LocalDate rescheduleToDate,
|
||||||
|
LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
|
||||||
|
// Standard Monthly Loan Holiday check
|
||||||
|
if (rescheduleToDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())
|
||||||
|
&& rescheduleToDate.isBefore(loanRepaymentScheduleInstallment.getDueDate().plusDays(30))) {
|
||||||
|
adjustedRescheduleToDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||||
|
}
|
||||||
|
return adjustedRescheduleToDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-20
@@ -23,10 +23,13 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanScheduleVariationsAddedBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanScheduleVariationsDeletedBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
@@ -34,41 +37,30 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePlatformService {
|
public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePlatformService {
|
||||||
|
|
||||||
private final LoanAccountDomainService loanAccountDomainService;
|
private final LoanAccountDomainService loanAccountDomainService;
|
||||||
private final LoanAssembler loanAssembler;
|
private final LoanAssembler loanAssembler;
|
||||||
private final LoanScheduleAssembler loanScheduleAssembler;
|
private final LoanScheduleAssembler loanScheduleAssembler;
|
||||||
private final PlatformSecurityContext context;
|
|
||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
@Autowired
|
|
||||||
public LoanScheduleWritePlatformServiceImpl(final LoanAccountDomainService loanAccountDomainService,
|
|
||||||
final LoanScheduleAssembler loanScheduleAssembler, final LoanAssembler loanAssembler, final PlatformSecurityContext context,
|
|
||||||
final LoanUtilService loanUtilService) {
|
|
||||||
this.loanAccountDomainService = loanAccountDomainService;
|
|
||||||
this.loanScheduleAssembler = loanScheduleAssembler;
|
|
||||||
this.loanAssembler = loanAssembler;
|
|
||||||
this.context = context;
|
|
||||||
this.loanUtilService = loanUtilService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult addLoanScheduleVariations(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult addLoanScheduleVariations(final Long loanId, final JsonCommand command) {
|
||||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
final Loan loan = loanAssembler.assembleFrom(loanId);
|
||||||
Map<Long, LoanTermVariations> loanTermVariations = new HashMap<>();
|
Map<Long, LoanTermVariations> loanTermVariations = new HashMap<>();
|
||||||
for (LoanTermVariations termVariations : loan.getLoanTermVariations()) {
|
for (LoanTermVariations termVariations : loan.getLoanTermVariations()) {
|
||||||
loanTermVariations.put(termVariations.getId(), termVariations);
|
loanTermVariations.put(termVariations.getId(), termVariations);
|
||||||
}
|
}
|
||||||
this.loanScheduleAssembler.assempleVariableScheduleFrom(loan, command.json());
|
loanScheduleAssembler.assempleVariableScheduleFrom(loan, command.json());
|
||||||
|
|
||||||
this.loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
|
loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
final Map<String, Object> changes = new HashMap<>();
|
final Map<String, Object> changes = new HashMap<>();
|
||||||
List<LoanTermVariationsData> newVariationsData = new ArrayList<>();
|
List<LoanTermVariationsData> newVariationsData = new ArrayList<>();
|
||||||
List<LoanTermVariations> modifiedVariations = loan.getLoanTermVariations();
|
List<LoanTermVariations> modifiedVariations = loan.getLoanTermVariations();
|
||||||
@@ -83,6 +75,7 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl
|
|||||||
changes.put("removedVariations", loanTermVariations.keySet());
|
changes.put("removedVariations", loanTermVariations.keySet());
|
||||||
}
|
}
|
||||||
changes.put("loanTermVariations", newVariationsData);
|
changes.put("loanTermVariations", newVariationsData);
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanScheduleVariationsAddedBusinessEvent(loan));
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withCommandId(command.commandId()) //
|
.withCommandId(command.commandId()) //
|
||||||
.withLoanId(loanId) //
|
.withLoanId(loanId) //
|
||||||
@@ -92,7 +85,7 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult deleteLoanScheduleVariations(final Long loanId) {
|
public CommandProcessingResult deleteLoanScheduleVariations(final Long loanId) {
|
||||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
final Loan loan = loanAssembler.assembleFrom(loanId);
|
||||||
List<LoanTermVariations> variations = loan.getLoanTermVariations();
|
List<LoanTermVariations> variations = loan.getLoanTermVariations();
|
||||||
List<Long> deletedVariations = new ArrayList<>(variations.size());
|
List<Long> deletedVariations = new ArrayList<>(variations.size());
|
||||||
for (LoanTermVariations loanTermVariations : variations) {
|
for (LoanTermVariations loanTermVariations : variations) {
|
||||||
@@ -102,9 +95,10 @@ public class LoanScheduleWritePlatformServiceImpl implements LoanScheduleWritePl
|
|||||||
changes.put("removedEntityIds", deletedVariations);
|
changes.put("removedEntityIds", deletedVariations);
|
||||||
loan.getLoanTermVariations().clear();
|
loan.getLoanTermVariations().clear();
|
||||||
final LocalDate recalculateFrom = null;
|
final LocalDate recalculateFrom = null;
|
||||||
ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||||
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
|
||||||
this.loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
|
loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanScheduleVariationsDeletedBusinessEvent(loan));
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withLoanId(loanId) //
|
.withLoanId(loanId) //
|
||||||
.with(changes) //
|
.with(changes) //
|
||||||
|
|||||||
+9
-90
@@ -25,13 +25,14 @@ import java.math.BigDecimal;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.temporal.ChronoField;
|
import java.time.temporal.ChronoField;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.PersistenceException;
|
import javax.persistence.PersistenceException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumberFormat;
|
import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumberFormat;
|
||||||
@@ -87,7 +88,6 @@ import org.apache.fineract.portfolio.client.domain.Client;
|
|||||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
|
import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
|
||||||
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
|
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
|
||||||
import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepository;
|
|
||||||
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler;
|
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler;
|
||||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||||
import org.apache.fineract.portfolio.fund.domain.Fund;
|
import org.apache.fineract.portfolio.fund.domain.Fund;
|
||||||
@@ -104,10 +104,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonit
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
@@ -144,9 +142,6 @@ import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
|||||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||||
import org.apache.fineract.portfolio.savings.service.GSIMReadPlatformService;
|
import org.apache.fineract.portfolio.savings.service.GSIMReadPlatformService;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
import org.springframework.orm.jpa.JpaSystemException;
|
import org.springframework.orm.jpa.JpaSystemException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -154,10 +149,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements LoanApplicationWritePlatformService {
|
public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements LoanApplicationWritePlatformService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(LoanApplicationWritePlatformServiceJpaRepositoryImpl.class);
|
|
||||||
|
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final FromJsonHelper fromJsonHelper;
|
private final FromJsonHelper fromJsonHelper;
|
||||||
private final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator;
|
private final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator;
|
||||||
@@ -181,7 +176,6 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||||
private final AccountAssociationsRepository accountAssociationsRepository;
|
private final AccountAssociationsRepository accountAssociationsRepository;
|
||||||
private final LoanReadPlatformService loanReadPlatformService;
|
private final LoanReadPlatformService loanReadPlatformService;
|
||||||
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
|
|
||||||
private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository;
|
private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository;
|
||||||
private final BusinessEventNotifierService businessEventNotifierService;
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
private final ConfigurationDomainService configurationDomainService;
|
private final ConfigurationDomainService configurationDomainService;
|
||||||
@@ -190,7 +184,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
private final CalendarReadPlatformService calendarReadPlatformService;
|
private final CalendarReadPlatformService calendarReadPlatformService;
|
||||||
private final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService;
|
private final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService;
|
||||||
private final GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
|
private final GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
|
||||||
private final FineractEntityToEntityMappingRepository repository;
|
private final FineractEntityToEntityMappingRepository entityMappingRepository;
|
||||||
private final FineractEntityRelationRepository fineractEntityRelationRepository;
|
private final FineractEntityRelationRepository fineractEntityRelationRepository;
|
||||||
private final LoanProductReadPlatformService loanProductReadPlatformService;
|
private final LoanProductReadPlatformService loanProductReadPlatformService;
|
||||||
|
|
||||||
@@ -199,84 +193,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
private final GLIMAccountInfoRepository glimRepository;
|
private final GLIMAccountInfoRepository glimRepository;
|
||||||
private final LoanRepository loanRepository;
|
private final LoanRepository loanRepository;
|
||||||
private final GSIMReadPlatformService gsimReadPlatformService;
|
private final GSIMReadPlatformService gsimReadPlatformService;
|
||||||
private final LoanCollateralManagementRepository loanCollateralManagementRepository;
|
|
||||||
private final ClientCollateralManagementRepository clientCollateralManagementRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
|
|
||||||
final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator,
|
|
||||||
final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer,
|
|
||||||
final LoanProductDataValidator loanProductCommandFromApiJsonDeserializer, final AprCalculator aprCalculator,
|
|
||||||
final LoanAssembler loanAssembler, final LoanChargeAssembler loanChargeAssembler,
|
|
||||||
final LoanCollateralAssembler loanCollateralAssembler, final LoanRepositoryWrapper loanRepositoryWrapper,
|
|
||||||
final NoteRepository noteRepository, final LoanScheduleCalculationPlatformService calculationPlatformService,
|
|
||||||
final ClientRepositoryWrapper clientRepository, final LoanProductRepository loanProductRepository,
|
|
||||||
final AccountNumberGenerator accountNumberGenerator, final LoanSummaryWrapper loanSummaryWrapper,
|
|
||||||
final GroupRepositoryWrapper groupRepository,
|
|
||||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
|
||||||
final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository,
|
|
||||||
final SavingsAccountAssembler savingsAccountAssembler, final AccountAssociationsRepository accountAssociationsRepository,
|
|
||||||
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
|
|
||||||
final LoanReadPlatformService loanReadPlatformService, final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository,
|
|
||||||
final BusinessEventNotifierService businessEventNotifierService, final ConfigurationDomainService configurationDomainService,
|
|
||||||
final LoanScheduleAssembler loanScheduleAssembler, final LoanUtilService loanUtilService,
|
|
||||||
final CalendarReadPlatformService calendarReadPlatformService,
|
|
||||||
final GlobalConfigurationRepositoryWrapper globalConfigurationRepository,
|
|
||||||
final FineractEntityToEntityMappingRepository repository,
|
|
||||||
final FineractEntityRelationRepository fineractEntityRelationRepository,
|
|
||||||
final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService,
|
|
||||||
final GLIMAccountInfoWritePlatformService glimAccountInfoWritePlatformService, final GLIMAccountInfoRepository glimRepository,
|
|
||||||
final LoanRepository loanRepository, final GSIMReadPlatformService gsimReadPlatformService, final RateAssembler rateAssembler,
|
|
||||||
final LoanProductReadPlatformService loanProductReadPlatformService,
|
|
||||||
final LoanCollateralManagementRepository loanCollateralManagementRepository,
|
|
||||||
final ClientCollateralManagementRepository clientCollateralManagementRepository) {
|
|
||||||
this.context = context;
|
|
||||||
this.fromJsonHelper = fromJsonHelper;
|
|
||||||
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
|
|
||||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
|
||||||
this.loanProductCommandFromApiJsonDeserializer = loanProductCommandFromApiJsonDeserializer;
|
|
||||||
this.aprCalculator = aprCalculator;
|
|
||||||
this.loanAssembler = loanAssembler;
|
|
||||||
this.loanChargeAssembler = loanChargeAssembler;
|
|
||||||
this.loanCollateralAssembler = loanCollateralAssembler;
|
|
||||||
this.loanRepositoryWrapper = loanRepositoryWrapper;
|
|
||||||
this.noteRepository = noteRepository;
|
|
||||||
this.calculationPlatformService = calculationPlatformService;
|
|
||||||
this.clientRepository = clientRepository;
|
|
||||||
this.loanProductRepository = loanProductRepository;
|
|
||||||
this.accountNumberGenerator = accountNumberGenerator;
|
|
||||||
this.loanSummaryWrapper = loanSummaryWrapper;
|
|
||||||
this.groupRepository = groupRepository;
|
|
||||||
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
|
|
||||||
this.calendarRepository = calendarRepository;
|
|
||||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
|
||||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
|
||||||
this.accountAssociationsRepository = accountAssociationsRepository;
|
|
||||||
this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository;
|
|
||||||
this.loanReadPlatformService = loanReadPlatformService;
|
|
||||||
this.accountNumberFormatRepository = accountNumberFormatRepository;
|
|
||||||
this.businessEventNotifierService = businessEventNotifierService;
|
|
||||||
this.configurationDomainService = configurationDomainService;
|
|
||||||
this.loanScheduleAssembler = loanScheduleAssembler;
|
|
||||||
this.loanUtilService = loanUtilService;
|
|
||||||
this.calendarReadPlatformService = calendarReadPlatformService;
|
|
||||||
this.entityDatatableChecksWritePlatformService = entityDatatableChecksWritePlatformService;
|
|
||||||
this.globalConfigurationRepository = globalConfigurationRepository;
|
|
||||||
this.repository = repository;
|
|
||||||
this.fineractEntityRelationRepository = fineractEntityRelationRepository;
|
|
||||||
this.loanProductReadPlatformService = loanProductReadPlatformService;
|
|
||||||
this.rateAssembler = rateAssembler;
|
|
||||||
this.glimAccountInfoWritePlatformService = glimAccountInfoWritePlatformService;
|
|
||||||
this.glimRepository = glimRepository;
|
|
||||||
this.loanRepository = loanRepository;
|
|
||||||
this.gsimReadPlatformService = gsimReadPlatformService;
|
|
||||||
this.loanCollateralManagementRepository = loanCollateralManagementRepository;
|
|
||||||
this.clientCollateralManagementRepository = clientCollateralManagementRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||||
final List<LoanStatus> allowedLoanStatuses = Arrays.asList(LoanStatus.values());
|
return new DefaultLoanLifecycleStateMachine(LoanStatus.values(), businessEventNotifierService);
|
||||||
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -1287,7 +1206,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void logAsErrorUnexpectedDataIntegrityException(final Exception dve) {
|
private void logAsErrorUnexpectedDataIntegrityException(final Exception dve) {
|
||||||
LOG.error("Error occured.", dve);
|
log.error("Error occured.", dve);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -1775,8 +1694,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
if (restrictToUserOfficeProperty.isEnabled()) {
|
if (restrictToUserOfficeProperty.isEnabled()) {
|
||||||
FineractEntityRelation fineractEntityRelation = fineractEntityRelationRepository
|
FineractEntityRelation fineractEntityRelation = fineractEntityRelationRepository
|
||||||
.findOneByCodeName(FineractEntityAccessType.OFFICE_ACCESS_TO_LOAN_PRODUCTS.toStr());
|
.findOneByCodeName(FineractEntityAccessType.OFFICE_ACCESS_TO_LOAN_PRODUCTS.toStr());
|
||||||
FineractEntityToEntityMapping officeToLoanProductMappingList = this.repository.findListByProductId(fineractEntityRelation,
|
FineractEntityToEntityMapping officeToLoanProductMappingList = this.entityMappingRepository
|
||||||
productId, officeId);
|
.findListByProductId(fineractEntityRelation, productId, officeId);
|
||||||
if (officeToLoanProductMappingList == null) {
|
if (officeToLoanProductMappingList == null) {
|
||||||
throw new NotOfficeSpecificProductException(productId, officeId);
|
throw new NotOfficeSpecificProductException(productId, officeId);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-36
@@ -22,11 +22,11 @@ import com.google.gson.JsonElement;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||||
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||||
@@ -34,6 +34,7 @@ import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDoma
|
|||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepository;
|
import org.apache.fineract.organisation.holiday.domain.HolidayRepository;
|
||||||
import org.apache.fineract.organisation.holiday.domain.HolidayStatusType;
|
import org.apache.fineract.organisation.holiday.domain.HolidayStatusType;
|
||||||
@@ -87,10 +88,10 @@ import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequired
|
|||||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
||||||
import org.apache.fineract.portfolio.rate.domain.Rate;
|
import org.apache.fineract.portfolio.rate.domain.Rate;
|
||||||
import org.apache.fineract.portfolio.rate.service.RateAssembler;
|
import org.apache.fineract.portfolio.rate.service.RateAssembler;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class LoanAssembler {
|
public class LoanAssembler {
|
||||||
|
|
||||||
private final FromJsonHelper fromApiJsonHelper;
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
@@ -112,38 +113,7 @@ public class LoanAssembler {
|
|||||||
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
private final WorkingDaysRepositoryWrapper workingDaysRepository;
|
||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
private final RateAssembler rateAssembler;
|
private final RateAssembler rateAssembler;
|
||||||
|
private final BusinessEventNotifierService businessEventNotifierService;
|
||||||
@Autowired
|
|
||||||
public LoanAssembler(final FromJsonHelper fromApiJsonHelper, final LoanRepositoryWrapper loanRepository,
|
|
||||||
final LoanProductRepository loanProductRepository, final ClientRepositoryWrapper clientRepository,
|
|
||||||
final GroupRepository groupRepository, final FundRepository fundRepository,
|
|
||||||
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository,
|
|
||||||
final StaffRepository staffRepository, final CodeValueRepositoryWrapper codeValueRepository,
|
|
||||||
final LoanScheduleAssembler loanScheduleAssembler, final LoanChargeAssembler loanChargeAssembler,
|
|
||||||
final LoanCollateralAssembler collateralAssembler, final LoanSummaryWrapper loanSummaryWrapper,
|
|
||||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
|
||||||
final HolidayRepository holidayRepository, final ConfigurationDomainService configurationDomainService,
|
|
||||||
final WorkingDaysRepositoryWrapper workingDaysRepository, final LoanUtilService loanUtilService, RateAssembler rateAssembler) {
|
|
||||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
|
||||||
this.loanRepository = loanRepository;
|
|
||||||
this.loanProductRepository = loanProductRepository;
|
|
||||||
this.clientRepository = clientRepository;
|
|
||||||
this.groupRepository = groupRepository;
|
|
||||||
this.fundRepository = fundRepository;
|
|
||||||
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
|
|
||||||
this.staffRepository = staffRepository;
|
|
||||||
this.codeValueRepository = codeValueRepository;
|
|
||||||
this.loanScheduleAssembler = loanScheduleAssembler;
|
|
||||||
this.loanChargeAssembler = loanChargeAssembler;
|
|
||||||
this.collateralAssembler = collateralAssembler;
|
|
||||||
this.loanSummaryWrapper = loanSummaryWrapper;
|
|
||||||
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
|
|
||||||
this.holidayRepository = holidayRepository;
|
|
||||||
this.configurationDomainService = configurationDomainService;
|
|
||||||
this.workingDaysRepository = workingDaysRepository;
|
|
||||||
this.loanUtilService = loanUtilService;
|
|
||||||
this.rateAssembler = rateAssembler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Loan assembleFrom(final Long accountId) {
|
public Loan assembleFrom(final Long accountId) {
|
||||||
final Loan loanAccount = this.loanRepository.findOneWithNotFoundDetection(accountId, true);
|
final Loan loanAccount = this.loanRepository.findOneWithNotFoundDetection(accountId, true);
|
||||||
@@ -354,8 +324,7 @@ public class LoanAssembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||||
final List<LoanStatus> allowedLoanStatuses = Arrays.asList(LoanStatus.values());
|
return new DefaultLoanLifecycleStateMachine(LoanStatus.values(), businessEventNotifierService);
|
||||||
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeValue findCodeValueByIdIfProvided(final Long codeValueId) {
|
public CodeValue findCodeValueByIdIfProvided(final Long codeValueId) {
|
||||||
|
|||||||
+14
-85
@@ -66,15 +66,17 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.LoanInteres
|
|||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanReassignOfficerBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanReassignOfficerBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRejectTransferBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRejectTransferBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRemoveOfficerBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRemoveOfficerBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRescheduledDueCalendarChangeBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanUndoDisbursalBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanUndoDisbursalBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanUndoLastDisbursalBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanUndoLastDisbursalBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanUpdateDisbursementDataBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanWithdrawTransferBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanWithdrawTransferBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanAddChargeBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanAddChargeBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanDeleteChargeBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanDeleteChargeBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanUpdateChargeBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanUpdateChargeBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanWaiveChargeBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanWaiveChargeBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanWaiveChargeUndoBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanWaiveChargeUndoBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanChargePaymentPostBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanChargeRefundBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoWrittenOffBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoWrittenOffBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanWaiveInterestBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanWaiveInterestBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanWrittenOffPostBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanWrittenOffPostBusinessEvent;
|
||||||
@@ -269,8 +271,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
private final LoanRepaymentScheduleInstallmentRepository loanRepaymentScheduleInstallmentRepository;
|
private final LoanRepaymentScheduleInstallmentRepository loanRepaymentScheduleInstallmentRepository;
|
||||||
|
|
||||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||||
final List<LoanStatus> allowedLoanStatuses = Arrays.asList(LoanStatus.values());
|
return new DefaultLoanLifecycleStateMachine(LoanStatus.values(), businessEventNotifierService);
|
||||||
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -795,8 +796,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult undoGLIMLoanDisbursal(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult undoGLIMLoanDisbursal(final Long loanId, final JsonCommand command) {
|
||||||
// GroupLoanIndividualMonitoringAccount
|
|
||||||
// glimAccount=glimRepository.findOne(loanId);
|
|
||||||
final Long parentLoanId = loanId;
|
final Long parentLoanId = loanId;
|
||||||
GroupLoanIndividualMonitoringAccount parentLoan = glimRepository.findById(parentLoanId).orElseThrow();
|
GroupLoanIndividualMonitoringAccount parentLoan = glimRepository.findById(parentLoanId).orElseThrow();
|
||||||
List<Loan> childLoans = this.loanRepository.findByGlimId(loanId);
|
List<Loan> childLoans = this.loanRepository.findByGlimId(loanId);
|
||||||
@@ -1727,7 +1726,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanChargePaymentPostBusinessEvent(newChargeRefundTxn));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanChargeRefundBusinessEvent(newChargeRefundTxn));
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2196,7 +2195,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
.withSavingsId(portfolioAccountData.getId()).build();
|
.withSavingsId(portfolioAccountData.getId()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disburseLoanToLoan(final Loan loan, final JsonCommand command, final BigDecimal amount) {
|
private void disburseLoanToLoan(final Loan loan, final JsonCommand command, final BigDecimal amount) {
|
||||||
|
|
||||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||||
@@ -2211,7 +2210,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loan.getTopupLoanDetails().setTopupAmount(amount);
|
loan.getTopupLoanDetails().setTopupAmount(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disburseLoanToSavings(final Loan loan, final JsonCommand command, final Money amount, final PaymentDetail paymentDetail) {
|
private void disburseLoanToSavings(final Loan loan, final JsonCommand command, final Money amount, final PaymentDetail paymentDetail) {
|
||||||
|
|
||||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||||
@@ -2518,6 +2517,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanRescheduledDueCalendarChangeBusinessEvent(loan));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2971,7 +2971,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loan.loanProduct().maxTrancheCount(), loan.getDisbursementDetails().size());
|
loan.loanProduct().maxTrancheCount(), loan.getDisbursementDetails().size());
|
||||||
}
|
}
|
||||||
LoanDisbursementDetails updateDetails = null;
|
LoanDisbursementDetails updateDetails = null;
|
||||||
return processLoanDisbursementDetail(loan, loanId, command, updateDetails);
|
CommandProcessingResult result = processLoanDisbursementDetail(loan, loanId, command, updateDetails);
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanUpdateDisbursementDataBusinessEvent(loan));
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3040,85 +3042,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
LoanDisbursementDetails loanDisbursementDetails = loan.fetchLoanDisbursementsById(disbursementId);
|
LoanDisbursementDetails loanDisbursementDetails = loan.fetchLoanDisbursementsById(disbursementId);
|
||||||
this.loanEventApiJsonValidator.validateUpdateDisbursementDateAndAmount(command.json(), loanDisbursementDetails);
|
this.loanEventApiJsonValidator.validateUpdateDisbursementDateAndAmount(command.json(), loanDisbursementDetails);
|
||||||
|
|
||||||
return processLoanDisbursementDetail(loan, loanId, command, loanDisbursementDetails);
|
CommandProcessingResult result = processLoanDisbursementDetail(loan, loanId, command, loanDisbursementDetails);
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanUpdateDisbursementDataBusinessEvent(loan));
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanTransaction disburseLoanAmountToSavings(final Long loanId, Long loanChargeId, final JsonCommand command,
|
|
||||||
final boolean isChargeIdIncludedInJson) {
|
|
||||||
|
|
||||||
LoanTransaction transaction = null;
|
|
||||||
|
|
||||||
this.loanEventApiJsonValidator.validateChargePaymentTransaction(command.json(), isChargeIdIncludedInJson);
|
|
||||||
if (isChargeIdIncludedInJson) {
|
|
||||||
loanChargeId = command.longValueOfParameterNamed("chargeId");
|
|
||||||
}
|
|
||||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
|
||||||
checkClientOrGroupActive(loan);
|
|
||||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
|
||||||
|
|
||||||
// Charges may be waived only when the loan associated with them are
|
|
||||||
// active
|
|
||||||
if (!loan.status().isActive()) {
|
|
||||||
throw new LoanChargeCannotBePayedException(LoanChargeCannotBePayedReason.LOAN_INACTIVE, loanCharge.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate loan charge is not already paid or waived
|
|
||||||
if (loanCharge.isWaived()) {
|
|
||||||
throw new LoanChargeCannotBePayedException(LoanChargeCannotBePayedReason.ALREADY_WAIVED, loanCharge.getId());
|
|
||||||
} else if (loanCharge.isPaid()) {
|
|
||||||
throw new LoanChargeCannotBePayedException(LoanChargeCannotBePayedReason.ALREADY_PAID, loanCharge.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()) {
|
|
||||||
throw new LoanChargeCannotBePayedException(LoanChargeCannotBePayedReason.CHARGE_NOT_ACCOUNT_TRANSFER, loanCharge.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
|
||||||
|
|
||||||
final Locale locale = command.extractLocale();
|
|
||||||
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
|
|
||||||
Integer loanInstallmentNumber = null;
|
|
||||||
BigDecimal amount = loanCharge.amountOutstanding();
|
|
||||||
if (loanCharge.isInstalmentFee()) {
|
|
||||||
LoanInstallmentCharge chargePerInstallment = null;
|
|
||||||
final LocalDate dueDate = command.localDateValueOfParameterNamed("dueDate");
|
|
||||||
final Integer installmentNumber = command.integerValueOfParameterNamed("installmentNumber");
|
|
||||||
if (dueDate != null) {
|
|
||||||
chargePerInstallment = loanCharge.getInstallmentLoanCharge(dueDate);
|
|
||||||
} else if (installmentNumber != null) {
|
|
||||||
chargePerInstallment = loanCharge.getInstallmentLoanCharge(installmentNumber);
|
|
||||||
}
|
|
||||||
if (chargePerInstallment == null) {
|
|
||||||
chargePerInstallment = loanCharge.getUnpaidInstallmentLoanCharge();
|
|
||||||
}
|
|
||||||
if (chargePerInstallment.isWaived()) {
|
|
||||||
throw new LoanChargeCannotBePayedException(LoanChargeCannotBePayedReason.ALREADY_WAIVED, loanCharge.getId());
|
|
||||||
} else if (chargePerInstallment.isPaid()) {
|
|
||||||
throw new LoanChargeCannotBePayedException(LoanChargeCannotBePayedReason.ALREADY_PAID, loanCharge.getId());
|
|
||||||
}
|
|
||||||
loanInstallmentNumber = chargePerInstallment.getRepaymentInstallment().getInstallmentNumber();
|
|
||||||
amount = chargePerInstallment.getAmountOutstanding();
|
|
||||||
}
|
|
||||||
|
|
||||||
final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(loanId);
|
|
||||||
if (portfolioAccountData == null) {
|
|
||||||
final String errorMessage = "Charge with id:" + loanChargeId + " requires linked savings account for payment";
|
|
||||||
throw new LinkedAccountRequiredException("loanCharge.pay", errorMessage, loanChargeId);
|
|
||||||
}
|
|
||||||
final SavingsAccount fromSavingsAccount = null;
|
|
||||||
final boolean isRegularTransaction = true;
|
|
||||||
final boolean isExceptionForBalanceCheck = false;
|
|
||||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
|
|
||||||
PortfolioAccountType.LOAN, portfolioAccountData.getId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
|
|
||||||
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber,
|
|
||||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction,
|
|
||||||
isExceptionForBalanceCheck);
|
|
||||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
|
||||||
|
|
||||||
return transaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public void recalculateInterest(final long loanId) {
|
public void recalculateInterest(final long loanId) {
|
||||||
|
|||||||
+5
-2
@@ -29,6 +29,7 @@ import java.time.LocalDate;
|
|||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
|
import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
|
||||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
@@ -43,7 +44,6 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.InjectMocks;
|
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
@@ -57,12 +57,15 @@ class ExternalEventServiceTest {
|
|||||||
private ExternalEventIdempotencyKeyGenerator idempotencyKeyGenerator;
|
private ExternalEventIdempotencyKeyGenerator idempotencyKeyGenerator;
|
||||||
@Mock
|
@Mock
|
||||||
private BusinessEventSerializerFactory serializerFactory;
|
private BusinessEventSerializerFactory serializerFactory;
|
||||||
|
@Mock
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
@InjectMocks
|
|
||||||
private ExternalEventService underTest;
|
private ExternalEventService underTest;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
|
underTest = new ExternalEventService(repository, idempotencyKeyGenerator, serializerFactory);
|
||||||
|
underTest.setEntityManager(entityManager);
|
||||||
FineractPlatformTenant tenant = new FineractPlatformTenant(1L, "default", "Default Tenant", "Europe/Budapest", null);
|
FineractPlatformTenant tenant = new FineractPlatformTenant(1L, "default", "Default Tenant", "Europe/Budapest", null);
|
||||||
ThreadLocalContextUtil.setTenant(tenant);
|
ThreadLocalContextUtil.setTenant(tenant);
|
||||||
ThreadLocalContextUtil
|
ThreadLocalContextUtil
|
||||||
|
|||||||
Reference in New Issue
Block a user