killbill-uncached
Changes
account/pom.xml 2(+1 -1)
api/pom.xml 2(+1 -1)
beatrix/pom.xml 2(+1 -1)
catalog/pom.xml 2(+1 -1)
currency/pom.xml 2(+1 -1)
entitlement/pom.xml 2(+1 -1)
entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java 540(+143 -397)
entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionEvent.java 396(+396 -0)
entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionApi.java 55(+55 -0)
entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java 537(+343 -194)
entitlement/src/test/java/com/ning/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java 3(+3 -0)
entitlement/src/test/java/com/ning/billing/entitlement/glue/TestEntitlementModuleWithEmbeddedDB.java 2(+2 -0)
invoice/pom.xml 2(+1 -1)
jaxrs/pom.xml 2(+1 -1)
junction/pom.xml 2(+1 -1)
NEWS 6(+6 -0)
osgi/pom.xml 2(+1 -1)
osgi-bundles/bundles/jruby/pom.xml 2(+1 -1)
osgi-bundles/bundles/logger/pom.xml 2(+1 -1)
osgi-bundles/bundles/pom.xml 2(+1 -1)
osgi-bundles/defaultbundles/pom.xml 2(+1 -1)
osgi-bundles/libs/killbill/pom.xml 2(+1 -1)
osgi-bundles/libs/pom.xml 2(+1 -1)
osgi-bundles/libs/slf4j-osgi/pom.xml 2(+1 -1)
osgi-bundles/pom.xml 2(+1 -1)
osgi-bundles/tests/beatrix/pom.xml 2(+1 -1)
osgi-bundles/tests/payment/pom.xml 2(+1 -1)
osgi-bundles/tests/pom.xml 2(+1 -1)
overdue/pom.xml 2(+1 -1)
payment/pom.xml 2(+1 -1)
pom.xml 4(+2 -2)
server/pom.xml 2(+1 -1)
subscription/pom.xml 2(+1 -1)
tenant/pom.xml 2(+1 -1)
usage/pom.xml 2(+1 -1)
util/pom.xml 2(+1 -1)
Details
account/pom.xml 2(+1 -1)
diff --git a/account/pom.xml b/account/pom.xml
index b4d7b88..b5603ba 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index d42225d..ff7292d 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-internal-api</artifactId>
beatrix/pom.xml 2(+1 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 1ee0c59..f71aa5c 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-beatrix</artifactId>
catalog/pom.xml 2(+1 -1)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index 82c5e90..ed64b49 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
currency/pom.xml 2(+1 -1)
diff --git a/currency/pom.xml b/currency/pom.xml
index 40f731b..6af9d27 100644
--- a/currency/pom.xml
+++ b/currency/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index f4d8b8a..dbee812 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java
index 20148a2..c182b4c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java
@@ -25,15 +25,15 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
-import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,9 +59,6 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
private final Logger logger = LoggerFactory.getLogger(DefaultSubscriptionBundleTimeline.class);
- // STEPH This is added to give us confidence the timeline we generate behaves as expected. Could be removed at some point
- private final static String TIMELINE_WARN_LOG = "Sanity Timeline: ";
-
public static final String BILLING_SERVICE_NAME = "billing-service";
public static final String ENT_BILLING_SERVICE_NAME = "entitlement+billing-service";
@@ -81,7 +78,7 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
this.events = computeEvents(entitlements, new LinkedList<BlockingState>(blockingStates), accountTimeZone);
}
- public DefaultSubscriptionBundleTimeline(final DateTimeZone accountTimeZone, final UUID accountId, final UUID bundleId, final String externalKey, final List<Entitlement> entitlements, List<BlockingState> allBlockingStates) {
+ public DefaultSubscriptionBundleTimeline(final DateTimeZone accountTimeZone, final UUID accountId, final UUID bundleId, final String externalKey, final List<Entitlement> entitlements, final List<BlockingState> allBlockingStates) {
this.accountId = accountId;
this.bundleId = bundleId;
this.externalKey = externalKey;
@@ -94,8 +91,7 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
// - base subscription events are already ordered for each Entitlement and so when we reorder at the bundle level we try not to break that initial ordering
// - blocking state events occur at various level (account, bundle and subscription) so for higher level, we need to dispatch that on each subscription.
//
- private List<SubscriptionEvent> computeEvents(final Collection<Entitlement> entitlements, List<BlockingState> allBlockingStates, final DateTimeZone accountTimeZone) {
-
+ private List<SubscriptionEvent> computeEvents(final Collection<Entitlement> entitlements, final List<BlockingState> allBlockingStates, final DateTimeZone accountTimeZone) {
// Extract ids for all entitlement in the list
final Set<UUID> allEntitlementUUIDs = new TreeSet(Collections2.transform(entitlements, new Function<Entitlement, UUID>() {
@Override
@@ -140,23 +136,44 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
if (createdDateComp != 0) {
return createdDateComp;
}
- logger.warn(TIMELINE_WARN_LOG + "Detected two identical blockingStates events for blockableId = " + o1.getBlockedId() +
- ", type = " + o1.getType() + ", ");
- // Underministic-- not sure that will ever happen. Once we are confident this never happens we should thrown IllegalException
+
+ // Non deterministic -- not sure that will ever happen. Once we are confident this never happens, we should throw ShouldntHappenException
return 0;
}
});
- for (BlockingState bs : allBlockingStates) {
-
+ for (final BlockingState bs : allBlockingStates) {
final List<SubscriptionEvent> newEvents = new ArrayList<SubscriptionEvent>();
- int index = insertFromBlockingEvent(accountTimeZone, allEntitlementUUIDs, result, bs, bs.getEffectiveDate(), newEvents);
+ final int index = insertFromBlockingEvent(accountTimeZone, allEntitlementUUIDs, result, bs, bs.getEffectiveDate(), newEvents);
insertAfterIndex(result, newEvents, index);
}
+
reOrderSubscriptionEventsOnSameDateByType(result);
+
+ removeOverlappingSubscriptionEvents(result);
+
return result;
}
+ // Make sure the argument supports the remove operation - hence expect a LinkedList, not a List
+ private void removeOverlappingSubscriptionEvents(final LinkedList<SubscriptionEvent> events) {
+ final Iterator<SubscriptionEvent> iterator = events.iterator();
+ final Map<String, DefaultSubscriptionEvent> prevPerService = new HashMap<String, DefaultSubscriptionEvent>();
+ while (iterator.hasNext()) {
+ final DefaultSubscriptionEvent current = (DefaultSubscriptionEvent) iterator.next();
+ final DefaultSubscriptionEvent prev = prevPerService.get(current.getServiceName());
+ if (prev != null) {
+ if (current.overlaps(prev)) {
+ iterator.remove();
+ } else {
+ prevPerService.put(current.getServiceName(), current);
+ }
+ } else {
+ prevPerService.put(current.getServiceName(), current);
+ }
+ }
+ }
+
//
// All events have been inserted and should be at the right place, except that we want to ensure that events for a given subscription,
// and for a given time are ordered by SubscriptionEventType.
@@ -172,8 +189,8 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
protected void reOrderSubscriptionEventsOnSameDateByType(final List<SubscriptionEvent> events) {
final int size = events.size();
for (int i = 0; i < size; i++) {
- final DefaultSubscriptionEvent cur = (DefaultSubscriptionEvent) events.get(i);
- final DefaultSubscriptionEvent next = (i < (size - 1)) ? (DefaultSubscriptionEvent) events.get(i + 1) : null;
+ final SubscriptionEvent cur = events.get(i);
+ final SubscriptionEvent next = (i < (size - 1)) ? events.get(i + 1) : null;
final boolean shouldSwap = (next != null && shouldSwap(cur, next, true));
final boolean shouldReverseSort = (next == null || shouldSwap);
@@ -184,8 +201,8 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
}
if (shouldReverseSort) {
while (currentIndex >= 1) {
- final DefaultSubscriptionEvent revCur = (DefaultSubscriptionEvent) events.get(currentIndex);
- final DefaultSubscriptionEvent other = (DefaultSubscriptionEvent) events.get(currentIndex - 1);
+ final SubscriptionEvent revCur = events.get(currentIndex);
+ final SubscriptionEvent other = events.get(currentIndex - 1);
if (shouldSwap(revCur, other, false)) {
Collections.swap(events, currentIndex, currentIndex - 1);
}
@@ -198,8 +215,7 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
}
}
- private boolean shouldSwap(DefaultSubscriptionEvent cur, DefaultSubscriptionEvent other, boolean isAscending) {
-
+ private boolean shouldSwap(final SubscriptionEvent cur, final SubscriptionEvent other, final boolean isAscending) {
// For a given date, order by subscriptionId, and within subscription by event type
final int idComp = cur.getEntitlementId().compareTo(other.getEntitlementId());
return (cur.getEffectiveDate().compareTo(other.getEffectiveDate()) == 0 &&
@@ -211,8 +227,7 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
(idComp == 0 && cur.getSubscriptionEventType().ordinal() < other.getSubscriptionEventType().ordinal())))));
}
- private void insertAfterIndex(final LinkedList<SubscriptionEvent> original, final List<SubscriptionEvent> newEvents, int index) {
-
+ private void insertAfterIndex(final LinkedList<SubscriptionEvent> original, final List<SubscriptionEvent> newEvents, final int index) {
final boolean firstPosition = (index == -1);
final boolean lastPosition = (index == original.size() - 1);
if (lastPosition || firstPosition) {
@@ -233,10 +248,9 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
// reOrderSubscriptionEventsOnSameDateByType would reorder them anyway if this was not the case.
//
private int insertFromBlockingEvent(final DateTimeZone accountTimeZone, final Set<UUID> allEntitlementUUIDs, final List<SubscriptionEvent> result, final BlockingState bs, final DateTime bsEffectiveDate, final List<SubscriptionEvent> newEvents) {
-
// Keep the current state per entitlement
final Map<UUID, TargetState> targetStates = new HashMap<UUID, TargetState>();
- for (UUID cur : allEntitlementUUIDs) {
+ for (final UUID cur : allEntitlementUUIDs) {
targetStates.put(cur, new TargetState());
}
@@ -248,7 +262,7 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
// Where we need to insert in that stream
DefaultSubscriptionEvent curInsertion = null;
while (it.hasNext()) {
- DefaultSubscriptionEvent cur = (DefaultSubscriptionEvent) it.next();
+ final DefaultSubscriptionEvent cur = (DefaultSubscriptionEvent) it.next();
final int compEffectiveDate = bsEffectiveDate.compareTo(cur.getEffectiveDateTime());
final boolean shouldContinue = (compEffectiveDate >= 0);
if (!shouldContinue) {
@@ -283,13 +297,12 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
ImmutableList.<UUID>copyOf(allEntitlementUUIDs);
// For each target compute the new events that should be inserted in the stream
- for (UUID target : targetEntitlementIds) {
-
+ for (final UUID target : targetEntitlementIds) {
final SubscriptionEvent[] prevNext = findPrevNext(result, target, curInsertion);
final TargetState curTargetState = targetStates.get(target);
final List<SubscriptionEventType> eventTypes = curTargetState.addStateAndReturnEventTypes(bs);
- for (SubscriptionEventType t : eventTypes) {
+ for (final SubscriptionEventType t : eventTypes) {
newEvents.add(toSubscriptionEvent(prevNext[0], prevNext[1], target, bs, t, accountTimeZone));
}
}
@@ -298,12 +311,11 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
// Extract prev and next events in the stream events for that particular target subscription from the insertionEvent
private SubscriptionEvent[] findPrevNext(final List<SubscriptionEvent> events, final UUID targetEntitlementId, final SubscriptionEvent insertionEvent) {
-
// Find prev/next event for the same entitlement
final SubscriptionEvent[] result = new DefaultSubscriptionEvent[2];
if (insertionEvent == null) {
result[0] = null;
- result[1] = events.size() > 0 ? events.get(0) : null;
+ result[1] = !events.isEmpty() ? events.get(0) : null;
return result;
}
@@ -344,64 +356,35 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
}
}
}
- sanitizeForBaseRecreateEvents(result);
- return result;
- }
- //
- // Old version of code would use CANCEL/RE_CREATE to simulate PAUSE_BILLING/RESUME_BILLING
- // (Relies on the assumption that there is no blocking_state event matching that CACNEL event so:
- // 1. The STOP_BILLING (coming from the row CANCEL event) should be transformed into a PAUSE_BILLING
- // 2. We also add a PAUSE_ENTITLEMENT at the same time as the PAUSE_BILLING
- //
- private void sanitizeForBaseRecreateEvents(final LinkedList<SubscriptionEvent> input) {
- final Collection<UUID> guiltyEntitlementIds = new TreeSet<UUID>();
- final ListIterator<SubscriptionEvent> it = input.listIterator(input.size());
- while (it.hasPrevious()) {
- final SubscriptionEvent cur = it.previous();
- if (cur.getSubscriptionEventType() == SubscriptionEventType.RESUME_BILLING) {
- guiltyEntitlementIds.add(cur.getEntitlementId());
- continue;
- }
- if (cur.getSubscriptionEventType() == SubscriptionEventType.STOP_BILLING &&
- guiltyEntitlementIds.contains(cur.getEntitlementId())) {
- guiltyEntitlementIds.remove(cur.getEntitlementId());
- final SubscriptionEvent correctedBillingEvent = new DefaultSubscriptionEvent((DefaultSubscriptionEvent) cur, SubscriptionEventType.PAUSE_BILLING);
- it.set(correctedBillingEvent);
-
- // Old versions of the code won't have an associated event in blocking_states - we need to add one on the fly
- final SubscriptionEvent correctedEntitlementEvent = new DefaultSubscriptionEvent((DefaultSubscriptionEvent) cur, SubscriptionEventType.PAUSE_ENTITLEMENT);
- it.add(correctedEntitlementEvent);
- }
- }
+ return result;
}
- private void insertSubscriptionEvent(final SubscriptionEvent event, final LinkedList<SubscriptionEvent> result) {
+ private void insertSubscriptionEvent(final SubscriptionEvent event, final List<SubscriptionEvent> result) {
int index = 0;
- for (SubscriptionEvent cur : result) {
- int compEffectiveDate = event.getEffectiveDate().compareTo(cur.getEffectiveDate());
+ for (final SubscriptionEvent cur : result) {
+ final int compEffectiveDate = event.getEffectiveDate().compareTo(cur.getEffectiveDate());
if (compEffectiveDate < 0) {
// EffectiveDate is less than cur -> insert here
break;
} else if (compEffectiveDate == 0) {
-
- int compUUID = event.getEntitlementId().compareTo(cur.getEntitlementId());
+ final int compUUID = event.getEntitlementId().compareTo(cur.getEntitlementId());
if (compUUID < 0) {
// Same EffectiveDate but subscription are different, no need top sort further just return something deterministic
break;
} else if (compUUID == 0) {
-
- int eventOrder = event.getSubscriptionEventType().ordinal() - cur.getSubscriptionEventType().ordinal();
+ final int eventOrder = event.getSubscriptionEventType().ordinal() - cur.getSubscriptionEventType().ordinal();
if (eventOrder < 0) {
// Same EffectiveDate and same subscription, order by SubscriptionEventType;
break;
}
- // Two identical event for the same subscription at the same time, this sounds like some data issue
+ // Two identical events for the same subscription in the same day, trust createdDate
if (eventOrder == 0) {
- logger.warn(TIMELINE_WARN_LOG + "Detected identical events type = " + event.getSubscriptionEventType() + " ids = " +
- event.getId() + ", " + cur.getId() + " for subscription " + cur.getEntitlementId());
- break;
+ final int compCreatedDate = (((DefaultSubscriptionEvent) event).getCreatedDate()).compareTo(((DefaultSubscriptionEvent) cur).getCreatedDate());
+ if (compCreatedDate <= 0) {
+ break;
+ }
}
}
}
@@ -410,7 +393,74 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
result.add(index, event);
}
- private SubscriptionEvent toSubscriptionEvent(final SubscriptionEvent prev, final SubscriptionEvent next, final UUID entitlementId, final BlockingState in, final SubscriptionEventType eventType, final DateTimeZone accountTimeZone) {
+ private SubscriptionEvent toSubscriptionEvent(@Nullable final SubscriptionEvent prev, @Nullable final SubscriptionEvent next,
+ final UUID entitlementId, final BlockingState in, final SubscriptionEventType eventType, final DateTimeZone accountTimeZone) {
+ final Product prevProduct;
+ final Plan prevPlan;
+ final PlanPhase prevPlanPhase;
+ final PriceList prevPriceList;
+ final BillingPeriod prevBillingPeriod;
+ // Enforce prev = null for start events
+ if (prev == null || SubscriptionEventType.START_ENTITLEMENT.equals(eventType) || SubscriptionEventType.START_BILLING.equals(eventType)) {
+ prevProduct = null;
+ prevPlan = null;
+ prevPlanPhase = null;
+ prevPriceList = null;
+ prevBillingPeriod = null;
+ } else {
+ // We look for the next for the 'prev' meaning we we are headed to, but if this is null -- for example on cancellation we get the prev which gives the correct state.
+ prevProduct = (prev.getNextProduct() != null ? prev.getNextProduct() : prev.getPrevProduct());
+ prevPlan = (prev.getNextPlan() != null ? prev.getNextPlan() : prev.getPrevPlan());
+ prevPlanPhase = (prev.getNextPhase() != null ? prev.getNextPhase() : prev.getPrevPhase());
+ prevPriceList = (prev.getNextPriceList() != null ? prev.getNextPriceList() : prev.getPrevPriceList());
+ prevBillingPeriod = (prev.getNextBillingPeriod() != null ? prev.getNextBillingPeriod() : prev.getPrevBillingPeriod());
+ }
+
+ final Product nextProduct;
+ final Plan nextPlan;
+ final PlanPhase nextPlanPhase;
+ final PriceList nextPriceList;
+ final BillingPeriod nextBillingPeriod;
+ if (SubscriptionEventType.PAUSE_ENTITLEMENT.equals(eventType) || SubscriptionEventType.PAUSE_BILLING.equals(eventType) ||
+ SubscriptionEventType.RESUME_ENTITLEMENT.equals(eventType) || SubscriptionEventType.RESUME_BILLING.equals(eventType) ||
+ (SubscriptionEventType.SERVICE_STATE_CHANGE.equals(eventType) && (prev == null || (!SubscriptionEventType.STOP_ENTITLEMENT.equals(prev.getSubscriptionEventType()) && !SubscriptionEventType.STOP_BILLING.equals(prev.getSubscriptionEventType()))))) {
+ // Enforce next = prev for pause/resume events as well as service changes
+ nextProduct = prevProduct;
+ nextPlan = prevPlan;
+ nextPlanPhase = prevPlanPhase;
+ nextPriceList = prevPriceList;
+ nextBillingPeriod = prevBillingPeriod;
+ } else if (next == null) {
+ // Enforce next = null for stop events
+ if (prev == null || SubscriptionEventType.STOP_ENTITLEMENT.equals(eventType) || SubscriptionEventType.STOP_BILLING.equals(eventType)) {
+ nextProduct = null;
+ nextPlan = null;
+ nextPlanPhase = null;
+ nextPriceList = null;
+ nextBillingPeriod = null;
+ } else {
+ nextProduct = prev.getNextProduct();
+ nextPlan = prev.getNextPlan();
+ nextPlanPhase = prev.getNextPhase();
+ nextPriceList = prev.getNextPriceList();
+ nextBillingPeriod = prev.getNextBillingPeriod();
+ }
+ } else {
+ nextProduct = next.getNextProduct();
+ nextPlan = next.getNextPlan();
+ nextPlanPhase = next.getNextPhase();
+ nextPriceList = next.getNextPriceList();
+ nextBillingPeriod = next.getNextBillingPeriod();
+ }
+
+ // See https://github.com/killbill/killbill/issues/135
+ final String serviceName;
+ if (DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME.equals(in.getService())) {
+ serviceName = getServiceName(eventType);
+ } else {
+ serviceName = in.getService();
+ }
+
return new DefaultSubscriptionEvent(in.getId(),
entitlementId,
in.getEffectiveDate(),
@@ -418,19 +468,18 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
eventType,
in.isBlockEntitlement(),
in.isBlockBilling(),
- in.getService(),
+ serviceName,
in.getStateName(),
- // We look for the next for the 'prev' meaning we we are headed to, but if this is null -- for example on cancellation we get the prev which gives the correct state.
- prev != null ? (prev.getNextProduct() != null ? prev.getNextProduct() : prev.getPrevProduct()) : null,
- prev != null ? (prev.getNextPlan() != null ? prev.getNextPlan() : prev.getPrevPlan()) : null,
- prev != null ? (prev.getNextPhase() != null ? prev.getNextPhase() : prev.getPrevPhase()) : null,
- prev != null ? (prev.getNextPriceList() != null ? prev.getNextPriceList() : prev.getPrevPriceList()) : null,
- prev != null ? (prev.getNextBillingPeriod() != null ? prev.getNextBillingPeriod() : prev.getPrevBillingPeriod()) : null,
- next != null ? next.getPrevProduct() : null,
- next != null ? next.getPrevPlan() : null,
- next != null ? next.getPrevPhase() : null,
- next != null ? next.getPrevPriceList() : null,
- next != null ? next.getPrevBillingPeriod() : null,
+ prevProduct,
+ prevPlan,
+ prevPlanPhase,
+ prevPriceList,
+ prevBillingPeriod,
+ nextProduct,
+ nextPlan,
+ nextPlanPhase,
+ nextPriceList,
+ nextBillingPeriod,
in.getCreatedDate(),
accountTimeZone);
}
@@ -492,11 +541,6 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
return ImmutableList.<SubscriptionEventType>of(SubscriptionEventType.STOP_BILLING);
case PHASE:
return ImmutableList.<SubscriptionEventType>of(SubscriptionEventType.PHASE);
- // This is the old way of pausing billing; not used any longer, but kept for compatibility reason. We return both RESUME_ENTITLEMENT and RESUME_BILLING
- // and will rely on the sanitizeForBaseRecreateEvents method to transform the STOP_BILLING (coming from CANCEL) into the correct events.
- //
- case RE_CREATE:
- return ImmutableList.<SubscriptionEventType>of(SubscriptionEventType.RESUME_ENTITLEMENT, SubscriptionEventType.RESUME_BILLING);
/*
* Those can be ignored:
*/
@@ -533,7 +577,7 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
//
// Internal class to keep the state associated with each subscription
//
- private final static class TargetState {
+ private static final class TargetState {
private boolean isEntitlementStarted;
private boolean isEntitlementStopped;
@@ -570,14 +614,12 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
e.getServiceStateName(), e.getServiceName(), false, e.isBlockedEntitlement(), e.isBlockedBilling(),
((DefaultSubscriptionEvent) e).getEffectiveDateTime());
perServiceBlockingState.put(converted.getService(), converted);
-
}
//
// From the current state of that subscription, compute the effect of the new state based on the incoming blockingState event
//
private List<SubscriptionEventType> addStateAndReturnEventTypes(final BlockingState bs) {
-
// Turn off isBlockedEntitlement and isBlockedBilling if there was not start event
final BlockingState fixedBlockingState = new DefaultBlockingState(bs.getBlockedId(),
bs.getType(),
@@ -600,7 +642,15 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
// across all services
//
final BlockingAggregator stateBefore = getState();
- perServiceBlockingState.put(fixedBlockingState.getService(), fixedBlockingState);
+ if (DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME.equals(fixedBlockingState.getService())) {
+ // Some blocking states will be added as entitlement-service and billing-service via addEntitlementEvent
+ // (see above). Because of it, we need to multiplex entitlement events here.
+ // TODO - this is magic and fragile. We should revisit how we create this state machine.
+ perServiceBlockingState.put(DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME, fixedBlockingState);
+ perServiceBlockingState.put(DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME, fixedBlockingState);
+ } else {
+ perServiceBlockingState.put(fixedBlockingState.getService(), fixedBlockingState);
+ }
final BlockingAggregator stateAfter = getState();
final boolean shouldResumeEntitlement = isEntitlementStarted && !isEntitlementStopped && stateBefore.isBlockEntitlement() && !stateAfter.isBlockEntitlement();
@@ -629,314 +679,10 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
private BlockingAggregator getState() {
final DefaultBlockingAggregator aggrBefore = new DefaultBlockingAggregator();
- for (BlockingState cur : perServiceBlockingState.values()) {
+ for (final BlockingState cur : perServiceBlockingState.values()) {
aggrBefore.or(cur);
}
return aggrBefore;
}
}
-
- protected static final class DefaultSubscriptionEvent implements SubscriptionEvent {
-
- private final UUID id;
- private final UUID entitlementId;
- private final DateTime effectiveDate;
- private final DateTime requestedDate;
- private final SubscriptionEventType eventType;
- private final boolean isBlockingEntitlement;
- private final boolean isBlockingBilling;
- private final String serviceName;
- private final String serviceStateName;
- private final Product prevProduct;
- private final Plan prevPlan;
- private final PlanPhase prevPlanPhase;
- private final PriceList prevPriceList;
- private final BillingPeriod prevBillingPeriod;
- private final Product nextProduct;
- private final Plan nextPlan;
- private final PlanPhase nextPlanPhase;
- private final PriceList nextPriceList;
- private final BillingPeriod nextBillingPeriod;
- private final DateTime createdDate;
- private final DateTimeZone accountTimeZone;
-
- public DefaultSubscriptionEvent(final UUID id,
- final UUID entitlementId,
- final DateTime effectiveDate,
- final DateTime requestedDate,
- final SubscriptionEventType eventType,
- final boolean blockingEntitlement,
- final boolean blockingBilling,
- final String serviceName,
- final String serviceStateName,
- final Product prevProduct,
- final Plan prevPlan,
- final PlanPhase prevPlanPhase,
- final PriceList prevPriceList,
- final BillingPeriod prevBillingPeriod,
- final Product nextProduct,
- final Plan nextPlan,
- final PlanPhase nextPlanPhase,
- final PriceList nextPriceList,
- final BillingPeriod nextBillingPeriod,
- final DateTime createDate,
- final DateTimeZone accountTimeZone) {
- this.id = id;
- this.entitlementId = entitlementId;
- this.effectiveDate = effectiveDate;
- this.requestedDate = requestedDate;
- this.eventType = eventType;
- this.isBlockingEntitlement = blockingEntitlement;
- this.isBlockingBilling = blockingBilling;
- this.serviceName = serviceName;
- this.serviceStateName = serviceStateName;
- this.prevProduct = prevProduct;
- this.prevPlan = prevPlan;
- this.prevPlanPhase = prevPlanPhase;
- this.prevPriceList = prevPriceList;
- this.prevBillingPeriod = prevBillingPeriod;
- this.nextProduct = nextProduct;
- this.nextPlan = nextPlan;
- this.nextPlanPhase = nextPlanPhase;
- this.nextPriceList = nextPriceList;
- this.nextBillingPeriod = nextBillingPeriod;
- this.createdDate = createDate;
- this.accountTimeZone = accountTimeZone;
- }
-
- private DefaultSubscriptionEvent(DefaultSubscriptionEvent copy, SubscriptionEventType newEventType) {
- this(copy.getId(),
- copy.getEntitlementId(),
- copy.getEffectiveDateTime(),
- copy.getRequestedDateTime(),
- newEventType,
- copy.isBlockedEntitlement(),
- copy.isBlockedBilling(),
- copy.getServiceName(),
- copy.getServiceStateName(),
- copy.getPrevProduct(),
- copy.getPrevPlan(),
- copy.getPrevPhase(),
- copy.getPrevPriceList(),
- copy.getPrevBillingPeriod(),
- copy.getNextProduct(),
- copy.getNextPlan(),
- copy.getNextPhase(),
- copy.getNextPriceList(),
- copy.getNextBillingPeriod(),
- copy.getCreatedDate(),
- copy.getAccountTimeZone());
- }
-
- public DateTimeZone getAccountTimeZone() {
- return accountTimeZone;
- }
-
- public DateTime getEffectiveDateTime() {
- return effectiveDate;
- }
-
- public DateTime getRequestedDateTime() {
- return requestedDate;
- }
-
- @Override
- public UUID getId() {
- return id;
- }
-
- @Override
- public UUID getEntitlementId() {
- return entitlementId;
- }
-
- @Override
- public LocalDate getEffectiveDate() {
- return effectiveDate != null ? new LocalDate(effectiveDate, accountTimeZone) : null;
- }
-
- @Override
- public LocalDate getRequestedDate() {
- return requestedDate != null ? new LocalDate(requestedDate, accountTimeZone) : null;
- }
-
- @Override
- public SubscriptionEventType getSubscriptionEventType() {
- return eventType;
- }
-
- @Override
- public boolean isBlockedBilling() {
- return isBlockingBilling;
- }
-
- @Override
- public boolean isBlockedEntitlement() {
- return isBlockingEntitlement;
- }
-
- @Override
- public String getServiceName() {
- return serviceName;
- }
-
- @Override
- public String getServiceStateName() {
- return serviceStateName;
- }
-
- @Override
- public Product getPrevProduct() {
- return prevProduct;
- }
-
- @Override
- public Plan getPrevPlan() {
- return prevPlan;
- }
-
- @Override
- public PlanPhase getPrevPhase() {
- return prevPlanPhase;
- }
-
- @Override
- public PriceList getPrevPriceList() {
- return prevPriceList;
- }
-
- @Override
- public BillingPeriod getPrevBillingPeriod() {
- return prevBillingPeriod;
- }
-
- @Override
- public Product getNextProduct() {
- return nextProduct;
- }
-
- @Override
- public Plan getNextPlan() {
- return nextPlan;
- }
-
- @Override
- public PlanPhase getNextPhase() {
- return nextPlanPhase;
- }
-
- @Override
- public PriceList getNextPriceList() {
- return nextPriceList;
- }
-
- @Override
- public BillingPeriod getNextBillingPeriod() {
- return nextBillingPeriod;
- }
-
- public DateTime getCreatedDate() {
- return createdDate;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- final DefaultSubscriptionEvent that = (DefaultSubscriptionEvent) o;
-
- if (isBlockingBilling != that.isBlockingBilling) {
- return false;
- }
- if (isBlockingEntitlement != that.isBlockingEntitlement) {
- return false;
- }
- if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
- return false;
- }
- if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
- return false;
- }
- if (entitlementId != null ? !entitlementId.equals(that.entitlementId) : that.entitlementId != null) {
- return false;
- }
- if (eventType != that.eventType) {
- return false;
- }
- if (id != null ? !id.equals(that.id) : that.id != null) {
- return false;
- }
- if (nextBillingPeriod != that.nextBillingPeriod) {
- return false;
- }
- if (nextPlan != null ? !nextPlan.equals(that.nextPlan) : that.nextPlan != null) {
- return false;
- }
- if (nextPlanPhase != null ? !nextPlanPhase.equals(that.nextPlanPhase) : that.nextPlanPhase != null) {
- return false;
- }
- if (nextPriceList != null ? !nextPriceList.equals(that.nextPriceList) : that.nextPriceList != null) {
- return false;
- }
- if (nextProduct != null ? !nextProduct.equals(that.nextProduct) : that.nextProduct != null) {
- return false;
- }
- if (prevBillingPeriod != that.prevBillingPeriod) {
- return false;
- }
- if (prevPlan != null ? !prevPlan.equals(that.prevPlan) : that.prevPlan != null) {
- return false;
- }
- if (prevPlanPhase != null ? !prevPlanPhase.equals(that.prevPlanPhase) : that.prevPlanPhase != null) {
- return false;
- }
- if (prevPriceList != null ? !prevPriceList.equals(that.prevPriceList) : that.prevPriceList != null) {
- return false;
- }
- if (prevProduct != null ? !prevProduct.equals(that.prevProduct) : that.prevProduct != null) {
- return false;
- }
- if (requestedDate != null ? !requestedDate.equals(that.requestedDate) : that.requestedDate != null) {
- return false;
- }
- if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
- return false;
- }
- if (serviceStateName != null ? !serviceStateName.equals(that.serviceStateName) : that.serviceStateName != null) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = id != null ? id.hashCode() : 0;
- result = 31 * result + (entitlementId != null ? entitlementId.hashCode() : 0);
- result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
- result = 31 * result + (requestedDate != null ? requestedDate.hashCode() : 0);
- result = 31 * result + (eventType != null ? eventType.hashCode() : 0);
- result = 31 * result + (isBlockingEntitlement ? 1 : 0);
- result = 31 * result + (isBlockingBilling ? 1 : 0);
- result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
- result = 31 * result + (serviceStateName != null ? serviceStateName.hashCode() : 0);
- result = 31 * result + (prevProduct != null ? prevProduct.hashCode() : 0);
- result = 31 * result + (prevPlan != null ? prevPlan.hashCode() : 0);
- result = 31 * result + (prevPlanPhase != null ? prevPlanPhase.hashCode() : 0);
- result = 31 * result + (prevPriceList != null ? prevPriceList.hashCode() : 0);
- result = 31 * result + (prevBillingPeriod != null ? prevBillingPeriod.hashCode() : 0);
- result = 31 * result + (nextProduct != null ? nextProduct.hashCode() : 0);
- result = 31 * result + (nextPlan != null ? nextPlan.hashCode() : 0);
- result = 31 * result + (nextPlanPhase != null ? nextPlanPhase.hashCode() : 0);
- result = 31 * result + (nextPriceList != null ? nextPriceList.hashCode() : 0);
- result = 31 * result + (nextBillingPeriod != null ? nextBillingPeriod.hashCode() : 0);
- result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
- return result;
- }
- }
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionEvent.java
new file mode 100644
index 0000000..fbd7ab6
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionEvent.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning 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
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.entitlement.api;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.Product;
+
+public class DefaultSubscriptionEvent implements SubscriptionEvent {
+
+ private final UUID id;
+ private final UUID entitlementId;
+ private final DateTime effectiveDate;
+ private final DateTime requestedDate;
+ private final SubscriptionEventType eventType;
+ private final boolean isBlockingEntitlement;
+ private final boolean isBlockingBilling;
+ private final String serviceName;
+ private final String serviceStateName;
+ private final Product prevProduct;
+ private final Plan prevPlan;
+ private final PlanPhase prevPlanPhase;
+ private final PriceList prevPriceList;
+ private final BillingPeriod prevBillingPeriod;
+ private final Product nextProduct;
+ private final Plan nextPlan;
+ private final PlanPhase nextPlanPhase;
+ private final PriceList nextPriceList;
+ private final BillingPeriod nextBillingPeriod;
+ private final DateTime createdDate;
+ private final DateTimeZone accountTimeZone;
+
+ public DefaultSubscriptionEvent(final UUID id,
+ final UUID entitlementId,
+ final DateTime effectiveDate,
+ final DateTime requestedDate,
+ final SubscriptionEventType eventType,
+ final boolean blockingEntitlement,
+ final boolean blockingBilling,
+ final String serviceName,
+ final String serviceStateName,
+ final Product prevProduct,
+ final Plan prevPlan,
+ final PlanPhase prevPlanPhase,
+ final PriceList prevPriceList,
+ final BillingPeriod prevBillingPeriod,
+ final Product nextProduct,
+ final Plan nextPlan,
+ final PlanPhase nextPlanPhase,
+ final PriceList nextPriceList,
+ final BillingPeriod nextBillingPeriod,
+ final DateTime createDate,
+ final DateTimeZone accountTimeZone) {
+ this.id = id;
+ this.entitlementId = entitlementId;
+ this.effectiveDate = effectiveDate;
+ this.requestedDate = requestedDate;
+ this.eventType = eventType;
+ this.isBlockingEntitlement = blockingEntitlement;
+ this.isBlockingBilling = blockingBilling;
+ this.serviceName = serviceName;
+ this.serviceStateName = serviceStateName;
+ this.prevProduct = prevProduct;
+ this.prevPlan = prevPlan;
+ this.prevPlanPhase = prevPlanPhase;
+ this.prevPriceList = prevPriceList;
+ this.prevBillingPeriod = prevBillingPeriod;
+ this.nextProduct = nextProduct;
+ this.nextPlan = nextPlan;
+ this.nextPlanPhase = nextPlanPhase;
+ this.nextPriceList = nextPriceList;
+ this.nextBillingPeriod = nextBillingPeriod;
+ this.createdDate = createDate;
+ this.accountTimeZone = accountTimeZone;
+ }
+
+ public DefaultSubscriptionEvent(final DefaultSubscriptionEvent copy, final SubscriptionEventType newEventType) {
+ this(copy.getId(),
+ copy.getEntitlementId(),
+ copy.getEffectiveDateTime(),
+ copy.getRequestedDateTime(),
+ newEventType,
+ copy.isBlockedEntitlement(),
+ copy.isBlockedBilling(),
+ copy.getServiceName(),
+ copy.getServiceStateName(),
+ copy.getPrevProduct(),
+ copy.getPrevPlan(),
+ copy.getPrevPhase(),
+ copy.getPrevPriceList(),
+ copy.getPrevBillingPeriod(),
+ copy.getNextProduct(),
+ copy.getNextPlan(),
+ copy.getNextPhase(),
+ copy.getNextPriceList(),
+ copy.getNextBillingPeriod(),
+ copy.getCreatedDate(),
+ copy.getAccountTimeZone());
+ }
+
+ public DateTimeZone getAccountTimeZone() {
+ return accountTimeZone;
+ }
+
+ public DateTime getEffectiveDateTime() {
+ return effectiveDate;
+ }
+
+ public DateTime getRequestedDateTime() {
+ return requestedDate;
+ }
+
+ @Override
+ public UUID getId() {
+ return id;
+ }
+
+ @Override
+ public UUID getEntitlementId() {
+ return entitlementId;
+ }
+
+ @Override
+ public LocalDate getEffectiveDate() {
+ return effectiveDate != null ? new LocalDate(effectiveDate, accountTimeZone) : null;
+ }
+
+ @Override
+ public LocalDate getRequestedDate() {
+ return requestedDate != null ? new LocalDate(requestedDate, accountTimeZone) : null;
+ }
+
+ @Override
+ public SubscriptionEventType getSubscriptionEventType() {
+ return eventType;
+ }
+
+ @Override
+ public boolean isBlockedBilling() {
+ return isBlockingBilling;
+ }
+
+ @Override
+ public boolean isBlockedEntitlement() {
+ return isBlockingEntitlement;
+ }
+
+ @Override
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ @Override
+ public String getServiceStateName() {
+ return serviceStateName;
+ }
+
+ @Override
+ public Product getPrevProduct() {
+ return prevProduct;
+ }
+
+ @Override
+ public Plan getPrevPlan() {
+ return prevPlan;
+ }
+
+ @Override
+ public PlanPhase getPrevPhase() {
+ return prevPlanPhase;
+ }
+
+ @Override
+ public PriceList getPrevPriceList() {
+ return prevPriceList;
+ }
+
+ @Override
+ public BillingPeriod getPrevBillingPeriod() {
+ return prevBillingPeriod;
+ }
+
+ @Override
+ public Product getNextProduct() {
+ return nextProduct;
+ }
+
+ @Override
+ public Plan getNextPlan() {
+ return nextPlan;
+ }
+
+ @Override
+ public PlanPhase getNextPhase() {
+ return nextPlanPhase;
+ }
+
+ @Override
+ public PriceList getNextPriceList() {
+ return nextPriceList;
+ }
+
+ @Override
+ public BillingPeriod getNextBillingPeriod() {
+ return nextBillingPeriod;
+ }
+
+ public DateTime getCreatedDate() {
+ return createdDate;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultSubscriptionEvent that = (DefaultSubscriptionEvent) o;
+
+ if (isBlockingBilling != that.isBlockingBilling) {
+ return false;
+ }
+ if (isBlockingEntitlement != that.isBlockingEntitlement) {
+ return false;
+ }
+ if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
+ return false;
+ }
+ if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
+ return false;
+ }
+ if (entitlementId != null ? !entitlementId.equals(that.entitlementId) : that.entitlementId != null) {
+ return false;
+ }
+ if (eventType != that.eventType) {
+ return false;
+ }
+ if (id != null ? !id.equals(that.id) : that.id != null) {
+ return false;
+ }
+ if (nextBillingPeriod != that.nextBillingPeriod) {
+ return false;
+ }
+ if (nextPlan != null ? !nextPlan.equals(that.nextPlan) : that.nextPlan != null) {
+ return false;
+ }
+ if (nextPlanPhase != null ? !nextPlanPhase.equals(that.nextPlanPhase) : that.nextPlanPhase != null) {
+ return false;
+ }
+ if (nextPriceList != null ? !nextPriceList.equals(that.nextPriceList) : that.nextPriceList != null) {
+ return false;
+ }
+ if (nextProduct != null ? !nextProduct.equals(that.nextProduct) : that.nextProduct != null) {
+ return false;
+ }
+ if (prevBillingPeriod != that.prevBillingPeriod) {
+ return false;
+ }
+ if (prevPlan != null ? !prevPlan.equals(that.prevPlan) : that.prevPlan != null) {
+ return false;
+ }
+ if (prevPlanPhase != null ? !prevPlanPhase.equals(that.prevPlanPhase) : that.prevPlanPhase != null) {
+ return false;
+ }
+ if (prevPriceList != null ? !prevPriceList.equals(that.prevPriceList) : that.prevPriceList != null) {
+ return false;
+ }
+ if (prevProduct != null ? !prevProduct.equals(that.prevProduct) : that.prevProduct != null) {
+ return false;
+ }
+ if (requestedDate != null ? !requestedDate.equals(that.requestedDate) : that.requestedDate != null) {
+ return false;
+ }
+ if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
+ return false;
+ }
+ if (serviceStateName != null ? !serviceStateName.equals(that.serviceStateName) : that.serviceStateName != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean overlaps(final DefaultSubscriptionEvent that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null || getClass() != that.getClass()) {
+ return false;
+ }
+
+ if (isBlockingBilling != that.isBlockingBilling) {
+ return false;
+ }
+ if (isBlockingEntitlement != that.isBlockingEntitlement) {
+ return false;
+ }
+ if (effectiveDate != null ? effectiveDate.compareTo(that.effectiveDate) < 0 : that.effectiveDate != null) {
+ return false;
+ }
+ if (entitlementId != null ? !entitlementId.equals(that.entitlementId) : that.entitlementId != null) {
+ return false;
+ }
+ if (eventType != that.eventType) {
+ return false;
+ }
+ if (nextBillingPeriod != that.nextBillingPeriod) {
+ return false;
+ }
+ if (nextPlan != null ? !nextPlan.equals(that.nextPlan) : that.nextPlan != null) {
+ return false;
+ }
+ if (nextPlanPhase != null ? !nextPlanPhase.equals(that.nextPlanPhase) : that.nextPlanPhase != null) {
+ return false;
+ }
+ if (nextPriceList != null ? !nextPriceList.equals(that.nextPriceList) : that.nextPriceList != null) {
+ return false;
+ }
+ if (nextProduct != null ? !nextProduct.equals(that.nextProduct) : that.nextProduct != null) {
+ return false;
+ }
+ if (prevBillingPeriod != that.prevBillingPeriod) {
+ return false;
+ }
+ if (prevPlan != null ? !prevPlan.equals(that.prevPlan) : that.prevPlan != null) {
+ return false;
+ }
+ if (prevPlanPhase != null ? !prevPlanPhase.equals(that.prevPlanPhase) : that.prevPlanPhase != null) {
+ return false;
+ }
+ if (prevPriceList != null ? !prevPriceList.equals(that.prevPriceList) : that.prevPriceList != null) {
+ return false;
+ }
+ if (prevProduct != null ? !prevProduct.equals(that.prevProduct) : that.prevProduct != null) {
+ return false;
+ }
+ if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
+ return false;
+ }
+ if (serviceStateName != null ? !serviceStateName.equals(that.serviceStateName) : that.serviceStateName != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id != null ? id.hashCode() : 0;
+ result = 31 * result + (entitlementId != null ? entitlementId.hashCode() : 0);
+ result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
+ result = 31 * result + (requestedDate != null ? requestedDate.hashCode() : 0);
+ result = 31 * result + (eventType != null ? eventType.hashCode() : 0);
+ result = 31 * result + (isBlockingEntitlement ? 1 : 0);
+ result = 31 * result + (isBlockingBilling ? 1 : 0);
+ result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
+ result = 31 * result + (serviceStateName != null ? serviceStateName.hashCode() : 0);
+ result = 31 * result + (prevProduct != null ? prevProduct.hashCode() : 0);
+ result = 31 * result + (prevPlan != null ? prevPlan.hashCode() : 0);
+ result = 31 * result + (prevPlanPhase != null ? prevPlanPhase.hashCode() : 0);
+ result = 31 * result + (prevPriceList != null ? prevPriceList.hashCode() : 0);
+ result = 31 * result + (prevBillingPeriod != null ? prevBillingPeriod.hashCode() : 0);
+ result = 31 * result + (nextProduct != null ? nextProduct.hashCode() : 0);
+ result = 31 * result + (nextPlan != null ? nextPlan.hashCode() : 0);
+ result = 31 * result + (nextPlanPhase != null ? nextPlanPhase.hashCode() : 0);
+ result = 31 * result + (nextPriceList != null ? nextPriceList.hashCode() : 0);
+ result = 31 * result + (nextBillingPeriod != null ? nextBillingPeriod.hashCode() : 0);
+ result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionApi.java
index 6f27ece..bcfd0f1 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionApi.java
@@ -32,6 +32,9 @@ import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
import com.ning.billing.junction.DefaultBlockingState;
+import com.ning.billing.util.api.AuditLevel;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.ChangeType;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@@ -175,4 +178,56 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
assertNull(thirdBundle.getSubscriptions().get(0).getBillingEndDate());
assertEquals(thirdBundle.getOriginalCreatedDate().compareTo(firstbundle.getCreatedDate()), 0);
}
+
+ @Test(groups = "slow", description = "Test for https://github.com/killbill/killbill/issues/136")
+ public void testAuditLogsForEntitlementAndSubscriptionBaseObjects() throws AccountApiException, EntitlementApiException, SubscriptionApiException {
+ final LocalDate initialDate = new LocalDate(2013, 8, 7);
+ clock.setDay(initialDate);
+
+ final Account account = accountApi.createAccount(getAccountData(7), callContext);
+
+ // Create entitlement
+ testListener.pushExpectedEvent(NextEvent.CREATE);
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+ final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
+ assertListenerStatus();
+
+ // Get the phase event out of the way
+ testListener.pushExpectedEvents(NextEvent.PHASE);
+ clock.setDay(new LocalDate(2013, 9, 7));
+ assertListenerStatus();
+
+ final LocalDate pauseDate = new LocalDate(2013, 9, 17);
+ entitlementApi.pause(baseEntitlement.getBundleId(), pauseDate, callContext);
+
+ final LocalDate resumeDate = new LocalDate(2013, 12, 24);
+ entitlementApi.resume(baseEntitlement.getBundleId(), resumeDate, callContext);
+
+ final LocalDate cancelDate = new LocalDate(2013, 12, 27);
+ baseEntitlement.cancelEntitlementWithDate(cancelDate, true, callContext);
+
+ testListener.pushExpectedEvents(NextEvent.PAUSE, NextEvent.BLOCK, NextEvent.RESUME, NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.BLOCK);
+ clock.setDay(cancelDate.plusDays(1));
+ assertListenerStatus();
+
+ final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(baseEntitlement.getBundleId(), callContext);
+ final List<SubscriptionEvent> transitions = bundle.getTimeline().getSubscriptionEvents();
+ assertEquals(transitions.size(), 9);
+ checkSubscriptionEventAuditLog(transitions, 0, SubscriptionEventType.START_ENTITLEMENT);
+ checkSubscriptionEventAuditLog(transitions, 1, SubscriptionEventType.START_BILLING);
+ checkSubscriptionEventAuditLog(transitions, 2, SubscriptionEventType.PHASE);
+ checkSubscriptionEventAuditLog(transitions, 3, SubscriptionEventType.PAUSE_ENTITLEMENT);
+ checkSubscriptionEventAuditLog(transitions, 4, SubscriptionEventType.PAUSE_BILLING);
+ checkSubscriptionEventAuditLog(transitions, 5, SubscriptionEventType.RESUME_ENTITLEMENT);
+ checkSubscriptionEventAuditLog(transitions, 6, SubscriptionEventType.RESUME_BILLING);
+ checkSubscriptionEventAuditLog(transitions, 7, SubscriptionEventType.STOP_ENTITLEMENT);
+ checkSubscriptionEventAuditLog(transitions, 8, SubscriptionEventType.STOP_BILLING);
+ }
+
+ private void checkSubscriptionEventAuditLog(final List<SubscriptionEvent> transitions, final int idx, final SubscriptionEventType expectedType) {
+ assertEquals(transitions.get(idx).getSubscriptionEventType(), expectedType);
+ final List<AuditLog> auditLogs = auditUserApi.getAuditLogs(transitions.get(idx).getId(), transitions.get(idx).getSubscriptionEventType().getObjectType(), AuditLevel.FULL, callContext);
+ assertEquals(auditLogs.size(), 1);
+ assertEquals(auditLogs.get(0).getChangeType(), ChangeType.INSERT);
+ }
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java
index 359f73c..fd225ad 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java
@@ -29,7 +29,6 @@ import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.CatalogApiException;
import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhase;
@@ -45,6 +44,7 @@ import com.ning.billing.subscription.events.SubscriptionBaseEvent.EventType;
import com.ning.billing.subscription.events.user.ApiEventType;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteNoDB {
@@ -56,7 +56,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
bundleId = UUID.randomUUID();
}
-
public class TestSubscriptionBundleTimeline extends DefaultSubscriptionBundleTimeline {
public TestSubscriptionBundleTimeline(final DateTimeZone accountTimeZone, final UUID accountId, final UUID bundleId, final String externalKey, final List<Entitlement> entitlements, final List<BlockingState> allBlockingStates) {
@@ -65,33 +64,33 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
public SubscriptionEvent createEvent(final UUID subscriptionId, final SubscriptionEventType type, final DateTime effectiveDate) {
return new DefaultSubscriptionEvent(UUID.randomUUID(),
- subscriptionId,
- effectiveDate,
- null,
- type,
- true,
- true,
- "foo",
- "bar",
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null);
+ subscriptionId,
+ effectiveDate,
+ null,
+ type,
+ true,
+ true,
+ "foo",
+ "bar",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null);
}
}
@Test(groups = "fast")
public void testReOrderSubscriptionEventsOnInvalidOrder1() {
- TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+ final TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
final UUID subscriptionId = UUID.randomUUID();
@@ -109,10 +108,9 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
Assert.assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
}
-
@Test(groups = "fast")
public void testReOrderSubscriptionEventsOnInvalidOrder2() {
- TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+ final TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
final UUID subscriptionId = UUID.randomUUID();
@@ -132,7 +130,7 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
@Test(groups = "fast")
public void testReOrderSubscriptionEventsOnInvalidOrder3() {
- TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+ final TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
final UUID subscriptionId = UUID.randomUUID();
@@ -150,10 +148,9 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
Assert.assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
}
-
@Test(groups = "fast")
public void testReOrderSubscriptionEventsOnInvalidOrderAndDifferentSubscriptionsSameDates1() {
- TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+ final TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
final UUID subscriptionId = UUID.fromString("60b64e0c-cefd-48c3-8de9-c731a9558165");
@@ -180,7 +177,7 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
@Test(groups = "fast")
public void testReOrderSubscriptionEventsOnInvalidOrderAndDifferentSubscriptionsSameDates2() {
- TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+ final TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
final UUID subscriptionId = UUID.fromString("35b3b340-31b2-46ea-b062-e9fc9fab3bc9");
@@ -208,7 +205,7 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
@Test(groups = "fast")
public void testReOrderSubscriptionEventsOnInvalidOrderAndDifferentSubscriptionsDates() {
- TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+ final TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
final UUID subscriptionId = UUID.randomUUID();
@@ -242,13 +239,11 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
Assert.assertEquals(events.get(7).getSubscriptionEventType(), SubscriptionEventType.PAUSE_BILLING);
Assert.assertEquals(events.get(8).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
Assert.assertEquals(events.get(9).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
-
-
}
@Test(groups = "fast")
public void testReOrderSubscriptionEventsOnCorrectOrder() {
- TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+ final TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
final UUID subscriptionId = UUID.randomUUID();
@@ -268,7 +263,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
@Test(groups = "fast")
public void testOneEntitlementNoBlockingStates() throws CatalogApiException {
-
clock.setDay(new LocalDate(2013, 1, 1));
final DateTimeZone accountTimeZone = DateTimeZone.UTC;
@@ -276,7 +270,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final UUID bundleId = UUID.randomUUID();
final String externalKey = "foo";
-
final UUID entitlementId = UUID.randomUUID();
final List<SubscriptionBaseTransition> allTransitions = new ArrayList<SubscriptionBaseTransition>();
@@ -291,24 +284,22 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final SubscriptionBaseTransition tr2 = createTransition(entitlementId, EventType.PHASE, null, requestedDate, effectiveDate, clock.getUTCNow(), "trial", "phase");
allTransitions.add(tr2);
-
effectiveDate = effectiveDate.plusDays(15);
clock.addDays(15);
final SubscriptionBaseTransition tr3 = createTransition(entitlementId, EventType.API_USER, ApiEventType.CANCEL, requestedDate, effectiveDate, clock.getUTCNow(), "phase", null);
allTransitions.add(tr3);
-
final List<Entitlement> entitlements = new ArrayList<Entitlement>();
final Entitlement entitlement = createEntitlement(entitlementId, allTransitions);
entitlements.add(entitlement);
- final DefaultSubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, Collections.<BlockingState>emptyList());
+ final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, Collections.<BlockingState>emptyList());
assertEquals(timeline.getAccountId(), accountId);
assertEquals(timeline.getBundleId(), bundleId);
assertEquals(timeline.getExternalKey(), externalKey);
- List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
+ final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
assertEquals(events.size(), 4);
assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
@@ -321,14 +312,23 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
assertEquals(events.get(2).getSubscriptionEventType(), SubscriptionEventType.PHASE);
assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
+ assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(1).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(2).getServiceName(), DefaultSubscriptionBundleTimeline.ENT_BILLING_SERVICE_NAME);
+ assertEquals(events.get(3).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+
+ assertNull(events.get(0).getPrevPhase());
assertEquals(events.get(0).getNextPhase().getName(), "trial");
+ assertNull(events.get(1).getPrevPhase());
assertEquals(events.get(1).getNextPhase().getName(), "trial");
+ assertEquals(events.get(2).getPrevPhase().getName(), "trial");
assertEquals(events.get(2).getNextPhase().getName(), "phase");
- assertEquals(events.get(3).getNextPhase(), null);
+ assertEquals(events.get(3).getPrevPhase().getName(), "phase");
+ assertNull(events.get(3).getNextPhase());
}
- @Test(groups = "fast")
- public void testOneEntitlementWithRecreate() throws CatalogApiException {
+ @Test(groups = "fast", description = "Test for https://github.com/killbill/killbill/issues/135")
+ public void testOneEntitlementWithPauseResume() throws CatalogApiException {
clock.setDay(new LocalDate(2013, 1, 1));
final DateTimeZone accountTimeZone = DateTimeZone.UTC;
@@ -339,6 +339,7 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final UUID entitlementId = UUID.randomUUID();
final List<SubscriptionBaseTransition> allTransitions = new ArrayList<SubscriptionBaseTransition>();
+ final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
final DateTime requestedDate = new DateTime();
DateTime effectiveDate = new DateTime(2013, 1, 1, 15, 43, 25, 0, DateTimeZone.UTC);
@@ -350,57 +351,112 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final SubscriptionBaseTransition tr2 = createTransition(entitlementId, EventType.PHASE, null, requestedDate, effectiveDate, clock.getUTCNow(), "trial", "phase");
allTransitions.add(tr2);
+ effectiveDate = effectiveDate.plusDays(12);
+ clock.addDays(12);
+ final BlockingState bs1 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION,
+ "NothingUseful1", DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME,
+ true, true, true, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+
+ blockingStates.add(bs1);
+
+ effectiveDate = effectiveDate.plusDays(42);
+ clock.addDays(42);
+ final BlockingState bs2 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION,
+ "NothingUseful2", DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME,
+ false, false, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+
+ blockingStates.add(bs2);
+
effectiveDate = effectiveDate.plusDays(15);
clock.addDays(15);
- final SubscriptionBaseTransition tr3 = createTransition(entitlementId, EventType.API_USER, ApiEventType.CANCEL, requestedDate, effectiveDate, clock.getUTCNow(), "phase", null);
- allTransitions.add(tr3);
+ final String service = "boo";
+ final BlockingState bs3 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION,
+ "NothingUseful3", service,
+ false, false, true, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+
+ blockingStates.add(bs3);
effectiveDate = effectiveDate.plusDays(15);
clock.addDays(15);
- final SubscriptionBaseTransition tr4 = createTransition(entitlementId, EventType.API_USER, ApiEventType.RE_CREATE, requestedDate, effectiveDate, clock.getUTCNow(), null, "phase");
- allTransitions.add(tr4);
+ final BlockingState bs4 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION,
+ "NothingUseful4", service,
+ false, false, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+
+ blockingStates.add(bs4);
final List<Entitlement> entitlements = new ArrayList<Entitlement>();
final Entitlement entitlement = createEntitlement(entitlementId, allTransitions);
entitlements.add(entitlement);
- final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, Collections.<BlockingState>emptyList());
+ final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
assertEquals(timeline.getAccountId(), accountId);
assertEquals(timeline.getBundleId(), bundleId);
assertEquals(timeline.getExternalKey(), externalKey);
final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
- assertEquals(events.size(), 7);
+ assertEquals(events.size(), 9);
assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
assertEquals(events.get(1).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
assertEquals(events.get(2).getEffectiveDate().compareTo(new LocalDate(tr2.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(3).getEffectiveDate().compareTo(new LocalDate(tr3.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(4).getEffectiveDate().compareTo(new LocalDate(tr3.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(5).getEffectiveDate().compareTo(new LocalDate(tr4.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(6).getEffectiveDate().compareTo(new LocalDate(tr4.getEffectiveTransitionTime(), accountTimeZone)), 0);
+ assertEquals(events.get(3).getEffectiveDate().compareTo(new LocalDate(bs1.getEffectiveDate(), accountTimeZone)), 0);
+ assertEquals(events.get(4).getEffectiveDate().compareTo(new LocalDate(bs1.getEffectiveDate(), accountTimeZone)), 0);
+ assertEquals(events.get(5).getEffectiveDate().compareTo(new LocalDate(bs2.getEffectiveDate(), accountTimeZone)), 0);
+ assertEquals(events.get(6).getEffectiveDate().compareTo(new LocalDate(bs2.getEffectiveDate(), accountTimeZone)), 0);
+ assertEquals(events.get(7).getEffectiveDate().compareTo(new LocalDate(bs3.getEffectiveDate(), accountTimeZone)), 0);
+ assertEquals(events.get(8).getEffectiveDate().compareTo(new LocalDate(bs4.getEffectiveDate(), accountTimeZone)), 0);
assertEquals(events.get(0).getSubscriptionEventType(), SubscriptionEventType.START_ENTITLEMENT);
assertEquals(events.get(1).getSubscriptionEventType(), SubscriptionEventType.START_BILLING);
+
assertEquals(events.get(2).getSubscriptionEventType(), SubscriptionEventType.PHASE);
+
assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.PAUSE_ENTITLEMENT);
assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.PAUSE_BILLING);
assertEquals(events.get(5).getSubscriptionEventType(), SubscriptionEventType.RESUME_ENTITLEMENT);
assertEquals(events.get(6).getSubscriptionEventType(), SubscriptionEventType.RESUME_BILLING);
+ assertEquals(events.get(7).getSubscriptionEventType(), SubscriptionEventType.SERVICE_STATE_CHANGE);
+ assertEquals(events.get(8).getSubscriptionEventType(), SubscriptionEventType.SERVICE_STATE_CHANGE);
+
+ assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(1).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+
+ assertEquals(events.get(2).getServiceName(), DefaultSubscriptionBundleTimeline.ENT_BILLING_SERVICE_NAME);
+
+ assertEquals(events.get(3).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(4).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(5).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(6).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+
+ assertEquals(events.get(7).getServiceName(), service);
+ assertEquals(events.get(8).getServiceName(), service);
+
+ assertNull(events.get(0).getPrevPhase());
assertEquals(events.get(0).getNextPhase().getName(), "trial");
+ assertNull(events.get(1).getPrevPhase());
assertEquals(events.get(1).getNextPhase().getName(), "trial");
+
+ assertEquals(events.get(2).getPrevPhase().getName(), "trial");
assertEquals(events.get(2).getNextPhase().getName(), "phase");
- assertEquals(events.get(3).getNextPhase(), null);
- assertEquals(events.get(4).getNextPhase(), null);
+
+ assertEquals(events.get(3).getPrevPhase().getName(), "phase");
+ assertEquals(events.get(3).getNextPhase().getName(), "phase");
+ assertEquals(events.get(4).getPrevPhase().getName(), "phase");
+ assertEquals(events.get(4).getNextPhase().getName(), "phase");
+ assertEquals(events.get(5).getPrevPhase().getName(), "phase");
assertEquals(events.get(5).getNextPhase().getName(), "phase");
+ assertEquals(events.get(6).getPrevPhase().getName(), "phase");
assertEquals(events.get(6).getNextPhase().getName(), "phase");
+ assertEquals(events.get(7).getPrevPhase().getName(), "phase");
+ assertEquals(events.get(7).getNextPhase().getName(), "phase");
+ assertEquals(events.get(8).getPrevPhase().getName(), "phase");
+ assertEquals(events.get(8).getNextPhase().getName(), "phase");
}
@Test(groups = "fast")
public void testOneEntitlementWithInitialBlockingState() throws CatalogApiException {
-
clock.setDay(new LocalDate(2013, 1, 1));
final DateTimeZone accountTimeZone = DateTimeZone.UTC;
@@ -408,7 +464,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final UUID bundleId = UUID.randomUUID();
final String externalKey = "foo";
-
final UUID entitlementId = UUID.randomUUID();
final List<SubscriptionBaseTransition> allTransitions = new ArrayList<SubscriptionBaseTransition>();
@@ -431,31 +486,29 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final SubscriptionBaseTransition tr2 = createTransition(entitlementId, EventType.PHASE, null, requestedDate, effectiveDate, clock.getUTCNow(), "trial", "phase");
allTransitions.add(tr2);
-
+ final String service = "boo";
final BlockingState bs2 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION,
- "NothingUseful", "boo",
+ "NothingUseful", service,
false, false, false, clock.getUTCNow(), clock.getUTCNow(), clock.getUTCNow());
blockingStates.add(bs2);
-
effectiveDate = effectiveDate.plusDays(15);
clock.addDays(15);
final SubscriptionBaseTransition tr3 = createTransition(entitlementId, EventType.API_USER, ApiEventType.CANCEL, requestedDate, effectiveDate, clock.getUTCNow(), "phase", null);
allTransitions.add(tr3);
-
final List<Entitlement> entitlements = new ArrayList<Entitlement>();
final Entitlement entitlement = createEntitlement(entitlementId, allTransitions);
entitlements.add(entitlement);
- final DefaultSubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
+ final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
assertEquals(timeline.getAccountId(), accountId);
assertEquals(timeline.getBundleId(), bundleId);
assertEquals(timeline.getExternalKey(), externalKey);
- List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
+ final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
assertEquals(events.size(), 5);
assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
@@ -470,18 +523,26 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.SERVICE_STATE_CHANGE);
assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
+ assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(1).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(2).getServiceName(), DefaultSubscriptionBundleTimeline.ENT_BILLING_SERVICE_NAME);
+ assertEquals(events.get(3).getServiceName(), service);
+ assertEquals(events.get(4).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+
+ assertNull(events.get(0).getPrevPhase());
assertEquals(events.get(0).getNextPhase().getName(), "trial");
+ assertNull(events.get(1).getPrevPhase());
assertEquals(events.get(1).getNextPhase().getName(), "trial");
+ assertEquals(events.get(2).getPrevPhase().getName(), "trial");
assertEquals(events.get(2).getNextPhase().getName(), "phase");
+ assertEquals(events.get(3).getPrevPhase().getName(), "phase");
assertEquals(events.get(3).getNextPhase().getName(), "phase");
- assertEquals(events.get(4).getNextPhase(), null);
+ assertEquals(events.get(4).getPrevPhase().getName(), "phase");
+ assertNull(events.get(4).getNextPhase());
}
-
-
@Test(groups = "fast")
public void testOneEntitlementWithBlockingStatesSubscription() throws CatalogApiException {
-
clock.setDay(new LocalDate(2013, 1, 1));
final DateTimeZone accountTimeZone = DateTimeZone.UTC;
@@ -489,7 +550,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final UUID bundleId = UUID.randomUUID();
final String externalKey = "foo";
-
final UUID entitlementId = UUID.randomUUID();
final List<SubscriptionBaseTransition> allTransitions = new ArrayList<SubscriptionBaseTransition>();
@@ -526,10 +586,9 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final Entitlement entitlement = createEntitlement(entitlementId, allTransitions);
entitlements.add(entitlement);
+ final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
- final DefaultSubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
-
- List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
+ final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
assertEquals(events.size(), 6);
assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
@@ -546,24 +605,32 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
assertEquals(events.get(5).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
- assertEquals(events.get(0).getPrevPhase(), null);
+ assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(1).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(2).getServiceName(), DefaultSubscriptionBundleTimeline.ENT_BILLING_SERVICE_NAME);
+ assertEquals(events.get(3).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(4).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(5).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+
+ assertNull(events.get(0).getPrevPhase());
assertEquals(events.get(0).getNextPhase().getName(), "trial");
- assertEquals(events.get(1).getPrevPhase(), null);
+ assertNull(events.get(1).getPrevPhase());
assertEquals(events.get(1).getNextPhase().getName(), "trial");
+
assertEquals(events.get(2).getPrevPhase().getName(), "trial");
assertEquals(events.get(2).getNextPhase().getName(), "phase");
+
assertEquals(events.get(3).getPrevPhase().getName(), "phase");
assertEquals(events.get(3).getNextPhase().getName(), "phase");
+
assertEquals(events.get(4).getPrevPhase().getName(), "phase");
- assertEquals(events.get(4).getNextPhase(), null);
+ assertNull(events.get(4).getNextPhase());
assertEquals(events.get(5).getPrevPhase().getName(), "phase");
- assertEquals(events.get(5).getNextPhase(), null);
+ assertNull(events.get(5).getNextPhase());
}
-
@Test(groups = "fast")
public void testWithMultipleEntitlements() throws CatalogApiException {
-
clock.setDay(new LocalDate(2013, 1, 1));
final DateTimeZone accountTimeZone = DateTimeZone.UTC;
@@ -571,7 +638,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final UUID bundleId = UUID.randomUUID();
final String externalKey = "foo";
-
final UUID entitlementId1 = UUID.fromString("cf5a597a-cf15-45d3-8f02-95371be7f927");
final UUID entitlementId2 = UUID.fromString("e37cc97a-7b98-4ab6-a29a-7259e45c3366");
@@ -584,7 +650,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final SubscriptionBaseTransition ent1Tr1 = createTransition(entitlementId1, EventType.API_USER, ApiEventType.CREATE, requestedDate, effectiveDate, clock.getUTCNow(), null, "trial1");
allTransitions1.add(ent1Tr1);
-
effectiveDate = effectiveDate.plusDays(15);
clock.addDays(15);
final SubscriptionBaseTransition ent2Tr1 = createTransition(entitlementId2, EventType.API_USER, ApiEventType.TRANSFER, requestedDate, effectiveDate, clock.getUTCNow(), null, "phase2");
@@ -619,10 +684,9 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final Entitlement entitlement2 = createEntitlement(entitlementId2, allTransitions2);
entitlements.add(entitlement2);
+ final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
- final DefaultSubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
-
- List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
+ final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
assertEquals(events.size(), 9);
assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(ent1Tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
@@ -651,13 +715,27 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
assertEquals(events.get(7).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
assertEquals(events.get(8).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
- assertEquals(events.get(0).getPrevPhase(), null);
+ assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(1).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(2).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(3).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+
+ assertEquals(events.get(4).getServiceName(), DefaultSubscriptionBundleTimeline.ENT_BILLING_SERVICE_NAME);
+
+ assertEquals(events.get(5).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(6).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+
+ assertEquals(events.get(7).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(8).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+
+ assertNull(events.get(0).getPrevPhase());
assertEquals(events.get(0).getNextPhase().getName(), "trial1");
- assertEquals(events.get(1).getPrevPhase(), null);
+ assertNull(events.get(1).getPrevPhase());
assertEquals(events.get(1).getNextPhase().getName(), "trial1");
- assertEquals(events.get(2).getPrevPhase(), null);
+
+ assertNull(events.get(2).getPrevPhase());
assertEquals(events.get(2).getNextPhase().getName(), "phase2");
- assertEquals(events.get(3).getPrevPhase(), null);
+ assertNull(events.get(3).getPrevPhase());
assertEquals(events.get(3).getNextPhase().getName(), "phase2");
assertEquals(events.get(4).getPrevPhase().getName(), "trial1");
@@ -667,20 +745,17 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
assertEquals(events.get(5).getNextPhase().getName(), "phase1");
assertEquals(events.get(6).getPrevPhase().getName(), "phase2");
- assertEquals(events.get(6).getNextPhase(), null);
+ assertEquals(events.get(6).getNextPhase().getName(), "phase2");
assertEquals(events.get(7).getPrevPhase().getName(), "phase1");
- assertEquals(events.get(7).getNextPhase(), null);
+ assertNull(events.get(7).getNextPhase());
assertEquals(events.get(8).getPrevPhase().getName(), "phase1");
- assertEquals(events.get(8).getNextPhase(), null);
-
+ assertNull(events.get(8).getNextPhase());
}
-
-
@Test(groups = "fast")
- public void testWithOverdueOfflineAndClear() throws CatalogApiException {
+ public void testWithOverdueOffline() throws CatalogApiException {
clock.setDay(new LocalDate(2013, 1, 1));
final DateTimeZone accountTimeZone = DateTimeZone.UTC;
@@ -704,45 +779,24 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final SubscriptionBaseTransition tr2 = createTransition(entitlementId, EventType.PHASE, null, requestedDate, effectiveDate, clock.getUTCNow(), "trial", "phase");
allTransitions.add(tr2);
- effectiveDate = effectiveDate.plusDays(6); // 2013-02-06
- clock.addDays(6);
+ effectiveDate = effectiveDate.plusDays(40); // 2013-03-12
+ clock.addDays(40);
final SubscriptionBaseTransition tr3 = createTransition(entitlementId, EventType.API_USER, ApiEventType.CANCEL, requestedDate, effectiveDate, clock.getUTCNow(), "phase", null);
allTransitions.add(tr3);
- effectiveDate = effectiveDate.plusDays(22);// 2013-02-28
- clock.addDays(22);
- final SubscriptionBaseTransition tr4 = createTransition(entitlementId, EventType.API_USER, ApiEventType.RE_CREATE, requestedDate, effectiveDate, clock.getUTCNow(), null, "phase");
- allTransitions.add(tr4);
-
- effectiveDate = effectiveDate.plusDays(12); // 2013-03-12
- clock.addDays(12);
- final SubscriptionBaseTransition tr5 = createTransition(entitlementId, EventType.API_USER, ApiEventType.CANCEL, requestedDate, effectiveDate, clock.getUTCNow(), "phase", null);
- allTransitions.add(tr5);
-
+ final String service = "overdue-service";
final BlockingState bs1 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.ACCOUNT,
- "OFFLINE", "overdue-service",
+ "OFFLINE", service,
true, true, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
blockingStates.add(bs1);
-
final BlockingState bs2 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION,
DefaultEntitlementApi.ENT_STATE_CANCELLED, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME,
true, true, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
blockingStates.add(bs2);
-
- effectiveDate = effectiveDate.plusDays(12); // 2013-03-24
- clock.addDays(12);
-
- final BlockingState bs3 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.ACCOUNT,
- "__KILLBILL__CLEAR__OVERDUE__STATE__", "overdue-service",
- false, false, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
-
- blockingStates.add(bs3);
-
-
final List<Entitlement> entitlements = new ArrayList<Entitlement>();
final Entitlement entitlement = createEntitlement(entitlementId, allTransitions);
entitlements.add(entitlement);
@@ -754,48 +808,132 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
assertEquals(timeline.getExternalKey(), externalKey);
final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
- assertEquals(events.size(), 11);
+ assertEquals(events.size(), 6);
assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
assertEquals(events.get(1).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
assertEquals(events.get(2).getEffectiveDate().compareTo(new LocalDate(tr2.getEffectiveTransitionTime(), accountTimeZone)), 0);
assertEquals(events.get(3).getEffectiveDate().compareTo(new LocalDate(tr3.getEffectiveTransitionTime(), accountTimeZone)), 0);
assertEquals(events.get(4).getEffectiveDate().compareTo(new LocalDate(tr3.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(5).getEffectiveDate().compareTo(new LocalDate(tr4.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(6).getEffectiveDate().compareTo(new LocalDate(tr4.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(7).getEffectiveDate().compareTo(new LocalDate(tr5.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(8).getEffectiveDate().compareTo(new LocalDate(tr5.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(9).getEffectiveDate().compareTo(new LocalDate(tr5.getEffectiveTransitionTime(), accountTimeZone)), 0);
- assertEquals(events.get(10).getEffectiveDate().compareTo(new LocalDate(bs3.getEffectiveDate(), accountTimeZone)), 0);
+ assertEquals(events.get(5).getEffectiveDate().compareTo(new LocalDate(bs1.getEffectiveDate(), accountTimeZone)), 0);
assertEquals(events.get(0).getSubscriptionEventType(), SubscriptionEventType.START_ENTITLEMENT);
assertEquals(events.get(1).getSubscriptionEventType(), SubscriptionEventType.START_BILLING);
assertEquals(events.get(2).getSubscriptionEventType(), SubscriptionEventType.PHASE);
- assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.PAUSE_ENTITLEMENT);
- assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.PAUSE_BILLING);
- assertEquals(events.get(5).getSubscriptionEventType(), SubscriptionEventType.RESUME_ENTITLEMENT);
- assertEquals(events.get(6).getSubscriptionEventType(), SubscriptionEventType.RESUME_BILLING);
- assertEquals(events.get(7).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
- assertEquals(events.get(8).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
- assertEquals(events.get(9).getSubscriptionEventType(), SubscriptionEventType.SERVICE_STATE_CHANGE);
- assertEquals(events.get(10).getSubscriptionEventType(), SubscriptionEventType.SERVICE_STATE_CHANGE);
+ assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
+ assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
+ assertEquals(events.get(5).getSubscriptionEventType(), SubscriptionEventType.SERVICE_STATE_CHANGE);
+
+ assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(1).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(2).getServiceName(), DefaultSubscriptionBundleTimeline.ENT_BILLING_SERVICE_NAME);
+ assertEquals(events.get(3).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(4).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(5).getServiceName(), service);
+ assertNull(events.get(0).getPrevPhase());
assertEquals(events.get(0).getNextPhase().getName(), "trial");
+ assertNull(events.get(1).getPrevPhase());
assertEquals(events.get(1).getNextPhase().getName(), "trial");
+
+ assertEquals(events.get(2).getPrevPhase().getName(), "trial");
assertEquals(events.get(2).getNextPhase().getName(), "phase");
- assertEquals(events.get(3).getNextPhase(), null);
- assertEquals(events.get(4).getNextPhase(), null);
- assertEquals(events.get(5).getNextPhase().getName(), "phase");
- assertEquals(events.get(6).getNextPhase().getName(), "phase");
- assertEquals(events.get(7).getNextPhase(), null);
- assertEquals(events.get(8).getNextPhase(), null);
- assertEquals(events.get(9).getNextPhase(), null);
- assertEquals(events.get(10).getNextPhase(), null);
+
+ assertEquals(events.get(3).getPrevPhase().getName(), "phase");
+ assertNull(events.get(3).getNextPhase());
+ assertEquals(events.get(4).getPrevPhase().getName(), "phase");
+ assertNull(events.get(4).getNextPhase());
+
+ assertEquals(events.get(5).getPrevPhase().getName(), "phase");
+ assertNull(events.get(5).getNextPhase());
}
+ @Test(groups = "fast", description = "Test for https://github.com/killbill/killbill/issues/134")
+ public void testRemoveOverlappingBlockingStates() throws CatalogApiException {
+ clock.setDay(new LocalDate(2013, 1, 1));
+
+ final DateTimeZone accountTimeZone = DateTimeZone.UTC;
+ final UUID accountId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
+ final String externalKey = "foo";
+
+ final UUID entitlementId = UUID.randomUUID();
+
+ final List<SubscriptionBaseTransition> allTransitions = new ArrayList<SubscriptionBaseTransition>();
+ final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
+
+ final DateTime requestedDate = new DateTime();
+ DateTime effectiveDate = new DateTime(2013, 1, 1, 15, 43, 25, 0, DateTimeZone.UTC);
+ final SubscriptionBaseTransition tr1 = createTransition(entitlementId, EventType.API_USER, ApiEventType.CREATE, requestedDate, effectiveDate, clock.getUTCNow(), null, "trial");
+ allTransitions.add(tr1);
+
+ // Overlapping ENT_STATE_BLOCKED - should merge
+ effectiveDate = effectiveDate.plusDays(5);
+ clock.addDays(5);
+ final BlockingState bs1 = new DefaultBlockingState(UUID.randomUUID(), entitlementId, BlockingStateType.SUBSCRIPTION,
+ DefaultEntitlementApi.ENT_STATE_BLOCKED, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME,
+ true, true, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+ blockingStates.add(bs1);
+
+ effectiveDate = effectiveDate.plusDays(1);
+ clock.addDays(1);
+ final BlockingState bs2 = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE,
+ DefaultEntitlementApi.ENT_STATE_BLOCKED, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME,
+ true, true, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+
+ blockingStates.add(bs2);
+
+ // Overlapping ENT_STATE_CANCELLED - should merge
+ effectiveDate = effectiveDate.plusDays(1);
+ clock.addDays(1);
+ final BlockingState bs3 = new DefaultBlockingState(UUID.randomUUID(), accountId, BlockingStateType.ACCOUNT,
+ DefaultEntitlementApi.ENT_STATE_CANCELLED, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME,
+ true, true, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+
+ blockingStates.add(bs3);
+ final BlockingState bs4 = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE,
+ DefaultEntitlementApi.ENT_STATE_CANCELLED, DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME,
+ true, true, false, effectiveDate, clock.getUTCNow(), clock.getUTCNow());
+
+ blockingStates.add(bs4);
+
+ final List<Entitlement> entitlements = new ArrayList<Entitlement>();
+ final Entitlement entitlement = createEntitlement(entitlementId, allTransitions);
+ entitlements.add(entitlement);
- private DefaultEntitlement createEntitlement(final UUID entitlementId, final List<SubscriptionBaseTransition> allTransitions) {
+ final SubscriptionBundleTimeline timeline = new DefaultSubscriptionBundleTimeline(accountTimeZone, accountId, bundleId, externalKey, entitlements, blockingStates);
+ final List<SubscriptionEvent> events = timeline.getSubscriptionEvents();
+ assertEquals(events.size(), 4);
+
+ assertEquals(events.get(0).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
+ assertEquals(events.get(1).getEffectiveDate().compareTo(new LocalDate(tr1.getEffectiveTransitionTime(), accountTimeZone)), 0);
+ assertEquals(events.get(2).getEffectiveDate().compareTo(new LocalDate(bs1.getEffectiveDate(), accountTimeZone)), 0);
+ assertEquals(events.get(3).getEffectiveDate().compareTo(new LocalDate(bs3.getEffectiveDate(), accountTimeZone)), 0);
+
+ assertEquals(events.get(0).getSubscriptionEventType(), SubscriptionEventType.START_ENTITLEMENT);
+ assertEquals(events.get(1).getSubscriptionEventType(), SubscriptionEventType.START_BILLING);
+ assertEquals(events.get(2).getSubscriptionEventType(), SubscriptionEventType.PAUSE_ENTITLEMENT);
+ assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
+
+ assertEquals(events.get(0).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(1).getServiceName(), DefaultSubscriptionBundleTimeline.BILLING_SERVICE_NAME);
+ assertEquals(events.get(2).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+ assertEquals(events.get(3).getServiceName(), DefaultEntitlementService.ENTITLEMENT_SERVICE_NAME);
+
+ assertNull(events.get(0).getPrevPhase());
+ assertEquals(events.get(0).getNextPhase().getName(), "trial");
+ assertNull(events.get(1).getPrevPhase());
+ assertEquals(events.get(1).getNextPhase().getName(), "trial");
+
+ assertEquals(events.get(2).getPrevPhase().getName(), "trial");
+ assertEquals(events.get(2).getNextPhase().getName(), "trial");
+
+ assertEquals(events.get(3).getPrevPhase().getName(), "trial");
+ assertNull(events.get(3).getNextPhase());
+ }
+
+ private Entitlement createEntitlement(final UUID entitlementId, final List<SubscriptionBaseTransition> allTransitions) {
final DefaultEntitlement result = Mockito.mock(DefaultEntitlement.class);
Mockito.when(result.getId()).thenReturn(entitlementId);
@@ -805,13 +943,6 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
return result;
}
- private String computePhaseName(final UUID entitlementId, final EventType eventType, final ApiEventType apiEventType) {
- return "phase-" +
- entitlementId.toString() +
- "-" +
- (eventType == EventType.API_USER ? apiEventType : eventType);
- }
-
private SubscriptionBaseTransition createTransition(final UUID entitlementId,
final EventType eventType,
final ApiEventType apiEventType,
@@ -821,58 +952,76 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
final String prevPhaseName,
final String nextPhaseName
) throws CatalogApiException {
+ final PlanPhase prevPhase;
+ final Plan prevPlan;
+ final Product prevProduct;
+ final PriceList prevPriceList;
+ if (prevPhaseName == null) {
+ prevPhase = null;
+ prevPlan = null;
+ prevProduct = null;
+ prevPriceList = null;
+ } else {
+ prevPhase = Mockito.mock(PlanPhase.class);
+ Mockito.when(prevPhase.getName()).thenReturn(prevPhaseName);
+ prevProduct = Mockito.mock(Product.class);
+ Mockito.when(prevProduct.getName()).thenReturn("product");
- final PlanPhase prevPhase = prevPhaseName != null ? Mockito.mock(PlanPhase.class) : null;
- if (prevPhase != null) {
- Mockito.when(prevPhase.getName()).thenReturn(prevPhaseName);
+ prevPlan = Mockito.mock(Plan.class);
+ Mockito.when(prevPlan.getName()).thenReturn("plan");
+ Mockito.when(prevPlan.getProduct()).thenReturn(prevProduct);
+
+ prevPriceList = Mockito.mock(PriceList.class);
+ Mockito.when(prevPriceList.getName()).thenReturn("pricelist");
}
- final PlanPhase nextPhase = nextPhaseName != null ? Mockito.mock(PlanPhase.class) : null;
- if (nextPhase != null) {
+ final PlanPhase nextPhase;
+ final Plan nextPlan;
+ final Product nextProduct;
+ final PriceList nextPriceList;
+ if (nextPhaseName == null) {
+ nextPhase = null;
+ nextPlan = null;
+ nextProduct = null;
+ nextPriceList = null;
+ } else {
+ nextPhase = Mockito.mock(PlanPhase.class);
Mockito.when(nextPhase.getName()).thenReturn(nextPhaseName);
+
+ nextProduct = Mockito.mock(Product.class);
+ Mockito.when(nextProduct.getName()).thenReturn("product");
+
+ nextPlan = Mockito.mock(Plan.class);
+ Mockito.when(nextPlan.getName()).thenReturn("plan");
+ Mockito.when(nextPlan.getProduct()).thenReturn(nextProduct);
+
+ nextPriceList = Mockito.mock(PriceList.class);
+ Mockito.when(nextPriceList.getName()).thenReturn("pricelist");
}
- //catalogService.getCurrentCatalog().findCurrentPhase("pistol-monthly-trial");
- final Plan plan = Mockito.mock(Plan.class);
- Mockito.when(plan.getName()).thenReturn("plan");
-
-
- //catalogService.getCurrentCatalog().findCurrentPlan("pistol-monthly");
- final Product product = Mockito.mock(Product.class);
- Mockito.when(product.getName()).thenReturn("product");
-
- //catalogService.getCurrentCatalog().findCurrentProduct("Pistol");
-
- final PriceList priceList = Mockito.mock(PriceList.class);
- Mockito.when(priceList.getName()).thenReturn("pricelist");
-
- //catalogService.getCurrentCatalog().findCurrentPricelist(PriceListSet.DEFAULT_PRICELIST_NAME);
- final BillingPeriod billingPeriod = BillingPeriod.MONTHLY;
-
- final SubscriptionBaseTransition transition = new SubscriptionBaseTransitionData(UUID.randomUUID(),
- entitlementId,
- bundleId,
- eventType,
- apiEventType,
- requestedDate,
- effectiveDate,
- null,
- null,
- null,
- plan,
- prevPhase,
- priceList,
- null,
- null,
- null,
- plan,
- nextPhase,
- priceList,
- 1L,
- createdDate,
- UUID.randomUUID(),
- true);
- return transition;
+ return new SubscriptionBaseTransitionData(UUID.randomUUID(),
+ entitlementId,
+ bundleId,
+ eventType,
+ apiEventType,
+ requestedDate,
+ effectiveDate,
+ null,
+ null,
+ null,
+ prevPlan,
+ prevPhase,
+ prevPriceList,
+ null,
+ null,
+ null,
+ nextPlan,
+ nextPhase,
+ nextPriceList,
+ 1L,
+ createdDate,
+ UUID.randomUUID(),
+ true);
}
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java b/entitlement/src/test/java/com/ning/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java
index 99711d9..e0396c1 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java
@@ -52,6 +52,7 @@ import com.ning.billing.subscription.api.SubscriptionBaseInternalApi;
import com.ning.billing.subscription.api.SubscriptionBaseService;
import com.ning.billing.subscription.engine.core.DefaultSubscriptionBaseService;
import com.ning.billing.tag.TagInternalApi;
+import com.ning.billing.util.api.AuditUserApi;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.svcsapi.bus.BusService;
import com.ning.billing.util.tag.dao.TagDao;
@@ -108,6 +109,8 @@ public class EntitlementTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteWi
@Inject
protected EventsStreamBuilder eventsStreamBuilder;
@Inject
+ protected AuditUserApi auditUserApi;
+ @Inject
protected InternalCallContextFactory internalCallContextFactory;
protected Catalog catalog;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/TestEntitlementModuleWithEmbeddedDB.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/TestEntitlementModuleWithEmbeddedDB.java
index 2369cb6..0b40737 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/TestEntitlementModuleWithEmbeddedDB.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/TestEntitlementModuleWithEmbeddedDB.java
@@ -25,6 +25,7 @@ import com.ning.billing.api.TestListenerStatus;
import com.ning.billing.catalog.glue.CatalogModule;
import com.ning.billing.entitlement.EntitlementTestListenerStatus;
import com.ning.billing.subscription.glue.DefaultSubscriptionModule;
+import com.ning.billing.util.glue.AuditModule;
import com.ning.billing.util.glue.BusModule;
import com.ning.billing.util.glue.MetricsModule;
import com.ning.billing.util.glue.NonEntityDaoModule;
@@ -49,6 +50,7 @@ public class TestEntitlementModuleWithEmbeddedDB extends TestEntitlementModule {
install(new CatalogModule(configSource));
install(new NotificationQueueModule(configSource));
install(new DefaultSubscriptionModule(configSource));
+ install(new AuditModule());
bind(TestListenerStatus.class).to(EntitlementTestListenerStatus.class).asEagerSingleton();
bind(TestApiListener.class).asEagerSingleton();
invoice/pom.xml 2(+1 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 1f78927..030497f 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-invoice</artifactId>
jaxrs/pom.xml 2(+1 -1)
diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index 345c7ca..68b4477 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-jaxrs</artifactId>
junction/pom.xml 2(+1 -1)
diff --git a/junction/pom.xml b/junction/pom.xml
index fb6b57f..e187bd6 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-junction</artifactId>
NEWS 6(+6 -0)
diff --git a/NEWS b/NEWS
index c528d75..3a050f2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+0.8.5
+ https://github.com/killbill/killbill/issues/134
+ https://github.com/killbill/killbill/issues/135
+ https://github.com/killbill/killbill/issues/136
+ https://github.com/killbill/killbill/issues/140
+
0.8.4
Subscription base speedups
Fix regression in bundle timeline API
osgi/pom.xml 2(+1 -1)
diff --git a/osgi/pom.xml b/osgi/pom.xml
index 9a64008..10b9dd3 100644
--- a/osgi/pom.xml
+++ b/osgi/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi</artifactId>
osgi-bundles/bundles/jruby/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/bundles/jruby/pom.xml b/osgi-bundles/bundles/jruby/pom.xml
index 1359ab5..fd3ade3 100644
--- a/osgi-bundles/bundles/jruby/pom.xml
+++ b/osgi-bundles/bundles/jruby/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill-osgi-bundles</artifactId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-jruby</artifactId>
osgi-bundles/bundles/logger/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/bundles/logger/pom.xml b/osgi-bundles/bundles/logger/pom.xml
index 50b2f75..bc85013 100644
--- a/osgi-bundles/bundles/logger/pom.xml
+++ b/osgi-bundles/bundles/logger/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-logger</artifactId>
osgi-bundles/bundles/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/bundles/pom.xml b/osgi-bundles/bundles/pom.xml
index 1a4372a..f582871 100644
--- a/osgi-bundles/bundles/pom.xml
+++ b/osgi-bundles/bundles/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles</artifactId>
diff --git a/osgi-bundles/bundles/webconsolebranding/pom.xml b/osgi-bundles/bundles/webconsolebranding/pom.xml
index 0065bd1..8f4d304 100644
--- a/osgi-bundles/bundles/webconsolebranding/pom.xml
+++ b/osgi-bundles/bundles/webconsolebranding/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-webconsolebranding</artifactId>
osgi-bundles/defaultbundles/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/defaultbundles/pom.xml b/osgi-bundles/defaultbundles/pom.xml
index 8d497e9..2447276 100644
--- a/osgi-bundles/defaultbundles/pom.xml
+++ b/osgi-bundles/defaultbundles/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-defaultbundles</artifactId>
osgi-bundles/libs/killbill/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/libs/killbill/pom.xml b/osgi-bundles/libs/killbill/pom.xml
index a1ce27b..1d327f7 100644
--- a/osgi-bundles/libs/killbill/pom.xml
+++ b/osgi-bundles/libs/killbill/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-lib-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-lib-killbill</artifactId>
osgi-bundles/libs/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/libs/pom.xml b/osgi-bundles/libs/pom.xml
index 7796ac0..655a061 100644
--- a/osgi-bundles/libs/pom.xml
+++ b/osgi-bundles/libs/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-lib-bundles</artifactId>
osgi-bundles/libs/slf4j-osgi/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/libs/slf4j-osgi/pom.xml b/osgi-bundles/libs/slf4j-osgi/pom.xml
index 4712edb..22a896f 100644
--- a/osgi-bundles/libs/slf4j-osgi/pom.xml
+++ b/osgi-bundles/libs/slf4j-osgi/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-lib-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-lib-slf4j-osgi</artifactId>
osgi-bundles/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/pom.xml b/osgi-bundles/pom.xml
index 4232e6b..c8d28b6 100644
--- a/osgi-bundles/pom.xml
+++ b/osgi-bundles/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
osgi-bundles/tests/beatrix/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/tests/beatrix/pom.xml b/osgi-bundles/tests/beatrix/pom.xml
index 0260789..a4e9c33 100644
--- a/osgi-bundles/tests/beatrix/pom.xml
+++ b/osgi-bundles/tests/beatrix/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-test-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-test-beatrix</artifactId>
osgi-bundles/tests/payment/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/tests/payment/pom.xml b/osgi-bundles/tests/payment/pom.xml
index dcf75c8..0a17689 100644
--- a/osgi-bundles/tests/payment/pom.xml
+++ b/osgi-bundles/tests/payment/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-test-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-bundles-test-payment</artifactId>
osgi-bundles/tests/pom.xml 2(+1 -1)
diff --git a/osgi-bundles/tests/pom.xml b/osgi-bundles/tests/pom.xml
index 664c307..629cbc8 100644
--- a/osgi-bundles/tests/pom.xml
+++ b/osgi-bundles/tests/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-osgi-all-bundles</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-osgi-test-bundles</artifactId>
overdue/pom.xml 2(+1 -1)
diff --git a/overdue/pom.xml b/overdue/pom.xml
index b7c00f4..7a324dd 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-overdue</artifactId>
payment/pom.xml 2(+1 -1)
diff --git a/payment/pom.xml b/payment/pom.xml
index d937594..36e140f 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPayment.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPayment.java
index 23a067b..b47865b 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPayment.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPayment.java
@@ -158,7 +158,7 @@ public class DefaultPayment extends EntityBase implements Payment {
BigDecimal result = amount;
for (RefundModelDao cur : refunds) {
- if (cur.getRefundStatus() != RefundStatus.CREATED) {
+ if (cur.getRefundStatus() == RefundStatus.COMPLETED) {
result = result.subtract(cur.getAmount());
}
}
pom.xml 4(+2 -2)
diff --git a/pom.xml b/pom.xml
index 220af20..858d7fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,10 +19,10 @@
<parent>
<artifactId>killbill-oss-parent</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.5.7</version>
+ <version>0.5.8</version>
</parent>
<artifactId>killbill</artifactId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<packaging>pom</packaging>
<name>killbill</name>
<description>Library for managing recurring subscriptions and the associated billing</description>
server/pom.xml 2(+1 -1)
diff --git a/server/pom.xml b/server/pom.xml
index b1b9f66..12e0b5a 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-server</artifactId>
subscription/pom.xml 2(+1 -1)
diff --git a/subscription/pom.xml b/subscription/pom.xml
index cfa35c4..856419f 100644
--- a/subscription/pom.xml
+++ b/subscription/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-subscription</artifactId>
tenant/pom.xml 2(+1 -1)
diff --git a/tenant/pom.xml b/tenant/pom.xml
index 5907887..082ca08 100644
--- a/tenant/pom.xml
+++ b/tenant/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-tenant</artifactId>
usage/pom.xml 2(+1 -1)
diff --git a/usage/pom.xml b/usage/pom.xml
index 02850db..1824d27 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-usage</artifactId>
util/pom.xml 2(+1 -1)
diff --git a/util/pom.xml b/util/pom.xml
index 1f89950..61bf29f 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -12,7 +12,7 @@
<parent>
<artifactId>killbill</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.8.5-SNAPSHOT</version>
+ <version>0.8.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>