Search in sources :

Example 16 with InvoiceWorkflowDataHolder

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

the class FundAvailabilityHolderValidatorTest method shouldCountAdjustmentsFundDistributionsDuringBudgetRemainingAmountValidation.

@Test
void shouldCountAdjustmentsFundDistributionsDuringBudgetRemainingAmountValidation() {
    String fiscalYearId = UUID.randomUUID().toString();
    String fundId = UUID.randomUUID().toString();
    String budgetId = UUID.randomUUID().toString();
    String ledgerId = UUID.randomUUID().toString();
    FiscalYear fiscalYear = new FiscalYear().withCurrency("USD").withId(fiscalYearId);
    Fund fund = new Fund().withId(fundId).withName("TestFund").withLedgerId(ledgerId).withCode("FC").withFundStatus(Fund.FundStatus.ACTIVE);
    Budget budget = new Budget().withId(budgetId).withFiscalYearId(fiscalYearId).withFundId(fundId).withAllocated(260d).withTotalFunding(260d).withAvailable(210d).withUnavailable(50d).withAwaitingPayment(50d).withAllowableExpenditure(100d);
    List<InvoiceWorkflowDataHolder> holders = new ArrayList<>();
    Transaction adjustmentPendingPayment = new Transaction().withAmount(20d).withCurrency("USD");
    Transaction linePendingPayment = new Transaction().withAmount(200d).withCurrency("USD");
    InvoiceWorkflowDataHolder holder1 = new InvoiceWorkflowDataHolder().withFund(fund).withBudget(budget).withRestrictExpenditures(true).withFiscalYear(fiscalYear).withNewTransaction(linePendingPayment);
    InvoiceWorkflowDataHolder holder2 = new InvoiceWorkflowDataHolder().withFund(fund).withBudget(budget).withRestrictExpenditures(true).withFiscalYear(fiscalYear).withNewTransaction(adjustmentPendingPayment);
    holders.add(holder1);
    holders.add(holder2);
    HttpException httpException = assertThrows(HttpException.class, () -> fundAvailabilityValidator.validate(holders));
    assertEquals(422, httpException.getCode());
    Error error = httpException.getErrors().getErrors().get(0);
    assertEquals(FUND_CANNOT_BE_PAID.getCode(), error.getCode());
    assertEquals(Collections.singletonList("FC").toString(), error.getParameters().get(0).getValue());
}
Also used : FiscalYear(org.folio.rest.acq.model.finance.FiscalYear) Fund(org.folio.rest.acq.model.finance.Fund) Transaction(org.folio.rest.acq.model.finance.Transaction) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) ArrayList(java.util.ArrayList) Error(org.folio.rest.jaxrs.model.Error) Budget(org.folio.rest.acq.model.finance.Budget) HttpException(org.folio.invoices.rest.exceptions.HttpException) Test(org.junit.jupiter.api.Test)

Example 17 with InvoiceWorkflowDataHolder

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

the class FundsDistributionService method distributeFunds.

public static <T extends InvoiceWorkflowDataHolder> List<T> distributeFunds(List<T> holders) {
    Map<InvoiceLine, List<InvoiceWorkflowDataHolder>> lineHoldersMap = holders.stream().filter(holder -> Objects.nonNull(holder.getInvoiceLine())).collect(Collectors.groupingBy(InvoiceWorkflowDataHolder::getInvoiceLine));
    lineHoldersMap.forEach((invoiceLine, invoiceWorkflowDataHolder) -> {
        CurrencyUnit invoiceCurrency = Monetary.getCurrency(holders.get(0).getInvoiceCurrency());
        CurrencyConversion conversion = invoiceWorkflowDataHolder.stream().map(InvoiceWorkflowDataHolder::getConversion).findFirst().get();
        MonetaryAmount expectedTotal = Money.of(invoiceLine.getTotal(), invoiceCurrency).with(conversion).with(getDefaultRounding());
        MonetaryAmount calculatedTotal = invoiceWorkflowDataHolder.stream().map(h -> h.getNewTransaction().getAmount()).map(aDouble -> Money.of(aDouble, conversion.getCurrency())).reduce(Money::add).orElse(Money.zero(conversion.getCurrency()));
        int calculatedTotalSignum = calculatedTotal.signum();
        final MonetaryAmount remainder = expectedTotal.abs().subtract(calculatedTotal.abs());
        Optional<Transaction> resultTransaction = Optional.of(invoiceWorkflowDataHolder).map(holder -> {
            if (remainder.isNegative()) {
                return holder.get(0);
            } else if (remainder.isPositiveOrZero()) {
                return holder.get(holder.size() - 1);
            }
            return null;
        }).map(InvoiceWorkflowDataHolder::getNewTransaction);
        resultTransaction.ifPresent(tr -> {
            MonetaryAmount resultReminder = tr.getTransactionType().equals(TransactionType.CREDIT) ? remainder : remainder.multiply(calculatedTotalSignum);
            tr.setAmount(Money.of(tr.getAmount(), conversion.getCurrency()).add(resultReminder).getNumber().doubleValue());
        });
    });
    return holders;
}
Also used : Monetary(javax.money.Monetary) TransactionType(org.folio.rest.acq.model.finance.Transaction.TransactionType) InvoiceLine(org.folio.rest.jaxrs.model.InvoiceLine) CurrencyConversion(javax.money.convert.CurrencyConversion) CurrencyUnit(javax.money.CurrencyUnit) Money(org.javamoney.moneta.Money) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) Transaction(org.folio.rest.acq.model.finance.Transaction) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) List(java.util.List) Map(java.util.Map) Monetary.getDefaultRounding(javax.money.Monetary.getDefaultRounding) Optional(java.util.Optional) MonetaryAmount(javax.money.MonetaryAmount) CurrencyUnit(javax.money.CurrencyUnit) MonetaryAmount(javax.money.MonetaryAmount) Transaction(org.folio.rest.acq.model.finance.Transaction) InvoiceLine(org.folio.rest.jaxrs.model.InvoiceLine) InvoiceWorkflowDataHolder(org.folio.models.InvoiceWorkflowDataHolder) CurrencyConversion(javax.money.convert.CurrencyConversion) List(java.util.List)

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