killbill-aplcache
Modify code to use raw entitlement events rather that SubscripyionTransition-- …
4/25/2012 3:37:32 PM
Changes
entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultEntitlementRepairApi.java 126(+72 -54)
entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultSubscriptionRepair.java 167(+154 -13)
Details
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultEntitlementRepairApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultEntitlementRepairApi.java
index e7cd999..9813448 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultEntitlementRepairApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultEntitlementRepairApi.java
@@ -32,6 +32,9 @@ import org.joda.time.DateTime;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.CatalogUserApi;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.SubscriptionFactory;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
@@ -42,6 +45,7 @@ import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory.SubscriptionBuilder;
+import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
import com.ning.billing.entitlement.events.EntitlementEvent;
@@ -55,18 +59,20 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
private final EntitlementDao dao;
private final SubscriptionFactory factory;
private final RepairEntitlementLifecycleDao repairDao;
+ private final CatalogService catalogService;
+
-
private enum RepairType {
BASE_REPAIR,
ADD_ON_REPAIR,
STANDALONE_REPAIR
}
-
+
@Inject
- public DefaultEntitlementRepairApi(@Named(EntitlementModule.REPAIR_NAMED) final SubscriptionFactory factory,
+ public DefaultEntitlementRepairApi(@Named(EntitlementModule.REPAIR_NAMED) final SubscriptionFactory factory, final CatalogService catalogService,
@Named(EntitlementModule.REPAIR_NAMED) final RepairEntitlementLifecycleDao repairDao, final EntitlementDao dao) {
+ this.catalogService = catalogService;
this.dao = dao;
this.repairDao = repairDao;
this.factory = factory;
@@ -77,20 +83,24 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
public BundleRepair getBundleRepair(final UUID bundleId)
throws EntitlementRepairException {
- SubscriptionBundle bundle = dao.getSubscriptionBundleFromId(bundleId);
- if (bundle == null) {
- throw new EntitlementRepairException(ErrorCode.ENT_REPAIR_UNKNOWN_BUNDLE, bundleId);
- }
- final List<Subscription> subscriptions = dao.getSubscriptions(factory, bundleId);
- if (subscriptions.size() == 0) {
- throw new EntitlementRepairException(ErrorCode.ENT_REPAIR_NO_ACTIVE_SUBSCRIPTIONS, bundleId);
+ try {
+ SubscriptionBundle bundle = dao.getSubscriptionBundleFromId(bundleId);
+ if (bundle == null) {
+ throw new EntitlementRepairException(ErrorCode.ENT_REPAIR_UNKNOWN_BUNDLE, bundleId);
+ }
+ final List<Subscription> subscriptions = dao.getSubscriptions(factory, bundleId);
+ if (subscriptions.size() == 0) {
+ throw new EntitlementRepairException(ErrorCode.ENT_REPAIR_NO_ACTIVE_SUBSCRIPTIONS, bundleId);
+ }
+ final String viewId = getViewId(((SubscriptionBundleData) bundle).getLastSysUpdateTime(), subscriptions);
+ final List<SubscriptionRepair> repairs = createGetSubscriptionRepairList(subscriptions, Collections.<SubscriptionRepair>emptyList());
+ return createGetBundleRepair(bundleId, viewId, repairs);
+ } catch (CatalogApiException e) {
+ throw new EntitlementRepairException(e);
}
- final String viewId = getViewId(((SubscriptionBundleData) bundle).getLastSysUpdateTime(), subscriptions);
- final List<SubscriptionRepair> repairs = createGetSubscriptionRepairList(subscriptions, Collections.<SubscriptionRepair>emptyList());
- return createGetBundleRepair(bundleId, viewId, repairs);
}
-
-
+
+
@Override
public BundleRepair repairBundle(final BundleRepair input, final boolean dryRun, final CallContext context)
@@ -130,21 +140,21 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
if (curRepair != null) {
SubscriptionDataRepair curInputRepair = ((SubscriptionDataRepair) cur);
final List<EntitlementEvent> remaining = getRemainingEventsAndValidateDeletedEvents(curInputRepair, firstDeletedBPEventTime, curRepair.getDeletedEvents());
-
+
final boolean isPlanRecreate = (curRepair.getNewEvents().size() > 0
&& (curRepair.getNewEvents().get(0).getSubscriptionTransitionType() == SubscriptionTransitionType.CREATE
|| curRepair.getNewEvents().get(0).getSubscriptionTransitionType() == SubscriptionTransitionType.RE_CREATE));
-
+
final DateTime newSubscriptionStartDate = isPlanRecreate ? curRepair.getNewEvents().get(0).getRequestedDate() : null;
-
+
if (isPlanRecreate && remaining.size() != 0) {
throw new EntitlementRepairException(ErrorCode.ENT_REPAIR_SUB_RECREATE_NOT_EMPTY, cur.getId(), cur.getBundleId());
}
-
+
if (!isPlanRecreate && remaining.size() == 0) {
throw new EntitlementRepairException(ErrorCode.ENT_REPAIR_SUB_EMPTY, cur.getId(), cur.getBundleId());
}
-
+
if (cur.getCategory() == ProductCategory.BASE) {
int bpTransitionSize =((SubscriptionData) cur).getAllTransitions().size();
@@ -175,30 +185,30 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
}
}
}
-
+
final RepairType repairType = getRepairType(subscriptions.get(0), (baseSubscriptionRepair != null));
switch(repairType) {
- case BASE_REPAIR:
- // We need to add any existing addon that are not in the input repair list
- for (Subscription cur : subscriptions) {
- if (cur.getCategory() == ProductCategory.ADD_ON && !inRepair.contains(cur)) {
- SubscriptionDataRepair curOutputRepair = createSubscriptionDataRepair((SubscriptionDataRepair) cur, newBundleStartDate, null, ((SubscriptionDataRepair) cur).getEvents());
- repairDao.initializeRepair(curOutputRepair.getId(), ((SubscriptionDataRepair) cur).getEvents());
- inRepair.add(curOutputRepair);
- addOnSubscriptionInRepair.add(curOutputRepair);
- }
+ case BASE_REPAIR:
+ // We need to add any existing addon that are not in the input repair list
+ for (Subscription cur : subscriptions) {
+ if (cur.getCategory() == ProductCategory.ADD_ON && !inRepair.contains(cur)) {
+ SubscriptionDataRepair curOutputRepair = createSubscriptionDataRepair((SubscriptionDataRepair) cur, newBundleStartDate, null, ((SubscriptionDataRepair) cur).getEvents());
+ repairDao.initializeRepair(curOutputRepair.getId(), ((SubscriptionDataRepair) cur).getEvents());
+ inRepair.add(curOutputRepair);
+ addOnSubscriptionInRepair.add(curOutputRepair);
}
-
- break;
- case ADD_ON_REPAIR:
- // We need to set the baseSubscription as it is useful to calculate addon validity
- SubscriptionDataRepair baseSubscription = (SubscriptionDataRepair) subscriptions.get(0);
- baseSubscriptionRepair = createSubscriptionDataRepair(baseSubscription, baseSubscription.getBundleStartDate(), baseSubscription.getStartDate(), baseSubscription.getEvents());
- break;
- case STANDALONE_REPAIR:
- default:
- break;
-
+ }
+
+ break;
+ case ADD_ON_REPAIR:
+ // We need to set the baseSubscription as it is useful to calculate addon validity
+ SubscriptionDataRepair baseSubscription = (SubscriptionDataRepair) subscriptions.get(0);
+ baseSubscriptionRepair = createSubscriptionDataRepair(baseSubscription, baseSubscription.getBundleStartDate(), baseSubscription.getStartDate(), baseSubscription.getEvents());
+ break;
+ case STANDALONE_REPAIR:
+ default:
+ break;
+
}
validateBasePlanRecreate(isBasePlanRecreate, subscriptions, input.getSubscriptions());
@@ -215,19 +225,27 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
}
curDataRepair.addNewRepairEvent(cur, baseSubscriptionRepair, addOnSubscriptionInRepair, context);
}
-
+
if (dryRun) {
+
+ baseSubscriptionRepair.addFutureAddonCancellation(addOnSubscriptionInRepair, context);
+
final List<SubscriptionRepair> repairs = createGetSubscriptionRepairList(subscriptions, convertDataRepair(inRepair));
return createGetBundleRepair(input.getBundleId(), input.getViewId(), repairs);
} else {
dao.repair(input.getBundleId(), inRepair, context);
return getBundleRepair(input.getBundleId());
}
+ } catch (CatalogApiException e) {
+ throw new EntitlementRepairException(e);
} finally {
repairDao.cleanup();
}
}
+
+
+
private RepairType getRepairType(final Subscription firstSubscription, final boolean gotBaseSubscription) {
if (firstSubscription.getCategory() == ProductCategory.BASE) {
return gotBaseSubscription ? RepairType.BASE_REPAIR : RepairType.ADD_ON_REPAIR;
@@ -235,10 +253,10 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
return RepairType.STANDALONE_REPAIR;
}
}
-
+
private void validateBasePlanRecreate(boolean isBasePlanRecreate, List<Subscription> subscriptions, List<SubscriptionRepair> input)
- throws EntitlementRepairException {
-
+ throws EntitlementRepairException {
+
if (!isBasePlanRecreate) {
return;
}
@@ -253,10 +271,10 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
}
}
}
-
-
+
+
private void validateInputSubscriptionsKnown(List<Subscription> subscriptions, List<SubscriptionRepair> input)
- throws EntitlementRepairException {
+ throws EntitlementRepairException {
for (SubscriptionRepair cur : input) {
boolean found = false;
@@ -284,7 +302,7 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
}
}
-
+
private Collection<NewEvent> createOrderedNewEventInput(List<SubscriptionRepair> subscriptionsReapir) {
TreeSet<NewEvent> newEventSet = new TreeSet<SubscriptionRepair.NewEvent>(new Comparator<NewEvent>() {
@Override
@@ -352,7 +370,7 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
return result;
}
-
+
private String getViewId(DateTime lastUpdateBundleDate, List<Subscription> subscriptions) {
StringBuilder tmp = new StringBuilder();
long lastOrderedId = -1;
@@ -383,7 +401,7 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
}
- private List<SubscriptionRepair> createGetSubscriptionRepairList(final List<Subscription> subscriptions, final List<SubscriptionRepair> inRepair) {
+ private List<SubscriptionRepair> createGetSubscriptionRepairList(final List<Subscription> subscriptions, final List<SubscriptionRepair> inRepair) throws CatalogApiException {
final List<SubscriptionRepair> result = new LinkedList<SubscriptionRepair>();
Set<UUID> repairIds = new TreeSet<UUID>();
@@ -393,17 +411,17 @@ public class DefaultEntitlementRepairApi implements EntitlementRepairApi {
}
for (final Subscription cur : subscriptions) {
if ( !repairIds.contains(cur.getId())) {
- result.add(new DefaultSubscriptionRepair((SubscriptionData) cur));
+ result.add(new DefaultSubscriptionRepair((SubscriptionDataRepair) cur, catalogService.getFullCatalog()));
}
}
return result;
}
- private List<SubscriptionRepair> convertDataRepair(List<SubscriptionDataRepair> input) {
+ private List<SubscriptionRepair> convertDataRepair(List<SubscriptionDataRepair> input) throws CatalogApiException {
List<SubscriptionRepair> result = new LinkedList<SubscriptionRepair>();
for (SubscriptionDataRepair cur : input) {
- result.add(new DefaultSubscriptionRepair(cur));
+ result.add(new DefaultSubscriptionRepair(cur, catalogService.getFullCatalog()));
}
return result;
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultSubscriptionRepair.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultSubscriptionRepair.java
index 297825c..7444385 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultSubscriptionRepair.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/DefaultSubscriptionRepair.java
@@ -25,7 +25,12 @@ import java.util.UUID;
import org.joda.time.DateTime;
import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.CatalogUserApi;
import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.Plan;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.SubscriptionTransitionType;
@@ -33,6 +38,12 @@ import com.ning.billing.entitlement.api.repair.SubscriptionRepair.ExistingEvent;
import com.ning.billing.entitlement.api.repair.SubscriptionRepair.NewEvent;
import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
+import com.ning.billing.entitlement.events.EntitlementEvent;
+import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
+import com.ning.billing.entitlement.events.phase.PhaseEvent;
+import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.sun.org.apache.xml.internal.resolver.CatalogException;
public class DefaultSubscriptionRepair implements SubscriptionRepair {
@@ -61,37 +72,74 @@ public class DefaultSubscriptionRepair implements SubscriptionRepair {
}
// CTOR for returning events only
- public DefaultSubscriptionRepair(SubscriptionData input) {
+ public DefaultSubscriptionRepair(SubscriptionDataRepair input, Catalog catalog) throws CatalogApiException {
this.id = input.getId();
- this.existingEvents = toExistingEvents(input.getCategory(), input.getAllTransitions());
+ this.existingEvents = toExistingEvents(catalog, input.getActiveVersion(), input.getCategory(), input.getEvents());
this.deletedEvents = null;
this.newEvents = null;
}
- private List<ExistingEvent> toExistingEvents(final ProductCategory category, final List<SubscriptionTransitionData> transitions) {
+ private List<ExistingEvent> toExistingEvents(final Catalog catalog, final long activeVersion, final ProductCategory category, final List<EntitlementEvent> events)
+ throws CatalogApiException {
+
List<ExistingEvent> result = new LinkedList<SubscriptionRepair.ExistingEvent>();
- for (final SubscriptionTransitionData cur : transitions) {
+
+ String prevProductName = null;
+ BillingPeriod prevBillingPeriod = null;
+ String prevPriceListName = null;
+ PhaseType prevPhaseType = null;
+
+ DateTime startDate = null;
+
+ for (final EntitlementEvent cur : events) {
- String productName = null;
+ // First active event is used to figure out which catalog version to use.
+ //startDate = (startDate == null && cur.getActiveVersion() == activeVersion) ? cur.getEffectiveDate() : startDate;
+
+ // STEPH that needs tp be reviewed if we support mutli version events
+ if (cur.getActiveVersion() != activeVersion) {
+ continue;
+ }
+ startDate = (startDate == null) ? cur.getEffectiveDate() : startDate;
+
+
+ String productName = null;
BillingPeriod billingPeriod = null;
String priceListName = null;
PhaseType phaseType = null;
- if (cur.getTransitionType() != SubscriptionTransitionType.CANCEL) {
- productName = cur.getNextPlan().getProduct().getName();
- billingPeriod = cur.getNextPhase().getBillingPeriod();
- priceListName = cur.getNextPriceList();
- phaseType = cur.getNextPhase().getPhaseType();
+
+ ApiEventType apiType = null;
+ switch (cur.getType()) {
+ case PHASE:
+ PhaseEvent phaseEV = (PhaseEvent) cur;
+ phaseType = catalog.findPhase(phaseEV.getPhase(), cur.getEffectiveDate(), startDate).getPhaseType();
+ productName = prevProductName;
+ billingPeriod = catalog.findPhase(phaseEV.getPhase(), cur.getEffectiveDate(), startDate).getBillingPeriod();
+ priceListName = prevPriceListName;
+ break;
+
+ case API_USER:
+ ApiEvent userEV = (ApiEvent) cur;
+ apiType = userEV.getEventType();
+ Plan plan = (userEV.getEventPlan() != null) ? catalog.findPlan(userEV.getEventPlan(), cur.getRequestedDate(), startDate) : null;
+ phaseType = (userEV.getEventPlanPhase() != null) ? catalog.findPhase(userEV.getEventPlanPhase(), cur.getEffectiveDate(), startDate).getPhaseType() : prevPhaseType;
+ productName = (plan != null) ? plan.getProduct().getName() : prevProductName;
+ billingPeriod = (userEV.getEventPlanPhase() != null) ? catalog.findPhase(userEV.getEventPlanPhase(), cur.getEffectiveDate(), startDate).getBillingPeriod() : prevBillingPeriod;
+ priceListName = (userEV.getPriceList() != null) ? userEV.getPriceList() : prevPriceListName;
+ break;
}
+
+ final SubscriptionTransitionType transitionType = SubscriptionTransitionData.toSubscriptionTransitionType(cur.getType(), apiType);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, category, billingPeriod, priceListName, phaseType);
result.add(new ExistingEvent() {
@Override
public SubscriptionTransitionType getSubscriptionTransitionType() {
- return cur.getTransitionType();
+ return transitionType;
}
@Override
public DateTime getRequestedDate() {
- return cur.getRequestedTransitionTime();
+ return cur.getRequestedDate();
}
@Override
public PlanPhaseSpecifier getPlanPhaseSpecifier() {
@@ -103,13 +151,106 @@ public class DefaultSubscriptionRepair implements SubscriptionRepair {
}
@Override
public DateTime getEffectiveDate() {
- return cur.getEffectiveTransitionTime();
+ return cur.getEffectiveDate();
}
});
+
+ prevProductName = productName;
+ prevBillingPeriod = billingPeriod;
+ prevPriceListName = priceListName;
+ prevPhaseType = phaseType;
+
}
sortExistingEvent(result);
return result;
}
+
+
+ /*
+
+ private List<ExistingEvent> toExistingEvents(final Catalog catalog, final long processingVersion, final ProductCategory category, final List<EntitlementEvent> events, List<ExistingEvent> result)
+ throws CatalogApiException {
+
+
+ String prevProductName = null;
+ BillingPeriod prevBillingPeriod = null;
+ String prevPriceListName = null;
+ PhaseType prevPhaseType = null;
+
+ DateTime startDate = null;
+
+ for (final EntitlementEvent cur : events) {
+
+ if (processingVersion != cur.getActiveVersion()) {
+ continue;
+ }
+
+ // First active event is used to figure out which catalog version to use.
+ startDate = (startDate == null && cur.getActiveVersion() == processingVersion) ? cur.getEffectiveDate() : startDate;
+
+ String productName = null;
+ BillingPeriod billingPeriod = null;
+ String priceListName = null;
+ PhaseType phaseType = null;
+
+ ApiEventType apiType = null;
+ switch (cur.getType()) {
+ case PHASE:
+ PhaseEvent phaseEV = (PhaseEvent) cur;
+ phaseType = catalog.findPhase(phaseEV.getPhase(), cur.getEffectiveDate(), startDate).getPhaseType();
+ productName = prevProductName;
+ billingPeriod = prevBillingPeriod;
+ priceListName = prevPriceListName;
+ break;
+
+ case API_USER:
+ ApiEvent userEV = (ApiEvent) cur;
+ apiType = userEV.getEventType();
+ Plan plan = (userEV.getEventPlan() != null) ? catalog.findPlan(userEV.getEventPlan(), cur.getRequestedDate(), startDate) : null;
+ phaseType = (userEV.getEventPlanPhase() != null) ? catalog.findPhase(userEV.getEventPlanPhase(), cur.getEffectiveDate(), startDate).getPhaseType() : prevPhaseType;
+ productName = (plan != null) ? plan.getProduct().getName() : prevProductName;
+ billingPeriod = (plan != null) ? plan.getBillingPeriod() : prevBillingPeriod;
+ priceListName = (userEV.getPriceList() != null) ? userEV.getPriceList() : prevPriceListName;
+ break;
+ }
+
+ final SubscriptionTransitionType transitionType = SubscriptionTransitionData.toSubscriptionTransitionType(cur.getType(), apiType);
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, category, billingPeriod, priceListName, phaseType);
+ result.add(new ExistingEvent() {
+ @Override
+ public SubscriptionTransitionType getSubscriptionTransitionType() {
+ return transitionType;
+ }
+ @Override
+ public DateTime getRequestedDate() {
+ return cur.getRequestedDate();
+ }
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifier() {
+ return spec;
+ }
+ @Override
+ public UUID getEventId() {
+ return cur.getId();
+ }
+ @Override
+ public DateTime getEffectiveDate() {
+ return cur.getEffectiveDate();
+ }
+ });
+ prevProductName = productName;
+ prevBillingPeriod = billingPeriod;
+ prevPriceListName = priceListName;
+ prevPhaseType = phaseType;
+ }
+ }
+ */
+
+
+
+
+
@Override
public UUID getId() {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/SubscriptionDataRepair.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/SubscriptionDataRepair.java
index 809c23c..b79d658 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/SubscriptionDataRepair.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/repair/SubscriptionDataRepair.java
@@ -34,8 +34,10 @@ import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.SubscriptionApiService;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory.SubscriptionBuilder;
import com.ning.billing.entitlement.engine.addon.AddonUtils;
import com.ning.billing.entitlement.engine.dao.EntitlementDao;
@@ -110,7 +112,6 @@ public class SubscriptionDataRepair extends SubscriptionData {
default:
throw new EntitlementRepairException(ErrorCode.ENT_REPAIR_UNKNOWN_TYPE, input.getSubscriptionTransitionType(), id);
}
-
} catch (EntitlementUserApiException e) {
throw new EntitlementRepairException(e);
} catch (CatalogApiException e) {
@@ -119,18 +120,40 @@ public class SubscriptionDataRepair extends SubscriptionData {
}
- private void trickleDownBPEffectForAddon(final List<SubscriptionDataRepair> addonSubscriptions, final DateTime effectiveDate, final CallContext context)
+ public void addFutureAddonCancellation(List<SubscriptionDataRepair> addOnSubscriptionInRepair, final CallContext context) {
+
+ if (category != ProductCategory.BASE) {
+ return;
+ }
+
+ SubscriptionEventTransition pendingTransition = getPendingTransition();
+ if (pendingTransition == null) {
+ return;
+ }
+ Product baseProduct = (pendingTransition.getTransitionType() == SubscriptionTransitionType.CANCEL) ? null :
+ pendingTransition.getNextPlan().getProduct();
+
+ addAddonCancellationIfRequired(addOnSubscriptionInRepair, baseProduct, pendingTransition.getEffectiveTransitionTime(), context);
+ }
+
+ private void trickleDownBPEffectForAddon(final List<SubscriptionDataRepair> addOnSubscriptionInRepair, final DateTime effectiveDate, final CallContext context)
throws EntitlementUserApiException {
if (category != ProductCategory.BASE) {
return;
}
-
- DateTime now = clock.getUTCNow();
+
Product baseProduct = (getState() == SubscriptionState.CANCELLED ) ?
null : getCurrentPlan().getProduct();
+ addAddonCancellationIfRequired(addOnSubscriptionInRepair, baseProduct, effectiveDate, context);
+ }
+
+
+
+ private void addAddonCancellationIfRequired(final List<SubscriptionDataRepair> addOnSubscriptionInRepair, Product baseProduct, final DateTime effectiveDate, final CallContext context) {
- Iterator<SubscriptionDataRepair> it = addonSubscriptions.iterator();
+ DateTime now = clock.getUTCNow();
+ Iterator<SubscriptionDataRepair> it = addOnSubscriptionInRepair.iterator();
while (it.hasNext()) {
SubscriptionDataRepair cur = it.next();
if (cur.getState() == SubscriptionState.CANCELLED ||
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index 9bfaa70..80f25ab 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -475,11 +475,9 @@ public class SubscriptionData extends ExtendedEntityBase implements
Plan nextPlan = null;
PlanPhase nextPhase = null;
try {
- nextPlan = (nextPlanName != null) ? catalog.findPlan(
- nextPlanName, cur.getRequestedDate(), getStartDate())
+ nextPlan = (nextPlanName != null) ? catalog.findPlan(nextPlanName, cur.getRequestedDate(), getStartDate())
: null;
- nextPhase = (nextPhaseName != null) ? catalog.findPhase(
- nextPhaseName, cur.getRequestedDate(), getStartDate())
+ nextPhase = (nextPhaseName != null) ? catalog.findPhase(nextPhaseName, cur.getRequestedDate(), getStartDate())
: null;
} catch (CatalogApiException e) {
log.error(String.format(
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestApiBaseRepair.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestApiBaseRepair.java
index 31e178d..b908bb6 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestApiBaseRepair.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestApiBaseRepair.java
@@ -23,8 +23,11 @@ import java.util.List;
import java.util.UUID;
import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.testng.Assert;
+
import com.ning.billing.ErrorCode;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PhaseType;
@@ -40,7 +43,8 @@ import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
public abstract class TestApiBaseRepair extends TestApiBase {
-
+ protected final static Logger log = LoggerFactory.getLogger(TestApiBaseRepair.class);
+
public interface TestWithExceptionCallback {
public void doTest() throws EntitlementRepairException, EntitlementUserApiException;
}
@@ -135,11 +139,18 @@ public abstract class TestApiBaseRepair extends TestApiBase {
return null;
}
protected void validateExistingEventForAssertion(final ExistingEvent expected, final ExistingEvent input) {
+
+ log.info(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getProductName(), expected.getPlanPhaseSpecifier().getProductName()));
assertEquals(input.getPlanPhaseSpecifier().getProductName(), expected.getPlanPhaseSpecifier().getProductName());
+ log.info(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getPhaseType(), expected.getPlanPhaseSpecifier().getPhaseType()));
assertEquals(input.getPlanPhaseSpecifier().getPhaseType(), expected.getPlanPhaseSpecifier().getPhaseType());
+ log.info(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getProductCategory(), expected.getPlanPhaseSpecifier().getProductCategory()));
assertEquals(input.getPlanPhaseSpecifier().getProductCategory(), expected.getPlanPhaseSpecifier().getProductCategory());
+ log.info(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getPriceListName(), expected.getPlanPhaseSpecifier().getPriceListName()));
assertEquals(input.getPlanPhaseSpecifier().getPriceListName(), expected.getPlanPhaseSpecifier().getPriceListName());
+ log.info(String.format("Got %s -> Expected %s", input.getPlanPhaseSpecifier().getBillingPeriod(), expected.getPlanPhaseSpecifier().getBillingPeriod()));
assertEquals(input.getPlanPhaseSpecifier().getBillingPeriod(), expected.getPlanPhaseSpecifier().getBillingPeriod());
+ log.info(String.format("Got %s -> Expected %s", input.getEffectiveDate(), expected.getEffectiveDate()));
assertEquals(input.getEffectiveDate(), expected.getEffectiveDate());
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairBP.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairBP.java
index fe25958..08bf2d0 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairBP.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairBP.java
@@ -162,8 +162,9 @@ public class TestRepairBP extends TestApiBaseRepair {
List<ExistingEvent> expected = new LinkedList<SubscriptionRepair.ExistingEvent>();
expected.add(createExistingEventForAssertion(SubscriptionTransitionType.CREATE, baseProduct, PhaseType.TRIAL,
ProductCategory.BASE, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.NO_BILLING_PERIOD, baseSubscription.getStartDate()));
- expected.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, null, null,
- ProductCategory.BASE, null, null, baseSubscription.getStartDate()));
+ expected.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, baseProduct, PhaseType.TRIAL,
+ ProductCategory.BASE, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.NO_BILLING_PERIOD,baseSubscription.getStartDate()));
+
for (ExistingEvent e : expected) {
validateExistingEventForAssertion(e, events.get(index++));
}
@@ -364,7 +365,10 @@ public class TestRepairBP extends TestApiBaseRepair {
assertEquals(cur.getId(), baseSubscription.getId());
events = cur.getExistingEvents();
- assertEquals(expectedEvents.size(), events.size());
+ for (ExistingEvent e : events) {
+ log.info(String.format("%s, %s, %s, %s", e.getSubscriptionTransitionType(), e.getEffectiveDate(), e.getPlanPhaseSpecifier().getProductName(), e.getPlanPhaseSpecifier().getPhaseType()));
+ }
+ assertEquals(events.size(), expectedEvents.size());
index = 0;
for (ExistingEvent e : expectedEvents) {
validateExistingEventForAssertion(e, events.get(index++));
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairWithAO.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairWithAO.java
index d238a6a..a4cfcd4 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairWithAO.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/repair/TestRepairWithAO.java
@@ -52,7 +52,7 @@ public class TestRepairWithAO extends TestApiBaseRepair {
@Override
public Injector getInjector() {
return Guice.createInjector(Stage.DEVELOPMENT, new MockEngineModuleSql());
- }
+ }
@Test(groups={"slow"})
public void testRepairChangeBPWithAddonIncluded() throws Exception {
@@ -116,8 +116,8 @@ public class TestRepairWithAO extends TestApiBaseRepair {
List<ExistingEvent> expectedAO = new LinkedList<SubscriptionRepair.ExistingEvent>();
expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CREATE, "Telescopic-Scope", PhaseType.DISCOUNT,
ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, aoSubscription.getStartDate()));
- expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, null, null,
- ProductCategory.ADD_ON, null, null, bpChangeDate));
+ expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, "Telescopic-Scope", PhaseType.DISCOUNT,
+ ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, bpChangeDate));
int index = 0;
for (ExistingEvent e : expectedAO) {
validateExistingEventForAssertion(e, aoRepair.getExistingEvents().get(index++));
@@ -262,8 +262,8 @@ public class TestRepairWithAO extends TestApiBaseRepair {
ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, aoSubscription.getStartDate()));
expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CREATE, "Telescopic-Scope", PhaseType.EVERGREEN,
ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, baseSubscription.getStartDate().plusMonths(1)));
- expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, null, null,
- ProductCategory.ADD_ON, null, null, bpChangeDate));
+ expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, "Telescopic-Scope", PhaseType.EVERGREEN,
+ ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, bpChangeDate));
int index = 0;
for (ExistingEvent e : expectedAO) {
validateExistingEventForAssertion(e, aoRepair.getExistingEvents().get(index++));
@@ -369,7 +369,7 @@ public class TestRepairWithAO extends TestApiBaseRepair {
BundleRepair dryRunBundleRepair = repairApi.repairBundle(bundleRepair, dryRun, context);
aoRepair = getSubscriptionRepair(aoSubscription.getId(), dryRunBundleRepair);
- assertEquals(aoRepair.getExistingEvents().size(), 2);
+ assertEquals(aoRepair.getExistingEvents().size(), 3);
bpRepair = getSubscriptionRepair(baseSubscription.getId(), dryRunBundleRepair);
assertEquals(bpRepair.getExistingEvents().size(), 3);
@@ -380,10 +380,9 @@ public class TestRepairWithAO extends TestApiBaseRepair {
ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, aoSubscription.getStartDate()));
expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.PHASE, "Telescopic-Scope", PhaseType.EVERGREEN,
ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, baseSubscription.getStartDate().plusMonths(1)));
- /*
- expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, null, null,
- ProductCategory.ADD_ON, null, null, newChargedThroughDate));
- */
+ expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, "Telescopic-Scope", PhaseType.EVERGREEN,
+ ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, newChargedThroughDate));
+
int index = 0;
for (ExistingEvent e : expectedAO) {
validateExistingEventForAssertion(e, aoRepair.getExistingEvents().get(index++));
@@ -395,8 +394,8 @@ public class TestRepairWithAO extends TestApiBaseRepair {
ProductCategory.BASE, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.NO_BILLING_PERIOD, baseSubscription.getStartDate()));
expectedBP.add(createExistingEventForAssertion(SubscriptionTransitionType.PHASE, "Shotgun", PhaseType.EVERGREEN,
ProductCategory.BASE, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, baseSubscription.getStartDate().plusDays(30)));
- expectedBP.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, null, null,
- ProductCategory.BASE, null, null, newChargedThroughDate));
+ expectedBP.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, "Shotgun", PhaseType.EVERGREEN,
+ ProductCategory.BASE, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, newChargedThroughDate));
index = 0;
for (ExistingEvent e : expectedBP) {
validateExistingEventForAssertion(e, bpRepair.getExistingEvents().get(index++));
@@ -421,9 +420,6 @@ public class TestRepairWithAO extends TestApiBaseRepair {
bpRepair = getSubscriptionRepair(baseSubscription.getId(), realRunBundleRepair);
assertEquals(bpRepair.getExistingEvents().size(), 3);
- // STEPH BUG -- WE ONLY SEE THAT AFTER WE HIT DISK.
- expectedAO.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, null, null,
- ProductCategory.ADD_ON, null, null, newChargedThroughDate));
index = 0;
for (ExistingEvent e : expectedAO) {
validateExistingEventForAssertion(e, aoRepair.getExistingEvents().get(index++));
@@ -515,8 +511,8 @@ public class TestRepairWithAO extends TestApiBaseRepair {
List<ExistingEvent> expected = new LinkedList<SubscriptionRepair.ExistingEvent>();
expected.add(createExistingEventForAssertion(SubscriptionTransitionType.CREATE, "Telescopic-Scope", PhaseType.DISCOUNT,
ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, aoSubscription.getStartDate()));
- expected.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, null, null,
- ProductCategory.ADD_ON, null, null, aoCancelDate));
+ expected.add(createExistingEventForAssertion(SubscriptionTransitionType.CANCEL, "Telescopic-Scope", PhaseType.DISCOUNT,
+ ProductCategory.ADD_ON, PriceListSet.DEFAULT_PRICELIST_NAME, BillingPeriod.MONTHLY, aoCancelDate));
int index = 0;
for (ExistingEvent e : expected) {
validateExistingEventForAssertion(e, aoRepair.getExistingEvents().get(index++));