killbill-aplcache
Changes
entitlement/killbill-entitlement.iml 5(+5 -0)
entitlement/pom.xml 5(+5 -0)
entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java 10(+10 -0)
entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg 17(+17 -0)
Details
entitlement/killbill-entitlement.iml 5(+5 -0)
diff --git a/entitlement/killbill-entitlement.iml b/entitlement/killbill-entitlement.iml
index b72ca26..f6d9154 100644
--- a/entitlement/killbill-entitlement.iml
+++ b/entitlement/killbill-entitlement.iml
@@ -19,6 +19,11 @@
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
+ <orderEntry type="library" scope="TEST" name="Maven: com.jayway.awaitility:awaitility:1.3.3" level="project" />
+ <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.1" level="project" />
+ <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
+ <orderEntry type="library" scope="TEST" name="Maven: cglib:cglib-nodep:2.2" level="project" />
+ <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:1.2" level="project" />
<orderEntry type="module" module-name="killbill-account" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.0" level="project" />
entitlement/pom.xml 5(+5 -0)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index fd23f09..0bc0275 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -50,6 +50,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>com.jayway.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>com.ning.billing</groupId>
<artifactId>killbill-account</artifactId>
</dependency>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java
index f17d56b..4e270a0 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java
@@ -22,8 +22,7 @@ import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
-import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.ErrorCode;
import com.ning.billing.catalog.api.BillingActionPolicy;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Plan;
@@ -32,44 +31,48 @@ import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.EntitlementService;
import com.ning.billing.entitlement.block.BlockingChecker;
+import com.ning.billing.entitlement.dao.BlockingStateDao;
import com.ning.billing.subscription.api.SubscriptionBase;
import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.entity.EntityBase;
-import com.ning.billing.util.svcapi.account.AccountInternalApi;
-import com.ning.billing.util.timezone.DateAndTimeZoneContext;
+import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
public class DefaultEntitlement extends EntityBase implements Entitlement {
- private final AccountInternalApi accountApi;
+ private final EntitlementDateHelper dateHelper;
private final SubscriptionBase subscriptionBase;
private final InternalCallContextFactory internalCallContextFactory;
private final Clock clock;
- private final boolean isBlocked;
+ private final EntitlementState state;
private final BlockingState entitlementBlockingState;
private final BlockingChecker checker;
private final UUID accountId;
private final String externalKey;
private final DateTimeZone accountTimeZone;
+ private final BlockingStateDao blockingStateDao;
- public DefaultEntitlement(final AccountInternalApi accountApi, final SubscriptionBase subscriptionBase, final UUID accountId,
- final String externalKey, final boolean isBlocked, final BlockingState entitlementBlockingState, final DateTimeZone accountTimeZone,
+ public DefaultEntitlement(final EntitlementDateHelper dateHelper, final SubscriptionBase subscriptionBase, final UUID accountId,
+ final String externalKey, final EntitlementState state, final BlockingState entitlementBlockingState, final DateTimeZone accountTimeZone,
final InternalCallContextFactory internalCallContextFactory,
+ final BlockingStateDao blockingStateDao,
final Clock clock, final BlockingChecker checker) {
super(subscriptionBase.getId(), subscriptionBase.getCreatedDate(), subscriptionBase.getUpdatedDate());
- this.accountApi = accountApi;
+ this.dateHelper = dateHelper;
this.subscriptionBase = subscriptionBase;
this.accountId = accountId;
this.externalKey = externalKey;
- this.isBlocked = isBlocked;
+ this.state = state;
this.entitlementBlockingState = entitlementBlockingState;
this.accountTimeZone = accountTimeZone;
this.internalCallContextFactory = internalCallContextFactory;
this.clock = clock;
this.checker = checker;
+ this.blockingStateDao = blockingStateDao;
}
// STEPH_ENT should be remove but beatrix tests need to be changed
@@ -99,7 +102,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
public EntitlementState getState() {
- return isBlocked ? EntitlementState.BLOCKED : subscriptionBase.getState();
+ return state;
}
@Override
@@ -115,9 +118,10 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
public LocalDate getEffectiveEndDate() {
if (entitlementBlockingState != null && entitlementBlockingState.getStateName().equals(DefaultEntitlementApi.ENT_STATE_CANCELLED)) {
- return new LocalDate(entitlementBlockingState.getCreatedDate(), accountTimeZone);
+ return new LocalDate(entitlementBlockingState.getEffectiveDate(), accountTimeZone);
}
- return subscriptionBase.getEndDate() != null ? new LocalDate(subscriptionBase.getEndDate(), accountTimeZone) : null;
+ return null;
+ //return subscriptionBase.getEndDate() != null ? new LocalDate(subscriptionBase.getEndDate(), accountTimeZone) : null;
}
@Override
@@ -173,12 +177,23 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
- public boolean cancelEntitlementWithDate(final LocalDate localDate, final CallContext callContext) throws EntitlementApiException {
+ public boolean cancelEntitlementWithPolicy(final EntitlementActionPolicy entitlementPolicy, final CallContext callContext) throws EntitlementApiException {
+ final LocalDate cancellationDate = getLocalDateFromEntitlementPolicy(entitlementPolicy);
+ return cancelEntitlementWithDate(cancellationDate, callContext);
+ }
- final InternalCallContext context = internalCallContextFactory.createInternalCallContext(accountId, callContext);
- final DateTime requestedDate = fromLocalDateAndReferenceTime(localDate, subscriptionBase.getStartDate(), clock, context);
+ @Override
+ public boolean cancelEntitlementWithDate(final LocalDate localCancelDate, final CallContext callContext) throws EntitlementApiException {
+
+ if (state == EntitlementState.CANCELLED) {
+ throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
+ }
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext);
+ final DateTime effectiveCancelDate = dateHelper.fromLocalDateAndReferenceTime(localCancelDate, subscriptionBase.getStartDate(), contextWithValidAccountRecordId);
try {
- return subscriptionBase.cancel(requestedDate, callContext);
+ subscriptionBase.cancel(null, callContext);
+ blockingStateDao.setBlockingState(new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, effectiveCancelDate), clock, contextWithValidAccountRecordId);
+ return localCancelDate.compareTo(new LocalDate(clock.getUTCNow())) <= 0;
} catch (SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
@@ -186,20 +201,45 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
- public boolean cancelEntitlementWithPolicy(final EntitlementActionPolicy entitlementPolicy, final CallContext callContext) throws EntitlementApiException {
- return false;
+ public boolean cancelEntitlementWithPolicyOverrideBillingPolicy(final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
+ final LocalDate cancellationDate = getLocalDateFromEntitlementPolicy(entitlementPolicy);
+ return cancelEntitlementWithDateOverrideBillingPolicy(cancellationDate, billingPolicy, callContext);
}
@Override
- public boolean cancelEntitlementWithDateOverrideBillingPolicy(final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final CallContext context) throws EntitlementApiException {
- return false; //To change body of implemented methods use File | Settings | File Templates.
+ public boolean cancelEntitlementWithDateOverrideBillingPolicy(final LocalDate localCancelDate, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
+
+ if (state == EntitlementState.CANCELLED) {
+ throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
+ }
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext);
+ final LocalDate effectiveLocalDate = new LocalDate(localCancelDate, accountTimeZone);
+ final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(effectiveLocalDate, subscriptionBase.getStartDate(), contextWithValidAccountRecordId);
+ try {
+ subscriptionBase.cancelWithPolicy(null, billingPolicy, callContext);
+ blockingStateDao.setBlockingState(new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, effectiveDate), clock, contextWithValidAccountRecordId);
+ return effectiveLocalDate.compareTo(new LocalDate(clock.getUTCNow())) <= 0;
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
+ }
}
- @Override
- public boolean cancelEntitlementWithPolicyOverrideBillingPolicy(final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy, final CallContext context) throws EntitlementApiException {
- return false; //To change body of implemented methods use File | Settings | File Templates.
+ private LocalDate getLocalDateFromEntitlementPolicy(final EntitlementActionPolicy entitlementPolicy) {
+ final LocalDate cancellationDate;
+ switch (entitlementPolicy) {
+ case IMM:
+ cancellationDate = new LocalDate(clock.getUTCNow(), accountTimeZone);
+ break;
+ case EOT:
+ cancellationDate = subscriptionBase.getChargedThroughDate() != null ? new LocalDate(subscriptionBase.getChargedThroughDate(), accountTimeZone) : new LocalDate(clock.getUTCNow(), accountTimeZone);
+ break;
+ default:
+ throw new RuntimeException("Unsupported policy " + entitlementPolicy);
+ }
+ return cancellationDate;
}
+
@Override
public void uncancel(final CallContext context) throws EntitlementApiException {
//To change body of implemented methods use File | Settings | File Templates.
@@ -209,8 +249,12 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
public boolean changePlan(final String productName, final BillingPeriod billingPeriod, final String priceList, final LocalDate localDate, final CallContext callContext) throws EntitlementApiException {
+ if (state != EntitlementState.ACTIVE) {
+ throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), state);
+ }
+
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(accountId, callContext);
- final DateTime requestedDate = fromLocalDateAndReferenceTime(localDate, subscriptionBase.getStartDate(), clock, context);
+ final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(localDate, subscriptionBase.getStartDate(), context);
try {
checker.checkBlockedChange(subscriptionBase, context);
return subscriptionBase.changePlan(productName, billingPeriod, priceList, requestedDate, callContext);
@@ -223,8 +267,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
public boolean changePlanOverrideBillingPolicy(final String productName, final BillingPeriod billingPeriod, final String priceList, final LocalDate localDate, final BillingActionPolicy actionPolicy, final CallContext callContext) throws EntitlementApiException {
+
+ if (state != EntitlementState.ACTIVE) {
+ throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), state);
+ }
+
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(accountId, callContext);
- final DateTime requestedDate = fromLocalDateAndReferenceTime(localDate, subscriptionBase.getStartDate(), clock, context);
+ final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(localDate, subscriptionBase.getStartDate(), context);
try {
checker.checkBlockedChange(subscriptionBase, context);
return subscriptionBase.changePlanWithPolicy(productName, billingPeriod, priceList, requestedDate, actionPolicy, callContext);
@@ -237,9 +286,6 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
public boolean block(final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
-
-
-
return false; //To change body of implemented methods use File | Settings | File Templates.
}
@@ -248,31 +294,4 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
-
-
- /**
- * Returns a DateTime that is equals or beforeNow and whose LocalDate using the account timeZone is the one provided
- * <p/>
- * Relies on the subscriptionStartDate for the reference time
- *
- * @param requestedDate
- * @param subscriptionStartDate
- * @param clock
- * @param callContext
- * @return
- * @throws EntitlementApiException
- */
- private DateTime fromLocalDateAndReferenceTime(final LocalDate requestedDate, final DateTime subscriptionStartDate, final Clock clock, final InternalCallContext callContext) throws EntitlementApiException {
- try {
- final Account account = accountApi.getAccountByRecordId(callContext.getAccountRecordId(), callContext);
- final DateAndTimeZoneContext timeZoneContext = new DateAndTimeZoneContext(subscriptionStartDate, account.getTimeZone(), clock);
- final DateTime computedTime = timeZoneContext.computeUTCDateTimeFromLocalDate(requestedDate);
-
- return computedTime.isAfter(clock.getUTCNow()) ? clock.getUTCNow() : computedTime;
- } catch (AccountApiException e) {
- throw new EntitlementApiException(e);
- }
- }
-
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
index f838d8d..407f104 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
@@ -74,7 +74,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
private final InternalCallContextFactory internalCallContextFactory;
private final BlockingChecker checker;
private final BlockingStateDao blockingStateDao;
-
+ private final EntitlementDateHelper dateHelper;
@Inject
public DefaultEntitlementApi(final InternalCallContextFactory internalCallContextFactory, final SubscriptionBaseInternalApi subscriptionInternalApi, final AccountInternalApi accountApi, final BlockingStateDao blockingStateDao, final Clock clock, final BlockingChecker checker) {
@@ -84,6 +84,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
this.clock = clock;
this.checker = checker;
this.blockingStateDao = blockingStateDao;
+ this.dateHelper = new EntitlementDateHelper(accountApi, clock);
}
@@ -94,7 +95,8 @@ public class DefaultEntitlementApi implements EntitlementApi {
final Account account = accountApi.getAccountById(accountId, contextWithValidAccountRecordId);
final SubscriptionBaseBundle bundle = subscriptionInternalApi.createBundleForAccount(accountId, externalKey, contextWithValidAccountRecordId);
final SubscriptionBase subscription = subscriptionInternalApi.createSubscription(bundle.getId(), planPhaseSpecifier, clock.getUTCNow(), contextWithValidAccountRecordId);
- return new DefaultEntitlement(accountApi, subscription, accountId, bundle.getExternalKey(), false, null, account.getTimeZone(), internalCallContextFactory, clock, checker);
+ return new DefaultEntitlement(dateHelper, subscription, accountId, bundle.getExternalKey(), EntitlementState.ACTIVE, null, account.getTimeZone(),
+ internalCallContextFactory, blockingStateDao, clock, checker);
} catch (SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
} catch (AccountApiException e) {
@@ -108,27 +110,30 @@ public class DefaultEntitlementApi implements EntitlementApi {
try {
final SubscriptionBaseBundle bundle = subscriptionInternalApi.getBundleFromId(bundleId, context);
final SubscriptionBase baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, context);
+
+
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundle.getAccountId(), callContext);
+ final BlockingState currentBaseState = blockingStateDao.getBlockingStateForService(baseSubscription.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
+
+ // Check if there is a BP and if it is active
+ final EntitlementState baseEntitlementState = getStateForEntitlement(baseSubscription, currentBaseState, contextWithValidAccountRecordId);
if (baseSubscription.getCategory() != ProductCategory.BASE ||
- baseSubscription.getState() != EntitlementState.ACTIVE) {
+ baseEntitlementState != EntitlementState.ACTIVE) {
throw new EntitlementApiException(ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION, baseSubscription.getBundleId());
}
- final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundle.getAccountId(), callContext);
+ // Check if BP is blockedChange
final BlockingAggregator blocking = checker.getBlockedStatus(baseSubscription, contextWithValidAccountRecordId);
if (blocking.isBlockChange()) {
throw new EntitlementApiException(new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, BlockingChecker.ACTION_CHANGE, BlockingChecker.TYPE_SUBSCRIPTION, baseSubscription.getId().toString()));
}
- final BlockingState currentState = blockingStateDao.getBlockingStateForService(baseSubscription.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
- if (currentState != null && currentState.getStateName().equals(ENT_STATE_CANCELLED)) {
- throw new EntitlementApiException(new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, BlockingChecker.ACTION_CHANGE, BlockingChecker.TYPE_SUBSCRIPTION, baseSubscription.getId().toString()));
- }
-
final Account account = accountApi.getAccountById(bundle.getAccountId(), context);
- final DateTime requestedDate = fromNowAndReferenceTime(baseSubscription.getStartDate(), contextWithValidAccountRecordId);
+ final DateTime requestedDate = dateHelper.fromNowAndReferenceTime(baseSubscription.getStartDate(), contextWithValidAccountRecordId);
final SubscriptionBase subscription = subscriptionInternalApi.createSubscription(baseSubscription.getBundleId(), planPhaseSpecifier, requestedDate, context);
- return new DefaultEntitlement(accountApi, subscription, bundle.getAccountId(), bundle.getExternalKey(), blocking.isBlockEntitlement(), null, account.getTimeZone(), internalCallContextFactory, clock, checker);
+ return new DefaultEntitlement(dateHelper, subscription, bundle.getAccountId(), bundle.getExternalKey(), getStateForEntitlement(subscription, currentBaseState, context), null, account.getTimeZone(),
+ internalCallContextFactory, blockingStateDao, clock, checker);
} catch (SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
} catch (BlockingApiException e) {
@@ -144,16 +149,14 @@ public class DefaultEntitlementApi implements EntitlementApi {
try {
final SubscriptionBase subscription = subscriptionInternalApi.getSubscriptionFromId(uuid, context);
final SubscriptionBaseBundle bundle = subscriptionInternalApi.getBundleFromId(subscription.getBundleId(), context);
- final BlockingAggregator blocking = checker.getBlockedStatus(subscription, context);
final Account account = accountApi.getAccountById(bundle.getAccountId(), context);
final BlockingState currentState = blockingStateDao.getBlockingStateForService(subscription.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
- return new DefaultEntitlement(accountApi, subscription, bundle.getAccountId(), bundle.getExternalKey(), blocking.isBlockEntitlement(), currentState, account.getTimeZone(), internalCallContextFactory, clock, checker);
+ return new DefaultEntitlement(dateHelper, subscription, bundle.getAccountId(), bundle.getExternalKey(), getStateForEntitlement(subscription, currentState, context), currentState, account.getTimeZone(),
+ internalCallContextFactory, blockingStateDao, clock, checker);
} catch (SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
- } catch (BlockingApiException e) {
- throw new EntitlementApiException(e);
} catch (AccountApiException e) {
throw new EntitlementApiException(e);
}
@@ -203,19 +206,14 @@ public class DefaultEntitlementApi implements EntitlementApi {
@Nullable
@Override
public Entitlement apply(@Nullable final SubscriptionBase input) {
- BlockingAggregator blocking = null;
- try {
- blocking = checker.getBlockedStatus(input, context);
- } catch (BlockingApiException e) {
- log.warn("Failed to extract blocking state for subscription " + input.getId().toString());
- }
+
final BlockingState currentState = blockingStateDao.getBlockingStateForService(input.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
- return new DefaultEntitlement(accountApi, input, accountId, externalKey,
- (blocking != null ? blocking.isBlockEntitlement() : false),
+ return new DefaultEntitlement(dateHelper, input, accountId, externalKey,
+ getStateForEntitlement(input, currentState, context),
currentState,
account.getTimeZone(),
- internalCallContextFactory, clock, checker);
+ internalCallContextFactory, blockingStateDao, clock, checker);
}
}));
} catch (AccountApiException e) {
@@ -223,27 +221,70 @@ public class DefaultEntitlementApi implements EntitlementApi {
}
}
+ private EntitlementState getStateForEntitlement(final SubscriptionBase subscriptionBase, final BlockingState currentState, final InternalTenantContext context) {
+
+ // Current state for the ENTITLEMENT_SERVICE_NAME is set to cancelled
+ if (currentState != null && currentState.getStateName().equals(ENT_STATE_CANCELLED)) {
+ return EntitlementState.CANCELLED;
+ }
+
+ try {
+ // Gather states across all services and check if one of them is set to 'blockEntitlement'
+ BlockingAggregator blocking = checker.getBlockedStatus(subscriptionBase, context);
+ return blocking != null && blocking.isBlockEntitlement() ? EntitlementState.BLOCKED : EntitlementState.ACTIVE;
+ } catch (BlockingApiException e) {
+ log.warn("Failed to extract blocking state for subscription " + subscriptionBase.getId().toString());
+ return null;
+ }
+ }
+
+
@Override
- public void block(final UUID bundleId, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
+ public void pause(final UUID bundleId, final LocalDate localEffectiveDate, final CallContext context) throws EntitlementApiException {
+ try {
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
+ final BlockingState currentState = blockingStateDao.getBlockingStateForService(bundleId, EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
+ if (currentState != null && currentState.getStateName().equals(ENT_STATE_BLOCKED)) {
+ throw new EntitlementApiException(ErrorCode.ENT_ALREADY_BLOCKED, bundleId);
+ }
+ final SubscriptionBase baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, contextWithValidAccountRecordId);
+ final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(localEffectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId);
- final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
- final BlockingState currentState = blockingStateDao.getBlockingStateForService(bundleId, EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
- if (currentState != null && currentState.getStateName().equals(ENT_STATE_BLOCKED)) {
- throw new EntitlementApiException(ErrorCode.ENT_ALREADY_BLOCKED, bundleId);
+ blockingStateDao.setBlockingState(new DefaultBlockingState(bundleId, BlockingStateType.BUNDLE, ENT_STATE_BLOCKED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, effectiveDate), clock, contextWithValidAccountRecordId);
+
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
}
- blockingStateDao.setBlockingState(new DefaultBlockingState(bundleId, BlockingStateType.BUNDLE, ENT_STATE_BLOCKED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, clock.getUTCNow()), clock, contextWithValidAccountRecordId);
}
@Override
- public void unblock(final UUID bundleId, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
+ public void resume(final UUID bundleId, final LocalDate localEffectiveDate, final CallContext context) throws EntitlementApiException {
+ try {
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
+ final BlockingState currentState = blockingStateDao.getBlockingStateForService(bundleId, EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
+ if (currentState == null || currentState.getStateName().equals(ENT_STATE_CLEAR)) {
+ // Nothing to do.
+ return;
+ }
+ final SubscriptionBase baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, contextWithValidAccountRecordId);
- final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
- final BlockingState currentState = blockingStateDao.getBlockingStateForService(bundleId, EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
- if (currentState == null || currentState.getStateName().equals(ENT_STATE_CLEAR)) {
- // Nothing to do.
- return;
+ final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(localEffectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId);
+
+ blockingStateDao.setBlockingState(new DefaultBlockingState(bundleId, BlockingStateType.BUNDLE, ENT_STATE_CLEAR, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, effectiveDate), clock, contextWithValidAccountRecordId);
+
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
}
- blockingStateDao.setBlockingState(new DefaultBlockingState(bundleId, BlockingStateType.BUNDLE, ENT_STATE_CLEAR, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, clock.getUTCNow()), clock, contextWithValidAccountRecordId);
+ }
+
+ @Override
+ public void block(final UUID bundleId, final String serviceName, final LocalDate effectiveDate, final boolean blockBilling, final boolean blockEntitlement, final boolean blockChange, final CallContext context) throws EntitlementApiException {
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
+
+ }
+
+ @Override
+ public void unblock(final UUID bundleId, final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
}
@@ -258,14 +299,5 @@ public class DefaultEntitlementApi implements EntitlementApi {
}
- private DateTime fromNowAndReferenceTime(final DateTime subscriptionStartDate, final InternalCallContext callContext) throws EntitlementApiException {
- try {
- final Account account = accountApi.getAccountByRecordId(callContext.getAccountRecordId(), callContext);
- final DateAndTimeZoneContext timeZoneContext = new DateAndTimeZoneContext(subscriptionStartDate, account.getTimeZone(), clock);
- return timeZoneContext.computeUTCDateTimeFromNow();
- } catch (AccountApiException e) {
- throw new EntitlementApiException(e);
- }
- }
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/EntitlementDateHelper.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/EntitlementDateHelper.java
new file mode 100644
index 0000000..5c80493
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/EntitlementDateHelper.java
@@ -0,0 +1,56 @@
+package com.ning.billing.entitlement.api;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.clock.Clock;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.timezone.DateAndTimeZoneContext;
+
+public class EntitlementDateHelper {
+
+ private final AccountInternalApi accountApi;
+ private final Clock clock;
+
+ public EntitlementDateHelper(final AccountInternalApi accountApi, final Clock clock) {
+ this.accountApi = accountApi;
+ this.clock = clock;
+ }
+
+ /**
+ * Returns a DateTime that is equals or beforeNow and whose LocalDate using the account timeZone is the one provided
+ * <p/>
+ * Relies on the subscriptionStartDate for the reference time
+ *
+ * @param requestedDate
+ * @param subscriptionStartDate
+ * @param callContext
+ * @return
+ * @throws EntitlementApiException
+ */
+ public DateTime fromLocalDateAndReferenceTime(final LocalDate requestedDate, final DateTime subscriptionStartDate, final InternalCallContext callContext) throws EntitlementApiException {
+ try {
+ final Account account = accountApi.getAccountByRecordId(callContext.getAccountRecordId(), callContext);
+ final DateAndTimeZoneContext timeZoneContext = new DateAndTimeZoneContext(subscriptionStartDate, account.getTimeZone(), clock);
+ final DateTime computedTime = timeZoneContext.computeUTCDateTimeFromLocalDate(requestedDate);
+
+ //return computedTime.isAfter(clock.getUTCNow()) ? clock.getUTCNow() : computedTime;
+ return computedTime;
+ } catch (AccountApiException e) {
+ throw new EntitlementApiException(e);
+ }
+ }
+
+ public DateTime fromNowAndReferenceTime(final DateTime subscriptionStartDate, final InternalCallContext callContext) throws EntitlementApiException {
+ try {
+ final Account account = accountApi.getAccountByRecordId(callContext.getAccountRecordId(), callContext);
+ final DateAndTimeZoneContext timeZoneContext = new DateAndTimeZoneContext(subscriptionStartDate, account.getTimeZone(), clock);
+ return timeZoneContext.computeUTCDateTimeFromNow();
+ } catch (AccountApiException e) {
+ throw new EntitlementApiException(e);
+ }
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java
index e2ae80c..7b17850 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java
@@ -78,6 +78,16 @@ public class DefaultInternalBlockingApi implements BlockingInternalApi {
}
@Override
+ public List<BlockingState> getBlockingAll(final Blockable overdueable, final InternalTenantContext context) {
+ return dao.getBlockingAll(overdueable.getId(), context);
+ }
+
+ @Override
+ public List<BlockingState> getBlockingAll(final UUID overdueableId, final InternalTenantContext context) {
+ return dao.getBlockingAll(overdueableId, context);
+ }
+
+ @Override
public void setBlockingState(final BlockingState state, final InternalCallContext context) {
dao.setBlockingState(state, clock, context);
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java
index 453c915..58bee54 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java
@@ -66,6 +66,15 @@ public interface BlockingStateDao {
public List<BlockingState> getBlockingHistory(UUID blockableId, InternalTenantContext context);
/**
+ * Return all the events (past and future) across all services
+ *
+ * @param blockableId
+ * @param context
+ * @return
+ */
+ public List<BlockingState> getBlockingAll(UUID blockableId, InternalTenantContext context);
+
+ /**
* Sets a new state for a specific service
*
* @param state
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java
index 8db83b7..0be4794 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java
@@ -37,11 +37,13 @@ public class BlockingStateModelDao extends EntityBase implements EntityModelDao<
private final Boolean blockChange;
private final Boolean blockEntitlement;
private final Boolean blockBilling;
+ private final DateTime effectiveDate;
public BlockingStateModelDao(final UUID id, final UUID blockableId, final BlockingStateType blockingStateType, final String state, final String service, final Boolean blockChange, final Boolean blockEntitlement,
- final Boolean blockBilling, final DateTime createDate, final DateTime updateDate) {
+ final Boolean blockBilling, final DateTime effectiveDate, final DateTime createDate, final DateTime updateDate) {
super(id, createDate, updateDate);
this.blockableId = blockableId;
+ this.effectiveDate = effectiveDate;
this.type = blockingStateType;
this.state = state;
this.service = service;
@@ -52,7 +54,7 @@ public class BlockingStateModelDao extends EntityBase implements EntityModelDao<
public BlockingStateModelDao(final BlockingState src, InternalCallContext context) {
this(src.getId(), src.getBlockedId(), src.getType(), src.getStateName(), src.getService(), src.isBlockChange(),
- src.isBlockEntitlement(), src.isBlockBilling(), context.getCreatedDate(), context.getUpdatedDate());
+ src.isBlockEntitlement(), src.isBlockBilling(), src.getEffectiveDate(), context.getCreatedDate(), context.getUpdatedDate());
}
public UUID getBlockableId() {
@@ -83,12 +85,16 @@ public class BlockingStateModelDao extends EntityBase implements EntityModelDao<
return type;
}
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
+ }
+
public static BlockingState toBlockingState(BlockingStateModelDao src) {
if (src == null) {
return null;
}
return new DefaultBlockingState(src.getId(), src.getBlockableId(), src.getType(), src.getState(), src.getService(), src.getBlockChange(), src.getBlockEntitlement(), src.getBlockBilling(),
- src.getCreatedDate(), src.getUpdatedDate());
+ src.getEffectiveDate(), src.getCreatedDate(), src.getUpdatedDate());
}
@Override
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java
index a7f6a83..6df54b4 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java
@@ -18,6 +18,7 @@ package com.ning.billing.entitlement.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.Date;
import java.util.List;
import java.util.UUID;
@@ -44,23 +45,32 @@ public interface BlockingStateSqlDao extends EntitySqlDao<BlockingStateModelDao,
@SqlQuery
public abstract BlockingStateModelDao getBlockingStateForService(@Bind("blockableId") UUID blockableId,
@Bind("service") String serviceName,
+ @Bind("effectiveDate") Date effectiveDate,
@BindBean final InternalTenantContext context);
@SqlQuery
public abstract List<BlockingStateModelDao> getBlockingState(@Bind("blockableId") UUID blockableId,
+ @Bind("effectiveDate") Date effectiveDate,
@BindBean final InternalTenantContext context);
@SqlQuery
public abstract List<BlockingStateModelDao> getBlockingHistoryForService(@Bind("blockableId") UUID blockableId,
@Bind("service") String serviceName,
+ @Bind("effectiveDate") Date effectiveDate,
@BindBean final InternalTenantContext context);
@SqlQuery
public abstract List<BlockingStateModelDao> getBlockingHistory(@Bind("blockableId") UUID blockableId,
+ @Bind("effectiveDate") Date effectiveDate,
@BindBean final InternalTenantContext context);
+ @SqlQuery
+ public abstract List<BlockingStateModelDao> getBlockingAll(@Bind("blockableId") UUID blockableId,
+ @BindBean final InternalTenantContext context);
+
+
public class BlockingHistorySqlMapper extends MapperBase implements ResultSetMapper<BlockingStateModelDao> {
@Override
@@ -74,6 +84,7 @@ public interface BlockingStateSqlDao extends EntitySqlDao<BlockingStateModelDao,
final boolean blockChange;
final boolean blockEntitlement;
final boolean blockBilling;
+ final DateTime effectiveDate;
final DateTime createdDate;
final BlockingStateType type;
@@ -85,8 +96,9 @@ public interface BlockingStateSqlDao extends EntitySqlDao<BlockingStateModelDao,
blockChange = r.getBoolean("block_change");
blockEntitlement = r.getBoolean("block_entitlement");
blockBilling = r.getBoolean("block_billing");
+ effectiveDate = getDateTime(r, "effective_date");
createdDate = getDateTime(r, "created_date");
- return new BlockingStateModelDao(id, blockableId, type, stateName, service, blockChange, blockEntitlement, blockBilling, createdDate, createdDate);
+ return new BlockingStateModelDao(id, blockableId, type, stateName, service, blockChange, blockEntitlement, blockBilling, effectiveDate, createdDate, createdDate);
}
}
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java
index 8c2ef5e..ac1b851 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java
@@ -43,10 +43,12 @@ import com.google.common.collect.Collections2;
public class DefaultBlockingStateDao implements BlockingStateDao {
private final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
+ private final Clock clock;
@Inject
public DefaultBlockingStateDao(final IDBI dbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao) {
this.transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao);
+ this.clock = clock;
}
@Override
@@ -54,7 +56,7 @@ public class DefaultBlockingStateDao implements BlockingStateDao {
return transactionalSqlDao.execute( new EntitySqlDaoTransactionWrapper<BlockingState>() {
@Override
public BlockingState inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- final BlockingStateModelDao model = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingStateForService(blockableId, serviceName, context);
+ final BlockingStateModelDao model = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingStateForService(blockableId, serviceName, clock.getUTCNow().toDate(), context);
return BlockingStateModelDao.toBlockingState(model);
}
@@ -66,7 +68,7 @@ public class DefaultBlockingStateDao implements BlockingStateDao {
return transactionalSqlDao.execute( new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
@Override
public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingState(blockableId, context);
+ final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingState(blockableId, clock.getUTCNow().toDate(), context);
return new ArrayList<BlockingState>(Collections2.transform(models, new Function<BlockingStateModelDao, BlockingState>() {
@Override
public BlockingState apply(@Nullable final BlockingStateModelDao src) {
@@ -82,7 +84,7 @@ public class DefaultBlockingStateDao implements BlockingStateDao {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
@Override
public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingHistoryForService(blockableId, serviceName, context);
+ final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingHistoryForService(blockableId, serviceName, clock.getUTCNow().toDate(), context);
return new ArrayList<BlockingState>(Collections2.transform(models, new Function<BlockingStateModelDao, BlockingState>() {
@Override
public BlockingState apply(@Nullable final BlockingStateModelDao src) {
@@ -98,7 +100,23 @@ public class DefaultBlockingStateDao implements BlockingStateDao {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
@Override
public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingHistory(blockableId, context);
+ final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingHistory(blockableId, clock.getUTCNow().toDate(), context);
+ return new ArrayList<BlockingState>(Collections2.transform(models, new Function<BlockingStateModelDao, BlockingState>() {
+ @Override
+ public BlockingState apply(@Nullable final BlockingStateModelDao src) {
+ return BlockingStateModelDao.toBlockingState(src);
+ }
+ }));
+ }
+ });
+ }
+
+ @Override
+ public List<BlockingState> getBlockingAll(final UUID blockableId, final InternalTenantContext context) {
+ return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
+ @Override
+ public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+ final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingAll(blockableId, context);
return new ArrayList<BlockingState>(Collections2.transform(models, new Function<BlockingStateModelDao, BlockingState>() {
@Override
public BlockingState apply(@Nullable final BlockingStateModelDao src) {
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
index 0a12fb5..ad7ed24 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
@@ -11,6 +11,7 @@ tableFields(prefix) ::= <<
, <prefix>block_change
, <prefix>block_entitlement
, <prefix>block_billing
+, <prefix>effective_date
, <prefix>created_date
>>
@@ -23,6 +24,7 @@ tableValues() ::= <<
, :blockChange
, :blockEntitlement
, :blockBilling
+, :effectiveDate
, :createdDate
>>
@@ -34,6 +36,7 @@ from
<tableName()>
where blockable_id = :blockableId
and service = :service
+and effective_date \<= :effectiveDate
<AND_CHECK_TENANT()>
-- We want the current state, hence the order desc and limit 1
order by record_id desc
@@ -51,6 +54,7 @@ getBlockingState() ::= <<
, service
from blocking_states
where blockable_id = :blockableId
+ and effective_date \<= :effectiveDate
<AND_CHECK_TENANT()>
group by service
) tmp
@@ -66,6 +70,7 @@ from
<tableName()>
where blockable_id = :blockableId
and service = :service
+and effective_date \<= :effectiveDate
<AND_CHECK_TENANT()>
order by record_id asc
;
@@ -77,7 +82,19 @@ select
from
<tableName()>
where blockable_id = :blockableId
+and effective_date \<= :effectiveDate
<AND_CHECK_TENANT()>
order by record_id asc
;
>>
+
+getBlockingAll) ::= <<
+select
+<allTableFields()>
+from
+<tableName()>
+where blockable_id = :blockableId
+<AND_CHECK_TENANT()>
+order by record_id asc
+;
+>>
\ No newline at end of file
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
index 2747e2d..cfa82ed 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
@@ -11,6 +11,7 @@ CREATE TABLE blocking_states (
block_change bool NOT NULL,
block_entitlement bool NOT NULL,
block_billing bool NOT NULL,
+ effective_date datetime NOT NULL,
created_date datetime NOT NULL,
account_record_id int(11) unsigned default null,
tenant_record_id int(11) unsigned default null,
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
new file mode 100644
index 0000000..1f8bcbe
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
@@ -0,0 +1,165 @@
+package com.ning.billing.entitlement.api;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.api.TestApiListener.NextEvent;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PriceListSet;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
+import com.ning.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
+import com.ning.billing.entitlement.api.Entitlement.EntitlementState;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
+
+
+ @Test(groups = "slow")
+ public void testCancelWithEntitlementDate() {
+
+ try {
+ final LocalDate initialDate = new LocalDate(2013, 8, 7);
+ clock.setDay(initialDate);
+
+ final Account account = accountApi.createAccount(getAccountData(7), callContext);
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+
+ // Create entitlement and check each field
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+ assertEquals(entitlement.getState(), EntitlementState.ACTIVE);
+
+ clock.addDays(5);
+ final LocalDate cancelDate = new LocalDate(clock.getUTCNow());
+ entitlement.cancelEntitlementWithDate(cancelDate, callContext);
+ final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+ assertEquals(entitlement2.getState(), EntitlementState.CANCELLED);
+ assertEquals(entitlement2.getEffectiveEndDate(), cancelDate);
+
+ } catch (EntitlementApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ } catch (AccountApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ }
+ }
+
+
+ @Test(groups = "slow")
+ public void testCancelWithEntitlementDateInFuture() {
+
+ try {
+ final LocalDate initialDate = new LocalDate(2013, 8, 7);
+ clock.setDay(initialDate);
+
+ final Account account = accountApi.createAccount(getAccountData(7), callContext);
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+
+ // Create entitlement and check each field
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+ assertEquals(entitlement.getState(), EntitlementState.ACTIVE);
+
+ clock.addDays(5);
+ final LocalDate cancelDate = new LocalDate(clock.getUTCToday().plusDays(1));
+ entitlement.cancelEntitlementWithDate(cancelDate, callContext);
+ final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+ assertEquals(entitlement2.getState(), EntitlementState.ACTIVE);
+ assertNull(entitlement2.getEffectiveEndDate());
+
+ clock.addDays(1);
+ final Entitlement entitlement3 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+ assertEquals(entitlement3.getState(), EntitlementState.CANCELLED);
+ assertEquals(entitlement3.getEffectiveEndDate(), cancelDate);
+
+
+ } catch (EntitlementApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ } catch (AccountApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ }
+ }
+
+ @Test(groups = "slow")
+ public void testCancelWithEntitlementPolicyEOTAndNOCTD() {
+
+ try {
+
+ final LocalDate initialDate = new LocalDate(2013, 8, 7);
+ clock.setDay(initialDate);
+
+ final Account account = accountApi.createAccount(getAccountData(7), callContext);
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+
+ // Create entitlement and check each field
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+
+ final boolean isCancelled = entitlement.cancelEntitlementWithPolicy(EntitlementActionPolicy.EOT, callContext);
+ assertTrue(isCancelled);
+
+ final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+ assertEquals(entitlement2.getState(), EntitlementState.CANCELLED);
+ assertEquals(entitlement2.getEffectiveEndDate(), initialDate);
+
+ } catch (EntitlementApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ } catch (AccountApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ }
+ }
+
+
+ @Test(groups = "slow")
+ public void testCancelWithEntitlementPolicyEOTAndCTD() {
+
+ try {
+
+ final LocalDate initialDate = new LocalDate(2013, 8, 7);
+ clock.setDay(initialDate);
+
+ final Account account = accountApi.createAccount(getAccountData(7), callContext);
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+
+ // Create entitlement and check each field
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+
+ final DateTime ctd = clock.getUTCNow().plusDays(30).plusMonths(1);
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ clock.addDays(32);
+ // Set manually since no invoice
+ subscriptionInternalApi.setChargedThroughDate(entitlement.getId(), ctd, internalCallContext);
+ assertTrue(testListener.isCompleted(5000));
+
+ final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+ final boolean isCancelled = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.EOT, callContext);
+ assertFalse(isCancelled);
+
+ final Entitlement entitlement3 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+ assertEquals(entitlement3.getState(), EntitlementState.ACTIVE);
+ assertNull(entitlement3.getEffectiveEndDate());
+
+ clock.addMonths(1);
+
+ final Entitlement entitlement4 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+ assertEquals(entitlement4.getState(), EntitlementState.CANCELLED);
+ assertEquals(entitlement4.getEffectiveEndDate(), new LocalDate(ctd));
+
+ } catch (EntitlementApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ } catch (AccountApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ }
+ }
+
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java
index 4bff189..4a7b482 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java
@@ -173,7 +173,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
@Test(groups = "slow")
- public void testBlockUnblock() {
+ public void testPauseUnpause() {
try {
@@ -194,7 +194,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Block all entitlement in the bundle
clock.addDays(5);
- entitlementApi.block(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
+ entitlementApi.pause(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
// Verify blocking state
final Entitlement baseEntitlement2 = entitlementApi.getEntitlementForId(baseEntitlement.getId(), callContext);
@@ -205,7 +205,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Check we can't block in a blocked state
try {
- entitlementApi.block(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
+ entitlementApi.pause(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
Assert.fail("Should not have succeeded to block in a blocked state");
} catch (EntitlementApiException e) {
assertEquals(e.getCode(), ErrorCode.ENT_ALREADY_BLOCKED.getCode());
@@ -223,14 +223,14 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
final PlanPhaseSpecifier spec3 = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
final Entitlement telescopicEntitlement3 = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, callContext);
} catch (EntitlementApiException e) {
- assertEquals(e.getCode(), ErrorCode.BLOCK_BLOCKED_ACTION.getCode());
+ assertEquals(e.getCode(), ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION.getCode());
}
clock.addDays(3);
- entitlementApi.unblock(baseEntitlement.getBundleId(), new LocalDate(), callContext);
+ entitlementApi.resume(baseEntitlement.getBundleId(), new LocalDate(), callContext);
// Verify call is idempotent
- entitlementApi.unblock(baseEntitlement.getBundleId(), new LocalDate(), callContext);
+ entitlementApi.resume(baseEntitlement.getBundleId(), new LocalDate(), callContext);
// Verify blocking state
final Entitlement baseEntitlement3 = entitlementApi.getEntitlementForId(baseEntitlement.getId(), callContext);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java
index be2bc15..b1b52e9 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java
@@ -52,7 +52,7 @@ public class TestDefaultBlockingApi extends EntitlementTestSuiteWithEmbeddedDB {
}
});
- final BlockingState blockingState = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.ACCOUNT, "BLOCKED", "myService", true, true, true, internalCallContext.getCreatedDate(), null);
+ final BlockingState blockingState = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.ACCOUNT, "BLOCKED", "myService", true, true, true, clock.getUTCNow(), internalCallContext.getCreatedDate(), null);
blockingInternalApi.setBlockingState(blockingState, internalCallContext);
// Verify the blocking state was applied
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java b/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java
index b284612..0d8377c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java
@@ -38,6 +38,8 @@ public class MockBlockingStateDao implements BlockingStateDao {
private final Map<UUID, List<BlockingState>> blockingStates = new HashMap<UUID, List<BlockingState>>();
+ // TODO This mock class should also check that events are past or present except for getBlockingAll
+
@Override
public BlockingState getBlockingStateForService(final UUID blockableId, final String serviceName, final InternalTenantContext context) {
final List<BlockingState> states = getBlockingHistory(blockableId, context);
@@ -63,7 +65,7 @@ public class MockBlockingStateDao implements BlockingStateDao {
final Map<String, BlockingState> tmp = new HashMap<String, BlockingState>();
for (BlockingState cur : blockingStatesForId) {
final BlockingState curStateForService = tmp.get(cur.getService());
- if (curStateForService == null || curStateForService.getCreatedDate().compareTo(cur.getCreatedDate()) < 0) {
+ if (curStateForService == null || curStateForService.getEffectiveDate().compareTo(cur.getEffectiveDate()) < 0) {
tmp.put(cur.getService(), cur);
}
}
@@ -95,6 +97,13 @@ public class MockBlockingStateDao implements BlockingStateDao {
}
@Override
+ public List<BlockingState> getBlockingAll(final UUID blockableId, final InternalTenantContext context) {
+ final List<BlockingState> states = blockingStates.get(blockableId);
+ // Note! The returned list cannot be immutable!
+ return states == null ? new ArrayList<BlockingState>() : states;
+ }
+
+ @Override
public synchronized void setBlockingState(final BlockingState state, final Clock clock, final InternalCallContext context) {
if (blockingStates.get(state.getBlockedId()) == null) {
blockingStates.put(state.getBlockedId(), new ArrayList<BlockingState>());
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
index 342f0fc..e881401 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
@@ -93,8 +93,8 @@ public class BlockingCalculator {
final SortedSet<BillingEvent> billingEventsToRemove = new TreeSet<BillingEvent>();
for (final UUID bundleId : bundleMap.keySet()) {
- final List<BlockingState> blockingEvents = blockingApi.getBlockingHistory(bundleId, context);
- blockingEvents.addAll(blockingApi.getBlockingHistory(account.getId(),context));
+ final List<BlockingState> blockingEvents = blockingApi.getBlockingAll(bundleId, context);
+ blockingEvents.addAll(blockingApi.getBlockingAll(account.getId(),context));
final List<DisabledDuration> blockingDurations = createBlockingDurations(blockingEvents);
for (final SubscriptionBase subscription : bundleMap.get(bundleId)) {
@@ -265,13 +265,13 @@ public class BlockingCalculator {
first = e;
} else if (first != null && !e.isBlockBilling()) {
// End of the interval
- result.add(new DisabledDuration(first.getTimestamp(), e.getTimestamp()));
+ result.add(new DisabledDuration(first.getEffectiveDate(), e.getEffectiveDate()));
first = null;
}
}
if (first != null) { // found a transition to disabled with no terminating event
- result.add(new DisabledDuration(first.getTimestamp(), null));
+ result.add(new DisabledDuration(first.getEffectiveDate(), null));
}
return result;
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
index 3f6c3af..91baf83 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
@@ -183,8 +183,8 @@ public class TestBillingApi extends JunctionTestSuiteNoDB {
final Account account = createAccount(32);
final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
- blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bunId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
- blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bunId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
+ blockingStates.add(new DefaultBlockingState(bunId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1)));
+ blockingStates.add(new DefaultBlockingState(bunId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2)));
((MockBlockingStateDao) blockingStateDao).setBlockingStates(bunId, blockingStates);
final SortedSet<BillingEvent> events = billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), internalCallContext);
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
index 837e66f..b256673 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
@@ -113,8 +113,8 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
billingEvents.add(D);
final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
- blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bundleId1, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now, null));
- blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bundleId1, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
+ blockingStates.add(new DefaultBlockingState(bundleId1, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now));
+ blockingStates.add(new DefaultBlockingState(bundleId1, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2)));
setBlockingStates(bundleId1, blockingStates);
@@ -646,8 +646,8 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
//simple events open clear -> disabled
blockingEvents = new ArrayList<BlockingState>();
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1)));
List<DisabledDuration> pairs = blockingCalculator.createBlockingDurations(blockingEvents);
assertEquals(pairs.size(), 1);
@@ -657,9 +657,9 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
//simple events closed clear -> disabled
blockingEvents = new ArrayList<BlockingState>();
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2)));
pairs = blockingCalculator.createBlockingDurations(blockingEvents);
assertEquals(pairs.size(), 1);
@@ -670,9 +670,9 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
//simple BUNDLE events closed clear -> disabled
blockingEvents = new ArrayList<BlockingState>();
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2)));
pairs = blockingCalculator.createBlockingDurations(blockingEvents);
assertEquals(pairs.size(), 1);
@@ -683,10 +683,10 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
//two or more disableds in a row
blockingEvents = new ArrayList<BlockingState>();
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(3), null));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(3)));
pairs = blockingCalculator.createBlockingDurations(blockingEvents);
assertEquals(pairs.size(), 1);
@@ -696,11 +696,11 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
assertEquals(pairs.get(0).getEnd(), now.plusDays(3));
blockingEvents = new ArrayList<BlockingState>();
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(3), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(4), null));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(3)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(4)));
pairs = blockingCalculator.createBlockingDurations(blockingEvents);
assertEquals(pairs.size(), 1);
@@ -723,10 +723,10 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
billingEvents.add(upgrade);
final List<BlockingState> blockingEvents = new ArrayList<BlockingState>();
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, false, false, new LocalDate(2012, 7, 5).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 15).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
- blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, false, false, new LocalDate(2012, 7, 5).toDateTimeAtStartOfDay(DateTimeZone.UTC)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 15).toDateTimeAtStartOfDay(DateTimeZone.UTC)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC)));
+ blockingEvents.add(new DefaultBlockingState(ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC)));
setBlockingStates(bundleId1, blockingEvents);
diff --git a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
index a013e59..c11a3d2 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
@@ -33,16 +33,13 @@ import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.bus.api.PersistentBus;
import com.ning.billing.catalog.api.BillingActionPolicy;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.api.Blockable;
+import com.ning.billing.entitlement.api.BlockingApiException;
import com.ning.billing.entitlement.api.BlockingStateType;
import com.ning.billing.entitlement.api.Entitlement;
import com.ning.billing.entitlement.api.EntitlementApi;
import com.ning.billing.entitlement.api.EntitlementApiException;
-import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
-import com.ning.billing.subscription.api.SubscriptionBase;
-import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
-import com.ning.billing.entitlement.api.Blockable;
-import com.ning.billing.entitlement.api.BlockingApiException;
import com.ning.billing.ovedue.notification.OverdueCheckPoster;
import com.ning.billing.overdue.OverdueApiException;
import com.ning.billing.overdue.OverdueCancellationPolicicy;
@@ -52,14 +49,12 @@ import com.ning.billing.overdue.config.api.BillingState;
import com.ning.billing.overdue.config.api.OverdueException;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
-import com.ning.billing.clock.Clock;
import com.ning.billing.util.email.DefaultEmailSender;
import com.ning.billing.util.email.EmailApiException;
import com.ning.billing.util.email.EmailConfig;
import com.ning.billing.util.email.EmailSender;
import com.ning.billing.util.events.OverdueChangeInternalEvent;
import com.ning.billing.util.svcapi.account.AccountInternalApi;
-import com.ning.billing.util.svcapi.subscription.SubscriptionBaseInternalApi;
import com.ning.billing.util.svcapi.junction.BlockingInternalApi;
import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
import com.ning.billing.util.svcapi.tag.TagInternalApi;
@@ -166,7 +161,7 @@ public class OverdueStateApplicator<T extends Blockable> {
}
private OverdueChangeInternalEvent createOverdueEvent(final Account overdueable, final String previousOverdueStateName, final String nextOverdueStateName, final InternalCallContext context) throws BlockingApiException {
- return new DefaultOverdueChangeEvent(overdueable.getId(), previousOverdueStateName, nextOverdueStateName,
+ return new DefaultOverdueChangeEvent(overdueable.getId(), previousOverdueStateName, nextOverdueStateName,
context.getAccountRecordId(), context.getTenantRecordId(), context.getUserToken());
}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java b/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java
index dfed584..f37d8b9 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java
@@ -66,7 +66,7 @@ public class ApplicatorMockJunctionModule extends AbstractModule {
}
@Override
- public DateTime getTimestamp() {
+ public DateTime getEffectiveDate() {
return null;
}
@@ -142,6 +142,16 @@ public class ApplicatorMockJunctionModule extends AbstractModule {
throw new UnsupportedOperationException();
}
+ @Override
+ public List<BlockingState> getBlockingAll(final Blockable overdueable, final InternalTenantContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<BlockingState> getBlockingAll(final UUID overdueableId, final InternalTenantContext context) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void setBlockingState(final BlockingState state, final InternalCallContext context) {
diff --git a/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java b/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java
index 6b5cf5c..1833a36 100644
--- a/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java
+++ b/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java
@@ -38,6 +38,10 @@ public interface BlockingInternalApi {
public List<BlockingState> getBlockingHistory(UUID overdueableId, InternalTenantContext context);
+ public List<BlockingState> getBlockingAll(Blockable overdueable, InternalTenantContext context);
+
+ public List<BlockingState> getBlockingAll(UUID overdueableId, InternalTenantContext context);
+
public void setBlockingState(BlockingState state, InternalCallContext context);
}
diff --git a/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java b/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java
index c2b532d..54e7a02 100644
--- a/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java
+++ b/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java
@@ -38,13 +38,13 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
private final boolean blockChange;
private final boolean blockEntitlement;
private final boolean blockBilling;
- private final DateTime timestamp;
+ private final DateTime effectiveDate;
private final BlockingStateType type;
public static BlockingState getClearState(final BlockingStateType type, final Clock clock) {
if (clearState == null) {
// STEPH_ENT should we not always have a service name?
- clearState = new DefaultBlockingState(null, null, type, CLEAR_STATE_NAME, null, false, false, false, clock.getUTCNow(), clock.getUTCNow());
+ clearState = new DefaultBlockingState(null, type, CLEAR_STATE_NAME, null, false, false, false, clock.getUTCNow());
}
return clearState;
}
@@ -58,6 +58,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
final boolean blockChange,
final boolean blockEntitlement,
final boolean blockBilling,
+ final DateTime effectiveDate,
final DateTime createDate,
final DateTime updatedDate) {
super(id, createDate, updatedDate);
@@ -68,8 +69,10 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
this.blockChange = blockChange;
this.blockEntitlement = blockEntitlement;
this.blockBilling = blockBilling;
- this.timestamp = createDate;
+ this.effectiveDate = effectiveDate;
}
+
+
public DefaultBlockingState(final UUID blockingId,
final BlockingStateType type,
final String stateName,
@@ -77,7 +80,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
final boolean blockChange,
final boolean blockEntitlement,
final boolean blockBilling,
- final DateTime createDate) {
+ final DateTime effectiveDate) {
this(UUID.randomUUID(),
blockingId,
type,
@@ -86,8 +89,9 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
blockChange,
blockEntitlement,
blockBilling,
- createDate,
- createDate);
+ effectiveDate,
+ null,
+ null);
}
@Override
@@ -112,8 +116,8 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
* @see com.ning.billing.junction.api.blocking.BlockingState#getTimestamp()
*/
@Override
- public DateTime getTimestamp() {
- return timestamp;
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
}
@Override
@@ -150,8 +154,8 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
*/
@Override
public int compareTo(final BlockingState arg0) {
- if (timestamp.compareTo(arg0.getTimestamp()) != 0) {
- return timestamp.compareTo(arg0.getTimestamp());
+ if (effectiveDate.compareTo(arg0.getEffectiveDate()) != 0) {
+ return effectiveDate.compareTo(arg0.getEffectiveDate());
} else {
return hashCode() - arg0.hashCode();
}
@@ -167,7 +171,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
result = prime * result + ((blockingId == null) ? 0 : blockingId.hashCode());
result = prime * result + ((service == null) ? 0 : service.hashCode());
result = prime * result + ((stateName == null) ? 0 : stateName.hashCode());
- result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
+ result = prime * result + ((effectiveDate == null) ? 0 : effectiveDate.hashCode());
return result;
}
@@ -213,11 +217,11 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
} else if (!stateName.equals(other.stateName)) {
return false;
}
- if (timestamp == null) {
- if (other.timestamp != null) {
+ if (effectiveDate == null) {
+ if (other.effectiveDate != null) {
return false;
}
- } else if (timestamp.compareTo(other.timestamp) != 0) {
+ } else if (effectiveDate.compareTo(other.effectiveDate) != 0) {
return false;
}
return true;
@@ -247,6 +251,6 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
public String toString() {
return "BlockingState [blockingId=" + blockingId + ", stateName=" + stateName + ", service="
+ service + ", blockChange=" + blockChange + ", blockEntitlement=" + blockEntitlement
- + ", blockBilling=" + blockBilling + ", timestamp=" + timestamp + "]";
+ + ", blockBilling=" + blockBilling + ", effectiveDate=" + effectiveDate + "]";
}
}