Search in sources :

Example 6 with InvoiceWorkflowDataHolder

use of org.folio.models.InvoiceWorkflowDataHolder in project mod-invoice by folio-org.

the class PaymentCreditWorkflowService method createTransactions.

private CompletionStage<Void> createTransactions(List<InvoiceWorkflowDataHolder> holders, RequestContext requestContext) {
    CompletableFuture<Void> future = completedFuture(null);
    for (InvoiceWorkflowDataHolder holder : holders) {
        Transaction tr = holder.getNewTransaction();
        future = future.thenCompose(v -> baseTransactionService.createTransaction(tr, requestContext).thenAccept(t -> {
        }).exceptionally(t -> {
            logger.error("Failed to create transaction for invoice with id - {}", tr.getSourceInvoiceId(), t);
            List<Parameter> parameters = new ArrayList<>();
            parameters.add(new Parameter().withKey("invoiceLineId").withValue(tr.getSourceInvoiceLineId()));
            parameters.add(new Parameter().withKey(FUND_ID).withValue((tr.getTransactionType() == Transaction.TransactionType.PAYMENT) ? tr.getFromFundId() : tr.getToFundId()));
            throw new HttpException(400, TRANSACTION_CREATION_FAILURE.toError().withParameters(parameters));
        }));
    }
    return future;
}
Also used : HelperUtils.convertToDoubleWithRounding(org.folio.invoices.utils.HelperUtils.convertToDoubleWithRounding) CompletableFuture.completedFuture(java.util.concurrent.CompletableFuture.completedFuture) CompletableFuture(java.util.concurrent.CompletableFuture) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) Transaction(org.folio.rest.acq.model.finance.Transaction) FundsDistributionService.distributeFunds(org.folio.services.FundsDistributionService.distributeFunds) ArrayList(java.util.ArrayList) HttpException(org.folio.invoices.rest.exceptions.HttpException) Collectors.toList(java.util.stream.Collectors.toList) HelperUtils.getFundDistributionAmount(org.folio.invoices.utils.HelperUtils.getFundDistributionAmount) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) Logger(org.apache.logging.log4j.Logger) RequestContext(org.folio.rest.core.models.RequestContext) Parameter(org.folio.rest.jaxrs.model.Parameter) LogManager(org.apache.logging.log4j.LogManager) MonetaryAmount(javax.money.MonetaryAmount) TRANSACTION_CREATION_FAILURE(org.folio.invoices.utils.ErrorCodes.TRANSACTION_CREATION_FAILURE) Transaction(org.folio.rest.acq.model.finance.Transaction) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) ArrayList(java.util.ArrayList) Parameter(org.folio.rest.jaxrs.model.Parameter) HttpException(org.folio.invoices.rest.exceptions.HttpException)

Example 7 with InvoiceWorkflowDataHolder

use of org.folio.models.InvoiceWorkflowDataHolder in project mod-invoice by folio-org.

the class PendingPaymentWorkflowService method handlePendingPaymentsCreation.

