killbill-aplcache

entitlement. See #431 Add api 'getBlockingStates' to retrieve

2/9/2016 2:02:35 AM

Details

diff --git a/api/src/main/java/org/killbill/billing/junction/DefaultBlockingState.java b/api/src/main/java/org/killbill/billing/junction/DefaultBlockingState.java
index 07537b0..b44b81d 100644
--- a/api/src/main/java/org/killbill/billing/junction/DefaultBlockingState.java
+++ b/api/src/main/java/org/killbill/billing/junction/DefaultBlockingState.java
@@ -204,6 +204,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
         return true;
     }
 
+
     @Override
     public int hashCode() {
         int result = super.hashCode();
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
index b3ac142..17f87de 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
@@ -26,12 +26,16 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import org.joda.time.DateTimeZone;
+import org.joda.time.Interval;
 import org.joda.time.LocalDate;
+import org.joda.time.Period;
 import org.killbill.billing.ErrorCode;
 import org.killbill.billing.ObjectType;
+import org.killbill.billing.OrderingType;
 import org.killbill.billing.account.api.AccountApiException;
 import org.killbill.billing.account.api.AccountInternalApi;
 import org.killbill.billing.account.api.ImmutableAccountData;
@@ -41,6 +45,7 @@ import org.killbill.billing.entitlement.AccountEntitlements;
 import org.killbill.billing.entitlement.EntitlementInternalApi;
 import org.killbill.billing.entitlement.EntitlementService;
 import org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin;
+import org.killbill.billing.entitlement.dao.BlockingStateDao;
 import org.killbill.billing.entitlement.engine.core.EntitlementUtils;
 import org.killbill.billing.entitlement.plugin.api.EntitlementContext;
 import org.killbill.billing.entitlement.plugin.api.OperationType;
@@ -64,6 +69,7 @@ import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Ordering;
 
 import static org.killbill.billing.util.entity.dao.DefaultPaginationHelper.getEntityPaginationNoException;
@@ -97,6 +103,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
     private final EntitlementUtils entitlementUtils;
     private final Clock clock;
     private final EntitlementPluginExecution pluginExecution;
+    private final BlockingStateDao blockingStateDao;
 
 
     @Inject
@@ -106,6 +113,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
                                   final InternalCallContextFactory internalCallContextFactory,
                                   final Clock clock,
                                   final EntitlementPluginExecution pluginExecution,
+                                  final BlockingStateDao blockingStateDao,
                                   final EntitlementUtils entitlementUtils) {
         this.accountApi = accountApi;
         this.entitlementInternalApi = entitlementInternalApi;
@@ -113,6 +121,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
         this.internalCallContextFactory = internalCallContextFactory;
         this.clock = clock;
         this.pluginExecution = pluginExecution;
+        this.blockingStateDao = blockingStateDao;
         this.entitlementUtils = entitlementUtils;
     }
 
@@ -375,6 +384,52 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
         pluginExecution.executeWithPlugin(addBlockingStateWithPlugin, pluginContext);
     }
 
