private PaymentLog createRefundEntryForOverflow(PaymentLog paymentLog, BigDecimal overflowInUsd) throws RefundEntryAlreadyExistsException { BigInteger cryptocurrencyAmount = overflowInUsd.multiply(paymentLog.getUsdFxRate()) .multiply(paymentLog.getCurrency().getAtomicUnitFactor()) .toBigInteger(); return createRefundEntryForAmount(paymentLog, RefundReason.TOKEN_OVERFLOW, cryptocurrencyAmount, overflowInUsd); }
PaymentLog allocateTokensWithRetries(PaymentLog paymentLog) throws Throwable { if (paymentLog.getUsdAmount() == null) { throw new IllegalArgumentException("PaymentLog's amount in USD must not be null."); } if (paymentLog.getBlockTime() == null) { throw new IllegalArgumentException("PaymentLog's block time must not be null."); } LOG.debug("Calling token allocation with {} USD for {} transaction {}.", paymentLog.getUsdAmount().toPlainString(), paymentLog.getCurrency(), paymentLog.getTransactionId()); try { // Retry as long as there are database locking exceptions. PaymentLog updatedPaymentLog = retryer.call( () -> monitorService.allocateTokens(paymentLog)); LOG.debug("Allocated {} tomics for {} transaction {}.", updatedPaymentLog.getAllocatedTomics(), updatedPaymentLog.getCurrency(), updatedPaymentLog.getTransactionId()); return updatedPaymentLog; } catch (Throwable e) { LOG.error("Failed to distribute payment to tiers for {} transaction {}.", paymentLog.getCurrency().name(), paymentLog.getTransactionId(), e.getCause()); RefundReason reason = RefundReason.TOKEN_ALLOCATION_FAILED; monitorService.createRefundEntryForPaymentLogAndCommit(paymentLog, reason); throw e; } }
@Transactional(propagation = Propagation.REQUIRED) public PaymentLog sendTransactionReceivedMessageAndSavePaymentLog(PaymentLog paymentLog, BigDecimal amountInMainUnit, String transactionUrl) { messageService.send(new TransactionReceivedEmailMessage( MessageDTOHelper.build(paymentLog.getInvestor()), amountInMainUnit, paymentLog.getCurrency(), transactionUrl)); paymentLog.setTransactionReceivedMessageSent(true); return paymentLogService.updateProcessedDateAndSave(paymentLog); }
private PaymentLog createRefundEntryForAmount( PaymentLog paymentLog, RefundReason reason, BigInteger cryptocurrencyAmount, BigDecimal usdAmount) throws RefundEntryAlreadyExistsException { EligibleForRefund refund = eligibleForRefundService.save( new EligibleForRefund(reason, cryptocurrencyAmount, usdAmount, paymentLog.getCurrency(), paymentLog.getInvestor(), paymentLog.getTransactionId())); paymentLog.setEligibleForRefund(refund); return paymentLog; }
@Transactional(propagation = Propagation.REQUIRED) public PaymentLog sendAllocationMessageAndSavePaymentLog(PaymentLog paymentLog, BigDecimal amountInMainUnit, String transactionUrl) { messageService.send(new TokensAllocatedEmailMessage( MessageDTOHelper.build(paymentLog.getInvestor()), amountInMainUnit, paymentLog.getCurrency(), transactionUrl, convertTomicsToTokens(paymentLog.getAllocatedTomics()))); paymentLog.setAllocationMessageSent(true); return paymentLogService.updateProcessedDateAndSave(paymentLog); }
LOG.info("{} transaction {} generated a overflow of {} USD", paymentLog.getCurrency().name(), paymentLog.getTransactionId(), result.getOverflow()); try { paymentLog = createRefundEntryForOverflow(paymentLog, result.getOverflow());