killbill-memoizeit

Fix Payment retry logic -- at least enough to have retries work

6/25/2014 12:23:12 AM

Details

diff --git a/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java b/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java
index 277389a..afffaa0 100644
--- a/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/control/InvoicePaymentControlPluginApi.java
@@ -170,7 +170,7 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
     public void process_AUTO_PAY_OFF_removal(final Account account, final InternalCallContext internalCallContext) {
         final List<PluginAutoPayOffModelDao> entries = controlDao.getAutoPayOffEntry(account.getId());
         for (PluginAutoPayOffModelDao cur : entries) {
-            retryServiceScheduler.scheduleRetry(cur.getPaymentId(), cur.getTransactionExternalKey(), PLUGIN_NAME, clock.getUTCNow());
+            retryServiceScheduler.scheduleRetry(ObjectType.ACCOUNT, account.getId(), cur.getTransactionExternalKey(), PLUGIN_NAME, clock.getUTCNow());
         }
         controlDao.removeAutoPayOffEntry(account.getId());
     }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
index 0de42d7..35324ce 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
@@ -467,14 +467,20 @@ public class DirectPaymentProcessor extends ProcessorBase {
     }
 
     private BusInternalEvent buildPaymentEvent(final Account account, final DirectPayment directPayment, final String transactionExternalKey, final InternalCallContext context) {
-        final DirectPaymentTransaction directPaymentTransaction = Iterables.<DirectPaymentTransaction>tryFind(directPayment.getTransactions(),
+
+
+        final DirectPaymentTransaction directPaymentTransaction = directPayment.getTransactions().get(directPayment.getTransactions().size() - 1);
+
+        /* STEPH
+        Iterables.<DirectPaymentTransaction>tryFind(directPayment.getTransactions(),
                                                                                                               new Predicate<DirectPaymentTransaction>() {
                                                                                                                   @Override
                                                                                                                   public boolean apply(final DirectPaymentTransaction input) {
                                                                                                                       return input.getExternalKey().equals(transactionExternalKey);
                                                                                                                   }
                                                                                                               }
-                                                                                                             ).get();
+                                                                                                             ).get()
+                                                                                                             */
 
         switch (directPaymentTransaction.getTransactionStatus()) {
             case SUCCESS:
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java
index 6a448d0..55ea1b8 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java
@@ -176,7 +176,10 @@ public class PluginControlledPaymentProcessor extends ProcessorBase {
 
             final PaymentAttemptModelDao attempt = paymentDao.getPaymentAttemptByExternalKey(transactionExternalKey, internalCallContext);
             final PaymentTransactionModelDao transaction = paymentDao.getDirectPaymentTransactionByExternalKey(transactionExternalKey, internalCallContext);
-            final PaymentModelDao payment = paymentDao.getDirectPayment(transaction.getPaymentId(), internalCallContext);
+            final PaymentModelDao payment = transaction != null ?
+                                            paymentDao.getDirectPayment(transaction.getPaymentId(), internalCallContext) :
+                                            null;
+            final UUID paymentId = payment != null ? payment.getId() : null;
 
             final List<PluginPropertyModelDao> properties = paymentDao.getProperties(transactionExternalKey, internalCallContext);
 
@@ -190,24 +193,22 @@ public class PluginControlledPaymentProcessor extends ProcessorBase {
                 }
             }));
 
-            final Account account = accountInternalApi.getAccountById(payment.getAccountId(), internalCallContext);
+            final Account account = accountInternalApi.getAccountById(attempt.getAccountId(), internalCallContext);
             final UUID tenantId = nonEntityDao.retrieveIdFromObject(internalCallContext.getTenantRecordId(), ObjectType.TENANT);
             final CallContext callContext = internalCallContext.toCallContext(tenantId);
 
 
-            // STEPH Nope, keep the original transactionExternalKey
-            final String newTransactionExternalKey = UUID.randomUUID().toString();
             final State state = pluginControlledDirectPaymentAutomatonRunner.fetchState(attempt.getStateName());
             pluginControlledDirectPaymentAutomatonRunner.run(state,
                                                       false,
-                                                      transaction.getTransactionType(),
+                                                      attempt.getTransactionType(),
                                                       account,
-                                                      payment.getPaymentMethodId(),
-                                                      payment.getId(),
-                                                      payment.getExternalKey(),
-                                                      newTransactionExternalKey,
-                                                      transaction.getAmount(),
-                                                      transaction.getCurrency(),
+                                                      attempt.getPaymentMethodId(),
+                                                      paymentId,
+                                                      attempt.getPaymentExternalKey(),
+                                                      attempt.getTransactionExternalKey(),
+                                                      attempt.getAmount(),
+                                                      attempt.getCurrency(),
                                                       pluginProperties,
                                                       pluginName,
                                                       callContext,
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryableDirectPaymentStateContext.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryableDirectPaymentStateContext.java
index f33be74..9be1db5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryableDirectPaymentStateContext.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryableDirectPaymentStateContext.java
@@ -33,17 +33,20 @@ import org.killbill.billing.util.callcontext.CallContext;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Ordering;
 
 public class RetryableDirectPaymentStateContext extends DirectPaymentStateContext {
 
+    private UUID attemptId;
     private boolean isApiPayment;
     private DateTime retryDate;
     private String pluginName;
     private DirectPayment result;
 
-    public RetryableDirectPaymentStateContext(@Nullable String pluginName, boolean isApiPayment, @Nullable final UUID directPaymentId, final String directPaymentExternalKey, @Nullable final String directPaymentTransactionExternalKey, final TransactionType transactionType, final Account account, @Nullable final UUID paymentMethodId,
+    public RetryableDirectPaymentStateContext(@Nullable final String pluginName, final boolean isApiPayment, @Nullable final UUID directPaymentId, final String directPaymentExternalKey, @Nullable final String directPaymentTransactionExternalKey, final TransactionType transactionType, final Account account, @Nullable final UUID paymentMethodId,
                                               final BigDecimal amount, final Currency currency, final Iterable<PluginProperty> properties, final InternalCallContext internalCallContext, final CallContext callContext) {
         super(directPaymentId, directPaymentExternalKey, directPaymentTransactionExternalKey, transactionType, account, paymentMethodId, amount, currency, true, properties, internalCallContext, callContext);
+        this.attemptId = attemptId;
         this.pluginName = pluginName;
         this.isApiPayment = isApiPayment;
     }
@@ -80,15 +83,27 @@ public class RetryableDirectPaymentStateContext extends DirectPaymentStateContex
         this.amount = adjustedAmount;
     }
 
+    public UUID getAttemptId() {
+        return attemptId;
+    }
+
+    public void setAttemptId(final UUID attemptId) {
+        this.attemptId = attemptId;
+    }
+
     public DirectPaymentTransaction getCurrentTransaction() {
-        if (result == null) {
+        if (result == null || result.getTransactions() == null || result.getTransactions().size() == 0) {
             return null;
         }
-        return Iterables.tryFind(result.getTransactions(), new Predicate<DirectPaymentTransaction>() {
+        return result.getTransactions().get(result.getTransactions().size() -1);
+/*
+STEPH
+        Iterables.filter(result.getTransactions(), new Predicate<DirectPaymentTransaction>() {
             @Override
             public boolean apply(final DirectPaymentTransaction input) {
                 return input.getExternalKey().equals(directPaymentTransactionExternalKey);
             }
-        }).orNull();
+        })
+        */
     }
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryEnteringStateCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryEnteringStateCallback.java
index aa926fe..fba08cf 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryEnteringStateCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryEnteringStateCallback.java
@@ -23,6 +23,7 @@ import org.killbill.automaton.OperationResult;
 import org.killbill.automaton.State;
 import org.killbill.automaton.State.EnteringStateCallback;
 import org.killbill.automaton.State.LeavingStateCallback;
+import org.killbill.billing.ObjectType;
 import org.killbill.billing.payment.dao.PaymentAttemptModelDao;
 import org.killbill.billing.payment.retry.BaseRetryService.RetryServiceScheduler;
 
@@ -42,14 +43,14 @@ public class RetryEnteringStateCallback implements EnteringStateCallback {
     @Override
     public void enteringState(final State state, final OperationCallback operationCallback, final OperationResult operationResult, final LeavingStateCallback leavingStateCallback) {
 
-        final PaymentAttemptModelDao attempt = retryableDirectPaymentAutomatonRunner.paymentDao.getPaymentAttemptByExternalKey(directPaymentStateContext.getDirectPaymentTransactionExternalKey(), directPaymentStateContext.internalCallContext);
+        final PaymentAttemptModelDao attempt = retryableDirectPaymentAutomatonRunner.paymentDao.getPaymentAttempt(directPaymentStateContext.getAttemptId(), directPaymentStateContext.internalCallContext);
         final UUID transactionId = directPaymentStateContext.getCurrentTransaction() != null ?
                                    directPaymentStateContext.getCurrentTransaction().getId() :
                                    null;
         retryableDirectPaymentAutomatonRunner.paymentDao.updatePaymentAttempt(attempt.getId(), transactionId, state.getName(), directPaymentStateContext.internalCallContext);
 
         if ("RETRIED".equals(state.getName())) {
-            retryServiceScheduler.scheduleRetry(directPaymentStateContext.directPaymentId, directPaymentStateContext.directPaymentTransactionExternalKey,
+            retryServiceScheduler.scheduleRetry(ObjectType.PAYMENT_ATTEMPT, attempt.getId(), directPaymentStateContext.directPaymentTransactionExternalKey,
                                                 directPaymentStateContext.getPluginName(), directPaymentStateContext.getRetryDate());
         }
     }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryLeavingStateCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryLeavingStateCallback.java
index 6b1721c..8076b73 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryLeavingStateCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryLeavingStateCallback.java
@@ -77,10 +77,14 @@ public class RetryLeavingStateCallback implements LeavingStateCallback {
                                                       stateContext.getPluginName(), input.getKey(), value, stateContext.getCallContext().getUserName(), stateContext.getCallContext().getCreatedDate());
                 }
             }));
-            retryableDirectPaymentAutomatonRunner.paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(utcNow, utcNow, stateContext.getDirectPaymentExternalKey(), null,
-                                                                                                                           stateContext.directPaymentTransactionExternalKey, state.getName(),
-                                                                                                                           transactionType.name(), stateContext.getPluginName()),
+            final PaymentAttemptModelDao attempt = retryableDirectPaymentAutomatonRunner.paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(stateContext.getAccount().getId(), stateContext.getPaymentMethodId(),
+                                                                                                        utcNow, utcNow, stateContext.getDirectPaymentExternalKey(), null,
+                                                                                                                           stateContext.directPaymentTransactionExternalKey, transactionType, state.getName(),
+                                                                                                                            stateContext.getAmount(), stateContext.getCurrency(),
+                                                                                                                           stateContext.getPluginName()),
                                                                                                 properties, stateContext.internalCallContext);
+
+            stateContext.setAttemptId(attempt.getId());
         }
     }
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryOperationCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryOperationCallback.java
index 20ed4e1..95d1b55 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryOperationCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryOperationCallback.java
@@ -119,6 +119,7 @@ public abstract class RetryOperationCallback extends OperationCallbackBase imple
                                                                                                                     directPaymentStateContext.paymentMethodId,
                                                                                                                     result.getId(),
                                                                                                                     result.getExternalKey(),
+                                                                                                                    transaction.getId(),
                                                                                                                     directPaymentStateContext.directPaymentTransactionExternalKey,
                                                                                                                     directPaymentStateContext.transactionType,
                                                                                                                     transaction.getAmount(),
@@ -226,6 +227,7 @@ public abstract class RetryOperationCallback extends OperationCallbackBase imple
         private final UUID paymentId;
         private final UUID paymentMethodId;
         private final String paymentExternalKey;
+        private final UUID transactionId;
         private final String transactionExternalKey;
         private final TransactionType transactionType;
         private final BigDecimal amount;
@@ -237,16 +239,17 @@ public abstract class RetryOperationCallback extends OperationCallbackBase imple
 
         public DefaultPaymentControlContext(final Account account, final UUID paymentMethodId, @Nullable final UUID paymentId, final String paymentExternalKey, final String transactionExternalKey, final TransactionType transactionType, final BigDecimal amount, final Currency currency,
                                             final Iterable<PluginProperty> properties, final boolean isApiPayment, final CallContext callContext) {
-            this(account, paymentMethodId, paymentId, paymentExternalKey, transactionExternalKey, transactionType, amount, currency, null, null, properties, isApiPayment, callContext);
+            this(account, paymentMethodId, paymentId, paymentExternalKey, null, transactionExternalKey, transactionType, amount, currency, null, null, properties, isApiPayment, callContext);
         }
 
-        public DefaultPaymentControlContext(final Account account, final UUID paymentMethodId, @Nullable final UUID paymentId, final String paymentExternalKey, final String transactionExternalKey, final TransactionType transactionType,
+        public DefaultPaymentControlContext(final Account account, final UUID paymentMethodId, @Nullable final UUID paymentId, final String paymentExternalKey, @Nullable final UUID transactionId, final String transactionExternalKey, final TransactionType transactionType,
                                             final BigDecimal amount, final Currency currency, @Nullable final BigDecimal processedAmount, @Nullable final Currency processedCurrency, final Iterable<PluginProperty> properties, final boolean isApiPayment, final CallContext callContext) {
             super(callContext.getTenantId(), callContext.getUserName(), callContext.getCallOrigin(), callContext.getUserType(), callContext.getReasonCode(), callContext.getComments(), callContext.getUserToken(), callContext.getCreatedDate(), callContext.getUpdatedDate());
             this.account = account;
             this.paymentId = paymentId;
             this.paymentMethodId = paymentMethodId;
             this.paymentExternalKey = paymentExternalKey;
+            this.transactionId = transactionId;
             this.transactionExternalKey = transactionExternalKey;
             this.transactionType = transactionType;
             this.amount = amount;
@@ -312,6 +315,12 @@ public abstract class RetryOperationCallback extends OperationCallbackBase imple
             return isApiPayment;
         }
 
+
+        public UUID getTransactionId() {
+            return transactionId;
+        }
+
+
         @Override
         public Iterable<PluginProperty> getPluginProperties() {
             return properties;
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptModelDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptModelDao.java
index bb4ce79..82bba44 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptModelDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptModelDao.java
@@ -16,43 +16,55 @@
 
 package org.killbill.billing.payment.dao;
 
+import java.math.BigDecimal;
 import java.util.UUID;
 
 import javax.annotation.Nullable;
 
 import org.joda.time.DateTime;
+import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.entity.EntityBase;
+import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.util.dao.TableName;
 import org.killbill.billing.util.entity.Entity;
 import org.killbill.billing.util.entity.dao.EntityModelDao;
 
 public class PaymentAttemptModelDao extends EntityBase implements EntityModelDao<Entity> {
 
+    private UUID accountId;
+    private UUID paymentMethodId;
     private String paymentExternalKey;
     private UUID transactionId;
     private String transactionExternalKey;
+    private TransactionType transactionType;
     private String stateName;
-    private String operationName;
+    private BigDecimal amount;
+    private Currency currency;
     private String pluginName;
 
     public PaymentAttemptModelDao() { /* For the DAO mapper */ }
 
-    public PaymentAttemptModelDao(final UUID id, @Nullable final DateTime createdDate, @Nullable final DateTime updatedDate,
-                                  final String paymentExternalKey, final UUID transactionId, final String externalKey, final String stateName, final String operationName,
-                                  final String pluginName) {
+    public PaymentAttemptModelDao(final UUID accountId, final UUID paymentMethodId, final UUID id, @Nullable final DateTime createdDate, @Nullable final DateTime updatedDate,
+                                  final String paymentExternalKey, final UUID transactionId, final String transactionExternalKey, final TransactionType transactionType,
+                                  final String stateName, final BigDecimal amount, final Currency currency, final String pluginName) {
         super(id, createdDate, updatedDate);
+        this.accountId = accountId;
+        this.paymentMethodId = paymentMethodId;
         this.paymentExternalKey = paymentExternalKey;
         this.transactionId = transactionId;
-        this.transactionExternalKey = externalKey;
+        this.transactionExternalKey = transactionExternalKey;
+        this.transactionType = transactionType;
         this.stateName = stateName;
-        this.operationName = operationName;
+        this.amount = amount;
+        this.currency = currency;
         this.pluginName = pluginName;
     }
 
-    public PaymentAttemptModelDao(@Nullable final DateTime createdDate, @Nullable final DateTime updatedDate,
-                                  final String paymentExternalKey, final UUID transactionId, final String externalKey, final String stateName, final String operationName,
-                                  final String pluginName) {
-        this(UUID.randomUUID(), createdDate, updatedDate, paymentExternalKey, transactionId, externalKey, stateName, operationName, pluginName);
+    public PaymentAttemptModelDao(final UUID accountId, final UUID paymentMethodId, @Nullable final DateTime createdDate, @Nullable final DateTime updatedDate,
+                                  final String paymentExternalKey, final UUID transactionId, final String transactionExternalKey, final TransactionType transactionType, final String stateName,
+                                  final BigDecimal amount, final Currency currency, final String pluginName) {
+        this(accountId, paymentMethodId, UUID.randomUUID(), createdDate, updatedDate, paymentExternalKey, transactionId, transactionExternalKey, transactionType, stateName,
+             amount, currency, pluginName);
     }
 
     public String getPaymentExternalKey() {
@@ -87,14 +99,6 @@ public class PaymentAttemptModelDao extends EntityBase implements EntityModelDao
         this.stateName = stateName;
     }
 
-    public String getOperationName() {
-        return operationName;
-    }
-
-    public void setOperationName(final String operationName) {
-        this.operationName = operationName;
-    }
-
     public String getPluginName() {
         return pluginName;
     }
@@ -103,6 +107,46 @@ public class PaymentAttemptModelDao extends EntityBase implements EntityModelDao
         this.pluginName = pluginName;
     }
 
+    public UUID getAccountId() {
+        return accountId;
+    }
+
+    public UUID getPaymentMethodId() {
+        return paymentMethodId;
+    }
+
+    public TransactionType getTransactionType() {
+        return transactionType;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    public void setAccountId(final UUID accountId) {
+        this.accountId = accountId;
+    }
+
+    public void setPaymentMethodId(final UUID paymentMethodId) {
+        this.paymentMethodId = paymentMethodId;
+    }
+
+    public void setTransactionType(final TransactionType transactionType) {
+        this.transactionType = transactionType;
+    }
+
+    public void setAmount(final BigDecimal amount) {
+        this.amount = amount;
+    }
+
+    public void setCurrency(final Currency currency) {
+        this.currency = currency;
+    }
+
     @Override
     public boolean equals(final Object o) {
         if (this == o) {
@@ -117,16 +161,19 @@ public class PaymentAttemptModelDao extends EntityBase implements EntityModelDao
 
         final PaymentAttemptModelDao that = (PaymentAttemptModelDao) o;
 
-        if (transactionId != null ? !transactionId.equals(that.transactionId) : that.transactionId != null) {
+        if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
             return false;
         }
-        if (paymentExternalKey != null ? !paymentExternalKey.equals(that.paymentExternalKey) : that.paymentExternalKey != null) {
+        if (amount != null ? amount.compareTo(that.amount) != 0 : that.amount != null) {
             return false;
         }
-        if (transactionExternalKey != null ? !transactionExternalKey.equals(that.transactionExternalKey) : that.transactionExternalKey != null) {
+        if (currency != that.currency) {
             return false;
         }
-        if (operationName != null ? !operationName.equals(that.operationName) : that.operationName != null) {
+        if (paymentExternalKey != null ? !paymentExternalKey.equals(that.paymentExternalKey) : that.paymentExternalKey != null) {
+            return false;
+        }
+        if (paymentMethodId != null ? !paymentMethodId.equals(that.paymentMethodId) : that.paymentMethodId != null) {
             return false;
         }
         if (pluginName != null ? !pluginName.equals(that.pluginName) : that.pluginName != null) {
@@ -135,17 +182,31 @@ public class PaymentAttemptModelDao extends EntityBase implements EntityModelDao
         if (stateName != null ? !stateName.equals(that.stateName) : that.stateName != null) {
             return false;
         }
+        if (transactionExternalKey != null ? !transactionExternalKey.equals(that.transactionExternalKey) : that.transactionExternalKey != null) {
+            return false;
+        }
+        if (transactionId != null ? !transactionId.equals(that.transactionId) : that.transactionId != null) {
+            return false;
+        }
+        if (transactionType != that.transactionType) {
+            return false;
+        }
+
         return true;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
-        result = 31 * result + (transactionId != null ? transactionId.hashCode() : 0);
+        result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+        result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
         result = 31 * result + (paymentExternalKey != null ? paymentExternalKey.hashCode() : 0);
+        result = 31 * result + (transactionId != null ? transactionId.hashCode() : 0);
         result = 31 * result + (transactionExternalKey != null ? transactionExternalKey.hashCode() : 0);
+        result = 31 * result + (transactionType != null ? transactionType.hashCode() : 0);
         result = 31 * result + (stateName != null ? stateName.hashCode() : 0);
-        result = 31 * result + (operationName != null ? operationName.hashCode() : 0);
+        result = 31 * result + (amount != null ? amount.hashCode() : 0);
+        result = 31 * result + (currency != null ? currency.hashCode() : 0);
         result = 31 * result + (pluginName != null ? pluginName.hashCode() : 0);
         return result;
     }
diff --git a/payment/src/main/java/org/killbill/billing/payment/glue/DefaultPaymentService.java b/payment/src/main/java/org/killbill/billing/payment/glue/DefaultPaymentService.java
index b70b321..09f8861 100644
--- a/payment/src/main/java/org/killbill/billing/payment/glue/DefaultPaymentService.java
+++ b/payment/src/main/java/org/killbill/billing/payment/glue/DefaultPaymentService.java
@@ -76,6 +76,7 @@ public class DefaultPaymentService implements PaymentService {
 
     @LifecycleHandlerType(LifecycleLevel.START_SERVICE)
     public void start() {
+        retryService.start();
     }
 
     @LifecycleHandlerType(LifecycleLevel.STOP_SERVICE)
diff --git a/payment/src/main/java/org/killbill/billing/payment/retry/BaseRetryService.java b/payment/src/main/java/org/killbill/billing/payment/retry/BaseRetryService.java
index fee7e85..972ff68 100644
--- a/payment/src/main/java/org/killbill/billing/payment/retry/BaseRetryService.java
+++ b/payment/src/main/java/org/killbill/billing/payment/retry/BaseRetryService.java
@@ -104,13 +104,13 @@ public abstract class BaseRetryService implements RetryService {
             this.internalCallContextFactory = internalCallContextFactory;
         }
 
-        public boolean scheduleRetry(final UUID paymentId, final String transactionExternalKey, final String pluginName, final DateTime timeOfRetry) {
-            return scheduleRetryInternal(paymentId, transactionExternalKey, pluginName, timeOfRetry, null);
+        public boolean scheduleRetry(final ObjectType objectType, final UUID objectId, final String transactionExternalKey, final String pluginName, final DateTime timeOfRetry) {
+            return scheduleRetryInternal(objectType, objectId, transactionExternalKey, pluginName, timeOfRetry, null);
         }
 
 
-        private boolean scheduleRetryInternal(final UUID paymentId, final String transactionExternalKey, final String pluginName, final DateTime timeOfRetry, final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao) {
-            final InternalCallContext context = createCallContextFromPaymentId(paymentId);
+        private boolean scheduleRetryInternal(final ObjectType objectType, final UUID objectId, final String transactionExternalKey, final String pluginName, final DateTime timeOfRetry, final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao) {
+            final InternalCallContext context = createCallContextFromPaymentId(objectType, objectId);
 
             try {
                 final NotificationQueue retryQueue = notificationQueueService.getNotificationQueue(DefaultPaymentService.SERVICE_NAME, getQueueName());
@@ -126,14 +126,14 @@ public abstract class BaseRetryService implements RetryService {
                 log.error(String.format("Failed to retrieve notification queue %s:%s", DefaultPaymentService.SERVICE_NAME, getQueueName()));
                 return false;
             } catch (IOException e) {
-                log.error(String.format("Failed to serialize notificationQueue event for paymentId %s", paymentId));
+                log.error(String.format("Failed to serialize notificationQueue event for object %s, objectId %s", objectId));
                 return false;
             }
             return true;
         }
 
-        protected InternalCallContext createCallContextFromPaymentId(final UUID paymentId) {
-            return internalCallContextFactory.createInternalCallContext(paymentId, ObjectType.PAYMENT, PAYMENT_RETRY_SERVICE, CallOrigin.INTERNAL, UserType.SYSTEM, null);
+        protected InternalCallContext createCallContextFromPaymentId(final ObjectType objectType, final UUID objectId) {
+            return internalCallContextFactory.createInternalCallContext(objectId, objectType, PAYMENT_RETRY_SERVICE, CallOrigin.INTERNAL, UserType.SYSTEM, null);
         }
 
         public abstract String getQueueName();
diff --git a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg
index 1dddcb0..9ba054d 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg
+++ b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg
@@ -5,12 +5,17 @@ tableName() ::= "payment_attempts"
 historyTableName() ::= "payment_attempt_history"
 
 
+
 tableFields(prefix) ::= <<
-  <prefix>payment_external_key
+  <prefix>account_id
+, <prefix>payment_method_id
+, <prefix>payment_external_key
 , <prefix>transaction_id
 , <prefix>transaction_external_key
+, <prefix>transaction_type
 , <prefix>state_name
-, <prefix>operation_name
+, <prefix>amount
+, <prefix>currency
 , <prefix>plugin_name
 , <prefix>created_by
 , <prefix>created_date
@@ -19,11 +24,15 @@ tableFields(prefix) ::= <<
 >>
 
 tableValues() ::= <<
-  :paymentExternalKey
+  :accountId
+, :paymentMethodId
+, :paymentExternalKey
 , :transactionId
 , :transactionExternalKey
+, :transactionType
 , :stateName
-, :operationName
+, :amount
+, :currency
 , :pluginName
 , :createdBy
 , :createdDate
diff --git a/payment/src/main/resources/org/killbill/billing/payment/ddl.sql b/payment/src/main/resources/org/killbill/billing/payment/ddl.sql
index bf801e6..47592a4 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/ddl.sql
+++ b/payment/src/main/resources/org/killbill/billing/payment/ddl.sql
@@ -5,11 +5,15 @@ DROP TABLE IF EXISTS payment_attempts;
 CREATE TABLE payment_attempts (
     record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
     id char(36) NOT NULL,
+    account_id char(36) NOT NULL,
+    payment_method_id char(36) DEFAULT NULL,
     payment_external_key char(128) NOT NULL,
     transaction_id char(36),
     transaction_external_key char(128) NOT NULL,
+    transaction_type varchar(32) NOT NULL,
     state_name varchar(32) NOT NULL,
-    operation_name varchar(32) NOT NULL,
+    amount numeric(15,9),
+    currency char(3),
     plugin_name varchar(50) NOT NULL,
     created_by varchar(50) NOT NULL,
     created_date datetime NOT NULL,
@@ -30,11 +34,15 @@ CREATE TABLE payment_attempt_history (
     record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
     id char(36) NOT NULL,
     target_record_id int(11) unsigned NOT NULL,
+    account_id char(36) NOT NULL,
+    payment_method_id char(36) DEFAULT NULL,
     payment_external_key char(128) NOT NULL,
     transaction_id char(36),
     transaction_external_key char(128) NOT NULL,
+    transaction_type varchar(32) NOT NULL,
     state_name varchar(32) NOT NULL,
-    operation_name varchar(32) NOT NULL,
+    amount numeric(15,9),
+    currency char(3),
     plugin_name varchar(50) NOT NULL,
     change_type char(6) NOT NULL,
     created_by varchar(50) NOT NULL,
@@ -206,11 +214,11 @@ CREATE TABLE payment_plugin_properties (
 ) /*! CHARACTER SET utf8 COLLATE utf8_bin */;
 CREATE INDEX payment_plugin_properties_ext ON payment_plugin_properties(transaction_external_key);
 
+
 /*  PaymentControlPlugin lives  here until this becomes a first class citizen plugin */
 DROP TABLE IF EXISTS _invoice_payment_control_plugin_auto_pay_off;
 CREATE TABLE _invoice_payment_control_plugin_auto_pay_off (
     record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
-    id char(36) NOT NULL,
     payment_external_key varchar(255) NOT NULL,
     transaction_external_key varchar(255) NOT NULL,
     account_id char(36) NOT NULL,
@@ -221,10 +229,6 @@ CREATE TABLE _invoice_payment_control_plugin_auto_pay_off (
     currency char(3),
     created_by varchar(50) NOT NULL,
     created_date datetime NOT NULL,
-    updated_by varchar(50) NOT NULL,
-    updated_date datetime NOT NULL,
-    account_record_id int(11) unsigned DEFAULT NULL,
-    tenant_record_id int(11) unsigned DEFAULT NULL,
     PRIMARY KEY (record_id)
 ) /*! CHARACTER SET utf8 COLLATE utf8_bin */;
 CREATE INDEX _invoice_payment_control_plugin_auto_pay_off_account ON _invoice_payment_control_plugin_auto_pay_off(account_id);
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
index f4b72de..a373c8e 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
@@ -35,7 +35,6 @@ import org.killbill.billing.payment.MockRecurringInvoiceItem;
 import org.killbill.billing.payment.PaymentTestSuiteWithEmbeddedDB;
 import org.killbill.billing.payment.control.InvoicePaymentControlPluginApi;
 import org.killbill.billing.payment.dao.PaymentAttemptModelDao;
-import org.killbill.billing.payment.dao.PluginPropertyModelDao;
 import org.killbill.billing.retry.plugin.api.PaymentControlApiException;
 import org.killbill.bus.api.PersistentBus.EventBusException;
 import org.testng.Assert;
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryableDirectPayment.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryableDirectPayment.java
index 13874a0..c65752e 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryableDirectPayment.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryableDirectPayment.java
@@ -106,7 +106,7 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
     private final String directPaymentTransactionExternalKey = "foobar";
     private final BigDecimal amount = BigDecimal.ONE;
     private final Currency currency = Currency.EUR;
-    private final ImmutableList<PluginProperty> emptyProperties = ImmutableList.<PluginProperty>of();
+    private final ImmutableList<PluginProperty> emptyProperties = ImmutableList.of();
     private final MockPaymentControlProviderPlugin mockRetryProviderPlugin = new MockPaymentControlProviderPlugin();
 
     private MockRetryableDirectPaymentAutomatonRunner runner;
@@ -119,7 +119,6 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
         super.beforeClass();
         account = testHelper.createTestAccount("lolo@gmail.com", false);
         Mockito.when(accountInternalApi.getAccountById(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(account);
-        final UUID uuid = UUID.randomUUID();
         //Mockito.when(nonEntityDao.retrieveIdFromObject(Mockito.<Long>any(), Mockito.<ObjectType>any())).thenReturn(uuid);
         retryPluginRegistry.registerService(new OSGIServiceDescriptor() {
             @Override
@@ -220,10 +219,10 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                    callContext,
                    internalCallContext);
 
-        final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
         assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
         assertEquals(pa.getStateName(), "ABORTED");
-        assertEquals(pa.getOperationName(), "AUTHORIZE");
+        assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
     }
 
     @Test(groups = "fast")
@@ -254,10 +253,10 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                    callContext,
                    internalCallContext);
 
-        final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
         assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
         assertEquals(pa.getStateName(), "SUCCESS");
-        assertEquals(pa.getOperationName(), "AUTHORIZE");
+        assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
     }
 
     @Test(groups = "fast")
@@ -287,10 +286,10 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                    null,
                    callContext, internalCallContext);
 
-        final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
         assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
         assertEquals(pa.getStateName(), "SUCCESS");
-        assertEquals(pa.getOperationName(), "AUTHORIZE");
+        assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
     }
 
     @Test(groups = "fast")
@@ -323,11 +322,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
 
             Assert.fail("Expected PaymentApiException...");
 
-        } catch (PaymentApiException e) {
-            final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        } catch (final PaymentApiException e) {
+            final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
             assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
             assertEquals(pa.getStateName(), "ABORTED");
-            assertEquals(pa.getOperationName(), "AUTHORIZE");
+            assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
         }
     }
 
@@ -360,11 +359,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                        callContext, internalCallContext);
 
             Assert.fail("Expected PaymentApiException...");
-        } catch (PaymentApiException e) {
-            final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        } catch (final PaymentApiException e) {
+            final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
             assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
             assertEquals(pa.getStateName(), "RETRIED");
-            assertEquals(pa.getOperationName(), "AUTHORIZE");
+            assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
         }
     }
 
@@ -397,11 +396,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                        callContext, internalCallContext);
 
             Assert.fail("Expected Exception...");
-        } catch (PaymentApiException e) {
-            final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        } catch (final PaymentApiException e) {
+            final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
             assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
             assertEquals(pa.getStateName(), "RETRIED");
-            assertEquals(pa.getOperationName(), "AUTHORIZE");
+            assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
         }
     }
 
@@ -434,11 +433,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                        callContext, internalCallContext);
 
             Assert.fail("Expected Exception...");
-        } catch (PaymentApiException e) {
-            final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        } catch (final PaymentApiException e) {
+            final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
             assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
             assertEquals(pa.getStateName(), "ABORTED");
-            assertEquals(pa.getOperationName(), "AUTHORIZE");
+            assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
         }
     }
 
@@ -458,8 +457,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
 
         final State state = runner.fetchState("RETRIED");
         final UUID directTransactionId = UUID.randomUUID();
-        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(utcNow, utcNow, directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey, state.getName(), TransactionType.AUTHORIZE.name(), null),
-                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext);
+        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow,
+                                                                                 directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey,
+                                                                                 TransactionType.AUTHORIZE, state.getName(), amount, currency, null),
+                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext
+                                                     );
         runner.run(state,
                    false,
                    TransactionType.AUTHORIZE,
@@ -475,10 +477,10 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                    callContext,
                    internalCallContext);
 
-        final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
         assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
         assertEquals(pa.getStateName(), "SUCCESS");
-        assertEquals(pa.getOperationName(), "AUTHORIZE");
+        assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
     }
 
     @Test(groups = "fast")
@@ -497,8 +499,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
 
         final State state = runner.fetchState("RETRIED");
         final UUID directTransactionId = UUID.randomUUID();
-        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(utcNow, utcNow, directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey, state.getName(), TransactionType.AUTHORIZE.name(), null),
-                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext);
+        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow,
+                                                                                 directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey,
+                                                                                 TransactionType.AUTHORIZE, state.getName(), amount, currency, null),
+                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext
+                                                     );
 
         try {
             runner.run(state,
@@ -517,11 +522,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                        internalCallContext);
 
             Assert.fail("Expecting paymentApiException...");
-        } catch (PaymentApiException e) {
-            final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        } catch (final PaymentApiException e) {
+            final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
             assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
             assertEquals(pa.getStateName(), "RETRIED");
-            assertEquals(pa.getOperationName(), "AUTHORIZE");
+            assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
         }
     }
 