public CompletableFuture<Void> handlePendingPaymentsCreation(List<InvoiceWorkflowDataHolder> dataHolders, RequestContext requestContext) {
    List<InvoiceWorkflowDataHolder> holders = withNewPendingPayments(dataHolders);
    holderValidator.validate(holders);
    InvoiceTransactionSummary summary = buildInvoiceTransactionsSummary(holders);
    return invoiceTransactionSummaryService.createInvoiceTransactionSummary(summary, requestContext).thenCompose(s -> createPendingPayments(holders, requestContext)).thenCompose(s -> cleanupOldEncumbrances(holders, requestContext));
}
Also used : HelperUtils.convertToDoubleWithRounding(org.folio.invoices.utils.HelperUtils.convertToDoubleWithRounding) CompletableFuture.completedFuture(java.util.concurrent.CompletableFuture.completedFuture) CompletableFuture(java.util.concurrent.CompletableFuture) FolioVertxCompletableFuture(org.folio.completablefuture.FolioVertxCompletableFuture) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) Transaction(org.folio.rest.acq.model.finance.Transaction) HolderValidator(org.folio.services.validator.HolderValidator) FundsDistributionService.distributeFunds(org.folio.services.FundsDistributionService.distributeFunds) ArrayList(java.util.ArrayList) HttpException(org.folio.invoices.rest.exceptions.HttpException) InvoiceTransactionSummary(org.folio.rest.acq.model.finance.InvoiceTransactionSummary) RequestContext(org.folio.rest.core.models.RequestContext) HelperUtils.collectResultsOnSuccess(org.folio.invoices.utils.HelperUtils.collectResultsOnSuccess) PENDING_PAYMENT_ERROR(org.folio.invoices.utils.ErrorCodes.PENDING_PAYMENT_ERROR) InvoiceLine(org.folio.rest.jaxrs.model.InvoiceLine) AwaitingPayment(org.folio.rest.acq.model.finance.AwaitingPayment) FundDistribution(org.folio.rest.jaxrs.model.FundDistribution) Collectors.toList(java.util.stream.Collectors.toList) HelperUtils.getFundDistributionAmount(org.folio.invoices.utils.HelperUtils.getFundDistributionAmount) List(java.util.List) Logger(org.apache.logging.log4j.Logger) Optional(java.util.Optional) LogManager(org.apache.logging.log4j.LogManager) MonetaryAmount(javax.money.MonetaryAmount) Invoice(org.folio.rest.jaxrs.model.Invoice) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) InvoiceTransactionSummary(org.folio.rest.acq.model.finance.InvoiceTransactionSummary)

Example 8 with InvoiceWorkflowDataHolder

use of org.folio.models.InvoiceWorkflowDataHolder in project mod-invoice by folio-org.

the class PendingPaymentWorkflowService method handlePendingPaymentsUpdate.

public CompletableFuture<Void> handlePendingPaymentsUpdate(List<InvoiceWorkflowDataHolder> dataHolders, RequestContext requestContext) {
    List<InvoiceWorkflowDataHolder> holders = withNewPendingPayments(dataHolders);
    holderValidator.validate(holders);
    InvoiceTransactionSummary invoiceTransactionSummary = buildInvoiceTransactionsSummary(holders);
    return invoiceTransactionSummaryService.updateInvoiceTransactionSummary(invoiceTransactionSummary, requestContext).thenCompose(aVoid -> updateTransactions(holders, requestContext));
}
Also used : InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) InvoiceTransactionSummary(org.folio.rest.acq.model.finance.InvoiceTransactionSummary)

Example 9 with InvoiceWorkflowDataHolder

use of org.folio.models.InvoiceWorkflowDataHolder in project mod-invoice by folio-org.

the class PendingPaymentWorkflowService method createPendingPayments.

