killbill-memoizeit

Merge remote-tracking branch 'origin/fix-for-981' into

6/17/2018 7:40:37 PM

Details

diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java b/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
index 1460429..0f2cba2 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/svcs/DefaultInvoiceInternalApi.java
@@ -220,6 +220,6 @@ public class DefaultInvoiceInternalApi implements InvoiceInternalApi {
     @Override
     public InvoicePayment getInvoicePaymentByCookieId(final String cookieId, final TenantContext context) {
         final InvoicePaymentModelDao invoicePaymentModelDao = dao.getInvoicePaymentByCookieId(cookieId, internalCallContextFactory.createInternalTenantContext(context.getAccountId(), ObjectType.ACCOUNT, context));
-        return new DefaultInvoicePayment(invoicePaymentModelDao);
+        return invoicePaymentModelDao == null ? null : new DefaultInvoicePayment(invoicePaymentModelDao);
     }
 }
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
index 54aa634..24b456d 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
@@ -164,9 +164,10 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
                                                 @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException, AccountApiException {
         verifyNonNullOrEmpty(json, "InvoicePaymentTransactionJson body should be specified");
 
-        final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request);
-        final Payment payment = paymentApi.getPayment(paymentId, false, false, ImmutableList.<PluginProperty>of(), callContext);
-        final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContext);
+        final CallContext callContextNoAccountId = context.createCallContextNoAccountId(createdBy, reason, comment, request);
+        final Payment payment = paymentApi.getPayment(paymentId, false, false, ImmutableList.<PluginProperty>of(), callContextNoAccountId);
+        final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContextNoAccountId);
+        final CallContext callContext = context.createCallContextWithAccountId(account.getId(), createdBy, reason, comment, request);
 
         final Iterable<PluginProperty> pluginProperties;
         final String transactionExternalKey = json.getTransactionExternalKey() != null ? json.getTransactionExternalKey() : UUIDs.randomUUID().toString();
@@ -187,37 +188,40 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
             pluginProperties = extractPluginProperties(pluginPropertiesString);
         }
 
-        final InvoicePayment result;
+        final UUID paymentIdToRedirectTo;
         if (externalPayment) {
-            result = invoicePaymentApi.createCreditForInvoicePayment(isAdjusted,
-                                                                     adjustments,
-                                                                     account,
-                                                                     paymentId,
-                                                                     paymentMethodId,
-                                                                     null,
-                                                                     json.getAmount(),
-                                                                     account.getCurrency(),
-                                                                     json.getEffectiveDate(),
-                                                                     paymentExternalKey,
-                                                                     transactionExternalKey,
-                                                                     pluginProperties,
-                                                                     createInvoicePaymentControlPluginApiPaymentOptions(true),
-                                                                     callContext);
+            final InvoicePayment result = invoicePaymentApi.createCreditForInvoicePayment(isAdjusted,
+                                                                                          adjustments,
+                                                                                          account,
+                                                                                          paymentId,
+                                                                                          paymentMethodId,
+                                                                                          null,
+                                                                                          json.getAmount(),
+                                                                                          account.getCurrency(),
+                                                                                          json.getEffectiveDate(),
+                                                                                          paymentExternalKey,
+                                                                                          transactionExternalKey,
+                                                                                          pluginProperties,
+                                                                                          createInvoicePaymentControlPluginApiPaymentOptions(true),
+                                                                                          callContext);
+            // /!\ Note! The invoicePayment#paymentId points to the original payment (PURCHASE) here, NOT the new one (CREDIT)
+            paymentIdToRedirectTo = paymentApi.getPaymentByTransactionExternalKey(transactionExternalKey, false, false, ImmutableList.<PluginProperty>of(), callContext).getId();
         } else {
-            result = invoicePaymentApi.createRefundForInvoicePayment(isAdjusted,
-                                                                     adjustments,
-                                                                     account,
-                                                                     payment.getId(),
-                                                                     json.getAmount(),
-                                                                     account.getCurrency(),
-                                                                     json.getEffectiveDate(),
-                                                                     transactionExternalKey,
-                                                                     pluginProperties,
-                                                                     createInvoicePaymentControlPluginApiPaymentOptions(false),
-                                                                     callContext);
+            final InvoicePayment result = invoicePaymentApi.createRefundForInvoicePayment(isAdjusted,
+                                                                                          adjustments,
+                                                                                          account,
+                                                                                          payment.getId(),
+                                                                                          json.getAmount(),
+                                                                                          account.getCurrency(),
+                                                                                          json.getEffectiveDate(),
+                                                                                          transactionExternalKey,
+                                                                                          pluginProperties,
+                                                                                          createInvoicePaymentControlPluginApiPaymentOptions(false),
+                                                                                          callContext);
+            paymentIdToRedirectTo = result.getPaymentId();
         }
 
