killbill-memoizeit

Changes

account/src/main/java/com/ning/billing/account/api/DefaultBillCycleDay.java 89(+0 -89)

api/src/main/java/com/ning/billing/account/api/BillCycleDay.java 27(+0 -27)

jaxrs/src/main/java/com/ning/billing/jaxrs/json/BillCycleDayJson.java 76(+0 -76)

util/src/test/java/com/ning/billing/mock/api/MockBillCycleDay.java 64(+0 -64)

Details

diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index 7bdb0f1..26eb1e1 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -38,7 +38,6 @@ public class DefaultAccount extends EntityBase implements Account {
     // some fields
     public static final String DEFAULT_STRING_VALUE = "";
     public static final Integer DEFAULT_INTEGER_VALUE = 0;
-    public static final BillCycleDay DEFAULT_BCD_VALUE = new DefaultBillCycleDay(DEFAULT_INTEGER_VALUE);
     public static final Currency DEFAULT_CURRENCY_VALUE = Currency.USD;
     public static final DateTimeZone DEFAULT_TIMEZONE_VALUE = DateTimeZone.UTC;
     private static final Boolean DEFAULT_MIGRATED_VALUE = true;
@@ -49,7 +48,7 @@ public class DefaultAccount extends EntityBase implements Account {
     private final String name;
     private final Integer firstNameLength;
     private final Currency currency;
-    private final BillCycleDay billCycleDay;
+    private final Integer billCycleDayLocal;
     private final UUID paymentMethodId;
     private final DateTimeZone timeZone;
     private final String locale;
@@ -72,7 +71,7 @@ public class DefaultAccount extends EntityBase implements Account {
      */
     public DefaultAccount(final UUID id, final AccountData data) {
         this(id, data.getExternalKey(), data.getEmail(), data.getName(), data.getFirstNameLength(),
-             data.getCurrency(), data.getBillCycleDay(), data.getPaymentMethodId(),
+             data.getCurrency(), data.getBillCycleDayLocal(), data.getPaymentMethodId(),
              data.getTimeZone(), data.getLocale(),
              data.getAddress1(), data.getAddress2(), data.getCompanyName(),
              data.getCity(), data.getStateOrProvince(), data.getCountry(),
@@ -84,13 +83,13 @@ public class DefaultAccount extends EntityBase implements Account {
     */
     public DefaultAccount(final UUID id, final String externalKey, final String email,
                           final String name, final Integer firstNameLength,
-                          final Currency currency, final BillCycleDay billCycleDay, final UUID paymentMethodId,
+                          final Currency currency, final int billCycleDayLocal, final UUID paymentMethodId,
                           final DateTimeZone timeZone, final String locale,
                           final String address1, final String address2, final String companyName,
                           final String city, final String stateOrProvince, final String country,
                           final String postalCode, final String phone,
                           final Boolean isMigrated, final Boolean isNotifiedForInvoices) {
-        this(id, null, null, externalKey, email, name, firstNameLength, currency, billCycleDay, paymentMethodId,
+        this(id, null, null, externalKey, email, name, firstNameLength, currency, billCycleDayLocal, paymentMethodId,
              timeZone, locale, address1, address2, companyName, city, stateOrProvince, country, postalCode,
              phone, isMigrated, isNotifiedForInvoices);
     }
@@ -98,7 +97,7 @@ public class DefaultAccount extends EntityBase implements Account {
     public DefaultAccount(final UUID id, @Nullable final DateTime createdDate, @Nullable final DateTime updatedDate,
                           final String externalKey, final String email,
                           final String name, final Integer firstNameLength,
-                          final Currency currency, final BillCycleDay billCycleDay, final UUID paymentMethodId,
+                          final Currency currency, final int billCycleDayLocal, final UUID paymentMethodId,
                           final DateTimeZone timeZone, final String locale,
                           final String address1, final String address2, final String companyName,
                           final String city, final String stateOrProvince, final String country,
@@ -110,7 +109,7 @@ public class DefaultAccount extends EntityBase implements Account {
         this.name = name;
         this.firstNameLength = firstNameLength;
         this.currency = currency;
-        this.billCycleDay = billCycleDay;
+        this.billCycleDayLocal = billCycleDayLocal;
         this.paymentMethodId = paymentMethodId;
         this.timeZone = timeZone;
         this.locale = locale;
@@ -129,7 +128,7 @@ public class DefaultAccount extends EntityBase implements Account {
     public DefaultAccount(final AccountModelDao accountModelDao) {
         this(accountModelDao.getId(), accountModelDao.getCreatedDate(), accountModelDao.getUpdatedDate(), accountModelDao.getExternalKey(),
              accountModelDao.getEmail(), accountModelDao.getName(), accountModelDao.getFirstNameLength(), accountModelDao.getCurrency(),
-             new DefaultBillCycleDay(accountModelDao.getBillingCycleDayLocal(), accountModelDao.getBillingCycleDayUtc()), accountModelDao.getPaymentMethodId(),
+             accountModelDao.getBillingCycleDayLocal(), accountModelDao.getPaymentMethodId(),
              accountModelDao.getTimeZone(), accountModelDao.getLocale(), accountModelDao.getAddress1(), accountModelDao.getAddress2(),
              accountModelDao.getCompanyName(), accountModelDao.getCity(), accountModelDao.getStateOrProvince(), accountModelDao.getCountry(),
              accountModelDao.getPostalCode(), accountModelDao.getPhone(), accountModelDao.getMigrated(), accountModelDao.getIsNotifiedForInvoices());
@@ -161,8 +160,8 @@ public class DefaultAccount extends EntityBase implements Account {
     }
 
     @Override
-    public BillCycleDay getBillCycleDay() {
-        return Objects.firstNonNull(billCycleDay, DEFAULT_BCD_VALUE);
+    public Integer getBillCycleDayLocal() {
+        return Objects.firstNonNull(billCycleDayLocal, DEFAULT_INTEGER_VALUE);
     }
 
     @Override
@@ -260,19 +259,15 @@ public class DefaultAccount extends EntityBase implements Account {
             accountData.setCurrency(currentAccount.getCurrency());
         }
 
-        if (billCycleDay != null && currentAccount.getBillCycleDay() != null && currentAccount.getBillCycleDay().getDayOfMonthLocal() != 0 && currentAccount.getBillCycleDay().getDayOfMonthUTC() != 0) {
-            // We can't just use .equals here as the BillCycleDay class might not have implemented it
-            if ((billCycleDay.getDayOfMonthUTC() != currentAccount.getBillCycleDay().getDayOfMonthUTC() ||
-                 billCycleDay.getDayOfMonthLocal() != currentAccount.getBillCycleDay().getDayOfMonthLocal())) {
-                throw new IllegalArgumentException(String.format("Killbill doesn't support updating the account BCD yet: new=%s, current=%s",
-                                                                 billCycleDay, currentAccount.getBillCycleDay()));
-            }
-        } else if (billCycleDay != null) {
+        if (billCycleDayLocal != null && billCycleDayLocal != 0 && currentAccount.getBillCycleDayLocal() != 0 && !billCycleDayLocal.equals(currentAccount.getBillCycleDayLocal())) {
+            throw new IllegalArgumentException(String.format("Killbill doesn't support updating the account BCD yet: new=%s, current=%s",
+                                                             billCycleDayLocal, currentAccount.getBillCycleDayLocal()));
+        } else if (billCycleDayLocal != null && billCycleDayLocal != 0) {
             // Junction sets it
-            accountData.setBillCycleDay(billCycleDay);
+            accountData.setBillCycleDayLocal(billCycleDayLocal);
         } else {
             // Default to current value
-            accountData.setBillCycleDay(currentAccount.getBillCycleDay());
+            accountData.setBillCycleDayLocal(currentAccount.getBillCycleDayLocal());
         }
 
         // Set all updatable fields with the new values if non null, otherwise defaults to the current values
@@ -305,7 +300,7 @@ public class DefaultAccount extends EntityBase implements Account {
                ", firstNameLength=" + firstNameLength +
                ", phone=" + phone +
                ", currency=" + currency +
-               ", billCycleDay=" + billCycleDay +
+               ", billCycleDayLocal=" + billCycleDayLocal +
                ", paymentMethodId=" + paymentMethodId +
                ", timezone=" + timeZone +
                ", locale=" + locale +
@@ -327,16 +322,19 @@ public class DefaultAccount extends EntityBase implements Account {
         if (o == null || getClass() != o.getClass()) {
             return false;
         }
+        if (!super.equals(o)) {
+            return false;
+        }
 
         final DefaultAccount that = (DefaultAccount) o;
 
-        if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) {
+        if (!billCycleDayLocal.equals(that.billCycleDayLocal)) {
             return false;
         }
-        if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) {
+        if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) {
             return false;
         }
-        if (billCycleDay != null ? !billCycleDay.equals(that.billCycleDay) : that.billCycleDay != null) {
+        if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) {
             return false;
         }
         if (city != null ? !city.equals(that.city) : that.city != null) {
@@ -393,12 +391,13 @@ public class DefaultAccount extends EntityBase implements Account {
 
     @Override
     public int hashCode() {
-        int result = externalKey != null ? externalKey.hashCode() : 0;
+        int result = super.hashCode();
+        result = 31 * result + (externalKey != null ? externalKey.hashCode() : 0);
         result = 31 * result + (email != null ? email.hashCode() : 0);
         result = 31 * result + (name != null ? name.hashCode() : 0);
         result = 31 * result + (firstNameLength != null ? firstNameLength.hashCode() : 0);
         result = 31 * result + (currency != null ? currency.hashCode() : 0);
-        result = 31 * result + (billCycleDay != null ? billCycleDay.hashCode() : 0);
+        result = 31 * result + billCycleDayLocal;
         result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
         result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
         result = 31 * result + (locale != null ? locale.hashCode() : 0);
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
index 5c92e84..45f7372 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
@@ -155,10 +155,6 @@ public class DefaultAccountChangeEvent extends DefaultBusInternalEvent implement
                           "billCycleDayLocal",
                           String.valueOf(oldData.getBillingCycleDayLocal()), String.valueOf(newData.getBillingCycleDayLocal()));
 
-        addIfValueChanged(tmpChangedFields,
-                          "billCycleDayUTC",
-                          String.valueOf(oldData.getBillingCycleDayUtc()), String.valueOf(newData.getBillingCycleDayUtc()));
-
         addIfValueChanged(tmpChangedFields, "paymentMethodId",
                           (oldData.getPaymentMethodId() != null) ? oldData.getPaymentMethodId().toString() : null,
                           (newData.getPaymentMethodId() != null) ? newData.getPaymentMethodId().toString() : null);
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
index 5b68254..933fb64 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
@@ -21,8 +21,6 @@ import java.util.UUID;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.BillCycleDay;
-import com.ning.billing.account.api.DefaultBillCycleDay;
 import com.ning.billing.account.dao.AccountModelDao;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.util.events.AccountCreationInternalEvent;
@@ -114,7 +112,7 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
         private final String name;
         private final Integer firstNameLength;
         private final String email;
-        private final DefaultBillCycleDay billCycleDay;
+        private final int billCycleDayLocal;
         private final String currency;
         private final UUID paymentMethodId;
         private final String timeZone;
@@ -135,7 +133,7 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
                  d.getName(),
                  d.getFirstNameLength(),
                  d.getEmail(),
-                 new DefaultBillCycleDay(d.getBillingCycleDayLocal(), d.getBillingCycleDayUtc()),
+                 d.getBillingCycleDayLocal(),
                  d.getCurrency() != null ? d.getCurrency().name() : null,
                  d.getPaymentMethodId(),
                  d.getTimeZone() != null ? d.getTimeZone().getID() : null,
@@ -157,7 +155,7 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
                                   @JsonProperty("name") final String name,
                                   @JsonProperty("firstNameLength") final Integer firstNameLength,
                                   @JsonProperty("email") final String email,
-                                  @JsonProperty("billCycleDay") final DefaultBillCycleDay billCycleDay,
+                                  @JsonProperty("billCycleDayLocal") final int billCycleDayLocal,
                                   @JsonProperty("currency") final String currency,
                                   @JsonProperty("paymentMethodId") final UUID paymentMethodId,
                                   @JsonProperty("timeZone") final String timeZone,
@@ -172,12 +170,11 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
                                   @JsonProperty("phone") final String phone,
                                   @JsonProperty("isMigrated") final boolean isMigrated,
                                   @JsonProperty("isNotifiedForInvoices") final boolean isNotifiedForInvoices) {
-            super();
             this.externalKey = externalKey;
             this.name = name;
             this.firstNameLength = firstNameLength;
             this.email = email;
-            this.billCycleDay = billCycleDay;
+            this.billCycleDayLocal = billCycleDayLocal;
             this.currency = currency;
             this.paymentMethodId = paymentMethodId;
             this.timeZone = timeZone;
@@ -215,8 +212,8 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
         }
 
         @Override
-        public BillCycleDay getBillCycleDay() {
-            return billCycleDay;
+        public Integer getBillCycleDayLocal() {
+            return billCycleDayLocal;
         }
 
         @Override
@@ -298,180 +295,99 @@ public class DefaultAccountCreationEvent extends DefaultBusInternalEvent impleme
         }
 
         @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result
-                     + ((address1 == null) ? 0 : address1.hashCode());
-            result = prime * result
-                     + ((address2 == null) ? 0 : address2.hashCode());
-            result = prime * result
-                     + ((billCycleDay == null) ? 0 : billCycleDay.hashCode());
-            result = prime * result + ((city == null) ? 0 : city.hashCode());
-            result = prime * result
-                     + ((companyName == null) ? 0 : companyName.hashCode());
-            result = prime * result
-                     + ((country == null) ? 0 : country.hashCode());
-            result = prime * result
-                     + ((currency == null) ? 0 : currency.hashCode());
-            result = prime * result + ((email == null) ? 0 : email.hashCode());
-            result = prime * result
-                     + ((externalKey == null) ? 0 : externalKey.hashCode());
-            result = prime
-                     * result
-                     + ((firstNameLength == null) ? 0 : firstNameLength
-                    .hashCode());
-            result = prime * result
-                     + ((locale == null) ? 0 : locale.hashCode());
-            result = prime * result + ((name == null) ? 0 : name.hashCode());
-            result = prime
-                     * result
-                     + ((paymentMethodId == null) ? 0 : paymentMethodId
-                    .hashCode());
-            result = prime * result + ((phone == null) ? 0 : phone.hashCode());
-            result = prime * result
-                     + ((postalCode == null) ? 0 : postalCode.hashCode());
-            result = prime
-                     * result
-                     + ((stateOrProvince == null) ? 0 : stateOrProvince
-                    .hashCode());
-            result = prime * result
-                     + ((timeZone == null) ? 0 : timeZone.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
+        public boolean equals(final Object o) {
+            if (this == o) {
                 return true;
             }
-            if (obj == null) {
+            if (o == null || getClass() != o.getClass()) {
                 return false;
             }
-            if (getClass() != obj.getClass()) {
+
+            final DefaultAccountData that = (DefaultAccountData) o;
+
+            if (billCycleDayLocal != that.billCycleDayLocal) {
                 return false;
             }
-            final DefaultAccountData other = (DefaultAccountData) obj;
-            if (address1 == null) {
-                if (other.address1 != null) {
-                    return false;
-                }
-            } else if (!address1.equals(other.address1)) {
+            if (isMigrated != that.isMigrated) {
                 return false;
             }
-            if (address2 == null) {
-                if (other.address2 != null) {
-                    return false;
-                }
-            } else if (!address2.equals(other.address2)) {
+            if (isNotifiedForInvoices != that.isNotifiedForInvoices) {
                 return false;
             }
-            if (billCycleDay == null) {
-                if (other.billCycleDay != null) {
-                    return false;
-                }
-            } else if (!billCycleDay.equals(other.billCycleDay)) {
+            if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) {
                 return false;
             }
-            if (city == null) {
-                if (other.city != null) {
-                    return false;
-                }
-            } else if (!city.equals(other.city)) {
+            if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) {
                 return false;
             }
-            if (companyName == null) {
-                if (other.companyName != null) {
-                    return false;
-                }
-            } else if (!companyName.equals(other.companyName)) {
+            if (city != null ? !city.equals(that.city) : that.city != null) {
                 return false;
             }
-            if (country == null) {
-                if (other.country != null) {
-                    return false;
-                }
-            } else if (!country.equals(other.country)) {
+            if (companyName != null ? !companyName.equals(that.companyName) : that.companyName != null) {
                 return false;
             }
-            if (currency == null) {
-                if (other.currency != null) {
-                    return false;
-                }
-            } else if (!currency.equals(other.currency)) {
+            if (country != null ? !country.equals(that.country) : that.country != null) {
                 return false;
             }
-            if (email == null) {
-                if (other.email != null) {
-                    return false;
-                }
-            } else if (!email.equals(other.email)) {
+            if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
                 return false;
             }
-            if (externalKey == null) {
-                if (other.externalKey != null) {
-                    return false;
-                }
-            } else if (!externalKey.equals(other.externalKey)) {
+            if (email != null ? !email.equals(that.email) : that.email != null) {
                 return false;
             }
-            if (firstNameLength == null) {
-                if (other.firstNameLength != null) {
-                    return false;
-                }
-            } else if (!firstNameLength.equals(other.firstNameLength)) {
+            if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
                 return false;
             }
-            if (locale == null) {
-                if (other.locale != null) {
-                    return false;
-                }
-            } else if (!locale.equals(other.locale)) {
+            if (firstNameLength != null ? !firstNameLength.equals(that.firstNameLength) : that.firstNameLength != null) {
                 return false;
             }
-            if (name == null) {
-                if (other.name != null) {
-                    return false;
-                }
-            } else if (!name.equals(other.name)) {
+            if (locale != null ? !locale.equals(that.locale) : that.locale != null) {
                 return false;
             }
-            if (paymentMethodId == null) {
-                if (other.paymentMethodId != null) {
-                    return false;
-                }
-            } else if (!paymentMethodId.equals(other.paymentMethodId)) {
+            if (name != null ? !name.equals(that.name) : that.name != null) {
                 return false;
             }
-            if (phone == null) {
-                if (other.phone != null) {
-                    return false;
-                }
-            } else if (!phone.equals(other.phone)) {
+            if (paymentMethodId != null ? !paymentMethodId.equals(that.paymentMethodId) : that.paymentMethodId != null) {
                 return false;
             }
-            if (postalCode == null) {
-                if (other.postalCode != null) {
-                    return false;
-                }
-            } else if (!postalCode.equals(other.postalCode)) {
+            if (phone != null ? !phone.equals(that.phone) : that.phone != null) {
                 return false;
             }
-            if (stateOrProvince == null) {
-                if (other.stateOrProvince != null) {
-                    return false;
-                }
-            } else if (!stateOrProvince.equals(other.stateOrProvince)) {
+            if (postalCode != null ? !postalCode.equals(that.postalCode) : that.postalCode != null) {
                 return false;
             }
-            if (timeZone == null) {
-                if (other.timeZone != null) {
-                    return false;
-                }
-            } else if (!timeZone.equals(other.timeZone)) {
+            if (stateOrProvince != null ? !stateOrProvince.equals(that.stateOrProvince) : that.stateOrProvince != null) {
                 return false;
             }
+            if (timeZone != null ? !timeZone.equals(that.timeZone) : that.timeZone != null) {
+                return false;
+            }
+
             return true;
         }
+
+        @Override
+        public int hashCode() {
+            int result = externalKey != null ? externalKey.hashCode() : 0;
+            result = 31 * result + (name != null ? name.hashCode() : 0);
+            result = 31 * result + (firstNameLength != null ? firstNameLength.hashCode() : 0);
+            result = 31 * result + (email != null ? email.hashCode() : 0);
+            result = 31 * result + billCycleDayLocal;
+            result = 31 * result + (currency != null ? currency.hashCode() : 0);
+            result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
+            result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
+            result = 31 * result + (locale != null ? locale.hashCode() : 0);
+            result = 31 * result + (address1 != null ? address1.hashCode() : 0);
+            result = 31 * result + (address2 != null ? address2.hashCode() : 0);
+            result = 31 * result + (companyName != null ? companyName.hashCode() : 0);
+            result = 31 * result + (city != null ? city.hashCode() : 0);
+            result = 31 * result + (stateOrProvince != null ? stateOrProvince.hashCode() : 0);
+            result = 31 * result + (postalCode != null ? postalCode.hashCode() : 0);
+            result = 31 * result + (country != null ? country.hashCode() : 0);
+            result = 31 * result + (phone != null ? phone.hashCode() : 0);
+            result = 31 * result + (isMigrated ? 1 : 0);
+            result = 31 * result + (isNotifiedForInvoices ? 1 : 0);
+            return result;
+        }
     }
 }
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountModelDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountModelDao.java
index b5a3398..b1961da 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountModelDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountModelDao.java
@@ -38,7 +38,6 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
     private Integer firstNameLength;
     private Currency currency;
     private int billingCycleDayLocal;
-    private int billingCycleDayUtc;
     private UUID paymentMethodId;
     private DateTimeZone timeZone;
     private String locale;
@@ -57,7 +56,7 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
 
     public AccountModelDao(final UUID id, final DateTime createdDate, final DateTime updatedDate, final String externalKey,
                            final String email, final String name, final Integer firstNameLength, final Currency currency,
-                           final int billingCycleDayLocal, final int billingCycleDayUtc, final UUID paymentMethodId, final DateTimeZone timeZone,
+                           final int billingCycleDayLocal, final UUID paymentMethodId, final DateTimeZone timeZone,
                            final String locale, final String address1, final String address2, final String companyName,
                            final String city, final String stateOrProvince, final String country, final String postalCode,
                            final String phone, final Boolean migrated, final Boolean notifiedForInvoices) {
@@ -68,7 +67,6 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
         this.firstNameLength = firstNameLength;
         this.currency = currency;
         this.billingCycleDayLocal = billingCycleDayLocal;
-        this.billingCycleDayUtc = billingCycleDayUtc;
         this.paymentMethodId = paymentMethodId;
         this.timeZone = timeZone;
         this.locale = locale;
@@ -86,8 +84,8 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
 
     public AccountModelDao(final UUID id, @Nullable final DateTime createdDate, final DateTime updatedDate, final AccountData account) {
         this(id, createdDate, updatedDate, account.getExternalKey(),
-             account.getEmail(), account.getName(), account.getFirstNameLength(), account.getCurrency(), account.getBillCycleDay() == null ? 0 : account.getBillCycleDay().getDayOfMonthLocal(),
-             account.getBillCycleDay() == null ? 0 : account.getBillCycleDay().getDayOfMonthUTC(), account.getPaymentMethodId(), account.getTimeZone(), account.getLocale(), account.getAddress1(), account.getAddress2(),
+             account.getEmail(), account.getName(), account.getFirstNameLength(), account.getCurrency(),
+             account.getBillCycleDayLocal() == null ? 0 : account.getBillCycleDayLocal(), account.getPaymentMethodId(), account.getTimeZone(), account.getLocale(), account.getAddress1(), account.getAddress2(),
              account.getCompanyName(), account.getCity(), account.getStateOrProvince(), account.getCountry(), account.getPostalCode(),
              account.getPhone(), account.isMigrated(), account.isNotifiedForInvoices());
     }
@@ -120,14 +118,10 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
         return currency;
     }
 
-    public int getBillingCycleDayLocal() {
+    public Integer getBillingCycleDayLocal() {
         return billingCycleDayLocal;
     }
 
-    public int getBillingCycleDayUtc() {
-        return billingCycleDayUtc;
-    }
-
     public UUID getPaymentMethodId() {
         return paymentMethodId;
     }
@@ -192,7 +186,6 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
         sb.append(", firstNameLength=").append(firstNameLength);
         sb.append(", currency=").append(currency);
         sb.append(", billingCycleDayLocal=").append(billingCycleDayLocal);
-        sb.append(", billingCycleDayUTC=").append(billingCycleDayUtc);
         sb.append(", paymentMethodId=").append(paymentMethodId);
         sb.append(", timeZone=").append(timeZone);
         sb.append(", locale='").append(locale).append('\'');
@@ -227,9 +220,6 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
         if (billingCycleDayLocal != that.billingCycleDayLocal) {
             return false;
         }
-        if (billingCycleDayUtc != that.billingCycleDayUtc) {
-            return false;
-        }
         if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) {
             return false;
         }
@@ -297,7 +287,6 @@ public class AccountModelDao extends EntityBase implements EntityModelDao<Accoun
         result = 31 * result + (firstNameLength != null ? firstNameLength.hashCode() : 0);
         result = 31 * result + (currency != null ? currency.hashCode() : 0);
         result = 31 * result + billingCycleDayLocal;
-        result = 31 * result + billingCycleDayUtc;
         result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
         result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
         result = 31 * result + (locale != null ? locale.hashCode() : 0);
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
index 7a61009..5ed297b 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
@@ -11,7 +11,6 @@ tableFields(prefix) ::= <<
 , <prefix>first_name_length
 , <prefix>currency
 , <prefix>billing_cycle_day_local
-, <prefix>billing_cycle_day_utc
 , <prefix>payment_method_id
 , <prefix>time_zone
 , <prefix>locale
@@ -38,7 +37,6 @@ tableValues() ::= <<
 , :firstNameLength
 , :currency
 , :billingCycleDayLocal
-, :billingCycleDayUtc
 , :paymentMethodId
 , :timeZone
 , :locale
@@ -65,7 +63,7 @@ accountRecordIdValueWithComma(prefix) ::= ""
 update() ::= <<
     UPDATE accounts
     SET email = :email, name = :name, first_name_length = :firstNameLength,
-        currency = :currency, billing_cycle_day_local = :billingCycleDayLocal, billing_cycle_day_utc = :billingCycleDayUtc,
+        currency = :currency, billing_cycle_day_local = :billingCycleDayLocal,
         payment_method_id = :paymentMethodId, time_zone = :timeZone, locale = :locale,
         address1 = :address1, address2 = :address2, company_name = :companyName, city = :city, state_or_province = :stateOrProvince,
         country = :country, postal_code = :postalCode, phone = :phone,
diff --git a/account/src/test/java/com/ning/billing/account/AccountTestUtils.java b/account/src/test/java/com/ning/billing/account/AccountTestUtils.java
index b451f8e..8db3b28 100644
--- a/account/src/test/java/com/ning/billing/account/AccountTestUtils.java
+++ b/account/src/test/java/com/ning/billing/account/AccountTestUtils.java
@@ -23,8 +23,6 @@ import org.joda.time.DateTimeZone;
 import org.testng.Assert;
 
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.BillCycleDay;
-import com.ning.billing.account.api.DefaultBillCycleDay;
 import com.ning.billing.account.api.DefaultMutableAccountData;
 import com.ning.billing.account.dao.AccountModelDao;
 import com.ning.billing.catalog.api.Currency;
@@ -51,7 +49,6 @@ public abstract class AccountTestUtils {
         Assert.assertEquals(retrievedAccount.getFirstNameLength(), account.getFirstNameLength());
         Assert.assertEquals(retrievedAccount.getCurrency(), account.getCurrency());
         Assert.assertEquals(retrievedAccount.getBillingCycleDayLocal(), account.getBillingCycleDayLocal());
-        Assert.assertEquals(retrievedAccount.getBillingCycleDayUtc(), account.getBillingCycleDayUtc());
         Assert.assertEquals(retrievedAccount.getPaymentMethodId(), account.getPaymentMethodId());
         Assert.assertEquals(retrievedAccount.getTimeZone(), account.getTimeZone());
         Assert.assertEquals(retrievedAccount.getLocale(), account.getLocale());
@@ -96,7 +93,6 @@ public abstract class AccountTestUtils {
         final DateTimeZone timeZone = DateTimeZone.forID("America/Los_Angeles");
         final int firstNameLength = name.length();
         final Currency currency = Currency.MXN;
-        final BillCycleDay billCycleDay = new DefaultBillCycleDay(billCycleDayLocal, billCycleDayUTC);
         final UUID paymentMethodId = UUID.randomUUID();
         final String address1 = UUID.randomUUID().toString();
         final String address2 = UUID.randomUUID().toString();
@@ -107,7 +103,7 @@ public abstract class AccountTestUtils {
         final String postalCode = UUID.randomUUID().toString().substring(0, 4);
 
         return new DefaultMutableAccountData(externalKey, email, name, firstNameLength, currency,
-                                             billCycleDay, paymentMethodId, timeZone,
+                                             billCycleDayLocal, paymentMethodId, timeZone,
                                              locale, address1, address2, companyName, city, stateOrProvince,
                                              country, postalCode, phone, false, true);
     }
diff --git a/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java b/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java
index 1f7d920..0c44818 100644
--- a/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java
+++ b/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApi.java
@@ -26,7 +26,6 @@ import org.testng.annotations.Test;
 import com.ning.billing.account.AccountTestSuiteWithEmbeddedDB;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.account.api.DefaultAccount;
 import com.ning.billing.account.api.DefaultMutableAccountData;
 import com.ning.billing.account.api.MigrationAccountData;
@@ -55,7 +54,7 @@ public class TestDefaultAccountUserApi extends AccountTestSuiteWithEmbeddedDB {
         final Account account = accountUserApi.createAccount(new DefaultAccount(createTestAccount()), callContext);
 
         // Update the address and leave other fields null
-        final MutableAccountData mutableAccountData = new DefaultMutableAccountData(null, null, null, 0, null, null, null,
+        final MutableAccountData mutableAccountData = new DefaultMutableAccountData(null, null, null, 0, null, 0, null,
                                                                                     null, null, null, null, null, null,
                                                                                     null, null, null, null, false, false);
         final String newAddress1 = UUID.randomUUID().toString();
@@ -68,8 +67,7 @@ public class TestDefaultAccountUserApi extends AccountTestSuiteWithEmbeddedDB {
         Assert.assertEquals(retrievedAccount.getAddress2(), account.getAddress2());
         Assert.assertEquals(retrievedAccount.getCurrency(), account.getCurrency());
         Assert.assertEquals(retrievedAccount.getExternalKey(), account.getExternalKey());
-        Assert.assertEquals(retrievedAccount.getBillCycleDay().getDayOfMonthLocal(), account.getBillCycleDay().getDayOfMonthLocal());
-        Assert.assertEquals(retrievedAccount.getBillCycleDay().getDayOfMonthUTC(), account.getBillCycleDay().getDayOfMonthUTC());
+        Assert.assertEquals(retrievedAccount.getBillCycleDayLocal(), account.getBillCycleDayLocal());
     }
 
     @Test(groups = "slow", expectedExceptions = IllegalArgumentException.class)
@@ -77,17 +75,7 @@ public class TestDefaultAccountUserApi extends AccountTestSuiteWithEmbeddedDB {
         final Account account = accountUserApi.createAccount(new DefaultAccount(createTestAccount()), callContext);
 
         final MutableAccountData otherAccount = new DefaultAccount(account.getId(), account).toMutableAccountData();
-        otherAccount.setBillCycleDay(new BillCycleDay() {
-            @Override
-            public int getDayOfMonthUTC() {
-                return account.getBillCycleDay().getDayOfMonthUTC() + 2;
-            }
-
-            @Override
-            public int getDayOfMonthLocal() {
-                return account.getBillCycleDay().getDayOfMonthLocal() + 2;
-            }
-        });
+        otherAccount.setBillCycleDayLocal(account.getBillCycleDayLocal() + 2);
 
         accountUserApi.updateAccount(new DefaultAccount(account.getId(), otherAccount), callContext);
     }
diff --git a/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApiWithMocks.java b/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApiWithMocks.java
index 8eb1f26..5de0e23 100644
--- a/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApiWithMocks.java
+++ b/account/src/test/java/com/ning/billing/account/api/user/TestDefaultAccountUserApiWithMocks.java
@@ -27,10 +27,8 @@ import org.testng.annotations.Test;
 import com.ning.billing.account.AccountTestSuiteNoDB;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.AccountEmail;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.account.api.DefaultAccount;
 import com.ning.billing.account.api.DefaultAccountEmail;
-import com.ning.billing.account.api.DefaultBillCycleDay;
 import com.ning.billing.account.dao.AccountDao;
 import com.ning.billing.account.dao.AccountModelDao;
 import com.ning.billing.account.dao.MockAccountDao;
@@ -65,7 +63,7 @@ public class TestDefaultAccountUserApiWithMocks extends AccountTestSuiteNoDB {
         final String name = UUID.randomUUID().toString();
         final Integer firstNameLength = Integer.MAX_VALUE;
         final Currency currency = Currency.BRL;
-        final BillCycleDay billCycleDay = new DefaultBillCycleDay(Integer.MIN_VALUE, Integer.MAX_VALUE);
+        final Integer billCycleDay = Integer.MAX_VALUE;
         final UUID paymentMethodId = UUID.randomUUID();
         final DateTimeZone timeZone = DateTimeZone.UTC;
         final String locale = UUID.randomUUID().toString();
@@ -91,8 +89,7 @@ public class TestDefaultAccountUserApiWithMocks extends AccountTestSuiteNoDB {
         Assert.assertEquals(account.getName(), name);
         Assert.assertEquals(account.getFirstNameLength(), firstNameLength);
         Assert.assertEquals(account.getCurrency(), currency);
-        Assert.assertEquals(account.getBillingCycleDayLocal(), billCycleDay.getDayOfMonthLocal());
-        Assert.assertEquals(account.getBillingCycleDayUtc(), billCycleDay.getDayOfMonthUTC());
+        Assert.assertEquals(account.getBillingCycleDayLocal(), (Integer) billCycleDay);
         Assert.assertEquals(account.getPaymentMethodId(), paymentMethodId);
         Assert.assertEquals(account.getTimeZone(), timeZone);
         Assert.assertEquals(account.getLocale(), locale);
diff --git a/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java b/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java
index be2ebc1..d0f82d7 100644
--- a/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java
+++ b/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java
@@ -24,7 +24,6 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.ning.billing.account.AccountTestSuiteNoDB;
-import com.ning.billing.account.api.DefaultBillCycleDay;
 import com.ning.billing.account.api.DefaultChangedField;
 import com.ning.billing.account.api.user.DefaultAccountCreationEvent.DefaultAccountData;
 import com.ning.billing.util.events.AccountChangeInternalEvent;
@@ -51,7 +50,7 @@ public class TestEventJson extends AccountTestSuiteNoDB {
 
     @Test(groups = "fast")
     public void testAccountCreationEvent() throws Exception {
-        final DefaultAccountData data = new DefaultAccountData("dsfdsf", "bobo", 3, "bobo@yahoo.com", new DefaultBillCycleDay(12), "USD", UUID.randomUUID(),
+        final DefaultAccountData data = new DefaultAccountData("dsfdsf", "bobo", 3, "bobo@yahoo.com", 12, "USD", UUID.randomUUID(),
                                                                "UTC", "US", "21 avenue", "", "Gling", "San Franciso", "CA", "94110", "USA", "4126789887", false, false);
         final DefaultAccountCreationEvent e = new DefaultAccountCreationEvent(data, UUID.randomUUID(), UUID.randomUUID(), 1L, 45L);
         final String json = mapper.writeValueAsString(e);
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
index 7e7d379..d58f6d7 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
@@ -31,7 +31,6 @@ import com.ning.billing.account.AccountTestSuiteWithEmbeddedDB;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.AccountEmail;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.account.api.DefaultAccount;
 import com.ning.billing.account.api.DefaultAccountEmail;
 import com.ning.billing.account.api.MutableAccountData;
@@ -199,49 +198,11 @@ public class TestAccountDao extends AccountTestSuiteWithEmbeddedDB {
     }
 
     @Test(groups = "slow")
-    public void testShouldBeAbleToHandleOtherBCDClass() throws Exception {
-        final AccountModelDao account = createTestAccount();
-        accountDao.create(account, internalCallContext);
-
-        final MutableAccountData otherAccount = new DefaultAccount(account).toMutableAccountData();
-        otherAccount.setAddress1(UUID.randomUUID().toString());
-        otherAccount.setEmail(UUID.randomUUID().toString());
-        // Same BCD, but no .equals method
-        otherAccount.setBillCycleDay(new BillCycleDay() {
-            @Override
-            public int getDayOfMonthUTC() {
-                return account.getBillingCycleDayUtc();
-            }
-
-            @Override
-            public int getDayOfMonthLocal() {
-                return account.getBillingCycleDayLocal();
-            }
-        });
-
-        final AccountModelDao newAccount = new AccountModelDao(account.getId(), otherAccount);
-        accountDao.update(newAccount, internalCallContext);
-
-        final AccountModelDao newFetchedAccount = accountDao.getById(account.getId(), internalCallContext);
-        checkAccountsEqual(newFetchedAccount, newAccount);
-        // Verify it is the same BCD
-        Assert.assertEquals(newFetchedAccount.getBillingCycleDayUtc(), account.getBillingCycleDayUtc());
-        Assert.assertEquals(newFetchedAccount.getBillingCycleDayLocal(), account.getBillingCycleDayLocal());
-    }
-
-    @Test(groups = "slow")
-    public void testShouldBeAbleToHandleBCDOfZeroZero() throws Exception {
+    public void testShouldBeAbleToHandleBCDOfZero() throws Exception {
         final AccountModelDao account = createTestAccount(0);
         accountDao.create(account, internalCallContext);
 
-        final MutableAccountData otherAccount = new DefaultAccount(account).toMutableAccountData();
-        // Set BCD to null
-        otherAccount.setBillCycleDay(null);
-
-        final AccountModelDao newAccount = new AccountModelDao(account.getId(), otherAccount);
-        accountDao.update(newAccount, internalCallContext);
-
-        // Same BCD (zero/zero)
+        // Same BCD (zero)
         final AccountModelDao retrievedAccount = accountDao.getById(account.getId(), internalCallContext);
         checkAccountsEqual(retrievedAccount, account);
     }
diff --git a/api/src/main/java/com/ning/billing/account/api/AccountData.java b/api/src/main/java/com/ning/billing/account/api/AccountData.java
index 77ddfef..e627f86 100644
--- a/api/src/main/java/com/ning/billing/account/api/AccountData.java
+++ b/api/src/main/java/com/ning/billing/account/api/AccountData.java
@@ -64,7 +64,7 @@ public interface AccountData {
      *
      * @see  com.ning.billing.catalog.api.BillingAlignment
      */
-    public BillCycleDay getBillCycleDay();
+    public Integer getBillCycleDayLocal();
 
     /**
      *
diff --git a/api/src/main/java/com/ning/billing/account/api/DefaultMutableAccountData.java b/api/src/main/java/com/ning/billing/account/api/DefaultMutableAccountData.java
index ffe7011..960978b 100644
--- a/api/src/main/java/com/ning/billing/account/api/DefaultMutableAccountData.java
+++ b/api/src/main/java/com/ning/billing/account/api/DefaultMutableAccountData.java
@@ -29,7 +29,7 @@ public class DefaultMutableAccountData implements MutableAccountData {
     private String name;
     private int firstNameLength;
     private Currency currency;
-    private BillCycleDay billCycleDay;
+    private int billCycleDayLocal;
     private UUID paymentMethodId;
     private DateTimeZone timeZone;
     private String locale;
@@ -45,19 +45,18 @@ public class DefaultMutableAccountData implements MutableAccountData {
     private boolean isNotifiedForInvoices;
 
     public DefaultMutableAccountData(final String externalKey, final String email, final String name,
-                                     final int firstNameLength, final Currency currency, final BillCycleDay billCycleDay,
+                                     final int firstNameLength, final Currency currency, final int billCycleDayLocal,
                                      final UUID paymentMethodId, final DateTimeZone timeZone,
                                      final String locale, final String address1, final String address2,
                                      final String companyName, final String city, final String stateOrProvince,
                                      final String country, final String postalCode, final String phone,
                                      final boolean isMigrated, final boolean isNotifiedForInvoices) {
-        super();
         this.externalKey = externalKey;
         this.email = email;
         this.name = name;
         this.firstNameLength = firstNameLength;
         this.currency = currency;
-        this.billCycleDay = billCycleDay;
+        this.billCycleDayLocal = billCycleDayLocal;
         this.paymentMethodId = paymentMethodId;
         this.timeZone = timeZone;
         this.locale = locale;
@@ -74,13 +73,12 @@ public class DefaultMutableAccountData implements MutableAccountData {
     }
 
     public DefaultMutableAccountData(final AccountData accountData) {
-        super();
         this.externalKey = accountData.getExternalKey();
         this.email = accountData.getEmail();
         this.name = accountData.getName();
         this.firstNameLength = accountData.getFirstNameLength();
         this.currency = accountData.getCurrency();
-        this.billCycleDay = accountData.getBillCycleDay();
+        this.billCycleDayLocal = accountData.getBillCycleDayLocal();
         this.paymentMethodId = accountData.getPaymentMethodId();
         this.timeZone = accountData.getTimeZone();
         this.locale = accountData.getLocale();
@@ -122,8 +120,8 @@ public class DefaultMutableAccountData implements MutableAccountData {
     }
 
     @Override
-    public BillCycleDay getBillCycleDay() {
-        return billCycleDay;
+    public Integer getBillCycleDayLocal() {
+        return billCycleDayLocal;
     }
 
     @Override
@@ -217,8 +215,8 @@ public class DefaultMutableAccountData implements MutableAccountData {
     }
 
     @Override
-    public void setBillCycleDay(final BillCycleDay billCycleDay) {
-        this.billCycleDay = billCycleDay;
+    public void setBillCycleDayLocal(final int billCycleDayLocal) {
+        this.billCycleDayLocal = billCycleDayLocal;
     }
 
     @Override
diff --git a/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java b/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java
index 48c464d..b85c701 100644
--- a/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java
+++ b/api/src/main/java/com/ning/billing/account/api/MutableAccountData.java
@@ -65,11 +65,11 @@ public interface MutableAccountData extends AccountData {
     public void setCurrency(Currency currency);
 
     /**
-     * Sets the account billCycleDay
+     * Sets the account billCycleDayLocal
      *
-     * @param billCycleDay
+     * @param billCycleDayLocal
      */
-    public void setBillCycleDay(BillCycleDay billCycleDay);
+    public void setBillCycleDayLocal(int billCycleDayLocal);
 
     /**
      * Sets the UUID of the default paymentMethod
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java
index bc58705..c27ac26 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java
@@ -15,20 +15,14 @@
  */
 package com.ning.billing.beatrix.integration;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
 import java.math.BigDecimal;
 import java.util.List;
 
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
-import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.api.TestApiListener.NextEvent;
 import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck;
 import com.ning.billing.catalog.api.BillingPeriod;
@@ -43,6 +37,10 @@ import com.ning.billing.invoice.api.InvoiceItemType;
 
 import com.google.common.collect.ImmutableList;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
 public class TestBundleTransfer extends TestIntegrationBase {
 
 
@@ -156,11 +154,11 @@ public class TestBundleTransfer extends TestIntegrationBase {
         assertListenerStatus();
 
         // Verify the BCD of the new account
-        final BillCycleDay oldBCD = accountUserApi.getAccountById(account.getId(), callContext).getBillCycleDay();
-        final BillCycleDay newBCD = accountUserApi.getAccountById(newAccount.getId(), callContext).getBillCycleDay();
-        assertEquals(oldBCD.getDayOfMonthUTC(), 1);
+        final Integer oldBCD = accountUserApi.getAccountById(account.getId(), callContext).getBillCycleDayLocal();
+        final Integer newBCD = accountUserApi.getAccountById(newAccount.getId(), callContext).getBillCycleDayLocal();
+        assertEquals(oldBCD, (Integer) 1);
         // Day of the transfer
-        assertEquals(newBCD.getDayOfMonthUTC(), 3);
+        assertEquals(newBCD, (Integer) 3);
 
         final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(newAccount.getId(), callContext);
         assertEquals(invoices.size(), 1);
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java
index a9f1a58..af1f885 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java
@@ -19,8 +19,8 @@ package com.ning.billing.beatrix.integration;
 import java.math.BigDecimal;
 import java.util.List;
 
+import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
-import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
 import com.ning.billing.account.api.Account;
@@ -52,7 +52,7 @@ public class TestEntitlement extends TestIntegrationBase {
         final Account account = createAccountWithPaymentMethod(getAccountData(1));
 
         // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
-        clock.setDeltaFromReality(today.toDateTimeAtCurrentTime().getMillis() - clock.getUTCNow().getMillis());
+        clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
         final SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever", callContext);
 
         final String productName = "Shotgun";
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index 6de9d54..6886bf6 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -26,7 +26,6 @@ import javax.annotation.Nullable;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
-import org.skife.jdbi.v2.IDBI;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -72,7 +71,6 @@ import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.invoice.model.InvoicingConfiguration;
 import com.ning.billing.junction.plumbing.api.BlockingSubscription;
 import com.ning.billing.mock.MockAccountBuilder;
-import com.ning.billing.mock.api.MockBillCycleDay;
 import com.ning.billing.overdue.OverdueUserApi;
 import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
 import com.ning.billing.payment.api.Payment;
@@ -81,7 +79,6 @@ import com.ning.billing.payment.api.PaymentApiException;
 import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
 import com.ning.billing.util.api.TagUserApi;
-import com.ning.billing.util.clock.ClockMock;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.junction.BlockingInternalApi;
 import com.ning.billing.util.svcsapi.bus.BusService;
@@ -336,7 +333,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
                                        .migrated(false)
                                        .isNotifiedForInvoices(false)
                                        .externalKey(UUID.randomUUID().toString().substring(1, 8))
-                                       .billingCycleDay(new MockBillCycleDay(billingDay))
+                                       .billingCycleDayLocal(billingDay)
                                        .currency(Currency.USD)
                                        .paymentMethodId(UUID.randomUUID())
                                        .timeZone(DateTimeZone.UTC)
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/util/AccountChecker.java b/beatrix/src/test/java/com/ning/billing/beatrix/util/AccountChecker.java
index 6ceb589..6dc368b 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/util/AccountChecker.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/util/AccountChecker.java
@@ -18,7 +18,6 @@ package com.ning.billing.beatrix.util;
 
 import java.util.UUID;
 
-
 import javax.inject.Inject;
 
 import org.slf4j.Logger;
@@ -37,14 +36,12 @@ public class AccountChecker {
     private final AccountUserApi accountApi;
     private final AuditChecker auditChecker;
 
-
     @Inject
     public AccountChecker(final AccountUserApi accountApi, final AuditChecker auditChecker) {
         this.accountApi = accountApi;
         this.auditChecker = auditChecker;
     }
 
-
     public Account checkAccount(final UUID accountId, final AccountData accountData, final CallContext context) throws Exception {
 
         final Account account = accountApi.getAccountById(accountId, context);
@@ -56,8 +53,7 @@ public class AccountChecker {
             Assert.assertEquals(account.getPhone(), accountData.getPhone());
             Assert.assertEquals(account.isNotifiedForInvoices(), accountData.isNotifiedForInvoices());
             Assert.assertEquals(account.getExternalKey(), accountData.getExternalKey());
-            Assert.assertEquals(account.getBillCycleDay().getDayOfMonthUTC(), accountData.getBillCycleDay().getDayOfMonthUTC());
-            Assert.assertEquals(account.getBillCycleDay().getDayOfMonthLocal(), accountData.getBillCycleDay().getDayOfMonthLocal());
+            Assert.assertEquals(account.getBillCycleDayLocal(), accountData.getBillCycleDayLocal());
             Assert.assertEquals(account.getCurrency(), accountData.getCurrency());
             Assert.assertEquals(account.getTimeZone(), accountData.getTimeZone());
             // createWithPaymentMethod will update the paymentMethod
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/DefaultEntitlementTestInitializer.java b/entitlement/src/test/java/com/ning/billing/entitlement/DefaultEntitlementTestInitializer.java
index 114b537..ac1c357 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/DefaultEntitlementTestInitializer.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/DefaultEntitlementTestInitializer.java
@@ -22,12 +22,10 @@ import java.util.UUID;
 
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
-import org.mockito.Mockito;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.api.TestApiListener;
 import com.ning.billing.api.TestListenerStatus;
 import com.ning.billing.catalog.DefaultCatalogService;
@@ -63,8 +61,6 @@ public class DefaultEntitlementTestInitializer implements EntitlementTestInitial
     }
 
     public AccountData initAccountData() {
-        final BillCycleDay billCycleDay = Mockito.mock(BillCycleDay.class);
-        Mockito.when(billCycleDay.getDayOfMonthUTC()).thenReturn(1);
         final AccountData accountData = new MockAccountBuilder().name(UUID.randomUUID().toString())
                                                                 .firstNameLength(6)
                                                                 .email(UUID.randomUUID().toString())
@@ -72,7 +68,7 @@ public class DefaultEntitlementTestInitializer implements EntitlementTestInitial
                                                                 .migrated(false)
                                                                 .isNotifiedForInvoices(false)
                                                                 .externalKey(UUID.randomUUID().toString())
-                                                                .billingCycleDay(billCycleDay)
+                                                                .billingCycleDayLocal(1)
                                                                 .currency(Currency.USD)
                                                                 .paymentMethodId(UUID.randomUUID())
                                                                 .timeZone(DateTimeZone.forID("Europe/Paris"))
diff --git a/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
index 6102259..b006da1 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/generator/DefaultInvoiceGenerator.java
@@ -349,7 +349,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
             if (!startDate.isAfter(targetDate)) {
                 final LocalDate endDate = (nextEvent == null) ? null : new LocalDate(nextEvent.getEffectiveDate(), nextEvent.getTimeZone());
 
-                final int billCycleDayLocal = thisEvent.getBillCycleDay().getDayOfMonthLocal();
+                final int billCycleDayLocal = thisEvent.getBillCycleDayLocal();
 
                 final List<RecurringInvoiceItemData> itemData;
                 try {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java b/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java
index ab14bf7..0fc291f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/generator/TestDefaultInvoiceGenerator.java
@@ -16,8 +16,6 @@
 
 package com.ning.billing.invoice.generator;
 
-import static com.ning.billing.invoice.TestInvoiceHelper.*;
-
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -66,6 +64,28 @@ import com.ning.billing.util.svcapi.junction.BillingEvent;
 import com.ning.billing.util.svcapi.junction.BillingEventSet;
 import com.ning.billing.util.svcapi.junction.BillingModeType;
 
+import static com.ning.billing.invoice.TestInvoiceHelper.EIGHT;
+import static com.ning.billing.invoice.TestInvoiceHelper.ELEVEN;
+import static com.ning.billing.invoice.TestInvoiceHelper.FIFTEEN;
+import static com.ning.billing.invoice.TestInvoiceHelper.FIVE;
+import static com.ning.billing.invoice.TestInvoiceHelper.FORTY;
+import static com.ning.billing.invoice.TestInvoiceHelper.FOURTEEN;
+import static com.ning.billing.invoice.TestInvoiceHelper.NINETEEN;
+import static com.ning.billing.invoice.TestInvoiceHelper.NUMBER_OF_DECIMALS;
+import static com.ning.billing.invoice.TestInvoiceHelper.ONE;
+import static com.ning.billing.invoice.TestInvoiceHelper.ONE_HUNDRED;
+import static com.ning.billing.invoice.TestInvoiceHelper.ROUNDING_METHOD;
+import static com.ning.billing.invoice.TestInvoiceHelper.TEN;
+import static com.ning.billing.invoice.TestInvoiceHelper.THIRTEEN;
+import static com.ning.billing.invoice.TestInvoiceHelper.THIRTY;
+import static com.ning.billing.invoice.TestInvoiceHelper.THIRTY_ONE;
+import static com.ning.billing.invoice.TestInvoiceHelper.TWELVE;
+import static com.ning.billing.invoice.TestInvoiceHelper.TWENTY;
+import static com.ning.billing.invoice.TestInvoiceHelper.TWENTY_FIVE;
+import static com.ning.billing.invoice.TestInvoiceHelper.TWENTY_FOUR;
+import static com.ning.billing.invoice.TestInvoiceHelper.TWENTY_SEVEN;
+import static com.ning.billing.invoice.TestInvoiceHelper.TWO;
+import static com.ning.billing.invoice.TestInvoiceHelper.ZERO;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
@@ -155,16 +175,14 @@ public class TestDefaultInvoiceGenerator extends InvoiceTestSuiteNoDB {
 
         // Start date was the 16 local, but was the 17 UTC
         final int bcdLocal = 16;
-        final int bcdUTC = 17;
         final LocalDate startDate = invoiceUtil.buildDate(2012, 7, bcdLocal);
 
         final BillingEventSet events = new MockBillingEventSet();
-        final BillingEvent event = createBillingEvent(sub.getId(), startDate, plan, phase, bcdUTC, bcdLocal);
+        final BillingEvent event = createBillingEvent(sub.getId(), startDate, plan, phase, bcdLocal);
         events.add(event);
 
         // Target date is the next BCD, in local time
         final LocalDate targetDate = invoiceUtil.buildDate(2012, 8, bcdLocal);
-        final DateTimeZone accountTimeZone = DateTimeZone.forID("HST");
         final Invoice invoice = generator.generateInvoice(accountId, events, null, targetDate, Currency.USD);
 
         assertNotNull(invoice);
@@ -181,12 +199,11 @@ public class TestDefaultInvoiceGenerator extends InvoiceTestSuiteNoDB {
         final Subscription sub = createZombieSubscription();
         final Plan plan = new MockPlan("Plan with a single discount phase");
         final PlanPhase phaseEvergreen = createMockMonthlyPlanPhase(EIGHT, PhaseType.DISCOUNT);
-        final DateTimeZone accountTimeZone = DateTimeZone.UTC;
-        final int bcdUTC = 16;
+        final int bcdLocal = 16;
         final LocalDate startDate = invoiceUtil.buildDate(2012, 7, 16);
 
         final BillingEventSet events = new MockBillingEventSet();
-        events.add(createBillingEvent(sub.getId(), startDate, plan, phaseEvergreen, bcdUTC));
+        events.add(createBillingEvent(sub.getId(), startDate, plan, phaseEvergreen, bcdLocal));
 
         // Set a target date of today (start date)
         final LocalDate targetDate = startDate;
@@ -749,12 +766,7 @@ public class TestDefaultInvoiceGenerator extends InvoiceTestSuiteNoDB {
     }
 
     private BillingEvent createBillingEvent(final UUID subscriptionId, final LocalDate startDate,
-                                            final Plan plan, final PlanPhase planPhase, final int billCycleDayUTC) throws CatalogApiException {
-        return createBillingEvent(subscriptionId, startDate, plan, planPhase, billCycleDayUTC, billCycleDayUTC);
-    }
-
-    private BillingEvent createBillingEvent(final UUID subscriptionId, final LocalDate startDate,
-                                            final Plan plan, final PlanPhase planPhase, final int billCycleDayUTC, final int billCycleDayLocal) throws CatalogApiException {
+                                            final Plan plan, final PlanPhase planPhase, final int billCycleDayLocal) throws CatalogApiException {
         final Subscription sub = createZombieSubscription(subscriptionId);
         final Currency currency = Currency.USD;
 
@@ -762,7 +774,7 @@ public class TestDefaultInvoiceGenerator extends InvoiceTestSuiteNoDB {
                                                   planPhase.getFixedPrice() == null ? null : planPhase.getFixedPrice().getPrice(currency),
                                                   planPhase.getRecurringPrice() == null ? null : planPhase.getRecurringPrice().getPrice(currency),
                                                   currency, planPhase.getBillingPeriod(),
-                                                  billCycleDayUTC, billCycleDayLocal, BillingModeType.IN_ADVANCE, "Test", 1L, SubscriptionTransitionType.CREATE);
+                                                  billCycleDayLocal, BillingModeType.IN_ADVANCE, "Test", 1L, SubscriptionTransitionType.CREATE);
     }
 
     private void testInvoiceGeneration(final UUID accountId, final BillingEventSet events, final List<Invoice> existingInvoices,
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
index fc7eda1..bea73f8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -26,8 +26,6 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
 import org.mockito.Mockito;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -123,23 +121,23 @@ public class TestInvoiceDispatcher extends InvoiceTestSuiteWithEmbeddedDB {
         final MockPlan bicycleTrialEvergreen1USD = MockPlan.createBicycleTrialEvergreen1USD();
         events.add(invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2012-05-01T00:03:42.000Z"), bicycleTrialEvergreen1USD,
                                                       new MockPlanPhase(bicycleTrialEvergreen1USD, PhaseType.TRIAL), BigDecimal.ZERO, null, account.getCurrency(), BillingPeriod.NO_BILLING_PERIOD,
-                                                      31, 31, BillingModeType.IN_ADVANCE, "CREATE", 1L, SubscriptionTransitionType.CREATE));
+                                                      31, BillingModeType.IN_ADVANCE, "CREATE", 1L, SubscriptionTransitionType.CREATE));
         // Phase change to evergreen
         events.add(invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2012-05-31T00:03:42.000Z"), bicycleTrialEvergreen1USD,
                                                       new MockPlanPhase(bicycleTrialEvergreen1USD, PhaseType.EVERGREEN), null, new BigDecimal("249.95"), account.getCurrency(), BillingPeriod.MONTHLY,
-                                                      31, 31, BillingModeType.IN_ADVANCE, "PHASE", 2L, SubscriptionTransitionType.PHASE));
+                                                      31, BillingModeType.IN_ADVANCE, "PHASE", 2L, SubscriptionTransitionType.PHASE));
         // Overdue period
         events.add(invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2012-07-15T00:00:00.000Z"), bicycleTrialEvergreen1USD,
                                                       new MockPlanPhase(bicycleTrialEvergreen1USD, PhaseType.EVERGREEN), null, null, account.getCurrency(), BillingPeriod.NO_BILLING_PERIOD,
-                                                      31, 31, BillingModeType.IN_ADVANCE, "", 0L, SubscriptionTransitionType.START_BILLING_DISABLED));
+                                                      31, BillingModeType.IN_ADVANCE, "", 0L, SubscriptionTransitionType.START_BILLING_DISABLED));
         events.add(invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2012-07-25T00:00:00.000Z"), bicycleTrialEvergreen1USD,
                                                       new MockPlanPhase(bicycleTrialEvergreen1USD, PhaseType.EVERGREEN), null, new BigDecimal("249.95"), account.getCurrency(), BillingPeriod.MONTHLY,
-                                                      31, 31, BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.END_BILLING_DISABLED));
+                                                      31, BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.END_BILLING_DISABLED));
         // Upgrade after the overdue period
         final MockPlan jetTrialEvergreen1000USD = MockPlan.createJetTrialEvergreen1000USD();
         events.add(invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2012-07-25T00:04:00.000Z"), jetTrialEvergreen1000USD,
                                                       new MockPlanPhase(jetTrialEvergreen1000USD, PhaseType.EVERGREEN), null, new BigDecimal("1000"), account.getCurrency(), BillingPeriod.MONTHLY,
-                                                      31, 31, BillingModeType.IN_ADVANCE, "CHANGE", 3L, SubscriptionTransitionType.CHANGE));
+                                                      31, BillingModeType.IN_ADVANCE, "CHANGE", 3L, SubscriptionTransitionType.CHANGE));
 
         Mockito.when(billingApi.getBillingEventsForAccountAndUpdateAccountBCD(Mockito.<UUID>any(), Mockito.<InternalCallContext>any())).thenReturn(events);
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
index 215cf57..64bb62e 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
@@ -32,7 +32,6 @@ import org.testng.Assert;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.MockPlan;
 import com.ning.billing.catalog.MockPlanPhase;
 import com.ning.billing.catalog.api.BillingPeriod;
@@ -45,11 +44,8 @@ import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoiceMigrationApi;
 import com.ning.billing.invoice.api.InvoiceNotifier;
 import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.invoice.api.InvoicePaymentApi;
-import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceItemModelDao;
 import com.ning.billing.invoice.dao.InvoiceItemSqlDao;
@@ -57,14 +53,10 @@ import com.ning.billing.invoice.dao.InvoiceModelDao;
 import com.ning.billing.invoice.dao.InvoiceModelDaoHelper;
 import com.ning.billing.invoice.dao.InvoicePaymentModelDao;
 import com.ning.billing.invoice.dao.InvoicePaymentSqlDao;
-import com.ning.billing.invoice.dao.InvoiceSqlDao;
 import com.ning.billing.invoice.generator.InvoiceGenerator;
 import com.ning.billing.invoice.model.InvoicingConfiguration;
 import com.ning.billing.invoice.notification.NullInvoiceNotifier;
-import com.ning.billing.mock.api.MockBillCycleDay;
-import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.callcontext.InternalCallContext;
-import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.entity.EntityPersistenceException;
@@ -218,7 +210,7 @@ public class TestInvoiceHelper {
         Mockito.when(account.getCurrency()).thenReturn(accountCurrency);
         Mockito.when(account.getId()).thenReturn(accountId);
         Mockito.when(account.isNotifiedForInvoices()).thenReturn(true);
-        Mockito.when(account.getBillCycleDay()).thenReturn(new MockBillCycleDay(31));
+        Mockito.when(account.getBillCycleDayLocal()).thenReturn(31);
         // The timezone is required to compute the date of the next invoice notification
         Mockito.when(account.getTimeZone()).thenReturn(DateTimeZone.UTC);
 
@@ -299,21 +291,8 @@ public class TestInvoiceHelper {
                                                final DateTime effectiveDate,
                                                final Plan plan, final PlanPhase planPhase,
                                                @Nullable final BigDecimal fixedPrice, @Nullable final BigDecimal recurringPrice,
-                                               final Currency currency, final BillingPeriod billingPeriod, final int billCycleDayUTC,
-                                               final BillingModeType billingModeType, final String description,
-                                               final long totalOrdering,
-                                               final SubscriptionTransitionType type) {
-        return createMockBillingEvent(account, subscription, effectiveDate, plan, planPhase, fixedPrice, recurringPrice,
-                                      currency, billingPeriod, billCycleDayUTC, billCycleDayUTC, billingModeType, description,
-                                      totalOrdering, type);
-    }
-
-    public BillingEvent createMockBillingEvent(@Nullable final Account account, final Subscription subscription,
-                                               final DateTime effectiveDate,
-                                               final Plan plan, final PlanPhase planPhase,
-                                               @Nullable final BigDecimal fixedPrice, @Nullable final BigDecimal recurringPrice,
                                                final Currency currency, final BillingPeriod billingPeriod,
-                                               final int billCycleDayUTC, final int billCycleDayLocal,
+                                               final int billCycleDayLocal,
                                                final BillingModeType billingModeType, final String description,
                                                final long totalOrdering,
                                                final SubscriptionTransitionType type) {
@@ -324,18 +303,8 @@ public class TestInvoiceHelper {
             }
 
             @Override
-            public BillCycleDay getBillCycleDay() {
-                return new BillCycleDay() {
-                    @Override
-                    public int getDayOfMonthUTC() {
-                        return billCycleDayUTC;
-                    }
-
-                    @Override
-                    public int getDayOfMonthLocal() {
-                        return billCycleDayLocal;
-                    }
-                };
+            public int getBillCycleDayLocal() {
+                return billCycleDayLocal;
             }
 
             @Override
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
index f48597b..f57124f 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
@@ -22,7 +22,6 @@ import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.api.Currency;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
@@ -33,7 +32,7 @@ public class AccountJson extends AccountJsonSimple {
     protected final String name;
     protected final Integer length;
     protected final String email;
-    protected final BillCycleDayJson billCycleDayJson;
+    protected final Integer billCycleDayLocal;
     protected final String currency;
     protected final String paymentMethodId;
     protected final String timeZone;
@@ -54,7 +53,7 @@ public class AccountJson extends AccountJsonSimple {
         this.name = account.getName();
         this.length = account.getFirstNameLength();
         this.email = account.getEmail();
-        this.billCycleDayJson = new BillCycleDayJson(account.getBillCycleDay());
+        this.billCycleDayLocal = account.getBillCycleDayLocal();
         this.currency = account.getCurrency() != null ? account.getCurrency().toString() : null;
         this.paymentMethodId = account.getPaymentMethodId() != null ? account.getPaymentMethodId().toString() : null;
         this.timeZone = account.getTimeZone().toString();
@@ -158,22 +157,8 @@ public class AccountJson extends AccountJsonSimple {
             }
 
             @Override
-            public BillCycleDay getBillCycleDay() {
-                if (billCycleDayJson == null) {
-                    return null;
-                }
-
-                return new BillCycleDay() {
-                    @Override
-                    public int getDayOfMonthUTC() {
-                        return billCycleDayJson.getDayOfMonthUTC();
-                    }
-
-                    @Override
-                    public int getDayOfMonthLocal() {
-                        return billCycleDayJson.getDayOfMonthLocal();
-                    }
-                };
+            public Integer getBillCycleDayLocal() {
+                return billCycleDayLocal;
             }
 
             @Override
@@ -194,7 +179,7 @@ public class AccountJson extends AccountJsonSimple {
                        @JsonProperty("firstNameLength") final Integer length,
                        @JsonProperty("externalKey") final String externalKey,
                        @JsonProperty("email") final String email,
-                       @JsonProperty("billCycleDay") final BillCycleDayJson billCycleDay,
+                       @JsonProperty("billCycleDayLocal") final Integer billCycleDayLocal,
                        @JsonProperty("currency") final String currency,
                        @JsonProperty("paymentMethodId") final String paymentMethodId,
                        @JsonProperty("timezone") final String timeZone,
@@ -213,7 +198,7 @@ public class AccountJson extends AccountJsonSimple {
         this.name = name;
         this.length = length;
         this.email = email;
-        this.billCycleDayJson = billCycleDay;
+        this.billCycleDayLocal = billCycleDayLocal;
         this.currency = currency;
         this.paymentMethodId = paymentMethodId;
         this.timeZone = timeZone;
@@ -242,8 +227,8 @@ public class AccountJson extends AccountJsonSimple {
         return email;
     }
 
-    public BillCycleDayJson getBillCycleDay() {
-        return billCycleDayJson;
+    public Integer getBillCycleDayLocal() {
+        return billCycleDayLocal;
     }
 
     public String getCurrency() {
@@ -311,7 +296,7 @@ public class AccountJson extends AccountJsonSimple {
         sb.append("{name='").append(name).append('\'');
         sb.append(", length=").append(length);
         sb.append(", email='").append(email).append('\'');
-        sb.append(", billCycleDayJson=").append(billCycleDayJson);
+        sb.append(", billCycleDayJson=").append(billCycleDayLocal);
         sb.append(", currency='").append(currency).append('\'');
         sb.append(", paymentMethodId='").append(paymentMethodId).append('\'');
         sb.append(", timeZone='").append(timeZone).append('\'');
@@ -356,7 +341,7 @@ public class AccountJson extends AccountJsonSimple {
         if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) {
             return false;
         }
-        if (billCycleDayJson != null ? !billCycleDayJson.equals(that.billCycleDayJson) : that.billCycleDayJson != null) {
+        if (billCycleDayLocal != null ? !billCycleDayLocal.equals(that.billCycleDayLocal) : that.billCycleDayLocal != null) {
             return false;
         }
         if (city != null ? !city.equals(that.city) : that.city != null) {
@@ -417,7 +402,7 @@ public class AccountJson extends AccountJsonSimple {
         result = 31 * result + (name != null ? name.hashCode() : 0);
         result = 31 * result + (length != null ? length.hashCode() : 0);
         result = 31 * result + (email != null ? email.hashCode() : 0);
-        result = 31 * result + (billCycleDayJson != null ? billCycleDayJson.hashCode() : 0);
+        result = 31 * result + (billCycleDayLocal != null ? billCycleDayLocal.hashCode() : 0);
         result = 31 * result + (currency != null ? currency.hashCode() : 0);
         result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
         result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalance.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalance.java
index 9607d56..e25c86e 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalance.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalance.java
@@ -38,7 +38,7 @@ public class AccountJsonWithBalance extends AccountJson {
                                   @JsonProperty("firstNameLength") final Integer length,
                                   @JsonProperty("externalKey") final String externalKey,
                                   @JsonProperty("email") final String email,
-                                  @JsonProperty("billCycleDay") final BillCycleDayJson billCycleDay,
+                                  @JsonProperty("billCycleDayLocal") final Integer billCycleDayLocal,
                                   @JsonProperty("currency") final String currency,
                                   @JsonProperty("paymentMethodId") final String paymentMethodId,
                                   @JsonProperty("timezone") final String timeZone,
@@ -54,7 +54,7 @@ public class AccountJsonWithBalance extends AccountJson {
                                   @JsonProperty("isMigrated") final Boolean isMigrated,
                                   @JsonProperty("isNotifiedForInvoices") final Boolean isNotifiedForInvoices,
                                   @JsonProperty("accountBalance") final BigDecimal accountBalance) {
-        super(accountId, name, length, externalKey, email, billCycleDay, currency, paymentMethodId, timeZone,
+        super(accountId, name, length, externalKey, email, billCycleDayLocal, currency, paymentMethodId, timeZone,
               address1, address2, postalCode, company, city, state, country, locale, phone, isMigrated, isNotifiedForInvoices);
         this.accountBalance = accountBalance;
     }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalanceAndCBA.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalanceAndCBA.java
index ff3a437..4b00470 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalanceAndCBA.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonWithBalanceAndCBA.java
@@ -38,7 +38,7 @@ public class AccountJsonWithBalanceAndCBA extends AccountJsonWithBalance {
                                         @JsonProperty("firstNameLength") final Integer length,
                                         @JsonProperty("externalKey") final String externalKey,
                                         @JsonProperty("email") final String email,
-                                        @JsonProperty("billCycleDay") final BillCycleDayJson billCycleDay,
+                                        @JsonProperty("billCycleDayLocal") final Integer billCycleDayLocal,
                                         @JsonProperty("currency") final String currency,
                                         @JsonProperty("paymentMethodId") final String paymentMethodId,
                                         @JsonProperty("timezone") final String timeZone,
@@ -55,7 +55,7 @@ public class AccountJsonWithBalanceAndCBA extends AccountJsonWithBalance {
                                         @JsonProperty("isNotifiedForInvoices") final Boolean isNotifiedForInvoices,
                                         @JsonProperty("accountBalance") final BigDecimal accountBalance,
                                         @JsonProperty("accountCBA") final BigDecimal accountCBA) {
-        super(accountId, name, length, externalKey, email, billCycleDay, currency, paymentMethodId, timeZone, address1,
+        super(accountId, name, length, externalKey, email, billCycleDayLocal, currency, paymentMethodId, timeZone, address1,
               address2, postalCode, company, city, state, country, locale, phone, isMigrated, isNotifiedForInvoices, accountBalance);
         this.accountCBA = accountCBA;
     }
diff --git a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java
index 1b73168..4c8bf55 100644
--- a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java
+++ b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAccountJson.java
@@ -26,7 +26,6 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.jaxrs.JaxrsTestSuiteNoDB;
 import com.ning.billing.mock.MockAccountBuilder;
-import com.ning.billing.mock.api.MockBillCycleDay;
 
 public class TestAccountJson extends JaxrsTestSuiteNoDB {
 
@@ -37,7 +36,7 @@ public class TestAccountJson extends JaxrsTestSuiteNoDB {
         final Integer length = 12;
         final String externalKey = UUID.randomUUID().toString();
         final String email = UUID.randomUUID().toString();
-        final BillCycleDayJson billCycleDay = new BillCycleDayJson(6, 6);
+        final Integer billCycleDayLocal = 6;
         final String currency = UUID.randomUUID().toString();
         final String paymentMethodId = UUID.randomUUID().toString();
         final String timeZone = UUID.randomUUID().toString();
@@ -54,7 +53,7 @@ public class TestAccountJson extends JaxrsTestSuiteNoDB {
         final Boolean isNotifiedForInvoice = false;
 
         final AccountJson accountJson = new AccountJson(accountId, name, length, externalKey,
-                                                        email, billCycleDay, currency, paymentMethodId,
+                                                        email, billCycleDayLocal, currency, paymentMethodId,
                                                         timeZone, address1, address2, postalCode, company, city, state,
                                                         country, locale, phone, isMigrated, isNotifiedForInvoice);
         Assert.assertEquals(accountJson.getAccountId(), accountId);
@@ -62,7 +61,7 @@ public class TestAccountJson extends JaxrsTestSuiteNoDB {
         Assert.assertEquals(accountJson.getLength(), length);
         Assert.assertEquals(accountJson.getExternalKey(), externalKey);
         Assert.assertEquals(accountJson.getEmail(), email);
-        Assert.assertEquals(accountJson.getBillCycleDay(), billCycleDay);
+        Assert.assertEquals(accountJson.getBillCycleDayLocal(), billCycleDayLocal);
         Assert.assertEquals(accountJson.getCurrency(), currency);
         Assert.assertEquals(accountJson.getPaymentMethodId(), paymentMethodId);
         Assert.assertEquals(accountJson.getTimeZone(), timeZone);
@@ -89,7 +88,7 @@ public class TestAccountJson extends JaxrsTestSuiteNoDB {
         accountBuilder.address1(UUID.randomUUID().toString());
         accountBuilder.address2(UUID.randomUUID().toString());
         final int bcd = 4;
-        accountBuilder.billingCycleDay(new MockBillCycleDay(bcd));
+        accountBuilder.billingCycleDayLocal(bcd);
         accountBuilder.city(UUID.randomUUID().toString());
         accountBuilder.companyName(UUID.randomUUID().toString());
         accountBuilder.country(UUID.randomUUID().toString());
@@ -111,7 +110,7 @@ public class TestAccountJson extends JaxrsTestSuiteNoDB {
         final AccountJson accountJson = new AccountJson(account);
         Assert.assertEquals(accountJson.getAddress1(), account.getAddress1());
         Assert.assertEquals(accountJson.getAddress2(), account.getAddress2());
-        Assert.assertEquals(accountJson.getBillCycleDay().toString(), "{\"dayOfMonthLocal\":" + bcd + ",\"dayOfMonthUTC\":" + bcd + "}");
+        Assert.assertEquals(accountJson.getBillCycleDayLocal(), (Integer) bcd);
         Assert.assertEquals(accountJson.getCountry(), account.getCountry());
         Assert.assertEquals(accountJson.getLocale(), account.getLocale());
         Assert.assertEquals(accountJson.getCompany(), account.getCompanyName());
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
index 03d3b33..e1dbeed 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
@@ -22,7 +22,6 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.account.api.MutableAccountData;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.junction.api.BlockingState;
@@ -78,8 +77,8 @@ public class BlockingAccount implements Account {
     }
 
     @Override
-    public BillCycleDay getBillCycleDay() {
-        return account.getBillCycleDay();
+    public Integer getBillCycleDayLocal() {
+        return account.getBillCycleDayLocal();
     }
 
     @Override
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
index aa1af04..9000579 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BillCycleDayCalculator.java
@@ -26,7 +26,6 @@ import org.slf4j.LoggerFactory;
 import com.ning.billing.ErrorCode;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.api.BillingAlignment;
 import com.ning.billing.catalog.api.Catalog;
 import com.ning.billing.catalog.api.CatalogApiException;
@@ -60,7 +59,7 @@ public class BillCycleDayCalculator {
         this.entitlementApi = entitlementApi;
     }
 
-    protected BillCycleDay calculateBcd(final SubscriptionBundle bundle, final Subscription subscription, final EffectiveSubscriptionInternalEvent transition, final Account account, final InternalCallContext context)
+    protected int calculateBcd(final SubscriptionBundle bundle, final Subscription subscription, final EffectiveSubscriptionInternalEvent transition, final Account account, final InternalCallContext context)
             throws CatalogApiException, AccountApiException, EntitlementUserApiException {
 
         final Catalog catalog = catalogService.getFullCatalog();
@@ -88,13 +87,13 @@ public class BillCycleDayCalculator {
     }
 
     @VisibleForTesting
-    BillCycleDay calculateBcdForAlignment(final BillingAlignment alignment, final SubscriptionBundle bundle, final Subscription subscription,
-                                          final Account account, final Catalog catalog, final Plan plan, final InternalCallContext context) throws AccountApiException, EntitlementUserApiException, CatalogApiException {
-        BillCycleDay result = null;
+    int calculateBcdForAlignment(final BillingAlignment alignment, final SubscriptionBundle bundle, final Subscription subscription,
+                                 final Account account, final Catalog catalog, final Plan plan, final InternalCallContext context) throws AccountApiException, EntitlementUserApiException, CatalogApiException {
+        int result = 0;
         switch (alignment) {
             case ACCOUNT:
-                result = account.getBillCycleDay();
-                if (result == null || result.getDayOfMonthUTC() == 0) {
+                result = account.getBillCycleDayLocal();
+                if (result == 0) {
                     result = calculateBcdFromSubscription(subscription, plan, account, catalog, context);
                 }
                 break;
@@ -112,7 +111,7 @@ public class BillCycleDayCalculator {
                 break;
         }
 
-        if (result == null) {
+        if (result == 0) {
             throw new CatalogApiException(ErrorCode.CAT_INVALID_BILLING_ALIGNMENT, alignment.toString());
         }
 
@@ -120,12 +119,12 @@ public class BillCycleDayCalculator {
     }
 
     @VisibleForTesting
-    BillCycleDay calculateBcdFromSubscription(final Subscription subscription, final Plan plan, final Account account, final Catalog catalog, final InternalCallContext context)
+    int calculateBcdFromSubscription(final Subscription subscription, final Plan plan, final Account account, final Catalog catalog, final InternalCallContext context)
             throws AccountApiException, CatalogApiException {
         // Retrieve the initial phase type for that subscription
         // TODO - this should be extracted somewhere, along with this code above
         final PhaseType initialPhaseType;
-        final List<EffectiveSubscriptionInternalEvent> transitions =  entitlementApi.getAllTransitions(subscription, context);
+        final List<EffectiveSubscriptionInternalEvent> transitions = entitlementApi.getAllTransitions(subscription, context);
         if (transitions.size() == 0) {
             initialPhaseType = null;
         } else {
@@ -144,45 +143,11 @@ public class BillCycleDayCalculator {
         }
 
         final DateTime date = plan.dateOfFirstRecurringNonZeroCharge(subscription.getStartDate(), initialPhaseType);
-        // There are really two kinds of billCycleDay:
-        // - a System billingCycleDay which should be computed from UTC time (in order to get the correct notification time at
-        //   the end of each service period)
-        // - a User billingCycleDay which should align with the account timezone
-        final CalculatedBillCycleDay calculatedBillCycleDay = new CalculatedBillCycleDay(account.getTimeZone(), date);
+        final int bcdUTC = date.toDateTime(DateTimeZone.UTC).getDayOfMonth();
+        final int bcdLocal = date.toDateTime(account.getTimeZone()).getDayOfMonth();
         log.info("Calculated BCD: subscription id {}, subscription start {}, timezone {}, bcd UTC {}, bcd local {}",
-                 new Object[]{subscription.getId(), date.toDateTimeISO(), account.getTimeZone(),
-                              calculatedBillCycleDay.getDayOfMonthUTC(), calculatedBillCycleDay.getDayOfMonthLocal()});
-        return calculatedBillCycleDay;
-    }
-
-    private static final class CalculatedBillCycleDay implements BillCycleDay {
-
-        private final DateTime bcdTime;
-        private final DateTimeZone accountTimeZone;
-
-        private CalculatedBillCycleDay(final DateTimeZone accountTimeZone, final DateTime bcdTime) {
-            this.accountTimeZone = accountTimeZone;
-            this.bcdTime = bcdTime;
-        }
+                 subscription.getId(), date.toDateTimeISO(), account.getTimeZone(), bcdUTC, bcdLocal);
 
-        @Override
-        public int getDayOfMonthUTC() {
-            return bcdTime.toDateTime(DateTimeZone.UTC).getDayOfMonth();
-        }
-
-        @Override
-        public int getDayOfMonthLocal() {
-            return bcdTime.toDateTime(accountTimeZone).getDayOfMonth();
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder sb = new StringBuilder();
-            sb.append("CalculatedBillCycleDay");
-            sb.append("{bcdTime=").append(bcdTime);
-            sb.append(", accountTimeZone=").append(accountTimeZone);
-            sb.append('}');
-            return sb.toString();
-        }
+        return bcdLocal;
     }
 }
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 c1aa23d..666a666 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
@@ -29,7 +29,6 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.Plan;
@@ -193,7 +192,7 @@ public class BlockingCalculator {
 
     protected BillingEvent createNewDisableEvent(final DateTime odEventTime, final BillingEvent previousEvent) {
         final Account account = previousEvent.getAccount();
-        final BillCycleDay billCycleDay = previousEvent.getBillCycleDay();
+        final int billCycleDay = previousEvent.getBillCycleDayLocal();
         final Subscription subscription = previousEvent.getSubscription();
         final DateTime effectiveDate = odEventTime;
         final PlanPhase planPhase = previousEvent.getPlanPhase();
@@ -221,7 +220,7 @@ public class BlockingCalculator {
     protected BillingEvent createNewReenableEvent(final DateTime odEventTime, final BillingEvent previousEvent) {
         // All fields are populated with the event state from before the blocking period, for invoice to resume invoicing
         final Account account = previousEvent.getAccount();
-        final BillCycleDay billCycleDay = previousEvent.getBillCycleDay();
+        final int billCycleDay = previousEvent.getBillCycleDayLocal();
         final Subscription subscription = previousEvent.getSubscription();
         final DateTime effectiveDate = odEventTime;
         final PlanPhase planPhase = previousEvent.getPlanPhase();
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEvent.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEvent.java
index c31fd82..4d7e135 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEvent.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEvent.java
@@ -22,7 +22,6 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Catalog;
 import com.ning.billing.catalog.api.CatalogApiException;
@@ -37,7 +36,7 @@ import com.ning.billing.util.svcapi.junction.BillingModeType;
 
 public class DefaultBillingEvent implements BillingEvent {
     private final Account account;
-    private final BillCycleDay billCycleDay;
+    private final int billCycleDayLocal;
     private final Subscription subscription;
     private final DateTime effectiveDate;
     private final PlanPhase planPhase;
@@ -52,10 +51,10 @@ public class DefaultBillingEvent implements BillingEvent {
     private final Long totalOrdering;
     private final DateTimeZone timeZone;
 
-    public DefaultBillingEvent(final Account account, final EffectiveSubscriptionInternalEvent transition, final Subscription subscription, final BillCycleDay billCycleDay, final Currency currency, final Catalog catalog) throws CatalogApiException {
+    public DefaultBillingEvent(final Account account, final EffectiveSubscriptionInternalEvent transition, final Subscription subscription, final int billCycleDayLocal, final Currency currency, final Catalog catalog) throws CatalogApiException {
 
         this.account = account;
-        this.billCycleDay = billCycleDay;
+        this.billCycleDayLocal = billCycleDayLocal;
         this.subscription = subscription;
         effectiveDate = transition.getEffectiveTransitionTime();
         final String planPhaseName = (transition.getTransitionType() != SubscriptionTransitionType.CANCEL) ?
@@ -88,7 +87,7 @@ public class DefaultBillingEvent implements BillingEvent {
 
     public DefaultBillingEvent(final Account account, final Subscription subscription, final DateTime effectiveDate, final Plan plan, final PlanPhase planPhase,
                                final BigDecimal fixedPrice, final BigDecimal recurringPrice, final Currency currency,
-                               final BillingPeriod billingPeriod, final BillCycleDay billCycleDay, final BillingModeType billingModeType,
+                               final BillingPeriod billingPeriod, final int billCycleDayLocal, final BillingModeType billingModeType,
                                final String description, final long totalOrdering, final SubscriptionTransitionType type, final DateTimeZone timeZone) {
         this.account = account;
         this.subscription = subscription;
@@ -99,7 +98,7 @@ public class DefaultBillingEvent implements BillingEvent {
         this.recurringPrice = recurringPrice;
         this.currency = currency;
         this.billingPeriod = billingPeriod;
-        this.billCycleDay = billCycleDay;
+        this.billCycleDayLocal = billCycleDayLocal;
         this.billingModeType = billingModeType;
         this.description = description;
         this.type = type;
@@ -159,8 +158,8 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     @Override
-    public BillCycleDay getBillCycleDay() {
-        return billCycleDay;
+    public int getBillCycleDayLocal() {
+        return billCycleDayLocal;
     }
 
     @Override
@@ -250,7 +249,10 @@ public class DefaultBillingEvent implements BillingEvent {
 
         final DefaultBillingEvent that = (DefaultBillingEvent) o;
 
-        if (billCycleDay != that.billCycleDay) {
+        if (billCycleDayLocal != that.billCycleDayLocal) {
+            return false;
+        }
+        if (account != null ? !account.equals(that.account) : that.account != null) {
             return false;
         }
         if (billingModeType != that.billingModeType) {
@@ -262,28 +264,31 @@ public class DefaultBillingEvent implements BillingEvent {
         if (currency != that.currency) {
             return false;
         }
-        if (!description.equals(that.description)) {
+        if (description != null ? !description.equals(that.description) : that.description != null) {
             return false;
         }
-        if (!effectiveDate.equals(that.effectiveDate)) {
+        if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
             return false;
         }
         if (fixedPrice != null ? !fixedPrice.equals(that.fixedPrice) : that.fixedPrice != null) {
             return false;
         }
-        if (!plan.equals(that.plan)) {
+        if (plan != null ? !plan.equals(that.plan) : that.plan != null) {
             return false;
         }
-        if (!planPhase.equals(that.planPhase)) {
+        if (planPhase != null ? !planPhase.equals(that.planPhase) : that.planPhase != null) {
             return false;
         }
         if (recurringPrice != null ? !recurringPrice.equals(that.recurringPrice) : that.recurringPrice != null) {
             return false;
         }
-        if (!subscription.equals(that.subscription)) {
+        if (subscription != null ? !subscription.equals(that.subscription) : that.subscription != null) {
+            return false;
+        }
+        if (timeZone != null ? !timeZone.equals(that.timeZone) : that.timeZone != null) {
             return false;
         }
-        if (!totalOrdering.equals(that.totalOrdering)) {
+        if (totalOrdering != null ? !totalOrdering.equals(that.totalOrdering) : that.totalOrdering != null) {
             return false;
         }
         if (type != that.type) {
@@ -295,19 +300,21 @@ public class DefaultBillingEvent implements BillingEvent {
 
     @Override
     public int hashCode() {
-        int result = billCycleDay.hashCode();
-        result = 31 * result + subscription.hashCode();
-        result = 31 * result + effectiveDate.hashCode();
-        result = 31 * result + planPhase.hashCode();
-        result = 31 * result + plan.hashCode();
+        int result = account != null ? account.hashCode() : 0;
+        result = 31 * result + billCycleDayLocal;
+        result = 31 * result + (subscription != null ? subscription.hashCode() : 0);
+        result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
+        result = 31 * result + (planPhase != null ? planPhase.hashCode() : 0);
+        result = 31 * result + (plan != null ? plan.hashCode() : 0);
         result = 31 * result + (fixedPrice != null ? fixedPrice.hashCode() : 0);
         result = 31 * result + (recurringPrice != null ? recurringPrice.hashCode() : 0);
-        result = 31 * result + currency.hashCode();
-        result = 31 * result + description.hashCode();
-        result = 31 * result + billingModeType.hashCode();
-        result = 31 * result + billingPeriod.hashCode();
-        result = 31 * result + type.hashCode();
-        result = 31 * result + totalOrdering.hashCode();
+        result = 31 * result + (currency != null ? currency.hashCode() : 0);
+        result = 31 * result + (description != null ? description.hashCode() : 0);
+        result = 31 * result + (billingModeType != null ? billingModeType.hashCode() : 0);
+        result = 31 * result + (billingPeriod != null ? billingPeriod.hashCode() : 0);
+        result = 31 * result + (type != null ? type.hashCode() : 0);
+        result = 31 * result + (totalOrdering != null ? totalOrdering.hashCode() : 0);
+        result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
         return result;
     }
 
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultInternalBillingApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
index 2507897..e6719fd 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
@@ -28,7 +28,6 @@ import org.slf4j.LoggerFactory;
 import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.account.api.MutableAccountData;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.CatalogService;
@@ -133,15 +132,15 @@ public class DefaultInternalBillingApi implements BillingInternalApi {
         for (final Subscription subscription : subscriptions) {
             for (final EffectiveSubscriptionInternalEvent transition : entitlementApi.getBillingTransitions(subscription, context)) {
                 try {
-                    final BillCycleDay bcd = bcdCalculator.calculateBcd(bundle, subscription, transition, account, context);
+                    final int bcdLocal = bcdCalculator.calculateBcd(bundle, subscription, transition, account, context);
 
-                    if (account.getBillCycleDay().getDayOfMonthUTC() == 0) {
+                    if (account.getBillCycleDayLocal() == 0) {
                         final MutableAccountData modifiedData = account.toMutableAccountData();
-                        modifiedData.setBillCycleDay(bcd);
+                        modifiedData.setBillCycleDayLocal(bcdLocal);
                         accountApi.updateAccount(account.getExternalKey(), modifiedData, context);
                     }
 
-                    final BillingEvent event = new DefaultBillingEvent(account, transition, subscription, bcd, account.getCurrency(), catalogService.getFullCatalog());
+                    final BillingEvent event = new DefaultBillingEvent(account, transition, subscription, bcdLocal, account.getCurrency(), catalogService.getFullCatalog());
                     result.add(event);
                 } catch (CatalogApiException e) {
                     log.error("Failing to identify catalog components while creating BillingEvent from transition: " +
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillCycleDayCalculator.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillCycleDayCalculator.java
index d030113..2fc5006 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillCycleDayCalculator.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillCycleDayCalculator.java
@@ -26,7 +26,6 @@ import org.testng.annotations.Test;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.api.BillingAlignment;
 import com.ning.billing.catalog.api.Catalog;
 import com.ning.billing.catalog.api.CatalogApiException;
@@ -63,60 +62,55 @@ public class TestBillCycleDayCalculator extends JunctionTestSuiteNoDB {
 
         final Account account = Mockito.mock(Account.class);
         Mockito.when(account.getTimeZone()).thenReturn(accountTimeZone);
-        final BillCycleDay billCycleDay = billCycleDayCalculator.calculateBcdForAlignment(BillingAlignment.BUNDLE, bundle, subscription,
+        final Integer billCycleDayLocal = billCycleDayCalculator.calculateBcdForAlignment(BillingAlignment.BUNDLE, bundle, subscription,
                                                                                           account, catalog, null, internalCallContext);
 
-        Assert.assertEquals(billCycleDay.getDayOfMonthUTC(), expectedBCDUTC);
+        Assert.assertEquals(billCycleDayLocal, (Integer) expectedBCDUTC);
     }
 
     @Test(groups = "fast")
     public void testCalculateBCDWithTimeZoneHST() throws Exception {
         final DateTimeZone accountTimeZone = DateTimeZone.forID("HST");
         final DateTime startDateUTC = new DateTime("2012-07-16T21:17:03.000Z", DateTimeZone.UTC);
-        final int bcdUTC = 16;
         final int bcdLocal = 16;
 
-        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdUTC, bcdLocal);
+        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdLocal);
     }
 
     @Test(groups = "fast")
     public void testCalculateBCDWithTimeZoneCEST() throws Exception {
         final DateTimeZone accountTimeZone = DateTimeZone.forID("Europe/Paris");
         final DateTime startDateUTC = new DateTime("2012-07-16T21:17:03.000Z", DateTimeZone.UTC);
-        final int bcdUTC = 16;
         final int bcdLocal = 16;
 
-        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdUTC, bcdLocal);
+        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdLocal);
     }
 
     @Test(groups = "fast")
     public void testCalculateBCDWithTimeZoneUTC() throws Exception {
         final DateTimeZone accountTimeZone = DateTimeZone.UTC;
         final DateTime startDateUTC = new DateTime("2012-07-16T21:17:03.000Z", DateTimeZone.UTC);
-        final int bcdUTC = 16;
         final int bcdLocal = 16;
 
-        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdUTC, bcdLocal);
+        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdLocal);
     }
 
     @Test(groups = "fast")
     public void testCalculateBCDWithTimeZoneEEST() throws Exception {
         final DateTimeZone accountTimeZone = DateTimeZone.forID("+0300");
         final DateTime startDateUTC = new DateTime("2012-07-16T21:17:03.000Z", DateTimeZone.UTC);
-        final int bcdUTC = 16;
         final int bcdLocal = 17;
 
-        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdUTC, bcdLocal);
+        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdLocal);
     }
 
     @Test(groups = "fast")
     public void testCalculateBCDWithTimeZoneJST() throws Exception {
         final DateTimeZone accountTimeZone = DateTimeZone.forID("Asia/Tokyo");
         final DateTime startDateUTC = new DateTime("2012-07-16T21:17:03.000Z", DateTimeZone.UTC);
-        final int bcdUTC = 16;
         final int bcdLocal = 17;
 
-        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdUTC, bcdLocal);
+        verifyBCDCalculation(accountTimeZone, startDateUTC, bcdLocal);
     }
 
     @Test(groups = "fast")
@@ -124,13 +118,12 @@ public class TestBillCycleDayCalculator extends JunctionTestSuiteNoDB {
         // Test to verify the computations don't rely implicitly on UTC
         final DateTimeZone accountTimeZone = DateTimeZone.forID("Asia/Tokyo");
         final DateTime startDate = new DateTime("2012-07-16T21:17:03.000Z", DateTimeZone.forID("HST"));
-        final int bcdUTC = 16;
         final int bcdLocal = 17;
 
-        verifyBCDCalculation(accountTimeZone, startDate, bcdUTC, bcdLocal);
+        verifyBCDCalculation(accountTimeZone, startDate, bcdLocal);
     }
 
-    private void verifyBCDCalculation(final DateTimeZone accountTimeZone, final DateTime startDateUTC, final int bcdUTC, final int bcdLocal) throws AccountApiException, CatalogApiException {
+    private void verifyBCDCalculation(final DateTimeZone accountTimeZone, final DateTime startDateUTC, final int bcdLocal) throws AccountApiException, CatalogApiException {
         final BillCycleDayCalculator billCycleDayCalculator = new BillCycleDayCalculator(Mockito.mock(CatalogService.class), Mockito.mock(EntitlementInternalApi.class));
 
         final Subscription subscription = Mockito.mock(Subscription.class);
@@ -142,8 +135,7 @@ public class TestBillCycleDayCalculator extends JunctionTestSuiteNoDB {
         final Account account = Mockito.mock(Account.class);
         Mockito.when(account.getTimeZone()).thenReturn(accountTimeZone);
 
-        final BillCycleDay bcd = billCycleDayCalculator.calculateBcdFromSubscription(subscription, plan, account, Mockito.mock(Catalog.class), internalCallContext);
-        Assert.assertEquals(bcd.getDayOfMonthUTC(), bcdUTC);
-        Assert.assertEquals(bcd.getDayOfMonthLocal(), bcdLocal);
+        final Integer bcd = billCycleDayCalculator.calculateBcdFromSubscription(subscription, plan, account, Mockito.mock(Catalog.class), internalCallContext);
+        Assert.assertEquals(bcd, (Integer) bcdLocal);
     }
 }
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 ff2fde3..6c27161 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
@@ -53,7 +53,6 @@ import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.junction.dao.MockBlockingStateDao;
 import com.ning.billing.mock.MockEffectiveSubscriptionEvent;
 import com.ning.billing.mock.MockSubscription;
-import com.ning.billing.mock.api.MockBillCycleDay;
 import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.events.EffectiveSubscriptionInternalEvent;
@@ -129,7 +128,7 @@ public class TestBillingApi extends JunctionTestSuiteNoDB {
         final Account account = createAccount(10);
 
         final SortedSet<BillingEvent> events = billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), internalCallContext);
-        checkFirstEvent(events, nextPlan, account.getBillCycleDay().getDayOfMonthUTC(), subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString());
+        checkFirstEvent(events, nextPlan, account.getBillCycleDayLocal(), subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString());
     }
 
     @Test(groups = "fast")
@@ -194,9 +193,9 @@ public class TestBillingApi extends JunctionTestSuiteNoDB {
         Assert.assertEquals(events.size(), 3);
         final Iterator<BillingEvent> it = events.iterator();
 
-        checkEvent(it.next(), nextPlan, account.getBillCycleDay().getDayOfMonthUTC(), subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
-        checkEvent(it.next(), nextPlan, account.getBillCycleDay().getDayOfMonthUTC(), subId, now.plusDays(1), nextPhase, SubscriptionTransitionType.START_BILLING_DISABLED.toString(), null, null);
-        checkEvent(it.next(), nextPlan, account.getBillCycleDay().getDayOfMonthUTC(), subId, now.plusDays(2), nextPhase, SubscriptionTransitionType.END_BILLING_DISABLED.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+        checkEvent(it.next(), nextPlan, account.getBillCycleDayLocal(), subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+        checkEvent(it.next(), nextPlan, account.getBillCycleDayLocal(), subId, now.plusDays(1), nextPhase, SubscriptionTransitionType.START_BILLING_DISABLED.toString(), null, null);
+        checkEvent(it.next(), nextPlan, account.getBillCycleDayLocal(), subId, now.plusDays(2), nextPhase, SubscriptionTransitionType.END_BILLING_DISABLED.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
     }
 
     @Test(groups = "fast")
@@ -252,7 +251,7 @@ public class TestBillingApi extends JunctionTestSuiteNoDB {
             assertNull(event.getRecurringPrice());
         }
 
-        Assert.assertEquals(BCD, event.getBillCycleDay().getDayOfMonthUTC());
+        Assert.assertEquals(BCD, event.getBillCycleDayLocal());
         Assert.assertEquals(id, event.getSubscription().getId());
         Assert.assertEquals(time.getDayOfMonth(), event.getEffectiveDate().getDayOfMonth());
         Assert.assertEquals(nextPhase, event.getPlanPhase());
@@ -266,7 +265,7 @@ public class TestBillingApi extends JunctionTestSuiteNoDB {
 
     private Account createAccount(final int billCycleDay) throws AccountApiException {
         final Account account = Mockito.mock(Account.class);
-        Mockito.when(account.getBillCycleDay()).thenReturn(new MockBillCycleDay(billCycleDay));
+        Mockito.when(account.getBillCycleDayLocal()).thenReturn(billCycleDay);
         Mockito.when(account.getCurrency()).thenReturn(Currency.USD);
         Mockito.when(account.getId()).thenReturn(UUID.randomUUID());
         Mockito.when(account.getTimeZone()).thenReturn(DateTimeZone.UTC);
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 d4b498f..c435d42 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
@@ -33,7 +33,6 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.MockPlan;
 import com.ning.billing.catalog.MockPlanPhase;
 import com.ning.billing.catalog.api.BillingPeriod;
@@ -48,7 +47,6 @@ import com.ning.billing.junction.api.Blockable.Type;
 import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.junction.dao.MockBlockingStateDao;
 import com.ning.billing.junction.plumbing.billing.BlockingCalculator.DisabledDuration;
-import com.ning.billing.mock.api.MockBillCycleDay;
 import com.ning.billing.util.svcapi.junction.BillingEvent;
 import com.ning.billing.util.svcapi.junction.BillingModeType;
 import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
@@ -528,7 +526,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
 
     protected BillingEvent createRealEvent(final DateTime effectiveDate, final Subscription subscription, final SubscriptionTransitionType type) {
         final Account account = this.account;
-        final BillCycleDay billCycleDay = new MockBillCycleDay(1);
+        final Integer billCycleDay = 1;
         final PlanPhase planPhase = new MockPlanPhase();
         final Plan plan = new MockPlan();
         final BigDecimal fixedPrice = BigDecimal.TEN;
@@ -573,7 +571,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         final BillingEvent event = new MockBillingEvent();
 
         final BillingEvent result = blockingCalculator.createNewDisableEvent(now, event);
-        assertEquals(result.getBillCycleDay(), event.getBillCycleDay());
+        assertEquals(result.getBillCycleDayLocal(), event.getBillCycleDayLocal());
         assertEquals(result.getEffectiveDate(), now);
         assertEquals(result.getPlanPhase(), event.getPlanPhase());
         assertEquals(result.getPlan(), event.getPlan());
@@ -594,7 +592,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         final BillingEvent event = new MockBillingEvent();
 
         final BillingEvent result = blockingCalculator.createNewReenableEvent(now, event);
-        assertEquals(result.getBillCycleDay(), event.getBillCycleDay());
+        assertEquals(result.getBillCycleDayLocal(), event.getBillCycleDayLocal());
         assertEquals(result.getEffectiveDate(), now);
         assertEquals(result.getPlanPhase(), event.getPlanPhase());
         assertEquals(result.getPlan(), event.getPlan());
@@ -613,7 +611,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
 
         public MockBillingEvent() {
             super(account, subscription1, clock.getUTCNow(), null, null, BigDecimal.ZERO, BigDecimal.TEN, Currency.USD, BillingPeriod.ANNUAL,
-                  new MockBillCycleDay(4), BillingModeType.IN_ADVANCE, "", 3L, SubscriptionTransitionType.CREATE, DateTimeZone.UTC);
+                  4, BillingModeType.IN_ADVANCE, "", 3L, SubscriptionTransitionType.CREATE, DateTimeZone.UTC);
         }
     }
 
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultBillingEvent.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultBillingEvent.java
index 0e9a636..e2b8f2c 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultBillingEvent.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultBillingEvent.java
@@ -44,7 +44,6 @@ import com.ning.billing.entitlement.api.SubscriptionTransitionType;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.junction.JunctionTestSuiteNoDB;
 import com.ning.billing.mock.MockAccountBuilder;
-import com.ning.billing.mock.api.MockBillCycleDay;
 import com.ning.billing.util.svcapi.junction.BillingEvent;
 import com.ning.billing.util.svcapi.junction.BillingModeType;
 
@@ -190,7 +189,7 @@ public class TestDefaultBillingEvent extends JunctionTestSuiteNoDB {
         final Account account = new MockAccountBuilder().build();
         return new DefaultBillingEvent(account, sub, effectiveDate,
                                        shotgun, shotgunMonthly,
-                                       BigDecimal.ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, new MockBillCycleDay(billCycleDay),
+                                       BigDecimal.ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, billCycleDay,
                                        BillingModeType.IN_ADVANCE, "Test Event 1", totalOrdering, type, DateTimeZone.UTC);
     }
 
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
index b2e91c5..946d8b6 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckPoster.java
@@ -16,32 +16,47 @@
 
 package com.ning.billing.ovedue.notification;
 
-import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.joda.time.DateTime;
+import org.skife.jdbi.v2.IDBI;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
 import com.ning.billing.overdue.service.DefaultOverdueService;
+import com.ning.billing.util.cache.CacheControllerDispatcher;
 import com.ning.billing.util.callcontext.InternalCallContext;
-import com.ning.billing.util.notificationq.NotificationKey;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.dao.NonEntityDao;
+import com.ning.billing.util.entity.dao.EntitySqlDao;
+import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
+import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
+import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
+import com.ning.billing.util.notificationq.Notification;
 import com.ning.billing.util.notificationq.NotificationQueue;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService.NoSuchNotificationQueue;
+import com.ning.billing.util.queue.PersistentQueueBase;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.inject.Inject;
 
 public class DefaultOverdueCheckPoster implements OverdueCheckPoster {
+
     private static final Logger log = LoggerFactory.getLogger(DefaultOverdueCheckNotifier.class);
 
     private final NotificationQueueService notificationQueueService;
+    private final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
 
     @Inject
-    public DefaultOverdueCheckPoster(
-            final NotificationQueueService notificationQueueService) {
-        super();
+    public DefaultOverdueCheckPoster(final NotificationQueueService notificationQueueService,
+                                     final IDBI dbi, final Clock clock,
+                                     final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao) {
         this.notificationQueueService = notificationQueueService;
+        this.transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao);
     }
 
     @Override
@@ -50,33 +65,89 @@ public class DefaultOverdueCheckPoster implements OverdueCheckPoster {
         try {
             checkOverdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
                                                                               DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
-            log.info("Queuing overdue check notification. id: {}, timestamp: {}", overdueable.getId().toString(), futureNotificationTime.toString());
 
-            checkOverdueQueue.recordFutureNotification(futureNotificationTime, new OverdueCheckNotificationKey(overdueable.getId(), Blockable.Type.get(overdueable)), context);
+            transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
+                @Override
+                public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+                    boolean shouldInsertNewNotification = true;
+
+                    // Check if we already have notifications for that key
+                    final List<Notification> futureNotifications = getFutureNotificationsForAccountAndOverdueableInTransaction(entitySqlDaoWrapperFactory, checkOverdueQueue, overdueable, context);
+                    if (futureNotifications.size() > 0) {
+                        // Results are ordered by effective date asc
+                        final DateTime earliestExistingNotificationDate = futureNotifications.get(0).getEffectiveDate();
+
+                        final int minIndexToDeleteFrom;
+                        if (earliestExistingNotificationDate.isBefore(futureNotificationTime)) {
+                            // We don't have to insert a new one. For sanity, delete any other future notification
+                            minIndexToDeleteFrom = 1;
+                            shouldInsertNewNotification = false;
+                        } else {
+                            // We win - we are before any other already recorded. Delete all others.
+                            minIndexToDeleteFrom = 0;
+                        }
+
+                        for (int i = minIndexToDeleteFrom; i < futureNotifications.size(); i++) {
+                            checkOverdueQueue.removeNotificationFromTransaction(entitySqlDaoWrapperFactory, futureNotifications.get(i).getId(), context);
+                        }
+                    }
+
+                    if (shouldInsertNewNotification) {
+                        log.info("Queuing overdue check notification. Overdueable id: {}, timestamp: {}", overdueable.getId().toString(), futureNotificationTime.toString());
+                        final OverdueCheckNotificationKey notificationKey = new OverdueCheckNotificationKey(overdueable.getId(), Type.get(overdueable));
+                        checkOverdueQueue.recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory, futureNotificationTime, notificationKey, context);
+                    } else {
+                        log.info("Skipping queuing overdue check notification. Overdueable id: {}, timestamp: {}", overdueable.getId().toString(), futureNotificationTime.toString());
+                    }
+
+                    return null;
+                }
+            });
         } catch (NoSuchNotificationQueue e) {
             log.error("Attempting to put items on a non-existent queue (DefaultOverdueCheck).", e);
-        } catch (IOException e) {
-            log.error("Failed to serialize notifcationKey for {}", overdueable.toString());
         }
     }
 
-
     @Override
     public void clearNotificationsFor(final Blockable overdueable, final InternalCallContext context) {
-        final NotificationQueue checkOverdueQueue;
         try {
-            checkOverdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
-                                                                              DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
-            final NotificationKey key = new NotificationKey() {
+            final NotificationQueue checkOverdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
+                                                                                                      DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
+            transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
+
                 @Override
-                public String toString() {
-                    return overdueable.getId().toString();
+                public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+                    final List<Notification> futureNotifications = getFutureNotificationsForAccountAndOverdueableInTransaction(entitySqlDaoWrapperFactory, checkOverdueQueue, overdueable, context);
+                    for (final Notification notification : futureNotifications) {
+                        checkOverdueQueue.removeNotificationFromTransaction(entitySqlDaoWrapperFactory, notification.getId(), context);
+                    }
+
+                    return null;
                 }
-            };
-            checkOverdueQueue.removeNotificationsByKey(key, context);
+            });
         } catch (NoSuchNotificationQueue e) {
             log.error("Attempting to clear items from a non-existent queue (DefaultOverdueCheck).", e);
         }
     }
 
+    @VisibleForTesting
+    List<Notification> getFutureNotificationsForAccountAndOverdueableInTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory,
+                                                                                   final NotificationQueue checkOverdueQueue,
+                                                                                   final Blockable overdueable,
+                                                                                   final InternalCallContext context) {
+        final List<Notification> notifications = new ArrayList<Notification>();
+
+        final List<Notification> candidates = checkOverdueQueue.getFutureNotificationsForAccountFromTransaction(entitySqlDaoWrapperFactory, context);
+        for (final Notification candidate : candidates) {
+            if (OverdueCheckNotificationKey.class.getName().equals(candidate.getNotificationKeyClass())) {
+                final OverdueCheckNotificationKey key = PersistentQueueBase.deserializeEvent(candidate.getNotificationKeyClass(), candidate.getNotificationKey());
+
+                if (Type.get(overdueable).equals(key.getType()) && overdueable.getId().equals(key.getUuidKey())) {
+                    notifications.add(candidate);
+                }
+            }
+        }
+
+        return notifications;
+    }
 }
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java
index 1ccd589..72e4f63 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckNotificationKey.java
@@ -18,19 +18,19 @@ package com.ning.billing.ovedue.notification;
 
 import java.util.UUID;
 
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.util.notificationq.DefaultUUIDNotificationKey;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 public class OverdueCheckNotificationKey extends DefaultUUIDNotificationKey {
 
     private final Blockable.Type type;
 
     @JsonCreator
-    public OverdueCheckNotificationKey(@JsonProperty("uuidKey") UUID uuidKey,
-            @JsonProperty("type") Blockable.Type type) {
+    public OverdueCheckNotificationKey(@JsonProperty("uuidKey") final UUID uuidKey,
+                                       @JsonProperty("type") final Blockable.Type type) {
         super(uuidKey);
         this.type = type;
     }
@@ -39,4 +39,42 @@ public class OverdueCheckNotificationKey extends DefaultUUIDNotificationKey {
     public Blockable.Type getType() {
         return type == null ? Blockable.Type.SUBSCRIPTION_BUNDLE : type;
     }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final OverdueCheckNotificationKey that = (OverdueCheckNotificationKey) o;
+
+        if (type != that.type) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (type != null ? type.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("OverdueCheckNotificationKey");
+        sb.append("{type=").append(type);
+        sb.append(", uuidKey=").append(getUuidKey());
+        sb.append('}');
+        return sb.toString();
+    }
 }
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckPoster.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckPoster.java
index 1c0d441..9768a62 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckPoster.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/OverdueCheckPoster.java
@@ -26,5 +26,4 @@ public interface OverdueCheckPoster {
     void insertOverdueCheckNotification(Blockable blockable, DateTime futureNotificationTime, final InternalCallContext context);
 
     void clearNotificationsFor(Blockable blockable, final InternalCallContext context);
-
 }
diff --git a/overdue/src/test/java/com/ning/billing/ovedue/notification/TestDefaultOverdueCheckPoster.java b/overdue/src/test/java/com/ning/billing/ovedue/notification/TestDefaultOverdueCheckPoster.java
new file mode 100644
index 0000000..30e8d83
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/ovedue/notification/TestDefaultOverdueCheckPoster.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2010-2013 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.ovedue.notification;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.overdue.OverdueTestSuiteWithEmbeddedDB;
+import com.ning.billing.overdue.service.DefaultOverdueService;
+import com.ning.billing.util.entity.dao.EntitySqlDao;
+import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
+import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
+import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
+import com.ning.billing.util.jackson.ObjectMapper;
+import com.ning.billing.util.notificationq.Notification;
+import com.ning.billing.util.notificationq.NotificationQueue;
+
+public class TestDefaultOverdueCheckPoster extends OverdueTestSuiteWithEmbeddedDB {
+
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+
+    private EntitySqlDaoTransactionalJdbiWrapper entitySqlDaoTransactionalJdbiWrapper;
+    private NotificationQueue overdueQueue;
+    private DateTime testReferenceTime;
+
+    @BeforeMethod(groups = "slow")
+    public void setUp() throws Exception {
+        entitySqlDaoTransactionalJdbiWrapper = new EntitySqlDaoTransactionalJdbiWrapper(getDBI(), clock, cacheControllerDispatcher, nonEntityDao);
+
+        overdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
+                                                                     DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
+        Assert.assertTrue(overdueQueue.isStarted());
+
+        testReferenceTime = clock.getUTCNow();
+    }
+
+    @Test(groups = "slow")
+    public void testShouldntInsertMultipleNotificationsPerOverdueable() throws Exception {
+        final UUID subscriptionId = UUID.randomUUID();
+        final Blockable overdueable = Mockito.mock(Subscription.class);
+        Mockito.when(overdueable.getId()).thenReturn(subscriptionId);
+
+        insertOverdueCheckAndVerifyQueueContent(overdueable, 10, 10);
+        insertOverdueCheckAndVerifyQueueContent(overdueable, 5, 5);
+        insertOverdueCheckAndVerifyQueueContent(overdueable, 15, 5);
+
+        // Check we don't conflict with other overdueables
+        final UUID bundleId = UUID.randomUUID();
+        final Blockable otherOverdueable = Mockito.mock(SubscriptionBundle.class);
+        Mockito.when(otherOverdueable.getId()).thenReturn(bundleId);
+
+        insertOverdueCheckAndVerifyQueueContent(otherOverdueable, 10, 10);
+        insertOverdueCheckAndVerifyQueueContent(otherOverdueable, 5, 5);
+        insertOverdueCheckAndVerifyQueueContent(otherOverdueable, 15, 5);
+
+        // Verify the final content of the queue
+        Assert.assertEquals(overdueQueue.getFutureNotificationsForAccount(internalCallContext).size(), 2);
+    }
+
+    private void insertOverdueCheckAndVerifyQueueContent(final Blockable overdueable, final int nbDaysInFuture, final int expectedNbDaysInFuture) throws IOException {
+        final DateTime futureNotificationTime = testReferenceTime.plusDays(nbDaysInFuture);
+        poster.insertOverdueCheckNotification(overdueable, futureNotificationTime, internalCallContext);
+
+        final OverdueCheckNotificationKey notificationKey = new OverdueCheckNotificationKey(overdueable.getId(), Blockable.Type.get(overdueable));
+        final List<Notification> notificationsForKey = getNotificationsForOverdueable(overdueable);
+        Assert.assertEquals(notificationsForKey.size(), 1);
+        Assert.assertEquals(notificationsForKey.get(0).getNotificationKey(), objectMapper.writeValueAsString(notificationKey));
+        Assert.assertEquals(notificationsForKey.get(0).getEffectiveDate(), testReferenceTime.plusDays(expectedNbDaysInFuture));
+    }
+
+    private List<Notification> getNotificationsForOverdueable(final Blockable overdueable) {
+        return entitySqlDaoTransactionalJdbiWrapper.execute(new EntitySqlDaoTransactionWrapper<List<Notification>>() {
+            @Override
+            public List<Notification> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+                return ((DefaultOverdueCheckPoster) poster).getFutureNotificationsForAccountAndOverdueableInTransaction(entitySqlDaoWrapperFactory, overdueQueue, overdueable, internalCallContext);
+            }
+        });
+    }
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java b/overdue/src/test/java/com/ning/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java
index a3c4e12..b7ab466 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java
@@ -30,7 +30,9 @@ import com.ning.billing.overdue.calculator.BillingStateCalculatorBundle;
 import com.ning.billing.overdue.glue.TestOverdueModuleWithEmbeddedDB;
 import com.ning.billing.overdue.service.DefaultOverdueService;
 import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
+import com.ning.billing.util.cache.CacheControllerDispatcher;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.entitlement.EntitlementInternalApi;
@@ -58,6 +60,8 @@ public abstract class OverdueTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
     @Inject
     protected EntitlementInternalApi entitlementApi;
     @Inject
+    protected CacheControllerDispatcher cacheControllerDispatcher;
+    @Inject
     protected InternalBus bus;
     @Inject
     protected InternalCallContextFactory internalCallContextFactory;
@@ -80,6 +84,8 @@ public abstract class OverdueTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
     @Inject
     protected OverdueWrapperFactory overdueWrapperFactory;
     @Inject
+    protected NonEntityDao nonEntityDao;
+    @Inject
     protected TestOverdueHelper testOverdueHelper;
 
     @BeforeClass(groups = "slow")
diff --git a/payment/src/test/java/com/ning/billing/payment/TestPaymentHelper.java b/payment/src/test/java/com/ning/billing/payment/TestPaymentHelper.java
index ad3385a..5455ca8 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestPaymentHelper.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestPaymentHelper.java
@@ -26,7 +26,6 @@ import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.mock.api.MockBillCycleDay;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.provider.DefaultNoOpPaymentMethodPlugin;
@@ -114,7 +113,7 @@ public class TestPaymentHelper {
         Mockito.when(account.getPhone()).thenReturn("123-456-7890");
         Mockito.when(account.getEmail()).thenReturn(email);
         Mockito.when(account.getCurrency()).thenReturn(Currency.USD);
-        Mockito.when(account.getBillCycleDay()).thenReturn(new MockBillCycleDay(1));
+        Mockito.when(account.getBillCycleDayLocal()).thenReturn(1);
         Mockito.when(account.isMigrated()).thenReturn(false);
         Mockito.when(account.isNotifiedForInvoices()).thenReturn(false);
 
diff --git a/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java b/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
index a9f0f49..35c7509 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
@@ -44,7 +44,6 @@ import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.jaxrs.json.AccountEmailJson;
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.AccountTimelineJson;
-import com.ning.billing.jaxrs.json.BillCycleDayJson;
 import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
 import com.ning.billing.jaxrs.json.ChargebackJson;
 import com.ning.billing.jaxrs.json.CreditJson;
@@ -908,8 +907,6 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
     public AccountJson getAccountJson(final String name, final String externalKey, final String email) {
         final String accountId = UUID.randomUUID().toString();
         final int length = 4;
-        // Let junction figure it out
-        final BillCycleDayJson billCycleDay = null;
         final String currency = DEFAULT_CURRENCY;
         final String timeZone = "UTC";
         final String address1 = "12 rue des ecoles";
@@ -923,7 +920,7 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         final String phone = "81 53 26 56";
 
         // Note: the accountId payload is ignored on account creation
-        return new AccountJson(accountId, name, length, externalKey, email, billCycleDay, currency, null, timeZone,
+        return new AccountJson(accountId, name, length, externalKey, email, null, currency, null, timeZone,
                                address1, address2, postalCode, company, city, state, country, locale, phone, false, false);
     }
 
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
index b55604c..c1d87c6 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -25,16 +25,12 @@ import java.util.UUID;
 
 import javax.ws.rs.core.Response.Status;
 
-import org.joda.time.DateTime;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.AccountJsonWithBalance;
-import com.ning.billing.jaxrs.json.AccountTimelineJson;
-import com.ning.billing.jaxrs.json.BillCycleDayJson;
 import com.ning.billing.jaxrs.json.CustomFieldJson;
-import com.ning.billing.jaxrs.json.InvoiceJsonSimple;
 import com.ning.billing.jaxrs.json.PaymentJsonSimple;
 import com.ning.billing.jaxrs.json.PaymentMethodJson;
 import com.ning.billing.jaxrs.json.RefundJson;
@@ -64,7 +60,7 @@ public class TestAccount extends TestJaxrsBase {
 
         // Update Account
         final AccountJson newInput = new AccountJson(input.getAccountId(),
-                                                     "zozo", 4, input.getExternalKey(), "rr@google.com", new BillCycleDayJson(18, 18),
+                                                     "zozo", 4, input.getExternalKey(), "rr@google.com", 18,
                                                      "USD", null, "UTC", "bl1", "bh2", "", "", "ca", "San Francisco", "usa", "en", "415-255-2991",
                                                      false, false);
         final AccountJson updatedAccount = updateAccount(input.getAccountId(), newInput);
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java b/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
index 4e59096..38a3086 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/dao/NotificationSqlDao.java
@@ -32,7 +32,7 @@ import org.skife.jdbi.v2.sqlobject.SqlUpdate;
 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.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.UseStringTemplate3StatementLocator;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
 import com.ning.billing.util.callcontext.InternalCallContext;
@@ -44,12 +44,9 @@ import com.ning.billing.util.notificationq.DefaultNotification;
 import com.ning.billing.util.notificationq.Notification;
 import com.ning.billing.util.queue.PersistentQueueEntryLifecycle.PersistentQueueEntryLifecycleState;
 
-@ExternalizedSqlViaStringTemplate3()
+@UseStringTemplate3StatementLocator()
 public interface NotificationSqlDao extends Transactional<NotificationSqlDao>, CloseMe {
 
-    //
-    // APIs for event notifications
-    //
     @SqlQuery
     @Mapper(NotificationSqlMapper.class)
     public List<Notification> getReadyNotifications(@Bind("now") Date now,
@@ -63,8 +60,8 @@ public interface NotificationSqlDao extends Transactional<NotificationSqlDao>, C
 
     @SqlQuery
     @Mapper(NotificationSqlMapper.class)
-    public List<Notification> getNotificationForAccountAndDate(@Bind("accountRecordId") final long accountRecordId,
-                                                               @Bind("effectiveDate") final Date effectiveDate,
+    public List<Notification> getFutureNotificationsForAccount(@Bind("now") Date now,
+                                                               @Bind("queueName") String queueName,
                                                                @InternalTenantContextBinder final InternalTenantContext context);
 
     @SqlUpdate
@@ -84,10 +81,6 @@ public interface NotificationSqlDao extends Transactional<NotificationSqlDao>, C
                                   @InternalTenantContextBinder final InternalCallContext context);
 
     @SqlUpdate
-    public void removeNotificationsByKey(@Bind("notificationKey") String key,
-                                         @InternalTenantContextBinder final InternalCallContext context);
-
-    @SqlUpdate
     public void insertNotification(@Bind(binder = NotificationSqlDaoBinder.class) Notification evt,
                                    @InternalTenantContextBinder final InternalCallContext context);
 
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotification.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotification.java
index c5310a4..7a1ca37 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotification.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotification.java
@@ -148,4 +148,101 @@ public class DefaultNotification extends EntityBase implements Notification {
     public Long getTenantRecordId() {
         return tenantRecordId;
     }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        if (!super.equals(o)) {
+            return false;
+        }
+
+        final DefaultNotification that = (DefaultNotification) o;
+
+        if (ordering != that.ordering) {
+            return false;
+        }
+        if (accountRecordId != null ? !accountRecordId.equals(that.accountRecordId) : that.accountRecordId != null) {
+            return false;
+        }
+        if (createdOwner != null ? !createdOwner.equals(that.createdOwner) : that.createdOwner != null) {
+            return false;
+        }
+        if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
+            return false;
+        }
+        if (futureUserToken != null ? !futureUserToken.equals(that.futureUserToken) : that.futureUserToken != null) {
+            return false;
+        }
+        if (lifecycleState != that.lifecycleState) {
+            return false;
+        }
+        if (nextAvailableDate != null ? !nextAvailableDate.equals(that.nextAvailableDate) : that.nextAvailableDate != null) {
+            return false;
+        }
+        if (notificationKey != null ? !notificationKey.equals(that.notificationKey) : that.notificationKey != null) {
+            return false;
+        }
+        if (notificationKeyClass != null ? !notificationKeyClass.equals(that.notificationKeyClass) : that.notificationKeyClass != null) {
+            return false;
+        }
+        if (owner != null ? !owner.equals(that.owner) : that.owner != null) {
+            return false;
+        }
+        if (queueName != null ? !queueName.equals(that.queueName) : that.queueName != null) {
+            return false;
+        }
+        if (tenantRecordId != null ? !tenantRecordId.equals(that.tenantRecordId) : that.tenantRecordId != null) {
+            return false;
+        }
+        if (userToken != null ? !userToken.equals(that.userToken) : that.userToken != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (int) (ordering ^ (ordering >>> 32));
+        result = 31 * result + (owner != null ? owner.hashCode() : 0);
+        result = 31 * result + (createdOwner != null ? createdOwner.hashCode() : 0);
+        result = 31 * result + (queueName != null ? queueName.hashCode() : 0);
+        result = 31 * result + (nextAvailableDate != null ? nextAvailableDate.hashCode() : 0);
+        result = 31 * result + (lifecycleState != null ? lifecycleState.hashCode() : 0);
+        result = 31 * result + (notificationKeyClass != null ? notificationKeyClass.hashCode() : 0);
+        result = 31 * result + (notificationKey != null ? notificationKey.hashCode() : 0);
+        result = 31 * result + (userToken != null ? userToken.hashCode() : 0);
+        result = 31 * result + (futureUserToken != null ? futureUserToken.hashCode() : 0);
+        result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
+        result = 31 * result + (accountRecordId != null ? accountRecordId.hashCode() : 0);
+        result = 31 * result + (tenantRecordId != null ? tenantRecordId.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("DefaultNotification");
+        sb.append("{ordering=").append(ordering);
+        sb.append(", owner='").append(owner).append('\'');
+        sb.append(", createdOwner='").append(createdOwner).append('\'');
+        sb.append(", queueName='").append(queueName).append('\'');
+        sb.append(", nextAvailableDate=").append(nextAvailableDate);
+        sb.append(", lifecycleState=").append(lifecycleState);
+        sb.append(", notificationKeyClass='").append(notificationKeyClass).append('\'');
+        sb.append(", notificationKey='").append(notificationKey).append('\'');
+        sb.append(", userToken=").append(userToken);
+        sb.append(", futureUserToken=").append(futureUserToken);
+        sb.append(", effectiveDate=").append(effectiveDate);
+        sb.append(", accountRecordId=").append(accountRecordId);
+        sb.append(", tenantRecordId=").append(tenantRecordId);
+        sb.append('}');
+        return sb.toString();
+    }
 }
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
index 208a211..563939e 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultNotificationQueue.java
@@ -18,69 +18,47 @@ package com.ning.billing.util.notificationq;
 
 import java.io.IOException;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
-import org.skife.jdbi.v2.Handle;
 import org.skife.jdbi.v2.IDBI;
-import org.skife.jdbi.v2.tweak.HandleCallback;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import com.ning.billing.ObjectType;
 import com.ning.billing.util.Hostname;
-
-import com.ning.billing.util.cache.Cachable.CacheType;
-import com.ning.billing.util.cache.CacheControllerDispatcher;
 import com.ning.billing.util.callcontext.InternalCallContext;
-import com.ning.billing.util.dao.NonEntityDao;
+import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.entity.dao.EntitySqlDao;
 import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
 import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueHandler;
 import com.ning.billing.util.notificationq.dao.NotificationSqlDao;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.ImmutableList;
 
 public class DefaultNotificationQueue implements NotificationQueue {
 
-    private static final Logger log = LoggerFactory.getLogger(DefaultNotificationQueue.class);
-
-    private final IDBI dbi;
     private final NotificationSqlDao dao;
     private final String hostname;
-
     private final String svcName;
     private final String queueName;
-
-    private final ObjectMapper objectMapper;
-
     private final NotificationQueueHandler handler;
-
     private final NotificationQueueService notificationQueueService;
-    private final NonEntityDao nonEntityDao;
-    private final CacheControllerDispatcher cacheControllerDispatcher;
-
+    private final ObjectMapper objectMapper;
+    private final Clock clock;
 
     private volatile boolean isStarted;
 
     public DefaultNotificationQueue(final String svcName, final String queueName, final NotificationQueueHandler handler,
                                     final IDBI dbi, final NotificationQueueService notificationQueueService,
-                                    final NonEntityDao nonEntityDao, final CacheControllerDispatcher cacheControllerDispatcher) {
+                                    final Clock clock) {
         this.svcName = svcName;
         this.queueName = queueName;
         this.handler = handler;
-        this.dbi = dbi;
-        this.nonEntityDao = nonEntityDao;
-        this.cacheControllerDispatcher = cacheControllerDispatcher;
         this.dao = dbi.onDemand(NotificationSqlDao.class);
         this.hostname = Hostname.get();
         this.notificationQueueService = notificationQueueService;
         this.objectMapper = new ObjectMapper();
+        this.clock = clock;
     }
 
-
     @Override
     public void recordFutureNotification(final DateTime futureNotificationTime,
                                          final NotificationKey notificationKey,
@@ -109,21 +87,20 @@ public class DefaultNotificationQueue implements NotificationQueue {
         thisDao.insertNotification(notification, context);
     }
 
-
-
     @Override
-    public void removeNotificationsByKey(final NotificationKey notificationKey, final InternalCallContext context) {
-        dao.removeNotificationsByKey(notificationKey.toString(), context);
+    public List<Notification> getFutureNotificationsForAccount(final InternalCallContext context) {
+        return getFutureNotificationsForAccountInternal(dao, context);
     }
 
     @Override
-    public List<Notification> getNotificationForAccountAndDate(final UUID accountId, final DateTime effectiveDate, final InternalCallContext context) {
-        final Long accountRecordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID));
-        if (accountId == null) {
-            return ImmutableList.<Notification>of();
-        } else {
-            return dao.getNotificationForAccountAndDate(accountRecordId, effectiveDate.toDate(), context);
-        }
+    public List<Notification> getFutureNotificationsForAccountFromTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao,
+                                                                              final InternalCallContext context) {
+        final NotificationSqlDao transactionalNotificationDao = transactionalDao.transmogrify(NotificationSqlDao.class);
+        return getFutureNotificationsForAccountInternal(transactionalNotificationDao, context);
+    }
+
+    private List<Notification> getFutureNotificationsForAccountInternal(final NotificationSqlDao transactionalDao, final InternalCallContext context) {
+        return transactionalDao.getFutureNotificationsForAccount(clock.getUTCNow().toDate(), getFullQName(), context);
     }
 
     @Override
@@ -132,6 +109,12 @@ public class DefaultNotificationQueue implements NotificationQueue {
     }
 
     @Override
+    public void removeNotificationFromTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao, final UUID notificationId, final InternalCallContext context) {
+        final NotificationSqlDao transactionalNotificationDao = transactionalDao.transmogrify(NotificationSqlDao.class);
+        transactionalNotificationDao.removeNotification(notificationId.toString(), context);
+    }
+
+    @Override
     public String getFullQName() {
         return NotificationQueueServiceBase.getCompositeName(svcName, queueName);
     }
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 d1a31db..88d17cd 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
@@ -18,34 +18,26 @@ package com.ning.billing.util.notificationq;
 
 import org.skife.jdbi.v2.IDBI;
 
-import com.ning.billing.util.cache.CacheControllerDispatcher;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.clock.Clock;
-import com.ning.billing.util.dao.NonEntityDao;
 
 import com.google.inject.Inject;
 
 public class DefaultNotificationQueueService extends NotificationQueueServiceBase {
 
     private final IDBI dbi;
-    private final NonEntityDao nonEntityDao;
-    private final CacheControllerDispatcher cacheControllerDispatcher;
-
 
     @Inject
     public DefaultNotificationQueueService(final IDBI dbi, final Clock clock, final NotificationQueueConfig config,
-                                           final InternalCallContextFactory internalCallContextFactory, final NonEntityDao nonEntityDao, final CacheControllerDispatcher cacheControllerDispatcher) {
+                                           final InternalCallContextFactory internalCallContextFactory) {
         super(clock, config, dbi, internalCallContextFactory);
         this.dbi = dbi;
-        this.nonEntityDao = nonEntityDao;
-        this.cacheControllerDispatcher = cacheControllerDispatcher;
     }
 
-
     @Override
     protected NotificationQueue createNotificationQueueInternal(final String svcName,
                                                                 final String queueName,
                                                                 final NotificationQueueHandler handler) {
-        return new DefaultNotificationQueue(svcName, queueName, handler, dbi, this, nonEntityDao, cacheControllerDispatcher);
+        return new DefaultNotificationQueue(svcName, queueName, handler, dbi, this, clock);
     }
 }
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/DefaultUUIDNotificationKey.java b/util/src/main/java/com/ning/billing/util/notificationq/DefaultUUIDNotificationKey.java
index 2c1203d..59573e1 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/DefaultUUIDNotificationKey.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/DefaultUUIDNotificationKey.java
@@ -13,6 +13,7 @@
  * License for the specific language governing permissions and limitations
  * under the License.
  */
+
 package com.ning.billing.util.notificationq;
 
 import java.util.UUID;
@@ -23,7 +24,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class DefaultUUIDNotificationKey implements NotificationKey {
 
     private final UUID uuidKey;
-    
+
     @JsonCreator
     public DefaultUUIDNotificationKey(@JsonProperty("uuidKey") final UUID uuidKey) {
         this.uuidKey = uuidKey;
@@ -42,19 +43,24 @@ public class DefaultUUIDNotificationKey implements NotificationKey {
     }
 
     @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
+    public boolean equals(final Object obj) {
+        if (this == obj) {
             return true;
-        if (obj == null)
+        }
+        if (obj == null) {
             return false;
-        if (getClass() != obj.getClass())
+        }
+        if (getClass() != obj.getClass()) {
             return false;
-        DefaultUUIDNotificationKey other = (DefaultUUIDNotificationKey) obj;
+        }
+        final DefaultUUIDNotificationKey other = (DefaultUUIDNotificationKey) obj;
         if (uuidKey == null) {
-            if (other.uuidKey != null)
+            if (other.uuidKey != null) {
                 return false;
-        } else if (!uuidKey.equals(other.uuidKey))
+            }
+        } else if (!uuidKey.equals(other.uuidKey)) {
             return false;
+        }
         return true;
     }
 }
diff --git a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java
index 58b49c4..afb4cc5 100644
--- a/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java
+++ b/util/src/main/java/com/ning/billing/util/notificationq/NotificationQueue.java
@@ -55,18 +55,30 @@ public interface NotificationQueue extends QueueLifecycle {
             throws IOException;
 
     /**
-     * Remove all notifications associated with this key
+     * Retrieve all future pending notifications for a given account (taken from the context)
+     * Results are ordered by effective date asc.
+     *
+     * @param context internal call context
+     * @return future notifications matching that key
      */
-    public void removeNotificationsByKey(final NotificationKey notificationKey,
-                                         final InternalCallContext context);
+    public List<Notification> getFutureNotificationsForAccount(final InternalCallContext context);
 
-    public List<Notification> getNotificationForAccountAndDate(final UUID accountId,
-                                                               final DateTime effectiveDate,
-                                                               final InternalCallContext context);
+    /**
+     * Retrieve all future pending notifications for a given account (taken from the context) in a transaction.
+     * Results are ordered by effective date asc.
+     *
+     * @param context internal call context
+     * @return future notifications matching that key
+     */
+    public List<Notification> getFutureNotificationsForAccountFromTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao,
+                                                                              final InternalCallContext context);
 
     public void removeNotification(final UUID notificationId,
                                    final InternalCallContext context);
 
+    public void removeNotificationFromTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao,
+                                                  final UUID notificationId,
+                                                  final InternalCallContext context);
 
     /**
      * @return the name of that queue
diff --git a/util/src/main/java/com/ning/billing/util/queue/PersistentQueueBase.java b/util/src/main/java/com/ning/billing/util/queue/PersistentQueueBase.java
index d3706bb..247cf8f 100644
--- a/util/src/main/java/com/ning/billing/util/queue/PersistentQueueBase.java
+++ b/util/src/main/java/com/ning/billing/util/queue/PersistentQueueBase.java
@@ -41,7 +41,7 @@ public abstract class PersistentQueueBase implements QueueLifecycle {
     private boolean isProcessingEvents;
     private int curActiveThreads;
 
-    protected final ObjectMapper objectMapper;
+    protected static final ObjectMapper objectMapper = new ObjectMapper();
 
     private final AtomicBoolean isStarted = new AtomicBoolean(false);
 
@@ -54,7 +54,6 @@ public abstract class PersistentQueueBase implements QueueLifecycle {
         this.nbThreads = nbThreads;
         this.svcQName = svcQName;
         this.config = config;
-        this.objectMapper = new ObjectMapper();        
         this.isProcessingEvents = false;
         this.curActiveThreads = 0;
         this.isProcessingSuspended = new AtomicBoolean(false);
@@ -188,8 +187,8 @@ public abstract class PersistentQueueBase implements QueueLifecycle {
         return isProcessingSuspended.get();
     }
 
-
-    protected <T> T deserializeEvent(final String className, final String json) {
+    // TODO PIERRE Better API?
+    public static <T> T deserializeEvent(final String className, final String json) {
         try {
             final Class<?> claz = Class.forName(className);
             return (T) objectMapper.readValue(json, claz);
diff --git a/util/src/main/java/com/ning/billing/util/svcapi/junction/BillingEvent.java b/util/src/main/java/com/ning/billing/util/svcapi/junction/BillingEvent.java
index 99e9eeb..9b69fa2 100644
--- a/util/src/main/java/com/ning/billing/util/svcapi/junction/BillingEvent.java
+++ b/util/src/main/java/com/ning/billing/util/svcapi/junction/BillingEvent.java
@@ -22,7 +22,6 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.Plan;
@@ -38,11 +37,11 @@ public interface BillingEvent extends Comparable<BillingEvent> {
     public Account getAccount();
 
     /**
-     * @return the billCycleDay as seen for that subscription at that time
+     * @return the billCycleDay in the account timezone as seen for that subscription at that time
      *         <p/>
      *         Note: The billCycleDay may come from the Account, or the bundle or the subscription itself
      */
-    public BillCycleDay getBillCycleDay();
+    public int getBillCycleDayLocal();
 
     /**
      * @return the subscription
diff --git a/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg
index d2266b9..3b3311e 100644
--- a/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/notificationq/dao/NotificationSqlDao.sql.stg
@@ -44,27 +44,30 @@ getPendingCountNotifications() ::= <<
     ;
 >>
 
-getNotificationForAccountAndDate() ::= <<
-   select
-       record_id
-     , id
-     , class_name
-     , notification_key
-     , user_token
-     , future_user_token
-     , created_date
-     , creating_owner
-     , effective_date
-     , queue_name
-     , processing_owner
-     , processing_available_date
-     , processing_state
-     , account_record_id
-     , tenant_record_id
-   from notifications
-   where
-   account_record_id = :accountRecordId AND effective_date = :effectiveDate
-   ;
+getFutureNotificationsForAccount() ::= <<
+select
+    record_id
+  , id
+  , class_name
+  , notification_key
+  , user_token
+  , future_user_token
+  , created_date
+  , creating_owner
+  , effective_date
+  , queue_name
+  , processing_owner
+  , processing_available_date
+  , processing_state
+  , account_record_id
+  , tenant_record_id
+from notifications
+where queue_name = :queueName
+and processing_state = 'AVAILABLE'
+and account_record_id = :accountRecordId
+and effective_date >= :now
+order by effective_date, record_id
+;
 >>
 
 removeNotification()  ::= <<
diff --git a/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java b/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
index 17137c5..6b0fbd1 100644
--- a/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
+++ b/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
@@ -28,7 +28,6 @@ import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.AccountEmail;
 import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.account.api.MigrationAccountData;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.mock.MockAccountBuilder;
@@ -45,7 +44,7 @@ public class MockAccountUserApi implements AccountUserApi {
                                  final String name,
                                  final int firstNameLength,
                                  final Currency currency,
-                                 final BillCycleDay billCycleDay,
+                                 final int billCycleDayLocal,
                                  final UUID paymentMethodId,
                                  final DateTimeZone timeZone,
                                  final String locale,
@@ -57,13 +56,12 @@ public class MockAccountUserApi implements AccountUserApi {
                                  final String country,
                                  final String postalCode,
                                  final String phone) {
-
         final Account result = new MockAccountBuilder(id)
                 .externalKey(externalKey)
                 .email(email)
                 .name(name).firstNameLength(firstNameLength)
                 .currency(currency)
-                .billingCycleDay(billCycleDay)
+                .billingCycleDayLocal(billCycleDayLocal)
                 .paymentMethodId(paymentMethodId)
                 .timeZone(timeZone)
                 .locale(locale)
diff --git a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
index 8e72a6e..0b447eb 100644
--- a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
+++ b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
@@ -23,7 +23,6 @@ import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.BillCycleDay;
 import com.ning.billing.account.api.MutableAccountData;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.junction.api.BlockingState;
@@ -36,7 +35,7 @@ public class MockAccountBuilder {
     private String name = "";
     private int firstNameLength;
     private Currency currency = Currency.USD;
-    private BillCycleDay billingCycleDay;
+    private int billingCycleDayLocal;
     private UUID paymentMethodId;
     private DateTimeZone timeZone = DateTimeZone.UTC;
     private String locale = "";
@@ -65,7 +64,7 @@ public class MockAccountBuilder {
         this.id = UUID.randomUUID();
         this.address1(data.getAddress1());
         this.address2(data.getAddress2());
-        this.billingCycleDay(data.getBillCycleDay());
+        this.billingCycleDayLocal(data.getBillCycleDayLocal());
         this.city(data.getCity());
         this.companyName(data.getCompanyName());
         this.country(data.getCountry());
@@ -104,8 +103,8 @@ public class MockAccountBuilder {
         return this;
     }
 
-    public MockAccountBuilder billingCycleDay(final BillCycleDay billingCycleDay) {
-        this.billingCycleDay = billingCycleDay;
+    public MockAccountBuilder billingCycleDayLocal(final int billingCycleDayLocal) {
+        this.billingCycleDayLocal = billingCycleDayLocal;
         return this;
     }
 
@@ -225,9 +224,9 @@ public class MockAccountBuilder {
             }
 
             @Override
-            public BillCycleDay getBillCycleDay() {
+            public Integer getBillCycleDayLocal() {
 
-                return billingCycleDay;
+                return billingCycleDayLocal;
             }
 
             @Override
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/dao/TestNotificationSqlDao.java b/util/src/test/java/com/ning/billing/util/notificationq/dao/TestNotificationSqlDao.java
index 1ef9b84..7bab177 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/dao/TestNotificationSqlDao.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/dao/TestNotificationSqlDao.java
@@ -25,7 +25,6 @@ import org.skife.jdbi.v2.Handle;
 import org.skife.jdbi.v2.tweak.HandleCallback;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeSuite;
 import org.testng.annotations.Test;
 
 import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
@@ -96,33 +95,6 @@ public class TestNotificationSqlDao extends UtilTestSuiteWithEmbeddedDB {
         validateDate(notification.getNextAvailableDate(), nextAvailable);
     }
 
-    @Test(groups = "slow")
-    public void testGetByAccountAndDate() throws InterruptedException {
-        final long accountRecordId = 1242L;
-        final String notificationKey = UUID.randomUUID().toString();
-        final DateTime effDt = new DateTime();
-        final Notification notif1 = new DefaultNotification("testBasic1", hostname, notificationKey.getClass().getName(), notificationKey, UUID.randomUUID(), UUID.randomUUID(), effDt,
-                                                            accountRecordId, internalCallContext.getTenantRecordId());
-        dao.insertNotification(notif1, internalCallContext);
-
-        final Notification notif2 = new DefaultNotification("testBasic2", hostname, notificationKey.getClass().getName(), notificationKey, UUID.randomUUID(), UUID.randomUUID(), effDt,
-                                                            accountRecordId, internalCallContext.getTenantRecordId());
-        dao.insertNotification(notif2, internalCallContext);
-
-        List<Notification> notifications = dao.getNotificationForAccountAndDate(accountRecordId, effDt.toDate(), internalCallContext);
-        assertEquals(notifications.size(), 2);
-        for (final Notification cur : notifications) {
-            Assert.assertEquals(cur.getProcessingState(), PersistentQueueEntryLifecycleState.AVAILABLE);
-            dao.removeNotification(cur.getId().toString(), internalCallContext);
-        }
-
-        notifications = dao.getNotificationForAccountAndDate(accountRecordId, effDt.toDate(), internalCallContext);
-        assertEquals(notifications.size(), 2);
-        for (final Notification cur : notifications) {
-            Assert.assertEquals(cur.getProcessingState(), PersistentQueueEntryLifecycleState.REMOVED);
-        }
-    }
-
     private Notification fetchNotification(final String notificationId) {
         return getDBI().withHandle(new HandleCallback<Notification>() {
             @Override
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
index ac267a7..4c5c817 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/MockNotificationQueue.java
@@ -23,6 +23,8 @@ import java.util.List;
 import java.util.TreeSet;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
+
 import org.joda.time.DateTime;
 
 import com.ning.billing.util.Hostname;
@@ -85,51 +87,41 @@ public class MockNotificationQueue implements NotificationQueue {
         recordFutureNotification(futureNotificationTime, notificationKey, context);
     }
 
-
     @Override
-    public void removeNotificationsByKey(final NotificationKey key, final InternalCallContext context) {
-        final List<Notification> toClearNotifications = new ArrayList<Notification>();
-        for (final Notification notification : notifications) {
-            if (notification.getNotificationKey().equals(key.toString())) {
-                toClearNotifications.add(notification);
-            }
-        }
-
-        synchronized (notifications) {
-            if (toClearNotifications.size() > 0) {
-                notifications.removeAll(toClearNotifications);
-            }
-        }
+    public List<Notification> getFutureNotificationsForAccount(final InternalCallContext context) {
+        return getFutureNotificationsForAccountFromTransaction(null, context);
     }
 
     @Override
-    public List<Notification> getNotificationForAccountAndDate(final UUID accountId, final DateTime effectiveDate, final InternalCallContext context) {
-        /*
+    public List<Notification> getFutureNotificationsForAccountFromTransaction(@Nullable final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao,
+                                                                              final InternalCallContext context) {
         final List<Notification> result = new ArrayList<Notification>();
         synchronized (notifications) {
-            for (Notification cur : notifications) {
-                if (cur.getAccountId().equals(accountId) || cur.getEffectiveDate().compareTo(effectiveDate) == 0) {
-                    result.add(cur);
+            for (final Notification notification : notifications) {
+                if (notification.getAccountRecordId().equals(context.getAccountRecordId()) && notification.getEffectiveDate().isAfter(clock.getUTCNow())) {
+                    result.add(notification);
                 }
             }
         }
+
         return result;
-        */
-        return null;
     }
 
-
     @Override
     public void removeNotification(final UUID notificationId, final InternalCallContext context) {
+        removeNotificationFromTransaction(null, notificationId, context);
+    }
+
+    @Override
+    public void removeNotificationFromTransaction(@Nullable final EntitySqlDaoWrapperFactory<EntitySqlDao> transactionalDao, final UUID notificationId, final InternalCallContext context) {
         synchronized (notifications) {
-            for (Notification cur : notifications) {
+            for (final Notification cur : notifications) {
                 if (cur.getId().equals(notificationId)) {
                     notifications.remove(cur);
                     break;
                 }
             }
         }
-
     }
 
     @Override
@@ -169,12 +161,7 @@ public class MockNotificationQueue implements NotificationQueue {
         return isStarted;
     }
 
-
     public List<Notification> getReadyNotifications() {
-        final int result;
-        final List<Notification> processedNotifications = new ArrayList<Notification>();
-        final List<Notification> oldNotifications = new ArrayList<Notification>();
-
         final List<Notification> readyNotifications = new ArrayList<Notification>();
         synchronized (notifications) {
             for (final Notification cur : notifications) {
diff --git a/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java b/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
index 6bd9ed1..3018299 100644
--- a/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
+++ b/util/src/test/java/com/ning/billing/util/notificationq/TestNotificationQueue.java
@@ -29,7 +29,6 @@ import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.BeforeSuite;
 import org.testng.annotations.Test;
 
 import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
@@ -90,6 +89,7 @@ public class TestNotificationQueue extends UtilTestSuiteWithEmbeddedDB {
         super.setup();
         entitySqlDaoTransactionalJdbiWrapper = new EntitySqlDaoTransactionalJdbiWrapper(getDBI(), clock, cacheControllerDispatcher, nonEntityDao);
     }
+
     @Override
     @BeforeMethod(groups = "slow")
     public void setupTest() throws Exception {
@@ -341,95 +341,4 @@ public class TestNotificationQueue extends UtilTestSuiteWithEmbeddedDB {
         Assert.assertTrue(expectedNotificationsFred.get(notificationKeyFred));
         Assert.assertFalse(expectedNotificationsFred.get(notificationKeyBarney));
     }
-
-    @Test(groups = "slow")
-    public void testRemoveNotifications() throws Exception {
-        final UUID key = UUID.randomUUID();
-        final NotificationKey notificationKey = new TestNotificationKey(key.toString());
-        final UUID key2 = UUID.randomUUID();
-        final NotificationKey notificationKey2 = new TestNotificationKey(key2.toString());
-
-        final NotificationQueue queue = queueService.createNotificationQueue("test-svc",
-                                                                             "remove",
-                                                                             new NotificationQueueHandler() {
-                                                                                 @Override
-                                                                                 public void handleReadyNotification(final NotificationKey inputKey, final DateTime eventDateTime, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
-                                                                                     if (inputKey.equals(notificationKey) || inputKey.equals(notificationKey2)) { //ignore stray events from other tests
-                                                                                         log.info("Received notification with key: " + notificationKey);
-                                                                                         eventsReceived++;
-                                                                                     }
-                                                                                 }
-                                                                             });
-        queue.startQueue();
-
-        final DateTime start = clock.getUTCNow().plusHours(1);
-        final int nextReadyTimeIncrementMs = 1000;
-
-        // add 3 events
-
-        entitySqlDaoTransactionalJdbiWrapper.execute(new EntitySqlDaoTransactionWrapper<Void>() {
-            @Override
-            public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
-                queue.recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory, start.plus(nextReadyTimeIncrementMs), notificationKey, internalCallContext);
-                queue.recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory, start.plus(2 * nextReadyTimeIncrementMs), notificationKey, internalCallContext);
-                queue.recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory, start.plus(3 * nextReadyTimeIncrementMs), notificationKey2, internalCallContext);
-                return null;
-            }
-        });
-
-        queue.removeNotificationsByKey(notificationKey, internalCallContext); // should remove 2 of the 3
-
-        // Move time in the future after the notification effectiveDate
-        ((ClockMock) clock).setDeltaFromReality(4000000 + nextReadyTimeIncrementMs * 3);
-
-        try {
-            await().atMost(10, TimeUnit.SECONDS).until(new Callable<Boolean>() {
-                @Override
-                public Boolean call() throws Exception {
-                    return eventsReceived >= 2;
-                }
-            });
-            Assert.fail("There should only have been only one event left in the queue we got: " + eventsReceived);
-        } catch (Exception e) {
-            // expected behavior
-        }
-        log.info("Received " + eventsReceived + " events");
-        queue.stopQueue();
-    }
-
-    static NotificationQueueConfig getNotificationConfig(final boolean off, final long sleepTime) {
-        return new NotificationQueueConfig() {
-            @Override
-            public boolean isProcessingOff() {
-                return off;
-            }
-
-            @Override
-            public int getPrefetchAmount() {
-                return 10;
-            }
-
-            @Override
-            public long getSleepTimeMs() {
-                return sleepTime;
-            }
-        };
-    }
-
-    /*
-    public static class TestNotificationQueueModule extends AbstractModule {
-
-        @Override
-        protected void configure() {
-            bind(Clock.class).to(ClockMock.class).asEagerSingleton();
-
-            final IDBI dbi = getDBI();
-            bind(IDBI.class).toInstance(dbi);
-            final IDBI otherDbi = getDBI();
-            bind(IDBI.class).annotatedWith(Names.named("global-lock")).toInstance(otherDbi);
-            bind(NotificationQueueService.class).to(DefaultNotificationQueueService.class).asEagerSingleton();
-            bind(NotificationQueueConfig.class).toInstance(getNotificationConfig(false, 100));
-        }
-    }
-    */
 }