/** * Create an adjustment for a given invoice item. This just creates the object in memory, it * doesn't write it to disk. * * @param invoiceToBeAdjusted the invoice * @param invoiceItemId the invoice item id to adjust * @param positiveAdjAmount the amount to adjust. Pass null to adjust the full amount of the * original item * @param currency the currency of the amount. Pass null to default to the original currency used * @param effectiveDate adjustment effective date, in the account timezone * @return the adjustment item */ public InvoiceItem createAdjustmentItem( final Invoice invoiceToBeAdjusted, final UUID invoiceItemId, @Nullable final BigDecimal positiveAdjAmount, @Nullable final Currency currency, final LocalDate effectiveDate, final InternalCallContext context) throws InvoiceApiException { final InvoiceItem invoiceItemToBeAdjusted = Iterables.<InvoiceItem>tryFind( invoiceToBeAdjusted.getInvoiceItems(), new Predicate<InvoiceItem>() { @Override public boolean apply(final InvoiceItem input) { return input.getId().equals(invoiceItemId); } }) .orNull(); if (invoiceItemToBeAdjusted == null) { throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, invoiceItemId); } // Check the specified currency matches the one of the existing invoice final Currency currencyForAdjustment = Objects.firstNonNull(currency, invoiceItemToBeAdjusted.getCurrency()); if (invoiceItemToBeAdjusted.getCurrency() != currencyForAdjustment) { throw new InvoiceApiException( ErrorCode.CURRENCY_INVALID, currency, invoiceItemToBeAdjusted.getCurrency()); } // Reuse the same logic we have for refund with item adjustment final Map<UUID, BigDecimal> input = new HashMap<UUID, BigDecimal>(); input.put(invoiceItemId, positiveAdjAmount); final Map<UUID, BigDecimal> output = dao.computeItemAdjustments(invoiceToBeAdjusted.getId().toString(), input, context); // If we pass that stage, it means the validation succeeded so we just need to extract resulting // amount and negate the result. final BigDecimal amountToAdjust = output.get(invoiceItemId).negate(); // Finally, create the adjustment return new ItemAdjInvoiceItem( UUIDs.randomUUID(), context.getCreatedDate(), invoiceItemToBeAdjusted.getInvoiceId(), invoiceItemToBeAdjusted.getAccountId(), effectiveDate, null, amountToAdjust, currencyForAdjustment, invoiceItemToBeAdjusted.getId()); }
public DefaultBlockingState( final UUID blockingId, final BlockingStateType type, final String stateName, final String service, final boolean blockChange, final boolean blockEntitlement, final boolean blockBilling, final DateTime effectiveDate) { this( UUIDs.randomUUID(), blockingId, type, stateName, service, blockChange, blockEntitlement, blockBilling, effectiveDate, null, null, 0L); }
@Override public void leavingState(final State state) throws OperationException { final DateTime utcNow = pluginControlPaymentAutomatonRunner.getClock().getUTCNow(); // Retrieve the associated payment transaction, if any PaymentTransactionModelDao paymentTransactionModelDaoCandidate = null; if (stateContext.getTransactionId() != null) { paymentTransactionModelDaoCandidate = paymentDao.getPaymentTransaction( stateContext.getTransactionId(), stateContext.getInternalCallContext()); Preconditions.checkNotNull( paymentTransactionModelDaoCandidate, "paymentTransaction cannot be null for id " + stateContext.getTransactionId()); } else if (stateContext.getPaymentTransactionExternalKey() != null) { final List<PaymentTransactionModelDao> paymentTransactionModelDaos = paymentDao.getPaymentTransactionsByExternalKey( stateContext.getPaymentTransactionExternalKey(), stateContext.getInternalCallContext()); if (!paymentTransactionModelDaos.isEmpty()) { paymentTransactionModelDaoCandidate = paymentTransactionModelDaos.get(paymentTransactionModelDaos.size() - 1); } } final PaymentTransactionModelDao paymentTransactionModelDao = paymentTransactionModelDaoCandidate != null && TRANSIENT_TRANSACTION_STATUSES.contains( paymentTransactionModelDaoCandidate.getTransactionStatus()) ? paymentTransactionModelDaoCandidate : null; if (stateContext.getPaymentId() != null && stateContext.getPaymentExternalKey() == null) { final PaymentModelDao payment = paymentDao.getPayment(stateContext.getPaymentId(), stateContext.getInternalCallContext()); Preconditions.checkNotNull( payment, "payment cannot be null for id " + stateContext.getPaymentId()); stateContext.setPaymentExternalKey(payment.getExternalKey()); stateContext.setPaymentMethodId(payment.getPaymentMethodId()); } else if (stateContext.getPaymentExternalKey() == null) { stateContext.setPaymentExternalKey(UUIDs.randomUUID().toString()); } if (paymentTransactionModelDao != null) { stateContext.setPaymentTransactionExternalKey( paymentTransactionModelDao.getTransactionExternalKey()); } else if (stateContext.getPaymentTransactionExternalKey() == null) { stateContext.setPaymentTransactionExternalKey(UUIDs.randomUUID().toString()); } if (stateContext.getPaymentMethodId() == null) { // Similar logic in PaymentAutomatonRunner stateContext.setPaymentMethodId(stateContext.getAccount().getPaymentMethodId()); } if (state.getName().equals(initialState.getName()) || state.getName().equals(retriedState.getName())) { try { final PaymentAttemptModelDao attempt; if (paymentTransactionModelDao != null && paymentTransactionModelDao.getAttemptId() != null) { attempt = pluginControlPaymentAutomatonRunner .getPaymentDao() .getPaymentAttempt( paymentTransactionModelDao.getAttemptId(), stateContext.getInternalCallContext()); Preconditions.checkNotNull( attempt, "attempt cannot be null for id " + paymentTransactionModelDao.getAttemptId()); } else { // // We don't serialize any properties at this stage to avoid serializing sensitive // information. // However, if after going through the control plugins, the attempt end up in RETRIED // state, // the properties will be serialized in the enteringState callback (any plugin that sets a // retried date is responsible to correctly remove sensitive information such as CVV, ...) // final byte[] serializedProperties = PluginPropertySerializer.serialize(ImmutableList.<PluginProperty>of()); attempt = new PaymentAttemptModelDao( stateContext.getAccount().getId(), stateContext.getPaymentMethodId(), utcNow, utcNow, stateContext.getPaymentExternalKey(), stateContext.getTransactionId(), stateContext.getPaymentTransactionExternalKey(), transactionType, initialState.getName(), stateContext.getAmount(), stateContext.getCurrency(), stateContext.getPaymentControlPluginNames(), serializedProperties); pluginControlPaymentAutomatonRunner .getPaymentDao() .insertPaymentAttemptWithProperties(attempt, stateContext.getInternalCallContext()); } stateContext.setAttemptId(attempt.getId()); } catch (final PluginPropertySerializerException e) { throw new OperationException(e); } } }