-        return uriBuilder.buildResponse(uriInfo, InvoicePaymentResource.class, "getInvoicePayment", result.getId(), request);
+        return uriBuilder.buildResponse(uriInfo, InvoicePaymentResource.class, "getInvoicePayment", paymentIdToRedirectTo, request);
     }
 
     @TimedResource
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
index 99bdd75..bceabc9 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
@@ -73,6 +73,7 @@ import org.killbill.commons.metrics.TimedResource;
 import com.google.common.collect.ImmutableList;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 
@@ -117,6 +118,25 @@ public class TransactionResource extends JaxRsResourceBase {
         return Response.status(Response.Status.OK).entity(result).build();
     }
 
+    @TimedResource(name = "getPaymentByTransactionExternalKey")
+    @GET
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Retrieve a payment by transaction external key", response = PaymentJson.class)
+    @ApiResponses(value = {@ApiResponse(code = 404, message = "Payment not found")})
+    public Response getPaymentByTransactionExternalKey(@ApiParam(required = true) @QueryParam(QUERY_TRANSACTION_EXTERNAL_KEY) final String paymentTransactionExternalKey,
+                                                       @QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+                                                       @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
+                                                       @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
+                                                       @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+                                                       @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
+        final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
+        final TenantContext tenantContext = context.createTenantContextNoAccountId(request);
+        final Payment payment = paymentApi.getPaymentByTransactionExternalKey(paymentTransactionExternalKey, withPluginInfo, withAttempts, pluginProperties, tenantContext);
+        final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext);
+        final PaymentJson result = new PaymentJson(payment, accountAuditLogs);
+        return Response.status(Response.Status.OK).entity(result).build();
+    }
+
     @TimedResource
     @POST
     @Path("/{transactionId:" + UUID_PATTERN + "}/")
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
index cf9d900..1418ef1 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
@@ -1085,6 +1085,15 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
         return payment;
     }
 
+    @Override
+    public Payment getPaymentByTransactionExternalKey(final String transactionExternalKey, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext context) throws PaymentApiException {
+        final Payment payment = paymentProcessor.getPaymentByTransactionExternalKey(transactionExternalKey, withPluginInfo, withAttempts, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
+        if (payment == null) {
+            throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT, transactionExternalKey);
+        }
+        return payment;
+    }
+
     private PaymentTransaction findPaymentTransaction(final Payment payment, @Nullable final String paymentTransactionExternalKey) {
         // By design, the payment transactions are already correctly sorted (by effective date asc)
         if (paymentTransactionExternalKey == null) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultInvoicePaymentInternalApi.java b/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultInvoicePaymentInternalApi.java
index 9f99f7b..bf91b44 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultInvoicePaymentInternalApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/svcs/DefaultInvoicePaymentInternalApi.java
@@ -95,11 +95,11 @@ public class DefaultInvoicePaymentInternalApi extends DefaultApiBase implements 
         }
         pluginProperties.add(new PluginProperty("IPCD_INVOICE_ID", invoiceId.toString(), false));
 
-        // TODO should we add paymentConfig.getPaymentControlPluginNames(internalTenantContext)?
-        final List<String> paymentControlPluginNames = InvoicePaymentPaymentOptions.create(paymentOptions).getPaymentControlPluginNames();
-
         final CallContext callContext = internalCallContextFactory.createCallContext(internalCallContext);
 