@@ -541,8 +546,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
 
         final State state = runner.fetchState("RETRIED");
         final UUID directTransactionId = UUID.randomUUID();
-        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(utcNow, utcNow, directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey, state.getName(), TransactionType.AUTHORIZE.name(), null),
-                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext);
+        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow,
+                                                                                 directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey,
+                                                                                 TransactionType.AUTHORIZE, state.getName(), amount, currency, null),
+                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext
+                                                     );
 
         try {
             runner.run(state,
@@ -561,11 +569,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
                        internalCallContext);
 
             Assert.fail("Expecting paymentApiException...");
-        } catch (PaymentApiException e) {
-            final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        } catch (final PaymentApiException e) {
+            final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
             assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
             assertEquals(pa.getStateName(), "ABORTED");
-            assertEquals(pa.getOperationName(), "AUTHORIZE");
+            assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
         }
     }
 
@@ -586,18 +594,21 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
         final State state = runner.fetchState("RETRIED");
         final UUID directTransactionId = UUID.randomUUID();
         final UUID directPaymentId = UUID.randomUUID();
-        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(utcNow, utcNow, directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey, state.getName(), TransactionType.AUTHORIZE.name(), null),
-                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext);
+        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow,
+                                                                                 directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey,
+                                                                                 TransactionType.AUTHORIZE, state.getName(), amount, currency, null),
+                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext
+                                                     );
         paymentDao.insertDirectPaymentWithFirstTransaction(new PaymentModelDao(directPaymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, directPaymentExternalKey),
                                                            new PaymentTransactionModelDao(directTransactionId, directPaymentTransactionExternalKey, utcNow, utcNow, directPaymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"),
                                                            internalCallContext);
 
         processor.retryPaymentTransaction(directPaymentTransactionExternalKey, MockPaymentControlProviderPlugin.PLUGIN_NAME, internalCallContext);
 
-        final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
         assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
         assertEquals(pa.getStateName(), "SUCCESS");
-        assertEquals(pa.getOperationName(), "AUTHORIZE");
+        assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
     }
 
     @Test(groups = "fast")
