killbill-memoizeit
Merge pull request #1108 from killbill/entitlement-plugin-api-fixes Entitlement …
Changes
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithEntilementPlugin.java 5(+5 -0)
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultBaseEntitlementWithAddOnsSpecifier.java 79(+76 -3)
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java 25(+17 -8)
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java 155(+135 -20)
entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java 12(+6 -6)
entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java 8(+4 -4)
entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java 6(+3 -3)
entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java 104(+43 -61)
Details
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithEntilementPlugin.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithEntilementPlugin.java
index f6037c5..1fb592d 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithEntilementPlugin.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithEntilementPlugin.java
@@ -49,6 +49,7 @@ import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -185,6 +186,10 @@ public class TestWithEntilementPlugin extends TestIntegrationBase {
@Override
public OnSuccessEntitlementResult onSuccessCall(final EntitlementContext entitlementContext, final Iterable<PluginProperty> properties) throws EntitlementPluginApiException {
+ for (final BaseEntitlementWithAddOnsSpecifier specifier : entitlementContext.getBaseEntitlementWithAddOnsSpecifiers()) {
+ Assert.assertNotNull(specifier.getBundleId());
+ Assert.assertNotNull(specifier.getExternalKey());
+ }
return null;
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultBaseEntitlementWithAddOnsSpecifier.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultBaseEntitlementWithAddOnsSpecifier.java
index 265d0b9..6332460 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultBaseEntitlementWithAddOnsSpecifier.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultBaseEntitlementWithAddOnsSpecifier.java
@@ -1,5 +1,6 @@
/*
- * Copyright 2016 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -22,13 +23,24 @@ import org.joda.time.LocalDate;
public class DefaultBaseEntitlementWithAddOnsSpecifier implements BaseEntitlementWithAddOnsSpecifier {
- private final UUID bundleId;
- private final String externalKey;
private final Iterable<EntitlementSpecifier> entitlementSpecifier;
private final LocalDate entitlementEffectiveDate;
private final LocalDate billingEffectiveDate;
private final boolean isMigrated;
+ // Maybe populated after create or transfer
+ private UUID bundleId;
+ private String externalKey;
+
+ public DefaultBaseEntitlementWithAddOnsSpecifier(final BaseEntitlementWithAddOnsSpecifier input) {
+ this(input.getBundleId(),
+ input.getExternalKey(),
+ input.getEntitlementSpecifier(),
+ input.getEntitlementEffectiveDate(),
+ input.getBillingEffectiveDate(),
+ input.isMigrated());
+ }
+
public DefaultBaseEntitlementWithAddOnsSpecifier(final UUID bundleId,
final String externalKey,
final Iterable<EntitlementSpecifier> entitlementSpecifier,
@@ -48,11 +60,19 @@ public class DefaultBaseEntitlementWithAddOnsSpecifier implements BaseEntitlemen
return bundleId;
}
+ public void setBundleId(final UUID bundleId) {
+ this.bundleId = bundleId;
+ }
+
@Override
public String getExternalKey() {
return externalKey;
}
+ public void setExternalKey(final String externalKey) {
+ this.externalKey = externalKey;
+ }
+
@Override
public Iterable<EntitlementSpecifier> getEntitlementSpecifier() {
return entitlementSpecifier;
@@ -72,4 +92,57 @@ public class DefaultBaseEntitlementWithAddOnsSpecifier implements BaseEntitlemen
public boolean isMigrated() {
return isMigrated;
}
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("DefaultBaseEntitlementWithAddOnsSpecifier{");
+ sb.append("entitlementSpecifier=").append(entitlementSpecifier);
+ sb.append(", entitlementEffectiveDate=").append(entitlementEffectiveDate);
+ sb.append(", billingEffectiveDate=").append(billingEffectiveDate);
+ sb.append(", isMigrated=").append(isMigrated);
+ sb.append(", bundleId=").append(bundleId);
+ sb.append(", externalKey='").append(externalKey).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultBaseEntitlementWithAddOnsSpecifier that = (DefaultBaseEntitlementWithAddOnsSpecifier) o;
+
+ if (isMigrated != that.isMigrated) {
+ return false;
+ }
+ if (entitlementSpecifier != null ? !entitlementSpecifier.equals(that.entitlementSpecifier) : that.entitlementSpecifier != null) {
+ return false;
+ }
+ if (entitlementEffectiveDate != null ? entitlementEffectiveDate.compareTo(that.entitlementEffectiveDate) != 0 : that.entitlementEffectiveDate != null) {
+ return false;
+ }
+ if (billingEffectiveDate != null ? billingEffectiveDate.compareTo(that.billingEffectiveDate) != 0 : that.billingEffectiveDate != null) {
+ return false;
+ }
+ if (bundleId != null ? !bundleId.equals(that.bundleId) : that.bundleId != null) {
+ return false;
+ }
+ return externalKey != null ? externalKey.equals(that.externalKey) : that.externalKey == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = entitlementSpecifier != null ? entitlementSpecifier.hashCode() : 0;
+ result = 31 * result + (entitlementEffectiveDate != null ? entitlementEffectiveDate.hashCode() : 0);
+ result = 31 * result + (billingEffectiveDate != null ? billingEffectiveDate.hashCode() : 0);
+ result = 31 * result + (isMigrated ? 1 : 0);
+ result = 31 * result + (bundleId != null ? bundleId.hashCode() : 0);
+ result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
+ return result;
+ }
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
index 4e3200b..794cc6b 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2018 Groupon, Inc
- * Copyright 2014-2018 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -336,7 +336,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
final WithEntitlementPlugin<Entitlement> cancelEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
if (eventsStream.isEntitlementCancelled()) {
throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
}
@@ -402,7 +402,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
final WithEntitlementPlugin<Void> uncancelEntitlementWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
- public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
if (eventsStream.isSubscriptionCancelled()) {
throw new EntitlementApiException(ErrorCode.SUB_UNCANCEL_BAD_STATE, getId());
}
@@ -484,7 +484,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
final WithEntitlementPlugin<Entitlement> cancelEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
if (eventsStream.isEntitlementCancelled()) {
throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
}
@@ -566,7 +566,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
if (!eventsStream.isEntitlementActive()) {
throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
}
@@ -638,7 +638,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
final WithEntitlementPlugin<Void> undoChangePlanEntitlementWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
- public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
try {
getSubscriptionBase().undoChangePlan(callContext);
@@ -682,7 +682,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
if (effectiveDate != null && effectiveDate.compareTo(eventsStream.getEntitlementEffectiveStartDate()) < 0) {
throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
@@ -757,7 +757,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
index 3deb24d..ea40e75 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2018 Groupon, Inc
- * Copyright 2014-2018 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -306,7 +306,7 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
final WithEntitlementPlugin<UUID> transferWithPlugin = new WithEntitlementPlugin<UUID>() {
@Override
- public UUID doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public UUID doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
final boolean cancelImm;
switch (billingPolicy) {
case IMMEDIATE:
@@ -332,11 +332,14 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
throw new EntitlementApiException(new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, externalKey));
}
- final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = getFirstBaseEntitlementWithAddOnsSpecifier(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers());
+ final DefaultBaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = getFirstBaseEntitlementWithAddOnsSpecifier(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers());
final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getBillingEffectiveDate(), updatedPluginContext.getCreatedDate(), contextWithSourceAccountRecordId);
final SubscriptionBaseBundle newBundle = subscriptionBaseTransferApi.transferBundle(sourceAccountId, destAccountId, externalKey, requestedDate, true, cancelImm, context);
+ // Update the context for plugins
+ baseEntitlementWithAddOnsSpecifier.setBundleId(newBundle.getId());
+ baseEntitlementWithAddOnsSpecifier.setExternalKey(newBundle.getExternalKey());
final Map<BlockingState, UUID> blockingStates = new HashMap<BlockingState, UUID>();
@@ -359,7 +362,6 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
}
entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(blockingStates, contextWithDestAccountRecordId);
-
return newBundle.getId();
} catch (final SubscriptionBaseTransferApiException e) {
throw new EntitlementApiException(e);
@@ -389,7 +391,7 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
final WithEntitlementPlugin<List<UUID>> createBaseEntitlementsWithAddOns = new WithEntitlementPlugin<List<UUID>>() {
@Override
- public List<UUID> doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public List<UUID> doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext);
final Catalog catalog;
@@ -446,13 +448,20 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
throw new EntitlementApiException(e);
}
+ // Update the context for plugins (assume underlying ordering is respected)
+ for (int i = 0; i < subscriptionsWithAddOns.size(); i++) {
+ final SubscriptionBaseWithAddOns subscriptionBaseWithAddOns = subscriptionsWithAddOns.get(i);
+ updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers(i).setBundleId(subscriptionBaseWithAddOns.getBundle().getId());
+ updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers(i).setExternalKey(subscriptionBaseWithAddOns.getBundle().getExternalKey());
+ }
+
return createEntitlementEvents(baseEntitlementWithAddOnsSpecifiersAfterPlugins, subscriptionsWithAddOns, updatedPluginContext, contextWithValidAccountRecordId);
}
};
return pluginExecution.executeWithPlugin(createBaseEntitlementsWithAddOns, pluginContext);
}
- private BaseEntitlementWithAddOnsSpecifier getFirstBaseEntitlementWithAddOnsSpecifier(final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers) throws SubscriptionBaseApiException {
+ private DefaultBaseEntitlementWithAddOnsSpecifier getFirstBaseEntitlementWithAddOnsSpecifier(final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers) throws SubscriptionBaseApiException {
if (baseEntitlementWithAddOnsSpecifiers == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_INVALID_ENTITLEMENT_SPECIFIER);
}
@@ -462,7 +471,7 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_INVALID_ENTITLEMENT_SPECIFIER);
}
- return iterator.next();
+ return (DefaultBaseEntitlementWithAddOnsSpecifier) iterator.next();
}
private UUID populateCaches(final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier,
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java
index 03811c9..c5ce58a 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -17,6 +17,7 @@
package org.killbill.billing.entitlement.api;
+import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -31,6 +32,8 @@ import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.CallOrigin;
import org.killbill.billing.util.callcontext.UserType;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
public class DefaultEntitlementContext implements EntitlementContext {
@@ -38,7 +41,7 @@ public class DefaultEntitlementContext implements EntitlementContext {
private final OperationType operationType;
private final UUID accountId;
private final UUID destinationAccountId;
- private final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers;
+ private final List<DefaultBaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers;
private final BillingActionPolicy billingActionPolicy;
private final Iterable<PluginProperty> pluginProperties;
private final UUID userToken;
@@ -56,26 +59,16 @@ public class DefaultEntitlementContext implements EntitlementContext {
this(prev.getOperationType(),
prev.getAccountId(),
prev.getDestinationAccountId(),
- pluginResult != null ? merge(prev.getBaseEntitlementWithAddOnsSpecifiers(), pluginResult.getAdjustedBaseEntitlementWithAddOnsSpecifiers()) : prev.getBaseEntitlementWithAddOnsSpecifiers(),
+ pluginResult != null ? lastUnlessEmptyOrFirst(prev.getBaseEntitlementWithAddOnsSpecifiers(), pluginResult.getAdjustedBaseEntitlementWithAddOnsSpecifiers()) : prev.getBaseEntitlementWithAddOnsSpecifiers(),
pluginResult != null && pluginResult.getAdjustedBillingActionPolicy() != null ? pluginResult.getAdjustedBillingActionPolicy() : prev.getBillingActionPolicy(),
- pluginResult != null ? merge(prev.getPluginProperties(), pluginResult.getAdjustedPluginProperties()) : prev.getPluginProperties(),
+ pluginResult != null ? lastUnlessEmptyOrFirst(prev.getPluginProperties(), pluginResult.getAdjustedPluginProperties()) : prev.getPluginProperties(),
prev);
}
- private static <T> Iterable<T> merge(final Iterable<T> prevValues, final Iterable<T> newValues) {
- // Be lenient if a plugin returns an empty list (default behavior for Ruby plugins): at this point,
- // we know the isAborted flag hasn't been set, so let's assume the user actually wants to use the previous list
- if (newValues != null && !Iterables.isEmpty(newValues)) {
- return newValues;
- } else {
- return prevValues;
- }
- }
-
public DefaultEntitlementContext(final OperationType operationType,
final UUID accountId,
final UUID destinationAccountId,
- final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers,
+ @Nullable final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers,
@Nullable final BillingActionPolicy actionPolicy,
final Iterable<PluginProperty> pluginProperties,
final CallContext callContext) {
@@ -84,11 +77,10 @@ public class DefaultEntitlementContext implements EntitlementContext {
callContext.getComments(), callContext.getCreatedDate(), callContext.getUpdatedDate(), callContext.getTenantId());
}
-
public DefaultEntitlementContext(final OperationType operationType,
final UUID accountId,
final UUID destinationAccountId,
- final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers,
+ @Nullable final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifiers,
@Nullable final BillingActionPolicy actionPolicy,
final Iterable<PluginProperty> pluginProperties,
final UUID userToken,
@@ -103,7 +95,17 @@ public class DefaultEntitlementContext implements EntitlementContext {
this.operationType = operationType;
this.accountId = accountId;
this.destinationAccountId = destinationAccountId;
- this.baseEntitlementWithAddOnsSpecifiers = baseEntitlementWithAddOnsSpecifiers;
+ if (baseEntitlementWithAddOnsSpecifiers == null) {
+ this.baseEntitlementWithAddOnsSpecifiers = ImmutableList.<DefaultBaseEntitlementWithAddOnsSpecifier>of();
+ } else {
+ this.baseEntitlementWithAddOnsSpecifiers = ImmutableList.<DefaultBaseEntitlementWithAddOnsSpecifier>copyOf(Iterables.<BaseEntitlementWithAddOnsSpecifier, DefaultBaseEntitlementWithAddOnsSpecifier>transform(baseEntitlementWithAddOnsSpecifiers,
+ new Function<BaseEntitlementWithAddOnsSpecifier, DefaultBaseEntitlementWithAddOnsSpecifier>() {
+ @Override
+ public DefaultBaseEntitlementWithAddOnsSpecifier apply(final BaseEntitlementWithAddOnsSpecifier input) {
+ return new DefaultBaseEntitlementWithAddOnsSpecifier(input);
+ }
+ }));
+ }
this.billingActionPolicy = actionPolicy;
this.pluginProperties = pluginProperties;
this.userToken = userToken;
@@ -117,6 +119,16 @@ public class DefaultEntitlementContext implements EntitlementContext {
this.tenantId = tenantId;
}
+ private static <T> Iterable<T> lastUnlessEmptyOrFirst(final Iterable<T> prevValues, final Iterable<T> newValues) {
+ // Be lenient if a plugin returns an empty list (default behavior for Ruby plugins): at this point,
+ // we know the isAborted flag hasn't been set, so let's assume the user actually wants to use the previous list
+ if (newValues != null && !Iterables.isEmpty(newValues)) {
+ return newValues;
+ } else {
+ return prevValues;
+ }
+ }
+
@Override
public OperationType getOperationType() {
return operationType;
@@ -134,7 +146,12 @@ public class DefaultEntitlementContext implements EntitlementContext {
@Override
public Iterable<BaseEntitlementWithAddOnsSpecifier> getBaseEntitlementWithAddOnsSpecifiers() {
- return baseEntitlementWithAddOnsSpecifiers;
+ //noinspection unchecked
+ return (Iterable) baseEntitlementWithAddOnsSpecifiers;
+ }
+
+ public DefaultBaseEntitlementWithAddOnsSpecifier getBaseEntitlementWithAddOnsSpecifiers(final int idx) {
+ return baseEntitlementWithAddOnsSpecifiers.get(idx);
}
@Override
@@ -191,4 +208,102 @@ public class DefaultEntitlementContext implements EntitlementContext {
public UUID getTenantId() {
return tenantId;
}
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("DefaultEntitlementContext{");
+ sb.append("operationType=").append(operationType);
+ sb.append(", accountId=").append(accountId);
+ sb.append(", destinationAccountId=").append(destinationAccountId);
+ sb.append(", baseEntitlementWithAddOnsSpecifiers=").append(baseEntitlementWithAddOnsSpecifiers);
+ sb.append(", billingActionPolicy=").append(billingActionPolicy);
+ sb.append(", pluginProperties=").append(pluginProperties);
+ sb.append(", userToken=").append(userToken);
+ sb.append(", userName='").append(userName).append('\'');
+ sb.append(", callOrigin=").append(callOrigin);
+ sb.append(", userType=").append(userType);
+ sb.append(", reasonCode='").append(reasonCode).append('\'');
+ sb.append(", comments='").append(comments).append('\'');
+ sb.append(", createdDate=").append(createdDate);
+ sb.append(", updatedDate=").append(updatedDate);
+ sb.append(", tenantId=").append(tenantId);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultEntitlementContext that = (DefaultEntitlementContext) o;
+
+ if (operationType != that.operationType) {
+ return false;
+ }
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (destinationAccountId != null ? !destinationAccountId.equals(that.destinationAccountId) : that.destinationAccountId != null) {
+ return false;
+ }
+ if (baseEntitlementWithAddOnsSpecifiers != null ? !baseEntitlementWithAddOnsSpecifiers.equals(that.baseEntitlementWithAddOnsSpecifiers) : that.baseEntitlementWithAddOnsSpecifiers != null) {
+ return false;
+ }
+ if (billingActionPolicy != that.billingActionPolicy) {
+ return false;
+ }
+ if (pluginProperties != null ? !pluginProperties.equals(that.pluginProperties) : that.pluginProperties != null) {
+ return false;
+ }
+ if (userToken != null ? !userToken.equals(that.userToken) : that.userToken != null) {
+ return false;
+ }
+ if (userName != null ? !userName.equals(that.userName) : that.userName != null) {
+ return false;
+ }
+ if (callOrigin != that.callOrigin) {
+ return false;
+ }
+ if (userType != that.userType) {
+ return false;
+ }
+ if (reasonCode != null ? !reasonCode.equals(that.reasonCode) : that.reasonCode != null) {
+ return false;
+ }
+ if (comments != null ? !comments.equals(that.comments) : that.comments != null) {
+ return false;
+ }
+ if (createdDate != null ? createdDate.compareTo(that.createdDate) != 0 : that.createdDate != null) {
+ return false;
+ }
+ if (updatedDate != null ? updatedDate.compareTo(that.updatedDate) != 0 : that.updatedDate != null) {
+ return false;
+ }
+ return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = operationType != null ? operationType.hashCode() : 0;
+ result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+ result = 31 * result + (destinationAccountId != null ? destinationAccountId.hashCode() : 0);
+ result = 31 * result + (baseEntitlementWithAddOnsSpecifiers != null ? baseEntitlementWithAddOnsSpecifiers.hashCode() : 0);
+ result = 31 * result + (billingActionPolicy != null ? billingActionPolicy.hashCode() : 0);
+ result = 31 * result + (pluginProperties != null ? pluginProperties.hashCode() : 0);
+ result = 31 * result + (userToken != null ? userToken.hashCode() : 0);
+ result = 31 * result + (userName != null ? userName.hashCode() : 0);
+ result = 31 * result + (callOrigin != null ? callOrigin.hashCode() : 0);
+ result = 31 * result + (userType != null ? userType.hashCode() : 0);
+ result = 31 * result + (reasonCode != null ? reasonCode.hashCode() : 0);
+ result = 31 * result + (comments != null ? comments.hashCode() : 0);
+ result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
+ result = 31 * result + (updatedDate != null ? updatedDate.hashCode() : 0);
+ result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
+ return result;
+ }
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
index 71ffea4..09d8f4c 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2018 Groupon, Inc
- * Copyright 2014-2018 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -313,7 +313,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
final InternalCallContext internalCallContextWithValidAccountId = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
@Override
- public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
subscriptionBaseInternalApi.updateExternalKey(bundleId, newExternalKey, internalCallContextWithValidAccountId);
return null;
}
@@ -401,7 +401,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
final WithEntitlementPlugin<Void> addBlockingStateWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
- public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(blockingState, internalCallContextWithValidAccountId);
return null;
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java
index 0596c73..45e427b 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -42,7 +42,7 @@ public class EntitlementPluginExecution {
private final OSGIServiceRegistration<EntitlementPluginApi> pluginRegistry;
public interface WithEntitlementPlugin<T> {
- T doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException;
+ T doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException;
}
@Inject
@@ -52,7 +52,7 @@ public class EntitlementPluginExecution {
}
public void executeWithPlugin(final Callable<Void> preCallbacksCallback, final List<WithEntitlementPlugin> callbacks, final Iterable<EntitlementContext> pluginContexts) throws EntitlementApiException {
- final List<EntitlementContext> updatedPluginContexts = new LinkedList<EntitlementContext>();
+ final List<DefaultEntitlementContext> updatedPluginContexts = new LinkedList<DefaultEntitlementContext>();
try {
for (final EntitlementContext pluginContext : pluginContexts) {
@@ -67,7 +67,7 @@ public class EntitlementPluginExecution {
try {
for (int i = 0; i < updatedPluginContexts.size(); i++) {
- final EntitlementContext updatedPluginContext = updatedPluginContexts.get(i);
+ final DefaultEntitlementContext updatedPluginContext = updatedPluginContexts.get(i);
final WithEntitlementPlugin callback = callbacks.get(i);
callback.doCall(entitlementApi, updatedPluginContext);
@@ -92,7 +92,7 @@ public class EntitlementPluginExecution {
if (priorEntitlementResult != null && priorEntitlementResult.isAborted()) {
throw new EntitlementApiException(ErrorCode.ENT_PLUGIN_API_ABORTED);
}
- final EntitlementContext updatedPluginContext = new DefaultEntitlementContext(pluginContext, priorEntitlementResult);
+ final DefaultEntitlementContext updatedPluginContext = new DefaultEntitlementContext(pluginContext, priorEntitlementResult);
try {
final T result = callback.doCall(entitlementApi, updatedPluginContext);
executePluginOnSuccessCalls(updatedPluginContext);
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java
index 61563f2..243f576 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -162,7 +162,7 @@ public class DefaultEntitlementApiBase {
final WithEntitlementPlugin<Void> pauseWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
- public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
try {
final SubscriptionBase baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, internalCallContext);
blockUnblockBundle(bundleId, DefaultEntitlementApi.ENT_STATE_BLOCKED, KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName(), localEffectiveDate, true, true, true, baseSubscription, internalCallContext);
@@ -195,7 +195,7 @@ public class DefaultEntitlementApiBase {
internalCallContextFactory.createCallContext(internalCallContext));
final WithEntitlementPlugin<Void> resumeWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
- public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
try {
final SubscriptionBase baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, internalCallContext);
blockUnblockBundle(bundleId, DefaultEntitlementApi.ENT_STATE_CLEAR, KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName(), localEffectiveDate, false, false, false, baseSubscription, internalCallContext);
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java
index d5c9e39..7b00232 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2018 Groupon, Inc
- * Copyright 2014-2018 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -219,7 +219,7 @@ public class DefaultEntitlementInternalApi extends DefaultEntitlementApiBase imp
}
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers().iterator().next().getEntitlementEffectiveDate(), updatedPluginContext.getCreatedDate(), internalCallContext);
//
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java b/entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java
index e3360d9..a844c84 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -33,41 +33,6 @@ import org.slf4j.Logger;
public abstract class EntitlementLoggingHelper {
- public static void logCreateEntitlement(final Logger log,
- final UUID bundleId,
- final PlanPhaseSpecifier spec,
- final List<PlanPhasePriceOverride> overrides,
- final LocalDate entitlementDate,
- final LocalDate billingDate) {
-
- if (log.isInfoEnabled()) {
- final StringBuilder logLine = new StringBuilder("Create")
- .append(bundleId != null ? " AO " : " BP ")
- .append("Entitlement: ");
-
- if (bundleId != null) {
- logLine.append("bundleId='")
- .append(bundleId)
- .append("'");
- }
- logPlanPhaseSpecifier(logLine, spec, true, true);
- if (overrides != null && !overrides.isEmpty()) {
- logPlanPhasePriceOverrides(logLine, overrides);
- }
- if (entitlementDate != null) {
- logLine.append(", entDate='")
- .append(entitlementDate)
- .append("'");
- }
- if (billingDate != null) {
- logLine.append(", billDate='")
- .append(billingDate)
- .append("'");
- }
- log.info(logLine.toString());
- }
- }
-
public static void logCreateEntitlementsWithAOs(final Logger log, final Iterable<BaseEntitlementWithAddOnsSpecifier> baseEntitlementSpecifiersWithAddOns) {
if (log.isInfoEnabled()) {
final StringBuilder logLine = new StringBuilder("Create Entitlements with AddOns: ");
@@ -96,16 +61,27 @@ public abstract class EntitlementLoggingHelper {
.append("'");
}
if (entitlementDate != null) {
- logLine.append(", entDate='")
+ if (externalKey != null) {
+ logLine.append(", ");
+ }
+ logLine.append("entDate='")
.append(entitlementDate)
.append("'");
}
if (billingDate != null) {
- logLine.append(", billDate='")
+ if (externalKey != null || entitlementDate != null) {
+ logLine.append(", ");
+ }
+ logLine.append("billDate='")
.append(billingDate)
.append("'");
}
- logEntitlementSpecifier(logLine, entitlementSpecifiers);
+ if (entitlementSpecifiers != null && entitlementSpecifiers.iterator().hasNext()) {
+ if (externalKey != null || entitlementDate != null || billingDate != null) {
+ logLine.append(", ");
+ }
+ logEntitlementSpecifier(logLine, entitlementSpecifiers);
+ }
}
public static void logPauseResumeEntitlement(final Logger log,
@@ -327,38 +303,44 @@ public abstract class EntitlementLoggingHelper {
}
private static void logEntitlementSpecifier(final StringBuilder logLine, final Iterable<EntitlementSpecifier> entitlementSpecifiers) {
- if (entitlementSpecifiers != null && entitlementSpecifiers.iterator().hasNext()) {
- logLine.append(",'[");
- boolean first = true;
- for (EntitlementSpecifier cur : entitlementSpecifiers) {
- if (!first) {
- logLine.append(",");
- }
- logPlanPhaseSpecifier(logLine, cur.getPlanPhaseSpecifier(), false, false);
- logPlanPhasePriceOverrides(logLine, cur.getOverrides());
- first = false;
+ logLine.append("'[");
+ boolean first = true;
+ for (final EntitlementSpecifier cur : entitlementSpecifiers) {
+ if (!first) {
+ logLine.append(",");
}
- logLine.append("]'");
+ logPlanPhaseSpecifier(logLine, cur.getPlanPhaseSpecifier(), false, false);
+ logPlanPhasePriceOverrides(logLine, cur.getOverrides());
+ first = false;
}
+ logLine.append("]'");
}
- private static void logPlanPhaseSpecifier(final StringBuilder logLine, final PlanPhaseSpecifier spec, boolean addComma, boolean addParentheseQuote) {
+ private static void logPlanPhaseSpecifier(final StringBuilder logLine, final PlanPhaseSpecifier spec, final boolean addComma, final boolean addParenthesisQuote) {
if (spec != null) {
if (addComma) {
logLine.append(", ");
}
- logLine.append("spec=");
- if (addParentheseQuote) {
- logLine.append("'(");
+ if (spec.getPlanName() != null) {
+ logLine.append("planName=");
+ if (addParenthesisQuote) {
+ logLine.append("'(");
+ }
+ logLine.append(spec.getPlanName());
+ } else {
+ logLine.append("spec=");
+ if (addParenthesisQuote) {
+ logLine.append("'(");
+ }
+ logLine.append(spec.getProductName() != null ? spec.getProductName() : "null");
+ logLine.append(":");
+ logLine.append(spec.getBillingPeriod() != null ? spec.getBillingPeriod() : "null");
+ logLine.append(":");
+ logLine.append(spec.getPriceListName() != null ? spec.getPriceListName() : "null");
}
- logLine.append(spec.getProductName() != null ? spec.getProductName() : "null");
- logLine.append(":");
- logLine.append(spec.getBillingPeriod() != null ? spec.getBillingPeriod() : "null");
logLine.append(":");
logLine.append(spec.getPhaseType() != null ? spec.getPhaseType() : "null");
- logLine.append(":");
- logLine.append(spec.getPriceListName() != null ? spec.getPriceListName() : "null");
- if (addParentheseQuote) {
+ if (addParenthesisQuote) {
logLine.append(")'");
}
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java
index fa8da71..a46c4d0 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -19,7 +19,6 @@
package org.killbill.billing.invoice.generator;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -34,7 +33,6 @@ import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
-import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoiceStatus;
import org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceGeneratorResult;
import org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates;
@@ -42,6 +40,8 @@ import org.killbill.billing.invoice.model.DefaultInvoice;
import org.killbill.billing.junction.BillingEventSet;
import org.killbill.billing.util.config.definition.InvoiceConfig;
import org.killbill.clock.Clock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
@@ -52,6 +52,8 @@ import com.google.inject.Inject;
public class DefaultInvoiceGenerator implements InvoiceGenerator {
+ private static final Logger logger = LoggerFactory.getLogger(DefaultInvoiceGenerator.class);
+
private final Clock clock;
private final InvoiceConfig config;
@@ -134,6 +136,11 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
maxDate = invoice.getTargetDate();
}
}
+
+ if (targetDate.compareTo(maxDate) != 0) {
+ logger.warn("Adjusting target date from {} to {}", targetDate, maxDate);
+ }
+
return maxDate;
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
index cc874e1..cf4deb0 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -526,12 +526,12 @@ public class InvoiceDispatcher {
}
private InvoiceWithFutureNotifications processAccountWithLockAndInputTargetDate(final UUID accountId,
- final LocalDate targetDate,
- final BillingEventSet billingEvents,
- final List<Invoice> existingInvoices,
- final boolean isDryRun,
- final boolean isRescheduled,
- final InternalCallContext internalCallContext) throws InvoiceApiException {
+ final LocalDate originalTargetDate,
+ final BillingEventSet billingEvents,
+ final List<Invoice> existingInvoices,
+ final boolean isDryRun,
+ final boolean isRescheduled,
+ final InternalCallContext internalCallContext) throws InvoiceApiException {
final CallContext callContext = buildCallContext(internalCallContext);
final ImmutableAccountData account;
@@ -539,11 +539,11 @@ public class InvoiceDispatcher {
account = accountApi.getImmutableAccountDataById(accountId, internalCallContext);
} catch (final AccountApiException e) {
log.error("Unable to generate invoice for accountId='{}', a future notification has NOT been recorded", accountId, e);
- invoicePluginDispatcher.onFailureCall(targetDate, null, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
+ invoicePluginDispatcher.onFailureCall(originalTargetDate, null, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
return null;
}
- final DateTime rescheduleDate = invoicePluginDispatcher.priorCall(targetDate, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
+ final DateTime rescheduleDate = invoicePluginDispatcher.priorCall(originalTargetDate, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
if (rescheduleDate != null) {
if (isDryRun) {
log.warn("Ignoring rescheduleDate='{}', delayed scheduling is unsupported in dry-run", rescheduleDate);
@@ -554,7 +554,7 @@ public class InvoiceDispatcher {
return null;
}
- final InvoiceWithMetadata invoiceWithMetadata = generateKillBillInvoice(account, targetDate, billingEvents, existingInvoices, internalCallContext);
+ final InvoiceWithMetadata invoiceWithMetadata = generateKillBillInvoice(account, originalTargetDate, billingEvents, existingInvoices, internalCallContext);
final DefaultInvoice invoice = invoiceWithMetadata.getInvoice();
// Compute future notifications
@@ -562,12 +562,12 @@ public class InvoiceDispatcher {
// If invoice comes back null, there is nothing new to generate, we can bail early
if (invoice == null) {
- invoicePluginDispatcher.onSuccessCall(targetDate, null, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
+ invoicePluginDispatcher.onSuccessCall(originalTargetDate, null, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
if (isDryRun) {
- log.info("Generated null dryRun invoice for accountId='{}', targetDate='{}'", accountId, targetDate);
+ log.info("Generated null dryRun invoice for accountId='{}', targetDate='{}'", accountId, originalTargetDate);
} else {
- log.info("Generated null invoice for accountId='{}', targetDate='{}'", accountId, targetDate);
+ log.info("Generated null invoice for accountId='{}', targetDate='{}'", accountId, originalTargetDate);
final BusInternalEvent event = new DefaultNullInvoiceEvent(accountId, clock.getUTCToday(),
internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId(), internalCallContext.getUserToken());
@@ -578,6 +578,7 @@ public class InvoiceDispatcher {
return null;
}
+ final LocalDate actualTargetDate = invoice.getTargetDate();
boolean success = false;
try {
// Generate missing credit (> 0 for generation and < 0 for use) prior we call the plugin(s)
@@ -609,7 +610,7 @@ public class InvoiceDispatcher {
final boolean isRealInvoiceWithItems = uniqueInvoiceIds.remove(invoice.getId());
final Set<UUID> adjustedUniqueOtherInvoiceId = uniqueInvoiceIds;
- logInvoiceWithItems(account, invoice, targetDate, adjustedUniqueOtherInvoiceId, isRealInvoiceWithItems);
+ logInvoiceWithItems(account, invoice, actualTargetDate, adjustedUniqueOtherInvoiceId, isRealInvoiceWithItems);
// Transformation to Invoice -> InvoiceModelDao
final InvoiceModelDao invoiceModelDao = new InvoiceModelDao(invoice);
@@ -642,9 +643,9 @@ public class InvoiceDispatcher {
if (isDryRun || success) {
final DefaultInvoice refreshedInvoice = isDryRun ? invoice : new DefaultInvoice(invoiceDao.getById(invoice.getId(), internalCallContext));
- invoicePluginDispatcher.onSuccessCall(targetDate, refreshedInvoice, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(),internalCallContext);
+ invoicePluginDispatcher.onSuccessCall(actualTargetDate, refreshedInvoice, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(),internalCallContext);
} else {
- invoicePluginDispatcher.onFailureCall(targetDate, invoice, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
+ invoicePluginDispatcher.onFailureCall(actualTargetDate, invoice, existingInvoices, isDryRun, isRescheduled, callContext, ImmutableList.<PluginProperty>of(), internalCallContext);
}
}