private CompletableFuture<Void> createPendingPayments(List<InvoiceWorkflowDataHolder> holders, RequestContext requestContext) {
    CompletableFuture<Void> future = completedFuture(null);
    for (InvoiceWorkflowDataHolder holder : holders) {
        Transaction pendingPayment = holder.getNewTransaction();
        future = future.thenCompose(v -> baseTransactionService.createTransaction(pendingPayment, requestContext).thenAccept(t -> {
        }).exceptionally(t -> {
            logger.error("Failed to create pending payment with id {}", pendingPayment.getId(), t);
            throw new HttpException(400, PENDING_PAYMENT_ERROR.toError());
        }));
    }
    return future;
}
Also used : HelperUtils.convertToDoubleWithRounding(org.folio.invoices.utils.HelperUtils.convertToDoubleWithRounding) CompletableFuture.completedFuture(java.util.concurrent.CompletableFuture.completedFuture) CompletableFuture(java.util.concurrent.CompletableFuture) FolioVertxCompletableFuture(org.folio.completablefuture.FolioVertxCompletableFuture) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) Transaction(org.folio.rest.acq.model.finance.Transaction) HolderValidator(org.folio.services.validator.HolderValidator) FundsDistributionService.distributeFunds(org.folio.services.FundsDistributionService.distributeFunds) ArrayList(java.util.ArrayList) HttpException(org.folio.invoices.rest.exceptions.HttpException) InvoiceTransactionSummary(org.folio.rest.acq.model.finance.InvoiceTransactionSummary) RequestContext(org.folio.rest.core.models.RequestContext) HelperUtils.collectResultsOnSuccess(org.folio.invoices.utils.HelperUtils.collectResultsOnSuccess) PENDING_PAYMENT_ERROR(org.folio.invoices.utils.ErrorCodes.PENDING_PAYMENT_ERROR) InvoiceLine(org.folio.rest.jaxrs.model.InvoiceLine) AwaitingPayment(org.folio.rest.acq.model.finance.AwaitingPayment) FundDistribution(org.folio.rest.jaxrs.model.FundDistribution) Collectors.toList(java.util.stream.Collectors.toList) HelperUtils.getFundDistributionAmount(org.folio.invoices.utils.HelperUtils.getFundDistributionAmount) List(java.util.List) Logger(org.apache.logging.log4j.Logger) Optional(java.util.Optional) LogManager(org.apache.logging.log4j.LogManager) MonetaryAmount(javax.money.MonetaryAmount) Invoice(org.folio.rest.jaxrs.model.Invoice) Transaction(org.folio.rest.acq.model.finance.Transaction) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) HttpException(org.folio.invoices.rest.exceptions.HttpException)

Example 10 with InvoiceWorkflowDataHolder

use of org.folio.models.InvoiceWorkflowDataHolder in project mod-invoice by folio-org.

the class PendingPaymentWorkflowServiceTest method updatePendingPayments.

