public DefaultPayment(
     final PaymentModelDao src,
     @Nullable final PaymentInfoPlugin paymentPluginInfo,
     final List<PaymentAttemptModelDao> attempts,
     final List<RefundModelDao> refunds) {
   this(
       src.getId(),
       src.getCreatedDate(),
       src.getUpdatedDate(),
       src.getAccountId(),
       src.getInvoiceId(),
       src.getPaymentMethodId(),
       src.getAmount(),
       toPaidAmount(src.getPaymentStatus(), src.getAmount(), refunds),
       src.getCurrency(),
       src.getEffectiveDate(),
       src.getPaymentNumber(),
       src.getPaymentStatus(),
       paymentPluginInfo,
       toPaymentAttempts(attempts));
 }
  // Used in bulk get API (getAccountPayments)
  private Payment toPayment(
      final PaymentModelDao curPaymentModelDao,
      final Iterable<PaymentTransactionModelDao> curTransactionsModelDao,
      @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions,
      final InternalTenantContext internalTenantContext) {
    final Ordering<PaymentTransaction> perPaymentTransactionOrdering =
        Ordering.<PaymentTransaction>from(
            new Comparator<PaymentTransaction>() {
              @Override
              public int compare(final PaymentTransaction o1, final PaymentTransaction o2) {
                return o1.getEffectiveDate().compareTo(o2.getEffectiveDate());
              }
            });

    // Need to filter for optimized codepaths looking up by account_record_id
    final Iterable<PaymentTransactionModelDao> filteredTransactions =
        Iterables.filter(
            curTransactionsModelDao,
            new Predicate<PaymentTransactionModelDao>() {
              @Override
              public boolean apply(final PaymentTransactionModelDao curPaymentTransactionModelDao) {
                return curPaymentTransactionModelDao
                    .getPaymentId()
                    .equals(curPaymentModelDao.getId());
              }
            });

    PaymentModelDao newPaymentModelDao = curPaymentModelDao;
    final Collection<PaymentTransaction> transactions = new LinkedList<PaymentTransaction>();
    for (final PaymentTransactionModelDao curPaymentTransactionModelDao : filteredTransactions) {
      PaymentTransactionModelDao newPaymentTransactionModelDao = curPaymentTransactionModelDao;

      final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin =
          findPaymentTransactionInfoPlugin(newPaymentTransactionModelDao, pluginTransactions);
      if (paymentTransactionInfoPlugin != null) {
        // Make sure to invoke the Janitor task in case the plugin fixes its state on the fly
        // See https://github.com/killbill/killbill/issues/341
        final boolean hasChanged =
            incompletePaymentTransactionTask.updatePaymentAndTransactionIfNeededWithAccountLock(
                newPaymentModelDao,
                newPaymentTransactionModelDao,
                paymentTransactionInfoPlugin,
                internalTenantContext);
        if (hasChanged) {
          newPaymentModelDao =
              paymentDao.getPayment(newPaymentModelDao.getId(), internalTenantContext);
          newPaymentTransactionModelDao =
              paymentDao.getPaymentTransaction(
                  newPaymentTransactionModelDao.getId(), internalTenantContext);
        }
      }

      final PaymentTransaction transaction =
          new DefaultPaymentTransaction(
              newPaymentTransactionModelDao.getId(),
              newPaymentTransactionModelDao.getAttemptId(),
              newPaymentTransactionModelDao.getTransactionExternalKey(),
              newPaymentTransactionModelDao.getCreatedDate(),
              newPaymentTransactionModelDao.getUpdatedDate(),
              newPaymentTransactionModelDao.getPaymentId(),
              newPaymentTransactionModelDao.getTransactionType(),
              newPaymentTransactionModelDao.getEffectiveDate(),
              newPaymentTransactionModelDao.getTransactionStatus(),
              newPaymentTransactionModelDao.getAmount(),
              newPaymentTransactionModelDao.getCurrency(),
              newPaymentTransactionModelDao.getProcessedAmount(),
              newPaymentTransactionModelDao.getProcessedCurrency(),
              newPaymentTransactionModelDao.getGatewayErrorCode(),
              newPaymentTransactionModelDao.getGatewayErrorMsg(),
              paymentTransactionInfoPlugin);
      transactions.add(transaction);
    }

    final List<PaymentTransaction> sortedTransactions =
        perPaymentTransactionOrdering.immutableSortedCopy(transactions);
    return new DefaultPayment(
        curPaymentModelDao.getId(),
        curPaymentModelDao.getCreatedDate(),
        curPaymentModelDao.getUpdatedDate(),
        curPaymentModelDao.getAccountId(),
        curPaymentModelDao.getPaymentMethodId(),
        curPaymentModelDao.getPaymentNumber(),
        curPaymentModelDao.getExternalKey(),
        sortedTransactions);
  }