use of org.folio.models.EncumbranceRelationsHolder in project mod-orders by folio-org.
the class EncumbranceRelationsHoldersBuilder method mapRestrictEncumbranceToHolders.
private List<EncumbranceRelationsHolder> mapRestrictEncumbranceToHolders(List<Ledger> ledgers, List<EncumbranceRelationsHolder> encumbranceHolders) {
Map<String, Ledger> idLedgerMap = ledgers.stream().collect(toMap(Ledger::getId, Function.identity()));
encumbranceHolders.stream().filter(holder -> Objects.nonNull(holder.getLedgerId())).forEach(holder -> {
Ledger ledger = idLedgerMap.get(holder.getLedgerId());
holder.withRestrictEncumbrances(Optional.ofNullable(ledger).map(Ledger::getRestrictEncumbrance).orElse(false));
});
return encumbranceHolders;
}
use of org.folio.models.EncumbranceRelationsHolder in project mod-orders by folio-org.
the class EncumbranceRelationsHoldersBuilder method withConversion.
public CompletableFuture<List<EncumbranceRelationsHolder>> withConversion(List<EncumbranceRelationsHolder> encumbranceHolders, RequestContext requestContext) {
return encumbranceHolders.stream().map(EncumbranceRelationsHolder::getCurrency).filter(Objects::nonNull).findFirst().map(transactionCurrency -> FolioVertxCompletableFuture.supplyBlockingAsync(requestContext.getContext(), () -> {
Map<String, List<EncumbranceRelationsHolder>> currencyHolderMap = encumbranceHolders.stream().filter(holder -> Objects.nonNull(holder.getPoLine())).collect(groupingBy(holder -> holder.getPoLine().getCost().getCurrency()));
currencyHolderMap.forEach((poLineCurrency, encumbranceRelationsHolders) -> {
Double exchangeRate = encumbranceRelationsHolders.stream().map(EncumbranceRelationsHolder::getPoLine).map(CompositePoLine::getCost).map(Cost::getExchangeRate).filter(Objects::nonNull).findFirst().orElse(null);
ConversionQuery conversionQuery = getConversionQuery(exchangeRate, poLineCurrency, transactionCurrency);
ExchangeRateProvider exchangeRateProvider = exchangeRateProviderResolver.resolve(conversionQuery, requestContext);
CurrencyConversion conversion = exchangeRateProvider.getCurrencyConversion(conversionQuery);
encumbranceRelationsHolders.forEach(holder -> holder.withPoLineToFyConversion(conversion));
});
return encumbranceHolders;
})).orElseGet(() -> CompletableFuture.completedFuture(encumbranceHolders));
}
use of org.folio.models.EncumbranceRelationsHolder in project mod-orders by folio-org.
the class EncumbranceService method createEncumbrances.
public CompletableFuture<Void> createEncumbrances(List<EncumbranceRelationsHolder> relationsHolders, RequestContext requestContext) {
List<CompletableFuture<Void>> futureList = new ArrayList<>();
CompletableFuture<Void> future = completedFuture(null);
for (EncumbranceRelationsHolder holder : relationsHolders) {
future = future.thenCompose(v -> transactionService.createTransaction(holder.getNewEncumbrance(), requestContext).thenAccept(transaction -> holder.getFundDistribution().setEncumbrance(transaction.getId())).exceptionally(fail -> {
checkCustomTransactionError(fail);
throw new CompletionException(fail);
}));
futureList.add(future);
}
return FolioVertxCompletableFuture.allOf(requestContext.getContext(), futureList.toArray(new CompletableFuture[0]));
}
use of org.folio.models.EncumbranceRelationsHolder in project mod-orders by folio-org.
the class FundsDistributionService method distributeFunds.
public <T extends EncumbranceRelationsHolder> List<T> distributeFunds(List<T> holders) {
Map<CompositePoLine, List<EncumbranceRelationsHolder>> lineHoldersMap = holders.stream().filter(holder -> Objects.nonNull(holder.getPoLine())).collect(Collectors.groupingBy(EncumbranceRelationsHolder::getPoLine));
lineHoldersMap.forEach((poLine, encumbranceRelationsHolders) -> {
poLine.getCost().setPoLineEstimatedPrice(HelperUtils.calculateEstimatedPrice(poLine.getCost()).getNumber().doubleValue());
CurrencyUnit poLineCurrency = Monetary.getCurrency(poLine.getCost().getCurrency());
CurrencyConversion conversion = encumbranceRelationsHolders.stream().map(EncumbranceRelationsHolder::getPoLineToFyConversion).findFirst().get();
MonetaryAmount expectedTotal = Money.of(poLine.getCost().getPoLineEstimatedPrice(), poLineCurrency).with(conversion).with(getDefaultRounding());
MonetaryAmount calculatedTotal = encumbranceRelationsHolders.stream().map(EncumbranceRelationsHolder::getFundDistribution).map(fundDistribution -> getDistributionAmount(fundDistribution, expectedTotal, poLineCurrency, conversion)).reduce((money, money2) -> Money.from(MonetaryFunctions.sum(money, money2))).orElseGet(() -> Money.zero(poLineCurrency));
MonetaryAmount remainder = expectedTotal.abs().subtract(calculatedTotal.abs());
int remainderSignum = remainder.signum();
MonetaryAmount smallestUnit = getSmallestUnit(expectedTotal, remainderSignum);
for (ListIterator<EncumbranceRelationsHolder> iterator = getIterator(encumbranceRelationsHolders, remainderSignum); isIteratorHasNext(iterator, remainderSignum); ) {
final EncumbranceRelationsHolder holder = iteratorNext(iterator, remainderSignum);
CurrencyUnit fyCurrency = Monetary.getCurrency(holder.getCurrency());
MonetaryAmount initialAmount = getDistributionAmount(holder.getFundDistribution(), expectedTotal, poLineCurrency, conversion);
if (FundDistribution.DistributionType.PERCENTAGE.equals(holder.getFundDistribution().getDistributionType()) && !remainder.isZero()) {
initialAmount = initialAmount.add(smallestUnit);
remainder = remainder.abs().subtract(smallestUnit.abs()).multiply(remainderSignum);
}
MonetaryAmount expended = Optional.of(holder).map(EncumbranceRelationsHolder::getNewEncumbrance).map(Transaction::getEncumbrance).map(Encumbrance::getAmountExpended).map(aDouble -> Money.of(aDouble, fyCurrency)).orElse(Money.zero(fyCurrency));
MonetaryAmount awaitingPayment = Optional.of(holder).map(EncumbranceRelationsHolder::getNewEncumbrance).map(Transaction::getEncumbrance).map(Encumbrance::getAmountAwaitingPayment).map(aDouble -> Money.of(aDouble, fyCurrency)).orElse(Money.zero(fyCurrency));
MonetaryAmount amount = MonetaryFunctions.max().apply(initialAmount.subtract(expended).subtract(awaitingPayment), Money.zero(fyCurrency));
holder.getNewEncumbrance().setAmount(amount.getNumber().doubleValue());
holder.getNewEncumbrance().getEncumbrance().setInitialAmountEncumbered(initialAmount.getNumber().doubleValue());
}
});
return holders;
}
use of org.folio.models.EncumbranceRelationsHolder in project mod-orders by folio-org.
the class EncumbranceRelationsHoldersBuilderTest method initMocks.
@BeforeEach
public void initMocks() {
MockitoAnnotations.openMocks(this);
order = new CompositePurchaseOrder().withId(UUID.randomUUID().toString()).withReEncumber(true).withOrderType(CompositePurchaseOrder.OrderType.ONGOING).withOngoing(new Ongoing().withIsSubscription(false));
distribution1 = new FundDistribution().withFundId(UUID.randomUUID().toString()).withDistributionType(FundDistribution.DistributionType.PERCENTAGE).withValue(100d).withEncumbrance(UUID.randomUUID().toString());
line1 = new CompositePoLine().withId(UUID.randomUUID().toString()).withCost(new Cost().withCurrency("USD").withListUnitPrice(68d).withQuantityPhysical(1)).withPurchaseOrderId(order.getId()).withFundDistribution(Collections.singletonList(distribution1));
distribution2 = new FundDistribution().withFundId(UUID.randomUUID().toString()).withDistributionType(FundDistribution.DistributionType.PERCENTAGE).withValue(100d).withEncumbrance(UUID.randomUUID().toString());
line2 = new CompositePoLine().withId(UUID.randomUUID().toString()).withCost(new Cost().withCurrency("USD").withListUnitPrice(34.95).withQuantityPhysical(1)).withPurchaseOrderId(order.getId()).withFundDistribution(Collections.singletonList(distribution2));
distribution3 = new FundDistribution().withFundId(UUID.randomUUID().toString()).withDistributionType(FundDistribution.DistributionType.PERCENTAGE).withExpenseClassId(UUID.randomUUID().toString()).withValue(100d).withEncumbrance(UUID.randomUUID().toString());
line3 = new CompositePoLine().withId(UUID.randomUUID().toString()).withCost(new Cost().withCurrency("EUR").withListUnitPrice(24.99).withQuantityPhysical(1)).withPurchaseOrderId(order.getId()).withFundDistribution(Collections.singletonList(distribution3));
order.setCompositePoLines(List.of(line1, line2, line3));
newEncumbrance1 = new Transaction().withFromFundId(distribution1.getFundId()).withSource(PO_LINE).withEncumbrance(new Encumbrance().withOrderType(ONGOING).withReEncumber(true).withOrderStatus(OPEN).withStatus(UNRELEASED).withSubscription(false).withSourcePurchaseOrderId(order.getId()).withSourcePoLineId(line1.getId()));
newEncumbrance2 = new Transaction().withFromFundId(distribution2.getFundId()).withSource(PO_LINE).withEncumbrance(new Encumbrance().withOrderType(ONGOING).withReEncumber(true).withOrderStatus(OPEN).withStatus(UNRELEASED).withSubscription(false).withSourcePurchaseOrderId(order.getId()).withSourcePoLineId(line2.getId()));
newEncumbrance3 = new Transaction().withFromFundId(distribution3.getFundId()).withSource(PO_LINE).withExpenseClassId(distribution3.getExpenseClassId()).withEncumbrance(new Encumbrance().withOrderType(ONGOING).withReEncumber(true).withOrderStatus(OPEN).withStatus(UNRELEASED).withSubscription(false).withSourcePurchaseOrderId(order.getId()).withSourcePoLineId(line3.getId()));
holder1 = new EncumbranceRelationsHolder().withPurchaseOrder(order).withPoLine(line1).withFundDistribution(distribution1).withNewEncumbrance(newEncumbrance1);
holder2 = new EncumbranceRelationsHolder().withPurchaseOrder(order).withPoLine(line2).withFundDistribution(distribution2).withNewEncumbrance(newEncumbrance2);
holder3 = new EncumbranceRelationsHolder().withPurchaseOrder(order).withPoLine(line3).withFundDistribution(distribution3).withNewEncumbrance(newEncumbrance3);
}
Aggregations