use of org.folio.models.ReEncumbranceHolder in project mod-orders by folio-org.
the class OrderReEncumberService method adjustPoLineCost.
private void adjustPoLineCost(CompositePoLine poLine, List<ReEncumbranceHolder> holders) {
MonetaryAmount poLineEstimatedPriceAfterRollover = Money.zero(Monetary.getCurrency(poLine.getCost().getCurrency()));
for (ReEncumbranceHolder holder : holders) {
if (holder.getEncumbranceRollover() != null && holder.getPoLineToFyConversion() != null) {
CurrencyConversion fyToPoLineConversion = holder.getFyToPoLineConversion();
Transaction fromEncumbrance = holder.getPreviousFyEncumbrance();
EncumbranceRollover encumbranceRollover = holder.getEncumbranceRollover();
MonetaryOperator percentOperator = MonetaryOperators.percent(encumbranceRollover.getIncreaseBy());
MonetaryAmount amount;
if (encumbranceRollover.getBasedOn() == EncumbranceRollover.BasedOn.REMAINING) {
amount = Money.of(fromEncumbrance.getAmount(), fromEncumbrance.getCurrency());
} else if (encumbranceRollover.getBasedOn() == EncumbranceRollover.BasedOn.EXPENDED) {
amount = Money.of(fromEncumbrance.getEncumbrance().getAmountExpended(), fromEncumbrance.getCurrency());
} else {
amount = Money.of(fromEncumbrance.getEncumbrance().getInitialAmountEncumbered(), fromEncumbrance.getCurrency());
}
amount = amount.add(amount.with(percentOperator)).with(fyToPoLineConversion);
poLineEstimatedPriceAfterRollover = poLineEstimatedPriceAfterRollover.add(amount);
}
}
MonetaryAmount poLineEstimatedPriceBeforeRollover = HelperUtils.calculateEstimatedPrice(poLine.getCost());
poLine.getCost().setFyroAdjustmentAmount(poLineEstimatedPriceAfterRollover.subtract(poLineEstimatedPriceBeforeRollover).getNumber().doubleValue());
for (ReEncumbranceHolder holder : holders) {
FundDistribution fundDistr = holder.getFundDistribution();
MonetaryAmount newFundAmount;
if (fundDistr.getDistributionType().equals(FundDistribution.DistributionType.AMOUNT)) {
MonetaryAmount fdAmount = Money.of(fundDistr.getValue(), poLine.getCost().getCurrency());
newFundAmount = fdAmount.divide(poLineEstimatedPriceBeforeRollover.getNumber().doubleValue()).multiply(poLineEstimatedPriceAfterRollover.getNumber().doubleValue());
fundDistr.setValue(newFundAmount.getNumber().doubleValue());
}
}
}
use of org.folio.models.ReEncumbranceHolder in project mod-orders by folio-org.
the class OrderReEncumberServiceTest method shouldThrowHttpExceptionWithRolloverNotCompletedCodeWhenAtLeastOneRolloverHasProgressNotStartedOrInProgress.
@Test
void shouldThrowHttpExceptionWithRolloverNotCompletedCodeWhenAtLeastOneRolloverHasProgressNotStartedOrInProgress() {
String orderId = UUID.randomUUID().toString();
String fundId1 = UUID.randomUUID().toString();
String fundId2 = UUID.randomUUID().toString();
String fundId3 = UUID.randomUUID().toString();
String ledgerId1 = UUID.randomUUID().toString();
String ledgerId2 = UUID.randomUUID().toString();
String ledgerId3 = UUID.randomUUID().toString();
String rolloverId1 = UUID.randomUUID().toString();
String rolloverId2 = UUID.randomUUID().toString();
String rolloverId3 = UUID.randomUUID().toString();
ReEncumbranceHolder holder1 = new ReEncumbranceHolder().withLedgerId(ledgerId1).withRollover(new LedgerFiscalYearRollover().withId(rolloverId1).withLedgerId(ledgerId1)).withFundDistribution(new FundDistribution().withFundId(fundId1));
ReEncumbranceHolder holder2 = new ReEncumbranceHolder().withLedgerId(ledgerId2).withRollover(new LedgerFiscalYearRollover().withId(rolloverId2).withLedgerId(ledgerId2)).withFundDistribution(new FundDistribution().withFundId(fundId2));
ReEncumbranceHolder holder3 = new ReEncumbranceHolder().withLedgerId(ledgerId3).withRollover(new LedgerFiscalYearRollover().withId(rolloverId3).withLedgerId(ledgerId3)).withFundDistribution(new FundDistribution().withFundId(fundId3));
List<ReEncumbranceHolder> holders = List.of(holder1, holder2, holder3);
when(purchaseOrderStorageService.getCompositeOrderById(anyString(), any())).thenReturn(completedFuture(new CompositePurchaseOrder()));
when(spyReEncumbranceHoldersBuilder.buildReEncumbranceHoldersWithOrdersData(any())).thenReturn(holders);
when(spyReEncumbranceHoldersBuilder.withFundsData(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withLedgersData(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withCurrentFiscalYearData(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withRollovers(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withEncumbranceRollover(any())).thenReturn(holders);
when(rolloverRetrieveService.getRolloversProgress(eq(rolloverId1), any())).thenReturn(completedFuture(Collections.singletonList(notStarted)));
when(rolloverRetrieveService.getRolloversProgress(eq(rolloverId2), any())).thenReturn(completedFuture(Collections.singletonList(inProgress)));
when(rolloverRetrieveService.getRolloversProgress(eq(rolloverId3), any())).thenReturn(completedFuture(Collections.singletonList(success)));
CompletionException completionException = assertThrows(CompletionException.class, () -> orderReEncumberService.reEncumber(orderId, requestContext).join());
assertNotNull(completionException.getCause());
assertThat(completionException.getCause(), instanceOf(HttpException.class));
HttpException e = (HttpException) completionException.getCause();
assertEquals(ROLLOVER_NOT_COMPLETED.getCode(), e.getError().getCode());
assertThat(e.getError().getParameters(), hasSize(1));
Parameter parameter = e.getError().getParameters().get(0);
assertThat(parameter.getValue(), containsString(ledgerId1));
assertThat(parameter.getValue(), containsString(ledgerId2));
}
use of org.folio.models.ReEncumbranceHolder in project mod-orders by folio-org.
the class OrderReEncumberServiceTest method shouldVerifyFYROAdjustmentAndFundDistributionValuesWhenMixedFunds.
@Test
void shouldVerifyFYROAdjustmentAndFundDistributionValuesWhenMixedFunds() {
String ledgerId = UUID.randomUUID().toString();
String fromFyId = UUID.randomUUID().toString();
String toFyId = UUID.randomUUID().toString();
String orderId = UUID.randomUUID().toString();
String fund1Id = UUID.randomUUID().toString();
String fund2Id = UUID.randomUUID().toString();
String rolloverId = UUID.randomUUID().toString();
Ledger notRestrictedLedger = new Ledger().withId(ledgerId).withRestrictEncumbrance(false);
double exchangeRate = 1.1d;
Fund fund1 = new Fund().withId(fund1Id).withLedgerId(ledgerId);
Fund fund2 = new Fund().withId(fund2Id).withLedgerId(ledgerId);
Budget notRestrictedBudget1 = new Budget().withId(UUID.randomUUID().toString()).withFundId(fund1Id);
EncumbranceRollover encumbranceRollover = new EncumbranceRollover().withBasedOn(EncumbranceRollover.BasedOn.EXPENDED).withOrderType(EncumbranceRollover.OrderType.ONE_TIME).withIncreaseBy(10d);
LedgerFiscalYearRollover rollover = new LedgerFiscalYearRollover().withId(rolloverId).withLedgerId(ledgerId).withFromFiscalYearId(fromFyId).withToFiscalYearId(toFyId).withEncumbrancesRollover(Collections.singletonList(encumbranceRollover));
CompositePurchaseOrder compPO = new CompositePurchaseOrder().withId(orderId).withOrderType(CompositePurchaseOrder.OrderType.ONE_TIME);
Cost cost1 = new Cost().withListUnitPrice(120d).withQuantityPhysical(1).withExchangeRate(exchangeRate).withCurrency("EUR").withPoLineEstimatedPrice(120d);
Transaction fromEncumbrance1 = new Transaction().withEncumbrance(new Encumbrance().withSourcePurchaseOrderId(orderId).withInitialAmountEncumbered(60d).withAmountExpended(40d)).withAmount(20d).withFiscalYearId(fromFyId).withFromFundId(fund1Id).withId(UUID.randomUUID().toString()).withCurrency("USD");
Transaction fromEncumbrance2 = new Transaction().withEncumbrance(new Encumbrance().withSourcePurchaseOrderId(orderId).withInitialAmountEncumbered(60d).withAmountExpended(30d)).withAmount(30d).withFiscalYearId(fromFyId).withFromFundId(fund2Id).withId(UUID.randomUUID().toString()).withCurrency("USD");
Transaction toEncumbrance1 = new Transaction().withEncumbrance(new Encumbrance().withStatus(Encumbrance.Status.UNRELEASED).withAmountAwaitingPayment(0d).withSourcePurchaseOrderId(orderId).withInitialAmountEncumbered(60d).withAmountExpended(0d)).withAmount(40d).withFiscalYearId(fromFyId).withFromFundId(fund1Id).withId(UUID.randomUUID().toString()).withCurrency("USD");
Transaction toEncumbrance2 = new Transaction().withEncumbrance(new Encumbrance().withStatus(Encumbrance.Status.UNRELEASED).withAmountAwaitingPayment(0d).withSourcePurchaseOrderId(orderId).withInitialAmountEncumbered(60d).withAmountExpended(0d)).withAmount(30d).withFiscalYearId(fromFyId).withFromFundId(fund2Id).withId(UUID.randomUUID().toString()).withCurrency("USD");
TransactionCollection toTransactionCollection = new TransactionCollection().withTransactions(Collections.EMPTY_LIST).withTotalRecords(0);
FundDistribution fundDistribution1 = new FundDistribution().withDistributionType(FundDistribution.DistributionType.PERCENTAGE).withValue(50d).withEncumbrance(fromEncumbrance1.getId()).withFundId(fund1Id);
FundDistribution fundDistribution2 = new FundDistribution().withDistributionType(FundDistribution.DistributionType.AMOUNT).withValue(60d).withEncumbrance(fromEncumbrance2.getId()).withFundId(fund2Id);
CompositePoLine line1 = new CompositePoLine().withId(UUID.randomUUID().toString()).withCost(cost1).withFundDistribution(List.of(fundDistribution1, fundDistribution2));
ConversionQuery conversionPoLineToFyQuery = ConversionQueryBuilder.of().setBaseCurrency("EUR").setTermCurrency("USD").set(ExchangeRateProviderResolver.RATE_KEY, exchangeRate).build();
ConversionQuery conversionFyToPoLineQuery = ConversionQueryBuilder.of().setBaseCurrency("USD").setTermCurrency("EUR").set(ExchangeRateProviderResolver.RATE_KEY, exchangeRate).build();
ReEncumbranceHolder holder1 = new ReEncumbranceHolder().withPurchaseOrder(compPO).withRollover(rollover).withPoLine(line1).withFundDistribution(fundDistribution1).withLedgerId(ledgerId).withRestrictEncumbrances(notRestrictedLedger.getRestrictEncumbrance()).withBudget(notRestrictedBudget1).withEncumbranceRollover(encumbranceRollover).withPreviousFyEncumbrance(fromEncumbrance1).withNewEncumbrance(toEncumbrance1).withPoLineToFyConversion(exchangeRateProvider.getCurrencyConversion(conversionPoLineToFyQuery)).withFyToPoLineConversion(exchangeRateProvider.getCurrencyConversion(conversionFyToPoLineQuery));
ReEncumbranceHolder holder2 = new ReEncumbranceHolder().withPurchaseOrder(compPO).withRollover(rollover).withPoLine(line1).withFundDistribution(fundDistribution2).withLedgerId(ledgerId).withRestrictEncumbrances(notRestrictedLedger.getRestrictEncumbrance()).withBudget(notRestrictedBudget1).withEncumbranceRollover(encumbranceRollover).withNewEncumbrance(toEncumbrance2).withPreviousFyEncumbrance(fromEncumbrance2).withPoLineToFyConversion(exchangeRateProvider.getCurrencyConversion(conversionPoLineToFyQuery)).withFyToPoLineConversion(exchangeRateProvider.getCurrencyConversion(conversionFyToPoLineQuery));
List<ReEncumbranceHolder> holders = Arrays.asList(holder1, holder2);
when(purchaseOrderStorageService.getCompositeOrderById(anyString(), eq(requestContext))).thenAnswer(invocation -> completedFuture(new CompositePurchaseOrder().withId(invocation.getArgument(0))));
doReturn(holders).when(spyReEncumbranceHoldersBuilder).buildReEncumbranceHoldersWithOrdersData(any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withFundsData(any(), any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withLedgersData(any(), any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withCurrentFiscalYearData(any(), any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withRollovers(any(), any());
doReturn(holders).when(spyReEncumbranceHoldersBuilder).withEncumbranceRollover(any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withBudgets(any(), any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withConversions(any(), any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withPreviousFyEncumbrances(any(), any());
doReturn(completedFuture(holders)).when(spyReEncumbranceHoldersBuilder).withToEncumbrances(any(), any());
doNothing().when(budgetRestrictionService).checkEncumbranceRestrictions(anyList());
when(rolloverErrorService.getLedgerFyRolloverErrors(anyString(), any())).thenReturn(completedFuture(new LedgerFiscalYearRolloverErrorCollection()));
when(rolloverErrorService.deleteRolloverErrors(anyList(), any())).thenReturn(completedFuture(null));
when(purchaseOrderLineService.saveOrderLines(anyList(), any())).thenReturn(completedFuture(null));
when(rolloverRetrieveService.getRolloversProgress(eq(rolloverId), any())).thenReturn(completedFuture(Collections.singletonList(success)));
when(exchangeRateProviderResolver.resolve(conversionPoLineToFyQuery, requestContext)).thenReturn(exchangeRateProvider);
when(exchangeRateProviderResolver.resolve(conversionFyToPoLineQuery, requestContext)).thenReturn(exchangeRateProvider);
when(transactionService.getTransactions(anyString(), eq(0), eq(Integer.MAX_VALUE), eq(requestContext))).thenReturn(completedFuture(toTransactionCollection));
when(transactionSummaryService.updateOrderTransactionSummary(eq(orderId), anyInt(), eq(requestContext))).thenReturn(completedFuture(null));
when(transactionService.createTransaction(any(), eq(requestContext))).thenReturn(completedFuture(new Transaction()));
// When
CompletableFuture<Void> future = orderReEncumberService.reEncumber(UUID.randomUUID().toString(), requestContext);
future.join();
// Then
assertFalse(future.isCompletedExceptionally());
assertEquals(-35.3d, line1.getCost().getFyroAdjustmentAmount());
assertEquals(50d, line1.getFundDistribution().get(0).getValue());
assertEquals(42.35d, line1.getFundDistribution().get(1).getValue());
}
use of org.folio.models.ReEncumbranceHolder in project mod-orders by folio-org.
the class OrderReEncumberServiceTest method shouldThrowHttpExceptionWithRolloverNotCompletedCodeWhenAtLeastOneRolloverIsMissing.
@Test
void shouldThrowHttpExceptionWithRolloverNotCompletedCodeWhenAtLeastOneRolloverIsMissing() {
String orderId = UUID.randomUUID().toString();
String fundId1 = UUID.randomUUID().toString();
String fundId2 = UUID.randomUUID().toString();
String fundId3 = UUID.randomUUID().toString();
String ledgerId1 = UUID.randomUUID().toString();
String ledgerId2 = UUID.randomUUID().toString();
String ledgerId3 = UUID.randomUUID().toString();
String rolloverId1 = UUID.randomUUID().toString();
String rolloverId2 = UUID.randomUUID().toString();
ReEncumbranceHolder holder1 = new ReEncumbranceHolder().withLedgerId(ledgerId1).withRollover(new LedgerFiscalYearRollover().withId(rolloverId1).withLedgerId(ledgerId1)).withFundDistribution(new FundDistribution().withFundId(fundId1));
ReEncumbranceHolder holder2 = new ReEncumbranceHolder().withLedgerId(ledgerId2).withRollover(new LedgerFiscalYearRollover().withId(rolloverId2).withLedgerId(ledgerId2)).withFundDistribution(new FundDistribution().withFundId(fundId2));
ReEncumbranceHolder holder3 = new ReEncumbranceHolder().withLedgerId(ledgerId3).withFundDistribution(new FundDistribution().withFundId(fundId3));
List<ReEncumbranceHolder> holders = List.of(holder1, holder2, holder3);
when(purchaseOrderStorageService.getCompositeOrderById(anyString(), any())).thenReturn(completedFuture(new CompositePurchaseOrder()));
when(spyReEncumbranceHoldersBuilder.buildReEncumbranceHoldersWithOrdersData(any())).thenReturn(holders);
when(spyReEncumbranceHoldersBuilder.withFundsData(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withLedgersData(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withCurrentFiscalYearData(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withRollovers(any(), any())).thenReturn(completedFuture(holders));
when(spyReEncumbranceHoldersBuilder.withEncumbranceRollover(any())).thenReturn(holders);
when(rolloverRetrieveService.getRolloversProgress(eq(rolloverId1), any())).thenReturn(completedFuture(Collections.singletonList(success)));
when(rolloverRetrieveService.getRolloversProgress(eq(rolloverId2), any())).thenReturn(completedFuture(Collections.singletonList(error)));
CompletionException completionException = assertThrows(CompletionException.class, () -> orderReEncumberService.reEncumber(orderId, requestContext).join());
assertNotNull(completionException.getCause());
assertThat(completionException.getCause(), instanceOf(HttpException.class));
HttpException e = (HttpException) completionException.getCause();
assertEquals(ROLLOVER_NOT_COMPLETED.getCode(), e.getError().getCode());
assertEquals(e.getError().getParameters(), Collections.singletonList(new Parameter().withKey("ledgerIds").withValue(ledgerId3)));
}
use of org.folio.models.ReEncumbranceHolder in project mod-orders by folio-org.
the class ReEncumbranceHoldersBuilderTest method shouldPopulateReEncumbranceHoldersWithConversionWhenHoldersContainsCurrency.
@Test
void shouldPopulateReEncumbranceHoldersWithConversionWhenHoldersContainsCurrency() {
FiscalYear fiscalYear = new FiscalYear().withCurrency("USD");
CompositePoLine line1 = new CompositePoLine().withCost(new Cost().withCurrency("EUR"));
CompositePoLine line2 = new CompositePoLine().withCost(new Cost().withCurrency("EUR"));
double exchangeEurToUsdRate = 1.1d;
ReEncumbranceHolder holder1 = new ReEncumbranceHolder().withCurrency(fiscalYear.getCurrency()).withPoLine(line1);
ReEncumbranceHolder holder2 = new ReEncumbranceHolder().withCurrency(fiscalYear.getCurrency()).withPoLine(line2);
CurrencyConversion poLineToFyConversion = mock(ManualCurrencyConversion.class, withSettings().name("poLineToFyConversion"));
CurrencyConversion poFyToPoLineConversion = mock(ManualCurrencyConversion.class, withSettings().name("poFyToPoLineConversion"));
ExchangeRate exchangeRate = mock(ExchangeRate.class);
List<ReEncumbranceHolder> holders = Arrays.asList(holder1, holder2);
when(exchangeRateProviderResolver.resolve(any(), any())).thenReturn(exchangeRateProvider);
when(exchangeRateProvider.getCurrencyConversion(any(ConversionQuery.class))).thenReturn(poLineToFyConversion, poFyToPoLineConversion);
when(exchangeRate.getFactor()).thenReturn(new DefaultNumberValue(exchangeEurToUsdRate));
when(poLineToFyConversion.getCurrency()).thenReturn(Monetary.getCurrency("EUR"));
when(poLineToFyConversion.getExchangeRate(any())).thenReturn(exchangeRate);
when(poFyToPoLineConversion.getCurrency()).thenReturn(Monetary.getCurrency("USD"));
when(requestContext.getContext()).thenReturn(Vertx.vertx().getOrCreateContext());
List<ReEncumbranceHolder> resultHolders = reEncumbranceHoldersBuilder.withConversions(holders, requestContext).join();
assertEquals(resultHolders.get(0).getPoLineToFyConversion().getCurrency(), poLineToFyConversion.getCurrency());
assertEquals(resultHolders.get(1).getPoLineToFyConversion().getCurrency(), poLineToFyConversion.getCurrency());
assertEquals(resultHolders.get(0).getFyToPoLineConversion().getCurrency(), poFyToPoLineConversion.getCurrency());
assertEquals(resultHolders.get(1).getFyToPoLineConversion().getCurrency(), poFyToPoLineConversion.getCurrency());
}
Aggregations