+        final List<String> defaultOrUserSpecifiedPaymentControlPluginNames = toPaymentControlPluginNames(paymentOptions, callContext);
+        final List<String> paymentControlPluginNames = InvoicePaymentPaymentOptions.addInvoicePaymentControlPlugin(defaultOrUserSpecifiedPaymentControlPluginNames);
+
         final UUID resolvedPaymentMethodId = (paymentMethodId == null && paymentOptions.isExternalPayment()) ?
                                              paymentMethodProcessor.createOrGetExternalPaymentMethod(UUIDs.randomUUID().toString(), account, pluginProperties, callContext, internalCallContext) :
                                              paymentMethodId;
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/svcs/InvoicePaymentPaymentOptions.java b/payment/src/main/java/org/killbill/billing/payment/api/svcs/InvoicePaymentPaymentOptions.java
index f6e81c8..ad2c6d3 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/svcs/InvoicePaymentPaymentOptions.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/svcs/InvoicePaymentPaymentOptions.java
@@ -17,6 +17,7 @@
 
 package org.killbill.billing.payment.api.svcs;
 
+import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -34,13 +35,18 @@ public class InvoicePaymentPaymentOptions implements PaymentOptions {
     }
 
     public static InvoicePaymentPaymentOptions create(final PaymentOptions paymentOptions) {
+        final List<String> controlPluginNamesFromUser = paymentOptions.getPaymentControlPluginNames();
+        final List<String> paymentControlPluginNames = addInvoicePaymentControlPlugin(controlPluginNamesFromUser);
+        return new InvoicePaymentPaymentOptions(paymentOptions.isExternalPayment(), paymentControlPluginNames);
+    }
+
+    public static List<String> addInvoicePaymentControlPlugin(final Collection<String> controlPluginNamesFromUser) {
         final List<String> paymentControlPluginNames = new LinkedList<String>();
-        paymentControlPluginNames.addAll(paymentOptions.getPaymentControlPluginNames());
+        paymentControlPluginNames.addAll(controlPluginNamesFromUser);
         if (!paymentControlPluginNames.contains(InvoicePaymentControlPluginApi.PLUGIN_NAME)) {
             paymentControlPluginNames.add(InvoicePaymentControlPluginApi.PLUGIN_NAME);
         }
-
-        return new InvoicePaymentPaymentOptions(paymentOptions.isExternalPayment(), paymentControlPluginNames);
+        return paymentControlPluginNames;
     }
 
     @Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
index ecaa6d8..e3bfbfa 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
@@ -435,12 +435,22 @@ public class PaymentProcessor extends ProcessorBase {
     public Payment getPaymentByTransactionId(final UUID transactionId, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
         final PaymentTransactionModelDao paymentTransactionDao = paymentDao.getPaymentTransaction(transactionId, internalTenantContext);
         if (null != paymentTransactionDao) {
-            PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentTransactionDao.getPaymentId(), internalTenantContext);
+            final PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentTransactionDao.getPaymentId(), internalTenantContext);
             return toPayment(paymentModelDao, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
         }
         return null;
     }
 
+    public Payment getPaymentByTransactionExternalKey(final String transactionExternalKey, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+        final List<PaymentTransactionModelDao> paymentTransactionDao = paymentDao.getPaymentTransactionsByExternalKey(transactionExternalKey, internalTenantContext);
+        if (paymentTransactionDao.isEmpty()) {
+            return null;
+        }
+        // All transactions must be on the same payment (see sanity in buildPaymentStateContext)
+        final PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentTransactionDao.get(0).getPaymentId(), internalTenantContext);
+        return toPayment(paymentModelDao, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
+    }
+
     private Payment performOperation(final boolean isApiPayment,
                                      @Nullable final UUID attemptId,
                                      final TransactionType transactionType,
diff --git a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
index c4ca078..530530f 100644
--- a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
@@ -66,6 +66,7 @@ public class GuicyKillbillTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
         }
 
         cleanupAllTables();
+        callContext.setDelegate(null, internalCallContext);
         controlCacheDispatcher.clearAll();
     }