@Override public InvoiceItemModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final InvoiceItemSqlDao invoiceItemSqlDao = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class); final InvoiceItemModelDao invoiceItemModelDao = invoiceItemSqlDao.getById(creditId.toString(), context); if (invoiceItemModelDao == null) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, creditId.toString()); } return invoiceItemModelDao; } });
@Override public InvoiceItemModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final InvoiceItemSqlDao invoiceItemSqlDao = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class); final InvoiceItemModelDao invoiceItemModelDao = invoiceItemSqlDao.getById(externalChargeId.toString(), context); if (invoiceItemModelDao == null) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, externalChargeId.toString()); } return invoiceItemModelDao; } });
private InvoiceItemModelDao getInvoiceItemForId(final InvoiceModelDao invoice, final UUID invoiceItemId) throws InvoiceApiException { for (final InvoiceItemModelDao invoiceItem : invoice.getInvoiceItems()) { if (invoiceItem.getId().equals(invoiceItemId)) { return invoiceItem; } } throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, invoiceItemId); }
@Override public InvoicePaymentModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final InvoicePaymentModelDao chargeback = entitySqlDaoWrapperFactory.become(InvoicePaymentSqlDao.class).getById(chargebackId.toString(), context); if (chargeback == null) { throw new InvoiceApiException(ErrorCode.CHARGE_BACK_DOES_NOT_EXIST, chargebackId); } else { return chargeback; } } });
@Override public Invoice triggerInvoiceGeneration(final UUID accountId, @Nullable final LocalDate targetDate, final CallContext context) throws InvoiceApiException { final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(accountId, context); final Invoice result = dispatcher.processAccount(true, accountId, targetDate, null, false, internalContext); if (result == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NOTHING_TO_DO, accountId, targetDate != null ? targetDate : "null"); } else { return result; } }
@Override public UUID inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final UUID accountId = entitySqlDaoWrapperFactory.become(InvoicePaymentSqlDao.class).getAccountIdFromInvoicePaymentId(invoicePaymentId.toString(), context); if (accountId == null) { throw new InvoiceApiException(ErrorCode.CHARGE_BACK_COULD_NOT_FIND_ACCOUNT_ID, invoicePaymentId); } else { return accountId; } } });
private static void computeItemAdjustmentsForTargetInvoiceItem(final InvoiceItemModelDao targetInvoiceItem, final List<InvoiceItemModelDao> adjustedOrRepairedItems, final Map<UUID, BigDecimal> inputAdjInvoiceItem, final Map<UUID, BigDecimal> outputAdjInvoiceItem) throws InvoiceApiException { final BigDecimal originalItemAmount = targetInvoiceItem.getAmount(); final BigDecimal maxAdjLeftAmount = computeItemAdjustmentAmount(originalItemAmount, adjustedOrRepairedItems); final BigDecimal proposedItemAmount = inputAdjInvoiceItem.get(targetInvoiceItem.getId()); if (proposedItemAmount != null && proposedItemAmount.compareTo(maxAdjLeftAmount) > 0) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_ADJUSTMENT_AMOUNT_INVALID, proposedItemAmount, maxAdjLeftAmount); } final BigDecimal itemAmountToAdjust = MoreObjects.firstNonNull(proposedItemAmount, maxAdjLeftAmount); if (itemAmountToAdjust.compareTo(BigDecimal.ZERO) > 0) { outputAdjInvoiceItem.put(targetInvoiceItem.getId(), itemAmountToAdjust); } }
@Override public Invoice triggerDryRunInvoiceGeneration(final UUID accountId, final LocalDate targetDate, final DryRunArguments dryRunArguments, final CallContext context) throws InvoiceApiException { final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(accountId, context); final Invoice result = dispatcher.processAccount(true, accountId, targetDate, dryRunArguments, false, internalContext); if (result == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NOTHING_TO_DO, accountId, targetDate != null ? targetDate : "null"); } else { return result; } }
@Override public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final InvoiceItemSqlDao transactional = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class); // Retrieve the invoice and make sure it belongs to the right account final InvoiceItemModelDao invoiceItem = transactional.getById(invoiceItemId.toString(), context); if (invoiceItem == null) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, invoiceItemId); } transactional.updateItemFields(invoiceItemId.toString(), amount, null, null, context); return null; } });
@Override public Map<UUID, BigDecimal> validateInvoiceItemAdjustments(final UUID paymentId, final Map<UUID, BigDecimal> idWithAmount, final InternalTenantContext context) throws InvoiceApiException { // We want to validate that only refund with invoice *item* adjustments are allowed (as opposed to refund with invoice adjustment) if (idWithAmount.size() == 0) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEMS_ADJUSTMENT_MISSING); } final InvoicePayment invoicePayment = getInvoicePayment(paymentId, InvoicePaymentType.ATTEMPT, context); return dao.computeItemAdjustments(invoicePayment.getInvoiceId().toString(), idWithAmount, context); }
private DefaultInvoice getInvoiceAndCheckCurrency(final UUID invoiceId, @Nullable final Currency currency, final TenantContext context) throws InvoiceApiException { final DefaultInvoice invoice = getInvoiceInternal(invoiceId, context); // Check the specified currency matches the one of the existing invoice if (currency != null && invoice.getCurrency() != currency) { throw new InvoiceApiException(ErrorCode.CURRENCY_INVALID, currency, invoice.getCurrency()); } return invoice; }
@Override public InvoiceModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final InvoiceSqlDao invoiceSqlDao = entitySqlDaoWrapperFactory.become(InvoiceSqlDao.class); final InvoiceModelDao invoice = invoiceSqlDao.getById(invoiceId.toString(), context); if (invoice == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceId); } invoiceDaoHelper.populateChildren(invoice, invoicesTags, entitySqlDaoWrapperFactory, context); return invoice; } });
private void validateInvoiceItemToBeAdjusted(final InvoiceItemSqlDao invoiceItemSqlDao, final InvoiceItemModelDao invoiceItemModelDao, final InternalCallContext context) throws InvoiceApiException { Preconditions.checkNotNull(invoiceItemModelDao.getLinkedItemId(), "LinkedItemId cannot be null for ITEM_ADJ item: " + invoiceItemModelDao); // Note: this assumes the linked item has already been created in or prior to the transaction, which should almost always be the case // (unless some whacky plugin creates an out-of-order item adjustment on a subsequent external charge) final InvoiceItemModelDao invoiceItemToBeAdjusted = invoiceItemSqlDao.getById(invoiceItemModelDao.getLinkedItemId().toString(), context); if (!INVOICE_ITEM_TYPES_ADJUSTABLE.contains(invoiceItemToBeAdjusted.getType())) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_ADJUSTMENT_ITEM_INVALID, invoiceItemToBeAdjusted.getId()); } }
private void canInvoiceBeVoided(final Invoice invoice) throws InvoiceApiException { final List<InvoicePayment> invoicePayments = invoice.getPayments(); final BigDecimal amountPaid = InvoiceCalculatorUtils.computeInvoiceAmountPaid(invoice.getCurrency(), invoicePayments) .add(InvoiceCalculatorUtils.computeInvoiceAmountRefunded(invoice.getCurrency(), invoicePayments)); if (amountPaid.compareTo(BigDecimal.ZERO) != 0) { throw new InvoiceApiException(ErrorCode.CAN_NOT_VOID_INVOICE_THAT_IS_PAID, invoice.getId().toString()); } } }
@Override public InvoiceModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final InvoiceSqlDao invoiceDao = entitySqlDaoWrapperFactory.become(InvoiceSqlDao.class); final InvoiceModelDao invoice = invoiceDao.getByRecordId(number.longValue(), context); if (invoice == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NUMBER_NOT_FOUND, number.longValue()); } // The context may not contain the account record id at this point - we couldn't do it in the API above // as we couldn't get access to the invoice object until now. final InternalTenantContext contextWithAccountRecordId = internalCallContextFactory.createInternalTenantContext(invoice.getAccountId(), context); invoiceDaoHelper.populateChildren(invoice, invoicesTags, entitySqlDaoWrapperFactory, contextWithAccountRecordId); return invoice; } });
@Override public InvoiceModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception { final InvoiceSqlDao invoiceSqlDao = entitySqlDaoWrapperFactory.become(InvoiceSqlDao.class); final InvoiceModelDao invoice = invoiceSqlDao.getInvoiceByInvoiceItemId(invoiceItemId.toString(), context); if (invoice == null) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, invoiceItemId); } final InternalTenantContext contextWithAccountRecordId = internalCallContextFactory.createInternalTenantContext(invoice.getAccountId(), context); invoiceDaoHelper.populateChildren(invoice, invoicesTags, entitySqlDaoWrapperFactory, contextWithAccountRecordId); return invoice; } });
private void validateTargetDate(final LocalDate targetDate, final InternalTenantContext context) throws InvoiceApiException { final int maximumNumberOfMonths = config.getNumberOfMonthsInFuture(context); if (Months.monthsBetween(clock.getUTCToday(), targetDate).getMonths() > maximumNumberOfMonths) { throw new InvoiceApiException(ErrorCode.INVOICE_TARGET_DATE_TOO_FAR_IN_THE_FUTURE, targetDate.toString()); } }
@Override public Invoice getInvoiceByPayment(final UUID paymentId, final TenantContext context) throws InvoiceApiException { final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(paymentId, ObjectType.PAYMENT, context); final UUID invoiceId = dao.getInvoiceIdByPaymentId(paymentId, internalTenantContext); if (invoiceId == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, paymentId); } final InvoiceModelDao invoiceModelDao = dao.getById(invoiceId, internalTenantContext); return new DefaultInvoice(invoiceModelDao, getCatalogSafelyForPrettyNames(internalTenantContext)); }
@Override public InvoiceItem getCreditById(final UUID creditId, final TenantContext context) throws InvoiceApiException { final InvoiceItem creditItem = InvoiceItemFactory.fromModelDao(dao.getCreditById(creditId, internalCallContextFactory.createInternalTenantContext(creditId, ObjectType.INVOICE_ITEM, context))); if (creditItem == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NO_SUCH_CREDIT, creditId); } return new CreditAdjInvoiceItem(creditItem.getId(), creditItem.getCreatedDate(), creditItem.getInvoiceId(), creditItem.getAccountId(), creditItem.getStartDate(), creditItem.getDescription(), creditItem.getAmount().negate(), creditItem.getCurrency(), creditItem.getItemDetails()); }
@Override public InvoiceItem getExternalChargeById(final UUID externalChargeId, final TenantContext context) throws InvoiceApiException { final InvoiceItem externalChargeItem = InvoiceItemFactory.fromModelDao(dao.getExternalChargeById(externalChargeId, internalCallContextFactory.createInternalTenantContext(externalChargeId, ObjectType.INVOICE_ITEM, context))); if (externalChargeItem == null) { throw new InvoiceApiException(ErrorCode.INVOICE_NO_SUCH_EXTERNAL_CHARGE, externalChargeId); } return new ExternalChargeInvoiceItem(externalChargeItem.getId(), externalChargeItem.getInvoiceId(), externalChargeItem.getAccountId(), externalChargeItem.getDescription(), externalChargeItem.getStartDate(), externalChargeItem.getEndDate(), externalChargeItem.getAmount(), externalChargeItem.getCurrency(), externalChargeItem.getItemDetails()); }