blob: 2b276cdce9f1850e4a167221ebda8043a6913da5 [file] [log] [blame]
/*
* 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.cn.individuallending.internal.mapper;
import org.apache.fineract.cn.individuallending.api.v1.domain.caseinstance.CaseParameters;
import org.apache.fineract.cn.individuallending.api.v1.domain.caseinstance.CreditWorthinessFactor;
import org.apache.fineract.cn.individuallending.api.v1.domain.caseinstance.CreditWorthinessSnapshot;
import org.apache.fineract.cn.individuallending.internal.repository.CaseCreditWorthinessFactorEntity;
import org.apache.fineract.cn.individuallending.internal.repository.CaseParametersEntity;
import org.apache.fineract.cn.individuallending.internal.repository.CreditWorthinessFactorType;
import org.apache.fineract.cn.portfolio.api.v1.domain.PaymentCycle;
import org.apache.fineract.cn.portfolio.api.v1.domain.TermRange;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author Myrle Krantz
*/
public class CaseParametersMapper {
public static CaseParametersEntity map(
final Long caseId,
final CaseParameters instance) {
final CaseParametersEntity ret = new CaseParametersEntity();
ret.setCaseId(caseId);
ret.setCustomerIdentifier(instance.getCustomerIdentifier());
ret.setTermRangeTemporalUnit(instance.getTermRange().getTemporalUnit());
ret.setTermRangeMinimum(0);
ret.setTermRangeMaximum(instance.getTermRange().getMaximum());
ret.setBalanceRangeMaximum(instance.getMaximumBalance());
ret.setPaymentCycleTemporalUnit(instance.getPaymentCycle().getTemporalUnit());
ret.setPaymentCyclePeriod(instance.getPaymentCycle().getPeriod());
ret.setPaymentCycleAlignmentDay(instance.getPaymentCycle().getAlignmentDay());
ret.setPaymentCycleAlignmentWeek(instance.getPaymentCycle().getAlignmentWeek());
ret.setPaymentCycleAlignmentMonth(instance.getPaymentCycle().getAlignmentMonth());
ret.setCreditWorthinessFactors(mapSnapshotsToFactors(instance.getCreditWorthinessSnapshots(), ret));
ret.setPaymentSize(BigDecimal.ONE.negate()); //semaphore for not yet set.
return ret;
}
public static Set<CaseCreditWorthinessFactorEntity> mapSnapshotsToFactors(
final List<CreditWorthinessSnapshot> creditWorthinessSnapshots,
final CaseParametersEntity caseParametersEntity) {
if (creditWorthinessSnapshots == null)
return Collections.emptySet();
return Stream.iterate(0, i -> i+1).limit(creditWorthinessSnapshots.size())
.flatMap(i -> mapSnapshotToFactors(
creditWorthinessSnapshots.get(i), i, caseParametersEntity)).collect(Collectors.toSet());
}
private static Stream<? extends CaseCreditWorthinessFactorEntity> mapSnapshotToFactors(
final CreditWorthinessSnapshot creditWorthinessSnapshot,
final int i,
final CaseParametersEntity caseParametersEntity) {
final String customerId = creditWorthinessSnapshot.getForCustomer();
return Stream.concat(Stream.concat(Stream.concat(
mapSnapshotPartToFactors(customerId, i,
CreditWorthinessFactorType.ASSET, creditWorthinessSnapshot.getAssets(),
caseParametersEntity),
mapSnapshotPartToFactors(customerId, i,
CreditWorthinessFactorType.INCOME_SOURCE, creditWorthinessSnapshot.getIncomeSources(),
caseParametersEntity)),
mapSnapshotPartToFactors(customerId, i,
CreditWorthinessFactorType.DEBT, creditWorthinessSnapshot.getDebts(),
caseParametersEntity)),
createPlaceHolder(customerId, i, caseParametersEntity)
);
}
private static Stream<CaseCreditWorthinessFactorEntity> createPlaceHolder(
final String customerIdentifier,
final int positionInCustomers,
final CaseParametersEntity caseParametersEntity) {
final CaseCreditWorthinessFactorEntity placeHolder = new CaseCreditWorthinessFactorEntity();
placeHolder.setFactorType(CreditWorthinessFactorType.PLACE_HOLDER);
placeHolder.setCustomerIdentifier(customerIdentifier);
placeHolder.setPositionInCustomers(positionInCustomers);
placeHolder.setPositionInFactor(0);
placeHolder.setCaseId(caseParametersEntity);
placeHolder.setAmount(BigDecimal.ZERO);
placeHolder.setDescription("placeholder");
return Stream.of(placeHolder);
}
private static Stream<CaseCreditWorthinessFactorEntity> mapSnapshotPartToFactors(
final String forCustomer,
final int i,
final CreditWorthinessFactorType factorType,
final List<CreditWorthinessFactor> part,
final CaseParametersEntity caseParametersEntity) {
return Stream.iterate(0, j -> j+1).limit(part.size())
.map(j -> {
final CaseCreditWorthinessFactorEntity ret = new CaseCreditWorthinessFactorEntity();
ret.setAmount(part.get(j).getAmount());
ret.setDescription(part.get(j).getDescription());
ret.setCaseId(caseParametersEntity);
ret.setCustomerIdentifier(forCustomer);
ret.setFactorType(factorType);
ret.setPositionInFactor(j);
ret.setPositionInCustomers(i);
return ret;
});
}
private static TermRange getTermRange(final CaseParametersEntity instance) {
final TermRange ret = new TermRange();
ret.setTemporalUnit(instance.getTermRangeTemporalUnit());
ret.setMaximum(instance.getTermRangeMaximum());
return ret;
}
private static PaymentCycle getPaymentCycle(final CaseParametersEntity instance) {
final PaymentCycle ret = new PaymentCycle();
ret.setTemporalUnit(instance.getPaymentCycleTemporalUnit());
ret.setPeriod(instance.getPaymentCyclePeriod());
ret.setAlignmentDay(instance.getPaymentCycleAlignmentDay());
ret.setAlignmentWeek(instance.getPaymentCycleAlignmentWeek());
ret.setAlignmentMonth(instance.getPaymentCycleAlignmentMonth());
//This is necessary because for a while inapproriate values were being accepted for the
//alignment week. Those values are being mapped to -1 which is a sentinel value used to represent the
//last week of the month. If we can fix the existing data, we can remove this code.
if (instance.getPaymentCycleAlignmentWeek() != null &&
((instance.getPaymentCycleAlignmentWeek() == 3) ||
(instance.getPaymentCycleAlignmentWeek() == 4)))
ret.setAlignmentWeek(-1);
return ret;
}
public static CaseParameters mapEntity(final CaseParametersEntity caseParametersEntity,
final int minorCurrencyUnitDigits) {
final CaseParameters ret = new CaseParameters();
ret.setCustomerIdentifier(caseParametersEntity.getCustomerIdentifier());
ret.setCreditWorthinessSnapshots(mapFactorsToSnapshots(caseParametersEntity.getCreditWorthinessFactors(), minorCurrencyUnitDigits));
ret.setTermRange(getTermRange(caseParametersEntity));
ret.setMaximumBalance(caseParametersEntity.getBalanceRangeMaximum().setScale(minorCurrencyUnitDigits, BigDecimal.ROUND_HALF_EVEN));
ret.setPaymentCycle(getPaymentCycle(caseParametersEntity));
return ret;
}
private static List<CreditWorthinessSnapshot> mapFactorsToSnapshots(
final Set<CaseCreditWorthinessFactorEntity> creditWorthinessFactors,
final int minorCurrencyUnitDigits) {
final Map<Integer, Set<CaseCreditWorthinessFactorEntity>> groupedByCustomerId
= creditWorthinessFactors.stream()
.collect(Collectors.groupingBy(CaseCreditWorthinessFactorEntity::getPositionInCustomers, Collectors.toSet()));
return groupedByCustomerId.entrySet().stream()
.sorted(Comparator.comparingInt(Map.Entry::getKey))
.map(customerEntry -> mapEntryToSnapshot(customerEntry, minorCurrencyUnitDigits)).collect(Collectors.toList());
}
private static CreditWorthinessSnapshot mapEntryToSnapshot(
final Map.Entry<Integer, Set<CaseCreditWorthinessFactorEntity>> customerEntry,
final int minorCurrencyUnitDigits) {
final CreditWorthinessSnapshot ret = new CreditWorthinessSnapshot();
final Map<CreditWorthinessFactorType, Set<CaseCreditWorthinessFactorEntity>> groupedByFactorType
= customerEntry.getValue().stream()
.collect(Collectors.groupingBy(CaseCreditWorthinessFactorEntity::getFactorType, Collectors.toSet()));
ret.setAssets(getFactorsByType(groupedByFactorType, CreditWorthinessFactorType.ASSET, minorCurrencyUnitDigits));
ret.setDebts(getFactorsByType(groupedByFactorType, CreditWorthinessFactorType.DEBT, minorCurrencyUnitDigits));
ret.setIncomeSources(getFactorsByType(groupedByFactorType, CreditWorthinessFactorType.INCOME_SOURCE, minorCurrencyUnitDigits));
final String customerId = customerEntry.getValue().stream()
.findFirst()
.map(CaseCreditWorthinessFactorEntity::getCustomerIdentifier)
.orElse("");
ret.setForCustomer(customerId);
return ret;
}
private static List<CreditWorthinessFactor> getFactorsByType(
final Map<CreditWorthinessFactorType, Set<CaseCreditWorthinessFactorEntity>> groupedByFactorType,
final CreditWorthinessFactorType factorType,
final int minorCurrencyUnitDigits) {
final Set<CaseCreditWorthinessFactorEntity> byFactorType = groupedByFactorType.get(factorType);
if (byFactorType == null)
return Collections.emptyList();
else {
return byFactorType.stream()
.sorted(Comparator.comparingInt(CaseCreditWorthinessFactorEntity::getPositionInFactor))
.map(caseCreditWorthinessFactorEntity -> mapEntryToFactor(caseCreditWorthinessFactorEntity, minorCurrencyUnitDigits))
.collect(Collectors.toList());
}
}
private static CreditWorthinessFactor mapEntryToFactor(
final CaseCreditWorthinessFactorEntity caseCreditWorthinessFactorEntity,
final int minorCurrencyUnitDigits) {
final CreditWorthinessFactor ret = new CreditWorthinessFactor();
ret.setDescription(caseCreditWorthinessFactorEntity.getDescription());
ret.setAmount(caseCreditWorthinessFactorEntity.getAmount().setScale(minorCurrencyUnitDigits, BigDecimal.ROUND_HALF_EVEN));
return ret;
}
}