killbill-aplcache

Adding Overdue DAO to Overdue and OverdueAccessDao to utils

4/5/2012 1:27:12 PM

Changes

overdue/pom.xml 11(+11 -0)

Details

diff --git a/api/src/main/java/com/ning/billing/catalog/api/overdue/OverdueStateSet.java b/api/src/main/java/com/ning/billing/catalog/api/overdue/OverdueStateSet.java
index 50bf592..c7127d4 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/overdue/OverdueStateSet.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/overdue/OverdueStateSet.java
@@ -18,10 +18,14 @@ package com.ning.billing.catalog.api.overdue;
 
 import org.joda.time.DateTime;
 
+import com.ning.billing.catalog.api.CatalogApiException;
+
 public interface OverdueStateSet<T extends Overdueable> {
 
     public abstract OverdueState<T> findClearState();
 
+    public abstract OverdueState<T> findState(String stateName) throws CatalogApiException;
+
     public abstract OverdueState<T> calculateOverdueState(BillingState<T> billingState, DateTime now);
 
     public abstract DateTime dateOfNextCheck(BillingState<T> billingState, DateTime now);
diff --git a/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java b/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
index fb2d2a6..9a81737 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
@@ -18,10 +18,6 @@ package com.ning.billing.catalog.api;
 
 import java.util.Date;
 
-import org.joda.time.DateTime;
-
-import com.ning.billing.catalog.api.overdue.BillingStateBundle;
-import com.ning.billing.catalog.api.overdue.OverdueState;
 import com.ning.billing.catalog.api.overdue.OverdueStateSet;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 9ef5338..36794e3 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -107,6 +107,10 @@ public enum ErrorCode {
      * Billing Alignment
      */
     CAT_INVALID_BILLING_ALIGNMENT(2060, "Invalid billing alignment '%s'"),
+    /*
+     * Overdue
+     */
+    CAT_NO_SUCH_OVEDUE_STATE(2070, "No such overdue state '%s'"),
 
    /*
     *
diff --git a/catalog/src/main/java/com/ning/billing/catalog/overdue/OverdueStatesBundle.java b/catalog/src/main/java/com/ning/billing/catalog/overdue/OverdueStatesBundle.java
index c506dfd..24aee7d 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/overdue/OverdueStatesBundle.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/overdue/OverdueStatesBundle.java
@@ -18,7 +18,10 @@ package com.ning.billing.catalog.overdue;
 
 import javax.xml.bind.annotation.XmlElement;
 
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.overdue.OverdueState;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.util.config.ValidationErrors;
 
@@ -44,6 +47,14 @@ public class OverdueStatesBundle extends DefaultOverdueStateSet<SubscriptionBund
         }
         return errors;
     }
+
+    @Override
+    public OverdueState<SubscriptionBundle> findState(String stateName) throws CatalogApiException {
+        for(DefaultOverdueState<SubscriptionBundle> state: bundleOverdueStates) {
+            if(state.getName().equals(stateName) ) { return state; }
+        }
+        throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_OVEDUE_STATE, stateName);
+    }
     
 
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
index f82eaef..60c36de 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
@@ -110,7 +110,7 @@ public class TestDefaultInvoiceMigrationApi {
 
     private final Clock clock = new ClockMock();
 
-	@BeforeClass(alwaysRun = true)
+	@BeforeClass(groups={"slow"})
 	public void setup() throws Exception
 	{
 		log.info("Starting set up");
@@ -133,7 +133,7 @@ public class TestDefaultInvoiceMigrationApi {
 		regularInvoiceId = generateRegularInvoice();
 	}
 
-	@AfterClass(alwaysRun = true)
+	@AfterClass(groups={"slow"})
 	public void tearDown() {
 		try {
 			((DefaultBusService) busService).stopBus();

overdue/pom.xml 11(+11 -0)

diff --git a/overdue/pom.xml b/overdue/pom.xml
index 759b56a..0f5a57d 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -78,6 +78,17 @@
             <artifactId>mysql-connector-java</artifactId>
             <scope>runtime</scope>
         </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-mxj</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-mxj-db-files</artifactId>
+            <scope>test</scope>
+        </dependency>
+ 
     </dependencies>
     <build>
         <plugins>
diff --git a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
index 97fab0b..cec80ad 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
@@ -19,28 +19,44 @@ package com.ning.billing.overdue.api;
 import org.apache.commons.lang.NotImplementedException;
 
 import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.StaticCatalog;
 import com.ning.billing.catalog.api.overdue.BillingState;
 import com.ning.billing.catalog.api.overdue.OverdueError;
 import com.ning.billing.catalog.api.overdue.OverdueState;
+import com.ning.billing.catalog.api.overdue.OverdueStateSet;
 import com.ning.billing.catalog.api.overdue.Overdueable;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.overdue.OverdueService;
 import com.ning.billing.overdue.OverdueUserApi;
-import com.ning.billing.overdue.dao.OverdueDao;
+import com.ning.billing.util.overdue.dao.OverdueAccessDao;
 
 public class DefaultOverdueUserApi implements OverdueUserApi{
 
-    private OverdueDao dao;
     private OverdueService service;
+    private CatalogService catalogService;
+    private OverdueAccessDao accessDao;
 
     @Inject
-    public DefaultOverdueUserApi(OverdueDao dao, OverdueService service) {
-        this.dao = dao;
+    public DefaultOverdueUserApi(OverdueService service, CatalogService catalogService, OverdueAccessDao accessDao) {
         this.service = service;
+        this.catalogService = catalogService;
+        this.accessDao = accessDao;
     }
     
+    @SuppressWarnings("unchecked")
     @Override
-    public <T extends Overdueable> OverdueState<T> getOverdueStateFor(T overdueable) {
-        return dao.getOverdueStateFor(overdueable);
+    public <T extends Overdueable> OverdueState<T> getOverdueStateFor(T overdueable) throws OverdueError {
+        try {
+            String stateName = accessDao.getOverdueStateNameFor(overdueable);
+            StaticCatalog catalog = catalogService.getCurrentCatalog();
+            OverdueStateSet<SubscriptionBundle> states = catalog.currentBundleOverdueStateSet();
+            return (OverdueState<T>) states.findState(stateName);
+        } catch (CatalogApiException e) {
+            throw new OverdueError(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED,overdueable.getId(), overdueable.getClass().getSimpleName());
+        }
     }
 
     @Override
diff --git a/overdue/src/main/java/com/ning/billing/overdue/dao/OverdueDao.java b/overdue/src/main/java/com/ning/billing/overdue/dao/OverdueDao.java
index 610aab0..75286de 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/dao/OverdueDao.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/dao/OverdueDao.java
@@ -18,11 +18,10 @@ package com.ning.billing.overdue.dao;
 
 import com.ning.billing.catalog.api.overdue.OverdueState;
 import com.ning.billing.catalog.api.overdue.Overdueable;
+import com.ning.billing.util.clock.Clock;
 
 public interface OverdueDao {
 
-    <T extends Overdueable> OverdueState<T> getOverdueStateFor(T overdueable);
-
-    <T extends Overdueable> void  setOverdueStateForBundle(T overdueable, OverdueState<T> newOverdueState);
+    <T extends Overdueable> void  setOverdueStateForBundle(T overdueable, OverdueState<T> newOverdueState, Clock clock);
 
 }
\ No newline at end of file
diff --git a/overdue/src/main/java/com/ning/billing/overdue/dao/OverdueSqlDao.java b/overdue/src/main/java/com/ning/billing/overdue/dao/OverdueSqlDao.java
new file mode 100644
index 0000000..dac4050
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/dao/OverdueSqlDao.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.dao;
+
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+
+import com.ning.billing.catalog.api.overdue.OverdueState;
+import com.ning.billing.catalog.api.overdue.Overdueable;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.entity.BinderBase;
+
+@ExternalizedSqlViaStringTemplate3()
+public interface OverdueSqlDao extends OverdueDao {
+
+    @Override
+    @SqlUpdate
+    public abstract <T extends Overdueable> void setOverdueStateForBundle(
+            @Bind(binder = OverdueableBinder.class) T overdueable, 
+            @Bind(binder = OverdueStateBinder.class) OverdueState<T> overdueState,
+            @Bind(binder = CurrentTimeBinder.class) Clock clock) ;
+
+    public static class OverdueableBinder extends BinderBase implements Binder<Bind, Overdueable> {
+        @Override
+        public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, Overdueable overdueable) {
+            stmt.bind("id", overdueable.getId().toString());
+        }
+    }
+    public static class OverdueStateBinder<T extends Overdueable> extends BinderBase implements Binder<Bind, OverdueState<T>> {
+        @Override
+        public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, OverdueState<T> overdueState) {
+            stmt.bind("state", overdueState.getName());
+        }
+    }
+    
+    public static class CurrentTimeBinder extends BinderBase implements Binder<Bind, Clock> {
+        @Override
+        public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, Clock clock) {
+            stmt.bind("created_date", clock.getUTCNow());
+        }
+        
+    }
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
new file mode 100644
index 0000000..5797b1b
--- /dev/null
+++ b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.glue;
+
+import org.skife.jdbi.v2.IDBI;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.ning.billing.overdue.dao.OverdueDao;
+import com.ning.billing.overdue.dao.OverdueSqlDao;
+
+public class OverdueModule extends AbstractModule {
+    
+    @Override
+    protected void configure() {
+        bind(OverdueDao.class).toProvider(OverdueDaoProvider.class);
+    }
+
+    public static class OverdueDaoProvider implements Provider<OverdueDao>{
+        
+        private IDBI dbi;
+
+
+        @Inject
+        public OverdueDaoProvider(IDBI dbi){
+            this.dbi = dbi;
+        }
+        
+
+        @Override
+        public OverdueDao get() {
+            return dbi.onDemand(OverdueSqlDao.class);
+        }   
+    }
+}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
index f2258bd..1b7feeb 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
@@ -21,27 +21,27 @@ import com.ning.billing.catalog.api.overdue.OverdueError;
 import com.ning.billing.catalog.api.overdue.OverdueState;
 import com.ning.billing.catalog.api.overdue.OverdueStateSet;
 import com.ning.billing.catalog.api.overdue.Overdueable;
+import com.ning.billing.overdue.OverdueUserApi;
 import com.ning.billing.overdue.applicator.OverdueStateApplicator;
 import com.ning.billing.overdue.calculator.BillingStateCalculator;
-import com.ning.billing.overdue.dao.OverdueDao;
 import com.ning.billing.util.clock.Clock;
 
 public class OverdueWrapper<T extends Overdueable> {
     private final T overdueable;
-    private final OverdueDao dao;
+    private final OverdueUserApi api;
     private final Clock clock;
     private final OverdueStateSet<T> overdueStateSet;
     private final BillingStateCalculator<T> billingStateCalcuator;
     private final OverdueStateApplicator<T> overdueStateApplicator;
 
-    public OverdueWrapper(T overdueable, OverdueDao dao,
+    public OverdueWrapper(T overdueable, OverdueUserApi api,
             OverdueStateSet<T> overdueStateSet,
             Clock clock,
             BillingStateCalculator<T> billingStateCalcuator,
             OverdueStateApplicator<T> overdueStateApplicator) {
         this.overdueable = overdueable;
         this.overdueStateSet = overdueStateSet;
-        this.dao = dao;
+        this.api = api;
         this.clock = clock;
         this.billingStateCalcuator = billingStateCalcuator;
         this.overdueStateApplicator = overdueStateApplicator;
@@ -49,7 +49,7 @@ public class OverdueWrapper<T extends Overdueable> {
 
     public OverdueState<T> refresh() throws OverdueError {
         BillingState<T> billingState = billingStateCalcuator.calculateBillingState(overdueable);
-        OverdueState<T> previousOverdueStateName = dao.getOverdueStateFor(overdueable);
+        OverdueState<T> previousOverdueStateName = api.getOverdueStateFor(overdueable);
         OverdueState<T> nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getUTCNow());
         if(!previousOverdueStateName.equals(nextOverdueState.getName())) {
             overdueStateApplicator.apply(overdueable, nextOverdueState, nextOverdueState, overdueStateSet.dateOfNextCheck(billingState, clock.getUTCNow())); 
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
index 594c606..76b3dd0 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
@@ -23,9 +23,9 @@ import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.api.overdue.OverdueError;
 import com.ning.billing.catalog.api.overdue.Overdueable;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.overdue.OverdueUserApi;
 import com.ning.billing.overdue.applicator.OverdueStateApplicatorBundle;
 import com.ning.billing.overdue.calculator.BillingStateCalculatorBundle;
-import com.ning.billing.overdue.dao.OverdueDao;
 import com.ning.billing.util.clock.Clock;
 
 public class OverdueWrapperFactory {
@@ -33,15 +33,15 @@ public class OverdueWrapperFactory {
     private final CatalogService catalogService;
     private final BillingStateCalculatorBundle billingStateCalcuatorBundle;
     private final OverdueStateApplicatorBundle overdueStateApplicatorBundle;
-    private final OverdueDao dao;
+    private final OverdueUserApi api;
     private final Clock clock;
 
     @Inject
-    public OverdueWrapperFactory(OverdueDao dao, CatalogService catalogService, Clock clock, BillingStateCalculatorBundle billingStateCalcuatorBundle, OverdueStateApplicatorBundle overdueStateApplicatorBundle) {
+    public OverdueWrapperFactory(OverdueUserApi api, CatalogService catalogService, Clock clock, BillingStateCalculatorBundle billingStateCalcuatorBundle, OverdueStateApplicatorBundle overdueStateApplicatorBundle) {
         this.billingStateCalcuatorBundle = billingStateCalcuatorBundle;
         this.overdueStateApplicatorBundle = overdueStateApplicatorBundle;
         this.catalogService = catalogService;
-        this.dao = dao;
+        this.api = api;
         this.clock = clock;
     }
 
@@ -50,7 +50,7 @@ public class OverdueWrapperFactory {
     public <T extends Overdueable> OverdueWrapper<T> createOverdueWrapperFor(T overdueable) throws OverdueError {
         try {
             if(overdueable instanceof SubscriptionBundle) {
-                return (OverdueWrapper<T>)new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle)overdueable, dao, catalogService.getCurrentCatalog().currentBundleOverdueStateSet(), 
+                return (OverdueWrapper<T>)new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle)overdueable, api, catalogService.getCurrentCatalog().currentBundleOverdueStateSet(), 
                         clock, billingStateCalcuatorBundle, overdueStateApplicatorBundle );
             } else {
                 throw new OverdueError(ErrorCode.OVERDUE_OVERDUEABLE_NOT_SUPPORTED, overdueable.getClass());
diff --git a/overdue/src/main/resources/com/ning/billing/overdue/dao/OverdueSqlDao.sql.stg b/overdue/src/main/resources/com/ning/billing/overdue/dao/OverdueSqlDao.sql.stg
new file mode 100644
index 0000000..229a6a7
--- /dev/null
+++ b/overdue/src/main/resources/com/ning/billing/overdue/dao/OverdueSqlDao.sql.stg
@@ -0,0 +1,13 @@
+group OverdueSqlDao;
+
+setOverdueStateForBundle() ::= <<
+    insert into overdue_states (
+        id
+      , state
+      , created_date
+    ) values (
+        :id
+      , :state
+      , NOW() 
+    );
+>>
\ No newline at end of file
diff --git a/overdue/src/test/java/com/ning/billing/overdue/dao/MockModule.java b/overdue/src/test/java/com/ning/billing/overdue/dao/MockModule.java
new file mode 100644
index 0000000..30adc91
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/dao/MockModule.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.dao;
+
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.IDBI;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.catalog.glue.CatalogModule;
+import com.ning.billing.dbi.DBIProvider;
+import com.ning.billing.dbi.DbiConfig;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+
+
+public class MockModule extends AbstractModule {
+    public static final String PLUGIN_NAME = "Booboo";
+
+    @Override
+    protected void configure() {
+        bind(Clock.class).to(ClockMock.class).asEagerSingleton();
+        bind(ClockMock.class).asEagerSingleton();
+        bind(CallContextFactory.class).to(DefaultCallContextFactory.class).asEagerSingleton();
+
+        final MysqlTestingHelper helper = new MysqlTestingHelper();
+        bind(MysqlTestingHelper.class).toInstance(helper);
+        if (helper.isUsingLocalInstance()) {
+            bind(IDBI.class).toProvider(DBIProvider.class).asEagerSingleton();
+            final DbiConfig config = new ConfigurationObjectFactory(System.getProperties()).build(DbiConfig.class);
+            bind(DbiConfig.class).toInstance(config);
+        } else {
+            final IDBI dbi = helper.getDBI(); 
+            bind(IDBI.class).toInstance(dbi);
+        }
+
+       install(new CatalogModule());
+    }
+    
+
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/dao/TestOverdueDao.java b/overdue/src/test/java/com/ning/billing/overdue/dao/TestOverdueDao.java
new file mode 100644
index 0000000..b49a670
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/dao/TestOverdueDao.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.dao;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.TimeUnit;
+import com.ning.billing.catalog.api.overdue.OverdueState;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.overdue.glue.OverdueModule;
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.glue.OverdueAccessModule;
+import com.ning.billing.util.overdue.dao.OverdueAccessDao;
+
+@Guice(modules = {MockModule.class, OverdueModule.class, OverdueAccessModule.class})
+public class TestOverdueDao {
+    private Logger log = LoggerFactory.getLogger(TestOverdueDao.class);
+    
+    @Inject
+    private MysqlTestingHelper helper;
+    
+    @Inject
+    private OverdueDao dao;
+
+    @Inject
+    private OverdueAccessDao accessDao;
+
+    @BeforeClass(groups={"slow"})
+    public void setup() throws IOException {
+        log.info("Starting set up");
+
+        final String utilDdl = IOUtils.toString(TestOverdueDao.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
+
+        helper.startMysql();
+        helper.initDb(utilDdl);
+
+    }
+    
+    
+    @Test(groups={"slow"}, enabled=true)
+    public void testDao() { 
+        ClockMock clock = new ClockMock();
+        SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+        UUID bundleId = UUID.randomUUID();
+        ((ZombieControl)bundle).addResult("getId", bundleId);
+        
+        String overdueStateName = "WayPassedItMan";
+        @SuppressWarnings("unchecked")
+        OverdueState<SubscriptionBundle> state = BrainDeadProxyFactory.createBrainDeadProxyFor(OverdueState.class);
+        ((ZombieControl)state).addResult("getName", overdueStateName);
+        
+        dao.setOverdueStateForBundle(bundle, state, clock);
+        clock.setDeltaFromReality(1000 * 3600 * 24);
+        
+        String overdueStateName2 = "NoReallyThisCantGoOn";
+        ((ZombieControl)state).addResult("getName", overdueStateName2);
+        dao.setOverdueStateForBundle(bundle, state, clock);
+        
+        Assert.assertEquals(accessDao.getOverdueStateNameFor(bundle), overdueStateName2);
+        
+    }
+    
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/OverdueAccessModule.java b/util/src/main/java/com/ning/billing/util/glue/OverdueAccessModule.java
new file mode 100644
index 0000000..8f4f634
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/OverdueAccessModule.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.glue;
+
+import org.skife.jdbi.v2.IDBI;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.ning.billing.util.overdue.dao.OverdueAccessDao;
+import com.ning.billing.util.overdue.dao.OverdueAccessSqlDao;
+
+public class OverdueAccessModule extends AbstractModule {
+
+    @Override
+    protected void configure() {
+        bind(OverdueAccessDao.class).toProvider(OverdueAccessDaoProvider.class);
+    }
+
+    public static class OverdueAccessDaoProvider implements Provider<OverdueAccessDao>{
+
+        private IDBI dbi;
+
+
+        @Inject
+        public OverdueAccessDaoProvider(IDBI dbi){
+            this.dbi = dbi;
+        }
+
+
+        @Override
+        public OverdueAccessDao get() {
+            return dbi.onDemand(OverdueAccessSqlDao.class);
+        }   
+    }
+
+
+}
diff --git a/util/src/main/java/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.java b/util/src/main/java/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.java
new file mode 100644
index 0000000..b6e0426
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.overdue.dao;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
+import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.catalog.api.overdue.Overdueable;
+import com.ning.billing.util.entity.BinderBase;
+import com.ning.billing.util.entity.MapperBase;
+import com.ning.billing.util.overdue.OverdueAccessApi;
+
+@ExternalizedSqlViaStringTemplate3()
+public interface OverdueAccessSqlDao extends Transactional<OverdueAccessSqlDao>, CloseMe, Transmogrifier, OverdueAccessDao {
+
+    @Override
+    @SqlQuery
+    @Mapper(OverdueStateSqlMapper.class)
+    public abstract String getOverdueStateNameFor(@Bind(binder = OverdueableBinder.class)Overdueable overdueable) ;
+    
+    public static class OverdueStateSqlMapper extends MapperBase implements ResultSetMapper<String> {
+
+        @Override
+        public String map(int index, ResultSet r, StatementContext ctx)
+                throws SQLException {
+            return r.getString("state") == null ? OverdueAccessApi.CLEAR_STATE_NAME : r.getString("state");
+        }
+    }
+    
+    public static class OverdueableBinder extends BinderBase implements Binder<Bind, Overdueable> {
+        @Override
+        public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, Overdueable overdueable) {
+            stmt.bind("id", overdueable.getId().toString());
+        }
+    }
+   
+}
diff --git a/util/src/main/java/com/ning/billing/util/overdue/DefaultOverdueAcessApi.java b/util/src/main/java/com/ning/billing/util/overdue/DefaultOverdueAcessApi.java
new file mode 100644
index 0000000..5b7e6be
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/overdue/DefaultOverdueAcessApi.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.overdue;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.overdue.Overdueable;
+import com.ning.billing.util.overdue.dao.OverdueAccessDao;
+
+public class DefaultOverdueAcessApi implements OverdueAccessApi {
+    private OverdueAccessDao dao;
+
+    @Inject
+    public DefaultOverdueAcessApi(OverdueAccessDao dao) {
+        this.dao = dao;
+    }
+    
+    @Override
+    public String getOverdueStateNameFor(Overdueable overdueable) {
+        return dao.getOverdueStateNameFor(overdueable);
+    }
+
+}
diff --git a/util/src/main/java/com/ning/billing/util/overdue/OverdueAccessApi.java b/util/src/main/java/com/ning/billing/util/overdue/OverdueAccessApi.java
new file mode 100644
index 0000000..4ca82d8
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/overdue/OverdueAccessApi.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.overdue;
+
+import com.ning.billing.catalog.api.overdue.Overdueable;
+
+public interface OverdueAccessApi {
+    public static final String CLEAR_STATE_NAME = "__KILLBILL__CLEAR__OVERDUE_STATE__";
+
+    public String getOverdueStateNameFor(Overdueable overdueable);
+
+
+}
diff --git a/util/src/main/resources/com/ning/billing/util/ddl.sql b/util/src/main/resources/com/ning/billing/util/ddl.sql
index 17442c1..2bce344 100644
--- a/util/src/main/resources/com/ning/billing/util/ddl.sql
+++ b/util/src/main/resources/com/ning/billing/util/ddl.sql
@@ -117,3 +117,12 @@ CREATE TABLE audit_log (
     comments varchar(255) DEFAULT NULL,
     PRIMARY KEY(id)
 ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS overdue_states;
+CREATE TABLE overdue_states (
+  id char(36) NOT NULL,
+  state varchar(50) NOT NULL,
+  created_date datetime NOT NULL
+) ENGINE=innodb;
+CREATE INDEX overdue_states_by_id ON overdue_states (id);
+
diff --git a/util/src/main/resources/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.sql.stg
new file mode 100644
index 0000000..606a4d0
--- /dev/null
+++ b/util/src/main/resources/com/ning/billing/util/overdue/dao/OverdueAccessSqlDao.sql.stg
@@ -0,0 +1,13 @@
+group OverdueAccessSqlDao;
+
+getOverdueStateNameFor() ::= <<
+    select
+        id
+      , state
+      , created_date   
+    from overdue_states
+    where id = :id
+    order by created_date desc
+    limit 1
+    ;
+>>
\ No newline at end of file