@@ -617,8 +628,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
         final State state = runner.fetchState("RETRIED");
         final UUID directTransactionId = UUID.randomUUID();
         final UUID directPaymentId = UUID.randomUUID();
-        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(utcNow, utcNow, directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey, state.getName(), TransactionType.AUTHORIZE.name(), null),
-                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext);
+        paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow,
+                                                                                 directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey,
+                                                                                 TransactionType.AUTHORIZE, state.getName(), amount, currency, null),
+                                                      ImmutableList.<PluginPropertyModelDao>of(), internalCallContext
+                                                     );
         paymentDao.insertDirectPaymentWithFirstTransaction(new PaymentModelDao(directPaymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, directPaymentExternalKey),
                                                            new PaymentTransactionModelDao(directTransactionId, directPaymentTransactionExternalKey, utcNow, utcNow, directPaymentId, TransactionType.AUTHORIZE, utcNow,
                                                                                           TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"),
@@ -627,10 +641,10 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
 
         processor.retryPaymentTransaction(directPaymentTransactionExternalKey, MockPaymentControlProviderPlugin.PLUGIN_NAME, internalCallContext);
 
-        final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+        final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
         assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
         assertEquals(pa.getStateName(), "ABORTED");
-        assertEquals(pa.getOperationName(), "AUTHORIZE");
+        assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
     }
 
     @Test(groups = "fast")
@@ -655,8 +669,11 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
             final State state = runner.fetchState("RETRIED");
             final UUID directTransactionId = UUID.randomUUID();
             final UUID directPaymentId = UUID.randomUUID();
-            paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(utcNow, utcNow, directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey, state.getName(), TransactionType.AUTHORIZE.name(), null),
-                                                          ImmutableList.<PluginPropertyModelDao>of(), internalCallContext);
+            paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow,
+                                                                                     directPaymentExternalKey, directTransactionId, directPaymentTransactionExternalKey,
+                                                                                     TransactionType.AUTHORIZE, state.getName(), amount, currency, null),
+                                                          ImmutableList.<PluginPropertyModelDao>of(), internalCallContext
+                                                         );
             paymentDao.insertDirectPaymentWithFirstTransaction(new PaymentModelDao(directPaymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, directPaymentExternalKey),
                                                                new PaymentTransactionModelDao(directTransactionId, directPaymentTransactionExternalKey, utcNow, utcNow, directPaymentId, TransactionType.AUTHORIZE, utcNow,
                                                                                               TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"),
@@ -665,11 +682,10 @@ public class TestRetryableDirectPayment extends PaymentTestSuiteNoDB {
 
             processor.retryPaymentTransaction(directPaymentTransactionExternalKey, MockPaymentControlProviderPlugin.PLUGIN_NAME, internalCallContext);
 
-            final PaymentAttemptModelDao pa = ((MockPaymentDao) paymentDao).getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+            final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByExternalKey(directPaymentTransactionExternalKey, internalCallContext);
             assertEquals(pa.getTransactionExternalKey(), directPaymentTransactionExternalKey);
             assertEquals(pa.getStateName(), "ABORTED");
-            assertEquals(pa.getOperationName(), "AUTHORIZE");
-
+            assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
         } finally {
             if (lock != null) {
                 lock.release();
diff --git a/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java b/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java
index 6507522..efafe53 100644
--- a/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java
+++ b/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java
@@ -42,7 +42,7 @@ public class TestPaymentDao extends PaymentTestSuiteWithEmbeddedDB {
         final String paymentExternalKey = "vraiment?";
         final String transactionExternalKey = "tduteuqweq";
         final String stateName = "INIT";
-        final String operationName = "AUTHORIZE";
+        final TransactionType transactionType = TransactionType.AUTHORIZE;
         final String pluginName = "superPlugin";
 
         final UUID accountId = UUID.randomUUID();
@@ -54,10 +54,12 @@ public class TestPaymentDao extends PaymentTestSuiteWithEmbeddedDB {
         props.add(prop2);
         props.add(prop3);
 
-        final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(clock.getUTCNow(), clock.getUTCNow(), paymentExternalKey, directTransactionId, transactionExternalKey, stateName, operationName, pluginName);
+        final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(UUID.randomUUID(), UUID.randomUUID(), clock.getUTCNow(), clock.getUTCNow(),
+                                                                          paymentExternalKey, directTransactionId, transactionExternalKey, transactionType, stateName,
+                                                                          BigDecimal.ZERO, Currency.ALL, pluginName);
         PaymentAttemptModelDao savedAttempt = paymentDao.insertPaymentAttemptWithProperties(attempt, props, internalCallContext);
         assertEquals(savedAttempt.getTransactionExternalKey(), transactionExternalKey);
-        assertEquals(savedAttempt.getOperationName(), operationName);
+        assertEquals(savedAttempt.getTransactionType(), transactionType);
         assertEquals(savedAttempt.getStateName(), stateName);
         assertEquals(savedAttempt.getPluginName(), pluginName);
 
@@ -81,13 +83,13 @@ public class TestPaymentDao extends PaymentTestSuiteWithEmbeddedDB {
 
         final PaymentAttemptModelDao retrievedAttempt1 = paymentDao.getPaymentAttempt(attempt.getId(), internalCallContext);
         assertEquals(retrievedAttempt1.getTransactionExternalKey(), transactionExternalKey);
-        assertEquals(retrievedAttempt1.getOperationName(), operationName);
+        assertEquals(retrievedAttempt1.getTransactionType(), transactionType);
         assertEquals(retrievedAttempt1.getStateName(), stateName);
         assertEquals(retrievedAttempt1.getPluginName(), pluginName);
 
         final PaymentAttemptModelDao retrievedAttempt2 = paymentDao.getPaymentAttemptByExternalKey(transactionExternalKey, internalCallContext);
         assertEquals(retrievedAttempt2.getTransactionExternalKey(), transactionExternalKey);
-        assertEquals(retrievedAttempt2.getOperationName(), operationName);
+        assertEquals(retrievedAttempt2.getTransactionType(), transactionType);
         assertEquals(retrievedAttempt2.getStateName(), stateName);
         assertEquals(retrievedAttempt2.getPluginName(), pluginName);
     }