killbill-memoizeit

Fix requested date for entitlement cancellation/change Remove

2/14/2012 11:16:41 PM

Details

diff --git a/api/src/main/java/com/ning/billing/config/EntitlementConfig.java b/api/src/main/java/com/ning/billing/config/EntitlementConfig.java
index 42399ce..1b6f3e2 100644
--- a/api/src/main/java/com/ning/billing/config/EntitlementConfig.java
+++ b/api/src/main/java/com/ning/billing/config/EntitlementConfig.java
@@ -33,7 +33,7 @@ public interface EntitlementConfig {
     @Default("500")
     public long getNotificationSleepTimeMs();
 
-    @Config("killbill.entitlement.engine.events.off")
+    @Config("killbill.notifications.off")
     @Default("false")
     public boolean isEventProcessingOff();
 }
diff --git a/api/src/main/java/com/ning/billing/config/InvoiceConfig.java b/api/src/main/java/com/ning/billing/config/InvoiceConfig.java
index a2b4270..78cc02f 100644
--- a/api/src/main/java/com/ning/billing/config/InvoiceConfig.java
+++ b/api/src/main/java/com/ning/billing/config/InvoiceConfig.java
@@ -33,7 +33,7 @@ public interface InvoiceConfig {
     @Default("500")
     public long getNotificationSleepTimeMs();
 
-    @Config("killbill.invoice.engine.events.off")
+    @Config("killbill.notifications.off")
     @Default("false")
     public boolean isEventProcessingOff();
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java b/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
index 53854d1..28084b2 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
@@ -18,7 +18,6 @@ package com.ning.billing.entitlement.api;
 
 import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.test.EntitlementTestApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.lifecycle.KillbillService;
 
@@ -31,7 +30,5 @@ public interface EntitlementService extends KillbillService {
 
     public EntitlementBillingApi getBillingApi();
 
-    public EntitlementTestApi getTestApi();
-
     public EntitlementMigrationApi getMigrationApi();
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index 41ecd78..5c626fc 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -64,7 +64,7 @@ public interface Subscription {
     public String getCurrentPriceList();
 
     public PlanPhase getCurrentPhase();
-    
+
     public DateTime getChargedThroughDate();
 
     public DateTime getPaidThroughDate();
@@ -76,4 +76,5 @@ public interface Subscription {
 
     public SubscriptionTransition getPendingTransition();
 
+    public SubscriptionTransition getPreviousTransition();
 }
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 3209c8c..f7825e9 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -29,7 +29,8 @@ public enum ErrorCode {
      *
      */
     /* Generic through APIs */
-    ENT_INVALID_REQUESTED_DATE(1001, "Requested in the future is not allowed : %s"),
+    ENT_INVALID_REQUESTED_FUTURE_DATE(1001, "Requested date %s in the future is not allowed"),
+    ENT_INVALID_REQUESTED_DATE(1001, "Requested date %s is not allowed to be prior to the previous transition %s"),
 
     /* Creation */
     ENT_CREATE_BAD_PHASE(1011, "Can't create plan initial phase %s"),
@@ -93,12 +94,12 @@ public enum ErrorCode {
      */
     CAT_NO_CATALOG_FOR_GIVEN_DATE(2050, "There is no catalog version that applies for the given date '%s'"),
     CAT_NO_CATALOG_ENTRIES_FOR_GIVEN_DATE(2051, "The are no catalog entries that apply for the given date '%s'"),
-    CAT_CATALOG_NAME_MISMATCH(2052, "The catalog name '%s' does not match the name of the catalog we are trying to add '%s'"),  
+    CAT_CATALOG_NAME_MISMATCH(2052, "The catalog name '%s' does not match the name of the catalog we are trying to add '%s'"),
     /*
      * Billing Alignment
      */
     CAT_INVALID_BILLING_ALIGNMENT(2060, "Invalid billing alignment '%s'"),
-    
+
    /*
     *
     * Range 3000 : ACCOUNT
@@ -120,7 +121,7 @@ public enum ErrorCode {
     TAG_DEFINITION_ALREADY_EXISTS(3901, "The tag definition name already exists (name: %s)"),
     TAG_DEFINITION_DOES_NOT_EXIST(3902, "The tag definition name does not exist (name: %s)"),
     TAG_DEFINITION_IN_USE(3903, "The tag definition name is currently in use (name: %s)"),
-   
+
    /*
     *
     * Range 4000: INVOICE
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
index d2af1a6..3143b7c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
@@ -99,10 +99,7 @@ public class SubscriptionApiService {
 
             DateTime now = clock.getUTCNow();
             requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
-            // STEPH needs to check if requestedDate is before last 'erasable event'?
-            if (requestedDate != null && requestedDate.isAfter(now)) {
-                throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
-            }
+            validateRequestedDateOnChangeOrCancel(subscription, now, requestedDate);
 
             Plan currentPlan = subscription.getCurrentPlan();
             PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
@@ -160,6 +157,7 @@ public class SubscriptionApiService {
         subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
     }
 
+
     public void changePlan(SubscriptionData subscription, String productName, BillingPeriod term,
             String priceList, DateTime requestedDate)
         throws EntitlementUserApiException {
@@ -169,10 +167,7 @@ public class SubscriptionApiService {
 
             DateTime now = clock.getUTCNow();
             requestedDate = (requestedDate != null) ? DefaultClock.truncateMs(requestedDate) : now;
-            // STEPH needs to check if requestedDate is before last 'erasable event'?
-            if (requestedDate != null && requestedDate.isAfter(now)) {
-                throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE, requestedDate.toString());
-            }
+            validateRequestedDateOnChangeOrCancel(subscription, now, requestedDate);
 
             String currentPriceList = subscription.getCurrentPriceList();
 
@@ -207,7 +202,7 @@ public class SubscriptionApiService {
             PriceList newPriceList = planChangeResult.getNewPriceList();
 
             Plan newPlan = catalogService.getFullCatalog().findPlan(productName, term, newPriceList.getName(), requestedDate);
-            DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, now);
+            DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, requestedDate);
 
             TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), requestedDate, effectiveDate);
 
@@ -237,4 +232,18 @@ public class SubscriptionApiService {
             throw new EntitlementUserApiException(e);
         }
     }
+
+    private void validateRequestedDateOnChangeOrCancel(SubscriptionData subscription, DateTime now, DateTime requestedDate)
+        throws EntitlementUserApiException {
+
+        if (requestedDate.isAfter(now) ) {
+            throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_FUTURE_DATE, requestedDate.toString());
+        }
+
+        SubscriptionTransition previousTransition = subscription.getPreviousTransition();
+        if (previousTransition.getEffectiveTransitionTime().isAfter(requestedDate)) {
+            throw new EntitlementUserApiException(ErrorCode.ENT_INVALID_REQUESTED_DATE,
+                    requestedDate.toString(), previousTransition.getEffectiveTransitionTime());
+        }
+    }
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index 342c9cc..f4bb22b 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -104,29 +104,29 @@ public class SubscriptionData implements Subscription {
 
     @Override
     public SubscriptionState getState() {
-        return (getLatestTransition() == null) ? null : getLatestTransition().getNextState();
+        return (getPreviousTransition() == null) ? null : getPreviousTransition().getNextState();
     }
 
     @Override
     public PlanPhase getCurrentPhase() {
-        return (getLatestTransition() == null) ? null : getLatestTransition().getNextPhase();
+        return (getPreviousTransition() == null) ? null : getPreviousTransition().getNextPhase();
     }
 
 
     @Override
     public Plan getCurrentPlan() {
-        return (getLatestTransition() == null) ? null : getLatestTransition().getNextPlan();
+        return (getPreviousTransition() == null) ? null : getPreviousTransition().getNextPlan();
     }
 
     @Override
     public String getCurrentPriceList() {
-        return (getLatestTransition() == null) ? null : getLatestTransition().getNextPriceList();
+        return (getPreviousTransition() == null) ? null : getPreviousTransition().getNextPriceList();
     }
 
 
     @Override
     public DateTime getEndDate() {
-        SubscriptionTransition latestTransition = getLatestTransition();
+        SubscriptionTransition latestTransition = getPreviousTransition();
         if (latestTransition.getNextState() == SubscriptionState.CANCELLED) {
             return latestTransition.getEffectiveTransitionTime();
         }
@@ -188,6 +188,7 @@ public class SubscriptionData implements Subscription {
         return result;
     }
 
+    @Override
     public SubscriptionTransition getPendingTransition() {
         if (transitions == null) {
             return null;
@@ -200,7 +201,7 @@ public class SubscriptionData implements Subscription {
         return null;
     }
 
-    public SubscriptionTransition getLatestTransition() {
+    public SubscriptionTransition getPreviousTransition() {
 
         if (transitions == null) {
             return null;
@@ -240,10 +241,12 @@ public class SubscriptionData implements Subscription {
         return bundleStartDate;
     }
 
+    @Override
     public DateTime getChargedThroughDate() {
         return chargedThroughDate;
     }
 
+    @Override
     public DateTime getPaidThroughDate() {
         return paidThroughDate;
     }
@@ -354,7 +357,7 @@ public class SubscriptionData implements Subscription {
         transitions = new LinkedList<SubscriptionTransitionData>();
         Plan previousPlan = null;
         PlanPhase previousPhase = null;
-        
+
         for (final EntitlementEvent cur : events) {
 
             if (!cur.isActive() || cur.getActiveVersion() < activeVersion) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index ce70ba7..a774b61 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -31,8 +31,6 @@ import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
 import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.entitlement.api.migration.DefaultEntitlementMigrationApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.test.DefaultEntitlementTestApi;
-import com.ning.billing.entitlement.api.test.EntitlementTestApi;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
@@ -65,7 +63,6 @@ public class Engine implements EventListener, EntitlementService {
     private final PlanAligner planAligner;
     private final EntitlementUserApi userApi;
     private final EntitlementBillingApi billingApi;
-    private final EntitlementTestApi testApi;
     private final EntitlementMigrationApi migrationApi;
     private final Bus eventBus;
     private final EntitlementConfig config;
@@ -76,7 +73,7 @@ public class Engine implements EventListener, EntitlementService {
     @Inject
     public Engine(Clock clock, EntitlementDao dao, PlanAligner planAligner,
             EntitlementConfig config, DefaultEntitlementUserApi userApi,
-            DefaultEntitlementBillingApi billingApi, DefaultEntitlementTestApi testApi,
+            DefaultEntitlementBillingApi billingApi,
             DefaultEntitlementMigrationApi migrationApi, Bus eventBus,
             NotificationQueueService notificationQueueService) {
         super();
@@ -84,7 +81,6 @@ public class Engine implements EventListener, EntitlementService {
         this.dao = dao;
         this.planAligner = planAligner;
         this.userApi = userApi;
-        this.testApi = testApi;
         this.billingApi = billingApi;
         this.migrationApi = migrationApi;
         this.config = config;
@@ -161,11 +157,6 @@ public class Engine implements EventListener, EntitlementService {
 
 
     @Override
-    public EntitlementTestApi getTestApi() {
-        return testApi;
-    }
-
-    @Override
     public EntitlementMigrationApi getMigrationApi() {
         return migrationApi;
     }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index c27a8f4..4f0dfec 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -27,8 +27,6 @@ import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
 import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.entitlement.api.migration.DefaultEntitlementMigrationApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.test.DefaultEntitlementTestApi;
-import com.ning.billing.entitlement.api.test.EntitlementTestApi;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.SubscriptionApiService;
@@ -57,7 +55,6 @@ public class EntitlementModule extends AbstractModule {
         bind(Engine.class).asEagerSingleton();
         bind(PlanAligner.class).asEagerSingleton();
         bind(MigrationPlanAligner.class).asEagerSingleton();
-        bind(EntitlementTestApi.class).to(DefaultEntitlementTestApi.class).asEagerSingleton();
         bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
         bind(EntitlementBillingApi.class).to(DefaultEntitlementBillingApi.class).asEagerSingleton();
         bind(EntitlementMigrationApi.class).to(DefaultEntitlementMigrationApi.class).asEagerSingleton();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java
index e55ba79..98cc376 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadSubscription.java
@@ -47,98 +47,103 @@ public class BrainDeadSubscription implements Subscription {
 			throws EntitlementUserApiException {
 		throw new UnsupportedOperationException();
 
-		
+
 	}
 
 	@Override
 	public void pause() throws EntitlementUserApiException {
 		throw new UnsupportedOperationException();
 
-		
+
 	}
 
 	@Override
 	public void resume() throws EntitlementUserApiException {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public UUID getId() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public UUID getBundleId() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public SubscriptionState getState() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public DateTime getStartDate() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public DateTime getEndDate() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public Plan getCurrentPlan() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public String getCurrentPriceList() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public PlanPhase getCurrentPhase() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public DateTime getChargedThroughDate() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public DateTime getPaidThroughDate() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public List<SubscriptionTransition> getActiveTransitions() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public List<SubscriptionTransition> getAllTransitions() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
 	@Override
 	public SubscriptionTransition getPendingTransition() {
 		throw new UnsupportedOperationException();
-		
+
 	}
 
+    @Override
+    public SubscriptionTransition getPreviousTransition() {
+        return null;
+    }
+
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
index 005a605..7a9253c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockSubscription.java
@@ -28,7 +28,7 @@ import java.util.List;
 import java.util.UUID;
 
 public class MockSubscription implements Subscription {
-    private UUID subscriptionId = UUID.randomUUID();
+    private final UUID subscriptionId = UUID.randomUUID();
 
     @Override
     public void cancel(DateTime requestedDate, boolean eot) throws EntitlementUserApiException {
@@ -119,4 +119,9 @@ public class MockSubscription implements Subscription {
     public SubscriptionTransition getPendingTransition() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public SubscriptionTransition getPreviousTransition() {
+        return null;
+    }
 }
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
index 91e7110..3b96ee4 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueueService.java
@@ -36,5 +36,4 @@ public class DefaultNotificationQueueService extends NotificationQueueServiceBas
             NotificationConfig config) {
         return new DefaultNotificationQueue(dbi, clock, svcName, queueName, handler, config);
     }
-
 }
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java
index 4fb17b5..5cb00aa 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueService.java
@@ -57,7 +57,7 @@ public interface NotificationQueueService {
      * @throws com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists is the queue associated with that service and name already exits
      *
      */
-    NotificationQueue createNotificationQueue(final String svcName, final String queueName, final NotificationQueueHandler handler, final NotificationConfig config)
+    public NotificationQueue createNotificationQueue(final String svcName, final String queueName, final NotificationQueueHandler handler, final NotificationConfig config)
         throws NotificationQueueAlreadyExists;
 
     /**
@@ -69,7 +69,14 @@ public interface NotificationQueueService {
      *
      * @throws NoSuchNotificationQueue if queue does not exist
      */
-    NotificationQueue getNotificationQueue(final String svcName, final String queueName)
+    public NotificationQueue getNotificationQueue(final String svcName, final String queueName)
         throws NoSuchNotificationQueue;
 
+
+    /**
+     *
+     * @param services
+     * @return
+     */
+    public void triggerManualQueueProcessing(final String [] services);
 }
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
index 98a10b1..7833529 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueueServiceBase.java
@@ -16,12 +16,16 @@
 
 package com.ning.billing.util.notificationq;
 
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Joiner;
 import com.google.inject.Inject;
 import com.ning.billing.util.clock.Clock;
 
@@ -79,6 +83,37 @@ public abstract class NotificationQueueServiceBase implements NotificationQueueS
     }
 
 
+    @Override
+    public void triggerManualQueueProcessing(final String [] services) {
+
+        List<NotificationQueue> manualQueues = null;
+        if (services == null) {
+            manualQueues = new ArrayList<NotificationQueue>(queues.values());
+        } else {
+            Joiner join = Joiner.on(",");
+            join.join(services);
+
+            log.info("Trigger manual processing for services {} ", join.toString());
+            manualQueues = new LinkedList<NotificationQueue>();
+            synchronized (queues) {
+                for (String svc : services) {
+                    addQueuesForService(manualQueues, svc);
+                }
+            }
+        }
+        for (NotificationQueue cur : manualQueues) {
+            cur.processReadyNotification();
+        }
+    }
+
+    private final void addQueuesForService(final List<NotificationQueue> result, final String svcName) {
+        for (String cur : queues.keySet()) {
+            if (cur.startsWith(svcName)) {
+                result.add(queues.get(cur));
+            }
+        }
+    }
+
     protected abstract NotificationQueue createNotificationQueueInternal(String svcName,
             String queueName, NotificationQueueHandler handler,
             NotificationConfig config);