@Test
void updatePendingPayments() {
    String fiscalYearId = UUID.randomUUID().toString();
    String fundId = UUID.randomUUID().toString();
    String invoiceId = UUID.randomUUID().toString();
    String invoiceLineId = UUID.randomUUID().toString();
    double exchangeRate = 1.3;
    FiscalYear fiscalYear = new FiscalYear().withId(fiscalYearId).withCurrency("USD");
    Transaction existingInvoiceLineTransaction = new Transaction().withId(UUID.randomUUID().toString()).withCurrency("USD").withFromFundId(fundId).withFiscalYearId(fiscalYearId).withSourceInvoiceId(invoiceId).withSourceInvoiceLineId(invoiceLineId).withAmount(50d);
    Transaction existingInvoiceTransaction = new Transaction().withId(UUID.randomUUID().toString()).withCurrency("USD").withFromFundId(fundId).withFiscalYearId(fiscalYearId).withSourceInvoiceId(invoiceId).withAmount(10d);
    FundDistribution invoiceFundDistribution = new FundDistribution().withDistributionType(FundDistribution.DistributionType.AMOUNT).withFundId(fundId).withValue(30.5);
    Adjustment adjustment = new Adjustment().withFundDistributions(Collections.singletonList(invoiceFundDistribution)).withProrate(Adjustment.Prorate.NOT_PRORATED).withValue(30.5).withType(Adjustment.Type.AMOUNT);
    Invoice invoice = new Invoice().withAdjustments(Collections.singletonList(adjustment)).withId(invoiceId).withSubTotal(50d).withExchangeRate(exchangeRate).withCurrency("EUR");
    InvoiceLine invoiceLine = new InvoiceLine().withSubTotal(60d).withTotal(60d).withId(invoiceLineId);
    FundDistribution invoiceLineFundDistribution = new FundDistribution().withDistributionType(FundDistribution.DistributionType.AMOUNT).withFundId(fundId).withValue(60d);
    invoiceLine.getFundDistributions().add(invoiceLineFundDistribution);
    ConversionQuery conversionQuery = ConversionQueryBuilder.of().setTermCurrency(DEFAULT_SYSTEM_CURRENCY).set(RATE_KEY, exchangeRate).build();
    ExchangeRateProvider exchangeRateProvider = new ExchangeRateProviderResolver().resolve(conversionQuery, new RequestContext(Vertx.currentContext(), Collections.emptyMap()));
    CurrencyConversion conversion = exchangeRateProvider.getCurrencyConversion(conversionQuery);
    List<InvoiceWorkflowDataHolder> holders = new ArrayList<>();
    InvoiceWorkflowDataHolder holder1 = new InvoiceWorkflowDataHolder().withInvoice(invoice).withInvoiceLine(invoiceLine).withFundDistribution(invoiceLineFundDistribution).withFiscalYear(fiscalYear).withExistingTransaction(existingInvoiceLineTransaction).withConversion(conversion);
    InvoiceWorkflowDataHolder holder2 = new InvoiceWorkflowDataHolder().withInvoice(invoice).withAdjustment(adjustment).withFundDistribution(invoiceFundDistribution).withFiscalYear(fiscalYear).withExistingTransaction(existingInvoiceTransaction).withConversion(conversion);
    holders.add(holder1);
    holders.add(holder2);
    doNothing().when(fundAvailabilityValidator).validate(anyList());
    when(invoiceTransactionSummaryService.updateInvoiceTransactionSummary(any(), any())).thenReturn(CompletableFuture.completedFuture(null));
    when(baseTransactionService.updateTransaction(any(), any())).thenReturn(CompletableFuture.completedFuture(null));
    when(requestContext.getContext()).thenReturn(Vertx.vertx().getOrCreateContext());
    pendingPaymentWorkflowService.handlePendingPaymentsUpdate(holders, requestContext);
    ArgumentCaptor<List<InvoiceWorkflowDataHolder>> argumentCaptor = ArgumentCaptor.forClass(List.class);
    verify(fundAvailabilityValidator).validate(argumentCaptor.capture());
    assertThat(argumentCaptor.getValue(), hasSize(2));
    List<InvoiceWorkflowDataHolder> holdersWithNewTransactions = argumentCaptor.getValue();
    Transaction newInvoiceTransaction = holdersWithNewTransactions.stream().map(InvoiceWorkflowDataHolder::getNewTransaction).filter(transaction -> Objects.isNull(transaction.getSourceInvoiceLineId())).findFirst().get();
    Transaction newInvoiceLineTransaction = holdersWithNewTransactions.stream().map(InvoiceWorkflowDataHolder::getNewTransaction).filter(transaction -> Objects.nonNull(transaction.getSourceInvoiceLineId())).findFirst().get();
    double expectedInvoiceLineTransactionAmount = BigDecimal.valueOf(60).multiply(BigDecimal.valueOf(exchangeRate)).doubleValue();
    assertEquals(expectedInvoiceLineTransactionAmount, newInvoiceLineTransaction.getAmount());
    assertEquals(fundId, newInvoiceLineTransaction.getFromFundId());
    assertEquals(fiscalYearId, newInvoiceLineTransaction.getFiscalYearId());
    assertEquals(invoiceId, newInvoiceLineTransaction.getSourceInvoiceId());
    assertEquals(invoiceLineId, newInvoiceLineTransaction.getSourceInvoiceLineId());
    assertEquals(Transaction.TransactionType.PENDING_PAYMENT, newInvoiceLineTransaction.getTransactionType());
    assertEquals(Transaction.Source.INVOICE, newInvoiceLineTransaction.getSource());
    double expectedInvoiceTransactionAmount = BigDecimal.valueOf(30.5).multiply(BigDecimal.valueOf(exchangeRate)).doubleValue();
    assertEquals(expectedInvoiceTransactionAmount, newInvoiceTransaction.getAmount());
    assertEquals(fundId, newInvoiceTransaction.getFromFundId());
    assertEquals(fiscalYearId, newInvoiceTransaction.getFiscalYearId());
    assertEquals(invoiceId, newInvoiceTransaction.getSourceInvoiceId());
    assertNull(newInvoiceTransaction.getSourceInvoiceLineId());
    assertEquals(Transaction.TransactionType.PENDING_PAYMENT, newInvoiceTransaction.getTransactionType());
    assertEquals(Transaction.Source.INVOICE, newInvoiceTransaction.getSource());
    InvoiceTransactionSummary expectedSummary = new InvoiceTransactionSummary().withId(invoiceId).withNumPaymentsCredits(2).withNumPendingPayments(2);
    verify(invoiceTransactionSummaryService).updateInvoiceTransactionSummary(eq(expectedSummary), eq(requestContext));
    ArgumentCaptor<Transaction> transactionArgumentCaptor = ArgumentCaptor.forClass(Transaction.class);
    verify(baseTransactionService, times(2)).updateTransaction(transactionArgumentCaptor.capture(), eq(requestContext));
    Transaction updateArgumentInvoiceTransaction = transactionArgumentCaptor.getAllValues().stream().filter(transaction -> Objects.isNull(transaction.getSourceInvoiceLineId())).findFirst().get();
    assertEquals(existingInvoiceTransaction.getId(), updateArgumentInvoiceTransaction.getId());
    assertEquals(expectedInvoiceTransactionAmount, updateArgumentInvoiceTransaction.getAmount());
    Transaction updateArgumentInvoiceLineTransaction = transactionArgumentCaptor.getAllValues().stream().filter(transaction -> Objects.nonNull(transaction.getSourceInvoiceLineId())).findFirst().get();
    assertEquals(existingInvoiceLineTransaction.getId(), updateArgumentInvoiceLineTransaction.getId());
    assertEquals(expectedInvoiceLineTransactionAmount, updateArgumentInvoiceLineTransaction.getAmount());
}
Also used : FiscalYear(org.folio.rest.acq.model.finance.FiscalYear) Invoice(org.folio.rest.jaxrs.model.Invoice) ExchangeRateProvider(javax.money.convert.ExchangeRateProvider) Adjustment(org.folio.rest.jaxrs.model.Adjustment) InvoiceLine(org.folio.rest.jaxrs.model.InvoiceLine) ArrayList(java.util.ArrayList) CurrencyConversion(javax.money.convert.CurrencyConversion) ManualCurrencyConversion(org.folio.services.exchange.ManualCurrencyConversion) ExchangeRateProviderResolver(org.folio.services.exchange.ExchangeRateProviderResolver) FundDistribution(org.folio.rest.jaxrs.model.FundDistribution) ConversionQuery(javax.money.convert.ConversionQuery) Transaction(org.folio.rest.acq.model.finance.Transaction) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) ArrayList(java.util.ArrayList) ArgumentMatchers.anyList(org.mockito.ArgumentMatchers.anyList) List(java.util.List) RequestContext(org.folio.rest.core.models.RequestContext) InvoiceTransactionSummary(org.folio.rest.acq.model.finance.InvoiceTransactionSummary) Test(org.junit.jupiter.api.Test)

Aggregations

InvoiceWorkflowDataHolder (org.folio.models.InvoiceWorkflowDataHolder)17 ArrayList (java.util.ArrayList)12 HttpException (org.folio.invoices.rest.exceptions.HttpException)11 Budget (org.folio.rest.acq.model.finance.Budget)11 Fund (org.folio.rest.acq.model.finance.Fund)11 Transaction (org.folio.rest.acq.model.finance.Transaction)11 List (java.util.List)10 Test (org.junit.jupiter.api.Test)9 MonetaryAmount (javax.money.MonetaryAmount)7 FiscalYear (org.folio.rest.acq.model.finance.FiscalYear)7 Optional (java.util.Optional)6 Collectors.toList (java.util.stream.Collectors.toList)6 RequestContext (org.folio.rest.core.models.RequestContext)6 InvoiceLine (org.folio.rest.jaxrs.model.InvoiceLine)6 Collections (java.util.Collections)5 CompletableFuture (java.util.concurrent.CompletableFuture)5 Error (org.folio.rest.jaxrs.model.Error)5 FundDistribution (org.folio.rest.jaxrs.model.FundDistribution)5 Invoice (org.folio.rest.jaxrs.model.Invoice)5 Map (java.util.Map)4