+    @Override
+    public Iterable<BlockingState> getBlockingStates(final UUID accountId, @Nullable final List<BlockingStateType> typeFilter, @Nullable final List<String> svcsFilter, final OrderingType orderingType, final int timeFilter, final TenantContext tenantContext) throws EntitlementApiException {
+
+        try {
+
+            final InternalTenantContext internalTenantContextWithValidAccountRecordId = internalCallContextFactory.createInternalTenantContext(accountId, tenantContext);
+            final List<BlockingState> allBlockingStates = blockingStateDao.getBlockingAllForAccountRecordId(internalTenantContextWithValidAccountRecordId);
+
+            final ImmutableAccountData account = accountApi.getImmutableAccountDataById(accountId, internalTenantContextWithValidAccountRecordId);
+
+            final Iterable<BlockingState> filteredByTypes = typeFilter != null  && !typeFilter.isEmpty() ?
+                                                            Iterables.filter(allBlockingStates, new Predicate<BlockingState>() {
+                                                                @Override
+                                                                public boolean apply(final BlockingState input) {
+                                                                    return typeFilter.contains(input.getType());
+                                                                }
+                                                            }) : allBlockingStates;
+
+            final Iterable<BlockingState> filteredByTypesAndSvcs = svcsFilter != null && !svcsFilter.isEmpty() ?
+                                                                   Iterables.filter(filteredByTypes, new Predicate<BlockingState>() {
+                                                                       @Override
+                                                                       public boolean apply(final BlockingState input) {
+                                                                           return svcsFilter.contains(input.getService());
+                                                                       }
+                                                                   }) : filteredByTypes;
+
+            final LocalDate localDateNowInAccountTimezone = new LocalDate(clock.getUTCNow(), account.getTimeZone());
+            final List<BlockingState> result = new ArrayList<BlockingState>();
+            for (final BlockingState cur : filteredByTypesAndSvcs) {
+
+                final LocalDate eventDate = new LocalDate(cur.getEffectiveDate(), account.getTimeZone());
+                final int comp = eventDate.compareTo(localDateNowInAccountTimezone);
+                if ((comp <= 1 && ((timeFilter & SubscriptionApi.PAST_EVENTS) == SubscriptionApi.PAST_EVENTS)) ||
+                    (comp == 0 && ((timeFilter & SubscriptionApi.PRESENT_EVENTS) == SubscriptionApi.PRESENT_EVENTS)) ||
+                    (comp >= 1 && ((timeFilter & SubscriptionApi.FUTURE_EVENTS) == SubscriptionApi.FUTURE_EVENTS))) {
+                    result.add(cur);
+                }
+            }
+
+            return orderingType == OrderingType.ASCENDING ? result : Lists.reverse(result);
+
+        } catch (AccountApiException e) {
+            throw new EntitlementApiException(e);
+        }
+    }
+
     private List<SubscriptionBundle> getSubscriptionBundlesForAccount(final UUID accountId, final TenantContext tenantContext) throws SubscriptionApiException {
         // Retrieve entitlements
         final AccountEntitlements accountEntitlements;
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
index 3b74850..7c212d1 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
@@ -16,10 +16,13 @@
 
 package org.killbill.billing.entitlement.api;
 
+import java.util.Iterator;
 import java.util.List;
 import java.util.UUID;
 
+import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
+import org.killbill.billing.OrderingType;
 import org.killbill.billing.catalog.api.BillingActionPolicy;
 import org.killbill.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
 import org.killbill.billing.entitlement.api.Entitlement.EntitlementState;
@@ -354,6 +357,61 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
         updateEntitlement = entitlementApi.getEntitlementForId(createdEntitlement.getId(), callContext);
         Assert.assertEquals(updateEntitlement.getState(), EntitlementState.BLOCKED);
 
+        // Now we remove the blocking state for the same service but at the SUBSCRIPTION level
+        testListener.pushExpectedEvent(NextEvent.BLOCK);
+        final BlockingState state3 = new DefaultBlockingState(createdEntitlement.getId(), BlockingStateType.SUBSCRIPTION, "subscriptionUnBlock", "svc1", false, false, false, clock.getUTCNow());
+        subscriptionApi.addBlockingState(state3, ImmutableList.<PluginProperty>of(), callContext);
+        assertListenerStatus();
+
+        updateEntitlement = entitlementApi.getEntitlementForId(createdEntitlement.getId(), callContext);
+        Assert.assertEquals(updateEntitlement.getState(), EntitlementState.BLOCKED);
+
+
+        final DateTime futureEffectiveDate = clock.getUTCNow().plusDays(1);
+        final BlockingState state4 = new DefaultBlockingState(createdEntitlement.getBundleId(), BlockingStateType.SUBSCRIPTION_BUNDLE, "blockBilling", "svc1", true, false, false, futureEffectiveDate);
+        subscriptionApi.addBlockingState(state4, ImmutableList.<PluginProperty>of(), callContext);
+
+
+        final Iterable<BlockingState> blockingStates1 = subscriptionApi.getBlockingStates(account.getId(), ImmutableList.of(BlockingStateType.ACCOUNT, BlockingStateType.SUBSCRIPTION), ImmutableList.of("svc1", "svc2"), OrderingType.ASCENDING, SubscriptionApi.PAST_OR_PRESENT_EVENTS, callContext);
+        verifyBlockingStates(blockingStates1, ImmutableList.<BlockingState>of(state1, state2, state3));
+
+        final Iterable<BlockingState> blockingStates3 = subscriptionApi.getBlockingStates(account.getId(), ImmutableList.of(BlockingStateType.SUBSCRIPTION), ImmutableList.of("svc1", "svc2"), OrderingType.DESCENDING, SubscriptionApi.PAST_OR_PRESENT_EVENTS, callContext);
+        verifyBlockingStates(blockingStates3, ImmutableList.<BlockingState>of(state3, state2));
+
+        final Iterable<BlockingState> blockingStates4 = subscriptionApi.getBlockingStates(account.getId(), ImmutableList.of(BlockingStateType.SUBSCRIPTION), ImmutableList.of("svc2"), OrderingType.DESCENDING, SubscriptionApi.PAST_OR_PRESENT_EVENTS, callContext);
+        verifyBlockingStates(blockingStates4, ImmutableList.<BlockingState>of(state2));
+
+        final Iterable<BlockingState> blockingStates2 = subscriptionApi.getBlockingStates(account.getId(), null, null, OrderingType.DESCENDING, SubscriptionApi.ALL_EVENTS, callContext);
+        verifyBlockingStates(blockingStates2, ImmutableList.<BlockingState>of(state4, state3, state2, state1));
+
+        final Iterable<BlockingState> blockingStates6 = subscriptionApi.getBlockingStates(account.getId(), ImmutableList.of(BlockingStateType.SUBSCRIPTION_BUNDLE), null, OrderingType.ASCENDING, SubscriptionApi.FUTURE_EVENTS, callContext);
+        verifyBlockingStates(blockingStates6, ImmutableList.<BlockingState>of(state4));
+
+        testListener.pushExpectedEvent(NextEvent.BLOCK);
+        clock.addDays(1);
+        assertListenerStatus();
+
+        final Iterable<BlockingState> blockingStates5 = subscriptionApi.getBlockingStates(account.getId(), null, null, OrderingType.ASCENDING, SubscriptionApi.PAST_OR_PRESENT_EVENTS, callContext);
+        verifyBlockingStates(blockingStates5, ImmutableList.<BlockingState>of(state1, state2, state3, state4));
+
+    }
+
+    private void verifyBlockingStates(final Iterable<BlockingState> result, final List<BlockingState> expected) {
+        int i = 0;
+        final Iterator<BlockingState> iterator = result.iterator();
+        while (iterator.hasNext()) {
+            final BlockingState cur = iterator.next();
+            final BlockingState expectedItem = expected.get(i);
+            assertEquals(cur.isBlockBilling(), expectedItem.isBlockBilling());
+            assertEquals(cur.isBlockEntitlement(), expectedItem.isBlockEntitlement());
+            assertEquals(cur.isBlockChange(), expectedItem.isBlockChange());
+            assertEquals(cur.getService(), expectedItem.getService());
+            assertEquals(cur.getStateName(), expectedItem.getStateName());
+            assertEquals(cur.getBlockedId(), expectedItem.getBlockedId());
+            assertEquals(cur.getEffectiveDate().compareTo(expectedItem.getEffectiveDate()), 0);
+            i++;
+        }
+        assertEquals(i, expected.size());
     }