killbill-memoizeit

Merged killbill-account branch into payment-work branch

12/13/2011 5:43:25 AM

Changes

account/pom.xml 2(+1 -1)

account/src/main/resources/com/ning/billing/account/dao/IAccountDaoSql.sql.stg 60(+0 -60)

api/pom.xml 2(+1 -1)

beatrix/pom.xml 2(+1 -1)

catalog/pom.xml 2(+1 -1)

invoice/pom.xml 38(+37 -1)

invoice/src/main/java/com/ning/billing/invoice/model/TestConsole.java 145(+0 -145)

payment/pom.xml 2(+1 -1)

pom.xml 2(+1 -1)

util/pom.xml 2(+1 -1)

Details

account/pom.xml 2(+1 -1)

diff --git a/account/pom.xml b/account/pom.xml
index 6808744..01b61f9 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-account</artifactId>
diff --git a/account/src/main/java/com/ning/billing/account/api/CustomizableEntityBase.java b/account/src/main/java/com/ning/billing/account/api/CustomizableEntityBase.java
new file mode 100644
index 0000000..076c760
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/CustomizableEntityBase.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.UUID;
+
+public abstract class CustomizableEntityBase extends EntityBase implements CustomizableEntity {
+    protected final FieldStore fields;
+
+    public CustomizableEntityBase(UUID id) {
+        super(id);
+        fields = DefaultFieldStore.create(getId(), getObjectName());
+    }
+
+    @Override
+    public String getFieldValue(String fieldName) {
+        return fields.getValue(fieldName);
+    }
+
+    @Override
+    public void setFieldValue(String fieldName, String fieldValue) {
+        fields.setValue(fieldName, fieldValue);
+    }
+
+    @Override
+    public FieldStore getFields() {
+        return fields;
+    }
+
+    public abstract String getObjectName();
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java b/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java
new file mode 100644
index 0000000..c97a894
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+
+public class DefaultChangedField implements ChangedField {
+    private final String fieldName;
+    private final String oldValue;
+    private final String newValue;
+    private final DateTime changeDate;
+
+    public DefaultChangedField(String fieldName, String oldValue, String newValue) {
+        this.changeDate = new DefaultClock().getUTCNow();
+        this.fieldName = fieldName;
+        this.oldValue = oldValue;
+        this.newValue = newValue;
+    }
+
+    @Override
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    @Override
+    public String getOldValue() {
+        return oldValue;
+    }
+
+    @Override
+    public String getNewValue() {
+        return newValue;
+    }
+
+    @Override
+    public DateTime getChangeDate() {
+        return changeDate;
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultTag.java b/account/src/main/java/com/ning/billing/account/api/DefaultTag.java
new file mode 100644
index 0000000..2732048
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultTag.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+
+public class DefaultTag extends EntityBase implements Tag {
+    private final UUID tagDescriptionId;
+    private final boolean processPayment;
+    private final boolean generateInvoice;
+    private final String addedBy;
+    private final DateTime dateAdded;
+    private final String name;
+
+    public DefaultTag(UUID id, UUID tagDescriptionId, String name, boolean processPayment, boolean generateInvoice,
+                      String addedBy, DateTime dateAdded) {
+        super(id);
+        this.tagDescriptionId = tagDescriptionId;
+        this.name = name;
+        this.processPayment = processPayment;
+        this.generateInvoice = generateInvoice;
+        this.addedBy = addedBy;
+        this.dateAdded = dateAdded;
+    }
+
+    public DefaultTag(UUID id, TagDescription tagDescription, String addedBy, DateTime dateAdded) {
+        this(id, tagDescription.getId(), tagDescription.getName(), tagDescription.getProcessPayment(),
+                tagDescription.getGenerateInvoice(), addedBy, dateAdded);
+    }
+
+    public DefaultTag(TagDescription tagDescription, String addedBy, DateTime dateAdded) {
+        this(UUID.randomUUID(), tagDescription.getId(), tagDescription.getName(), tagDescription.getProcessPayment(),
+                tagDescription.getGenerateInvoice(), addedBy, dateAdded);
+    }
+
+    @Override
+    public UUID getTagDescriptionId() {
+        return tagDescriptionId;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean getProcessPayment() {
+        return processPayment;
+    }
+
+    @Override
+    public boolean getGenerateInvoice() {
+        return generateInvoice;
+    }
+
+    @Override
+    public String getAddedBy() {
+        return addedBy;
+    }
+
+    @Override
+    public DateTime getDateAdded() {
+        return dateAdded;
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultTagDescription.java b/account/src/main/java/com/ning/billing/account/api/DefaultTagDescription.java
new file mode 100644
index 0000000..2f1c407
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultTagDescription.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+
+public class DefaultTagDescription extends EntityBase implements TagDescription {
+    private String name;
+    private String description;
+    private boolean generateInvoice;
+    private boolean processPayment;
+    private String createdBy;
+    private DateTime creationDate;
+
+    public DefaultTagDescription(String name, String description,
+                                 boolean processPayment, boolean generateInvoice,
+                                 String createdBy, DateTime creationDate) {
+        this(UUID.randomUUID(), name, description, processPayment, generateInvoice, createdBy, creationDate);
+    }
+
+    public DefaultTagDescription(UUID id, String name, String description,
+                                 boolean processPayment, boolean generateInvoice,
+                                 String createdBy, DateTime creationDate) {
+        super(id);
+        this.name = name;
+        this.description = description;
+        this.processPayment = processPayment;
+        this.generateInvoice = generateInvoice;
+        this.createdBy = createdBy;
+        this.creationDate = creationDate;
+    }
+    
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getCreatedBy() {
+        return createdBy;
+    }
+
+    @Override
+    public DateTime getCreationDate() {
+        return creationDate;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public boolean getGenerateInvoice() {
+        return generateInvoice;
+    }
+
+    @Override
+    public boolean getProcessPayment() {
+        return processPayment;
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultTagStore.java b/account/src/main/java/com/ning/billing/account/api/DefaultTagStore.java
new file mode 100644
index 0000000..151bb23
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultTagStore.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.UUID;
+
+public class DefaultTagStore extends EntityCollectionBase<Tag> implements TagStore {
+    public DefaultTagStore(UUID objectId, String objectType) {
+        super(objectId, objectType);
+    }
+
+    @Override
+    public String getEntityKey(Tag entity) {
+        return entity.getName();
+    }
+
+    @Override
+    /***
+     * Collates the contents of the TagStore to determine if payments should be processed
+     * @return true is no tags contraindicate payment processing
+     */
+    public boolean processPayment() {
+        for (Tag tag : entities.values()) {
+            if (!tag.getProcessPayment()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /***
+     * Collates the contents of the TagStore to determine if invoices should be generated
+     * @return true is no tags contraindicate invoice generation
+     */
+    @Override
+    public boolean generateInvoice() {
+        for (Tag tag : entities.values()) {
+            if (!tag.getGenerateInvoice()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void remove(String tagName) {
+        entities.remove(entities.get(tagName));
+    }
+
+    @Override
+    public boolean containsTag(String tagName) {
+        for (Tag tag : entities.values()) {
+            if (tag.getName() == tagName) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/account/src/main/java/com/ning/billing/account/api/EntityBase.java b/account/src/main/java/com/ning/billing/account/api/EntityBase.java
new file mode 100644
index 0000000..813be5f
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/EntityBase.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.UUID;
+
+public abstract class EntityBase<T> implements Entity {
+    protected final UUID id;
+
+    public EntityBase(UUID id) {
+        this.id = id;
+    }
+
+    public EntityBase() {
+        this(UUID.randomUUID());
+    }
+
+    @Override
+    public UUID getId() {
+        return id;
+    }
+}
\ No newline at end of file
diff --git a/account/src/main/java/com/ning/billing/account/api/EntityCollectionBase.java b/account/src/main/java/com/ning/billing/account/api/EntityCollectionBase.java
new file mode 100644
index 0000000..c17cf6f
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/EntityCollectionBase.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public abstract class EntityCollectionBase<T extends Entity> implements EntityCollection<T> {
+    protected Map<String, T> entities = new HashMap<String, T>();
+    protected final UUID objectId;
+    protected final String objectType;
+
+    public EntityCollectionBase(UUID objectId, String objectType) {
+        this.objectId = objectId;
+        this.objectType = objectType;
+    }
+
+    @Override
+    public void clear() {
+        entities.clear();
+    }
+
+    @Override
+    public abstract String getEntityKey(T entity);
+
+    @Override
+    public void add(T entity) {
+        entities.put(getEntityKey(entity), entity);
+    }
+
+    @Override
+    public void add(List<T> entities) {
+        for (T entity : entities) {
+            add(entity);
+        }
+    }
+
+    @Override
+    public void remove(T entity) {
+        entities.remove(entity);
+    }
+
+    @Override
+    public List<T> getEntityList() {
+        return new ArrayList<T>(entities.values());
+    }
+//    public void save() {
+//        IEntityCollectionDao<T> dao = getCollectionDao();
+//
+//        dao.save(objectId.toString(), objectType, new ArrayList(entities.values()));
+//    }
+//
+//    public void load() {
+//        IEntityCollectionDao<T> dao = getCollectionDao();
+//
+//        List<T> entities = dao.load(objectId.toString(), objectType);
+//        this.entities.clear();
+//        if (entities != null) {
+//            for (T entity : entities) {
+//                this.entities.put(getEntityKey(entity), entity);
+//            }
+//        }
+//    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/TagBuilder.java b/account/src/main/java/com/ning/billing/account/api/TagBuilder.java
new file mode 100644
index 0000000..8c4f0ab
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/TagBuilder.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+
+public class TagBuilder {
+    private UUID id = UUID.randomUUID();
+    private UUID tagDescriptionId;
+    private String name;
+    private boolean processPayment;
+    private boolean generateInvoice;
+    private String addedBy;
+    private DateTime dateAdded;
+
+    public TagBuilder id(UUID id) {
+        this.id = id;
+        return this;
+    }
+
+    public TagBuilder tagDescriptionId(UUID tagDescriptionId) {
+        this.tagDescriptionId = tagDescriptionId;
+        return this;
+    }
+
+    public TagBuilder name(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public TagBuilder processPayment(boolean processPayment) {
+        this.processPayment = processPayment;
+        return this;
+    }
+
+    public TagBuilder generateInvoice(boolean generateInvoice) {
+        this.generateInvoice = generateInvoice;
+        return this;
+    }
+
+    public TagBuilder addedBy(String addedBy) {
+        this.addedBy = addedBy;
+        return this;
+    }
+
+    public TagBuilder dateAdded(DateTime dateAdded) {
+        this.dateAdded = dateAdded;
+        return this;
+    }
+
+    public Tag build() {
+        return new DefaultTag(id, tagDescriptionId, name, processPayment, generateInvoice, addedBy, dateAdded);
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/AccountBuilder.java b/account/src/main/java/com/ning/billing/account/api/user/AccountBuilder.java
new file mode 100644
index 0000000..873b690
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/user/AccountBuilder.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api.user;
+
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.catalog.api.Currency;
+
+import java.util.UUID;
+
+public class AccountBuilder {
+    private UUID id;
+    private String externalKey;
+    private String email;
+    private String name;
+    private int firstNameLength;
+    private String phone;
+    private Currency currency;
+    private int billingCycleDay;
+    private String paymentProviderName;
+
+    public AccountBuilder() {
+        this(UUID.randomUUID());
+    }
+
+    public AccountBuilder(UUID id) {
+        this.id = id;
+    }
+
+    public AccountBuilder externalKey(String externalKey) {
+        this.externalKey = externalKey;
+        return this;
+    }
+
+    public AccountBuilder email(String email) {
+        this.email = email;
+        return this;
+    }
+
+    public AccountBuilder name(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public AccountBuilder firstNameLength(int firstNameLength) {
+        this.firstNameLength = firstNameLength;
+        return this;
+    }
+
+    public AccountBuilder phone(String phone) {
+        this.phone = phone;
+        return this;
+    }
+
+    public AccountBuilder billingCycleDay(int billingCycleDay) {
+        this.billingCycleDay = billingCycleDay;
+        return this;
+    }
+
+    public AccountBuilder currency(Currency currency) {
+        this.currency = currency;
+        return this;
+    }
+
+    public AccountBuilder paymentProviderName(String paymentProviderName) {
+        this.paymentProviderName = paymentProviderName;
+        return this;
+    }
+
+    public DefaultAccount build() {
+        return new DefaultAccount(id, externalKey, email, name, firstNameLength, phone, currency, billingCycleDay, paymentProviderName);
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/AccountChangeNotificationDefault.java b/account/src/main/java/com/ning/billing/account/api/user/AccountChangeNotificationDefault.java
new file mode 100644
index 0000000..d66c308
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/user/AccountChangeNotificationDefault.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api.user;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountChangeNotification;
+import com.ning.billing.account.api.ChangedField;
+import com.ning.billing.account.api.DefaultChangedField;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class AccountChangeNotificationDefault implements AccountChangeNotification {
+    private final List<ChangedField> changedFields;
+    private final UUID id;
+
+    public AccountChangeNotificationDefault(UUID id, Account oldData, Account newData) {
+        this.id = id;
+        this.changedFields = calculateChangedFields(oldData, newData);
+    }
+
+    @Override
+    public UUID getAccountId() {
+        return id;
+    }
+
+    @Override
+    public List<ChangedField> getChangedFields() {
+        return changedFields;
+    }
+
+    @Override
+    public boolean hasChanges() {
+        return (changedFields.size() > 0);
+    }
+
+    private List<ChangedField> calculateChangedFields(Account oldData, Account newData) {
+        List<ChangedField> changedFields = new ArrayList<ChangedField>();
+
+        if (!newData.getExternalKey().equals(oldData.getExternalKey())) {
+            changedFields.add(new DefaultChangedField("externalKey", oldData.getExternalKey(), newData.getExternalKey()));
+        }
+        if (!newData.getEmail().equals(oldData.getEmail())) {
+            changedFields.add(new DefaultChangedField("email", oldData.getEmail(), newData.getEmail()));
+        }
+        if (!newData.getName().equals(oldData.getName())) {
+            changedFields.add(new DefaultChangedField("firstName", oldData.getName(), newData.getName()));
+        }
+        if (!newData.getPhone().equals(oldData.getPhone())) {
+            changedFields.add(new DefaultChangedField("phone", oldData.getPhone(), newData.getPhone()));
+        }
+        if (!newData.getCurrency().equals(oldData.getCurrency())) {
+            changedFields.add(new DefaultChangedField("currency", oldData.getCurrency().toString(), newData.getCurrency().toString()));
+        }
+        if (newData.getBillCycleDay() != oldData.getBillCycleDay()) {
+            changedFields.add(new DefaultChangedField("billCycleDay", Integer.toString(oldData.getBillCycleDay()),
+                                                               Integer.toString(newData.getBillCycleDay())));
+        }
+        if (!newData.getPaymentProviderName().equals(oldData.getPaymentProviderName())) {
+            changedFields.add((new DefaultChangedField("paymentProviderName", oldData.getPaymentProviderName(), newData.getPaymentProviderName())));
+        }
+
+        return changedFields;
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/AccountCreationEventDefault.java b/account/src/main/java/com/ning/billing/account/api/user/AccountCreationEventDefault.java
new file mode 100644
index 0000000..50bee77
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/user/AccountCreationEventDefault.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api.user;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountCreationNotification;
+import com.ning.billing.account.api.AccountData;
+
+import java.util.UUID;
+
+public class AccountCreationEventDefault implements AccountCreationNotification {
+    private final UUID id;
+    private final AccountData data;
+
+    public AccountCreationEventDefault(Account data) {
+        this.id = data.getId();
+        this.data = data;
+    }
+
+    @Override
+    public UUID getId() {
+        return id;
+    }
+
+    @Override
+    public AccountData getData() {
+        return data;
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/core/Engine.java b/account/src/main/java/com/ning/billing/account/core/Engine.java
new file mode 100644
index 0000000..f95605b
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/core/Engine.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.core;
+
+import com.ning.billing.account.api.AccountService;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+import com.ning.billing.util.eventbus.EventBus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+
+public class Engine implements AccountService {
+    private final static Logger log = LoggerFactory.getLogger(Engine.class);
+
+    private static final String ACCOUNT_SERVICE_NAME = "account-service";
+    private final EventBus eventBus;
+    private final AccountUserApi userApi;
+
+    @Inject
+    public Engine(EventBus eventBus, AccountUserApi userApi) {
+        this.eventBus = eventBus;
+        this.userApi = userApi;
+    }
+
+    @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.INIT_SERVICE)
+    public void initialize() {
+    }
+
+    @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.START_SERVICE)
+    public void start() {
+    }
+
+    @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.STOP_SERVICE)
+    public void stop() {
+    }
+
+    @Override
+    public AccountUserApi getAccountUserApi() {
+        return userApi;
+    }
+
+    @Override
+    public String getName() {
+        return ACCOUNT_SERVICE_NAME;
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
index 32e1d0d..c6cfbf3 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
@@ -16,91 +16,82 @@
 
 package com.ning.billing.account.dao;
 
-import java.util.List;
-import java.util.UUID;
-
-import org.skife.jdbi.v2.IDBI;
-
-import com.google.inject.Inject;
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountData;
-import com.ning.billing.account.api.ICustomField;
-
-public class AccountDao implements IAccountDao {
-
-    private final IAccountDaoSql dao;
-
-    @Inject
-    public AccountDao(IDBI dbi) {
-        this.dao = dbi.onDemand(IAccountDaoSql.class);
-    }
-
-    @Override
-    public IAccount createAccount(IAccountData input) {
-        IAccount result = new Account().withKey(input.getKey());
-        dao.insertAccount(result);
-        return result;
-    }
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.account.api.user.AccountBuilder;
+import com.ning.billing.catalog.api.Currency;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
 
-    @Override
-    public IAccount getAccountByKey(String key) {
-        IAccount account = dao.getAccountByKey(key);
-        if (account != null) {
-            loadFields(account);
-        }
-        return account;
-    }
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(AccountDaoWrapper.AccountMapper.class)
+public interface AccountDao extends EntityDao<Account> {
+    @SqlQuery
+    public Account getAccountByKey(@Bind("externalKey") final String key);
 
     @Override
-    public IAccount getAccountById(UUID uid) {
-        IAccount account = dao.getAccountFromId(uid.toString());
-        if (account != null) {
-            loadFields(account);
+    @SqlUpdate
+    public void save(@AccountBinder Account account);
+
+    public static class AccountMapper implements ResultSetMapper<Account> {
+        @Override
+        public Account map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID id = UUID.fromString(result.getString("id"));
+            String externalKey = result.getString("external_key");
+            String email = result.getString("email");
+            String name = result.getString("name");
+            int firstNameLength = result.getInt("first_name_length");
+            String phone = result.getString("phone");
+            int billingCycleDay = result.getInt("billing_cycle_day");
+            Currency currency = Currency.valueOf(result.getString("currency"));
+            String paymentProviderName = result.getString("payment_provider_name");
+
+            return new AccountBuilder(id).externalKey(externalKey).email(email)
+                                         .name(name).firstNameLength(firstNameLength)
+                                         .phone(phone).currency(currency)
+                                         .billingCycleDay(billingCycleDay)
+                                         .paymentProviderName(paymentProviderName).build();
         }
-        return account;
     }
 
-    private void loadFields(IAccount account) {
-        List<ICustomField> fields = dao.getFields(account.getId().toString(), Account.OBJECT_TYPE);
-        account.getFields().clear();
-        if (fields != null) {
-            for (ICustomField field : fields) {
-                account.getFields().setValue(field.getName(), field.getValue());
+    @BindingAnnotation(AccountBinder.AccountBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface AccountBinder {
+        public static class AccountBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<AccountBinder, DefaultAccount>() {
+                    public void bind(SQLStatement q, AccountBinder bind, DefaultAccount account) {
+                        q.bind("id", account.getId().toString());
+                        q.bind("externalKey", account.getExternalKey());
+                        q.bind("email", account.getEmail());
+                        q.bind("name", account.getName());
+                        q.bind("firstNameLength", account.getFirstNameLength());
+                        q.bind("phone", account.getPhone());
+                        q.bind("currency", account.getCurrency().toString());
+                        q.bind("billingCycleDay", account.getBillCycleDay());
+                        q.bind("paymentProviderName", account.getPaymentProviderName());
+                    }
+                };
             }
         }
     }
-
-    @Override
-    public List<IAccount> getAccounts() {
-        return dao.getAccounts();
-    }
-
-    @Override
-    public void test() {
-        dao.test();
-    }
-
-    @Override
-    public void save(IAccount account) {
-        final String objectId = account.getId().toString();
-        final String objectType = Account.OBJECT_TYPE;
-
-        dao.begin();
-        try {
-            dao.insertAccount(account);
-            List<ICustomField> newFields = account.getFields().getNewFields();
-            dao.createFields(objectId, objectType, newFields);
-            for (ICustomField field : newFields) {
-                field.setAsSaved();
-            }
-
-            dao.saveFields(objectId, objectType, account.getFields().getUpdatedFields());
-            dao.commit();
-        }
-        catch (RuntimeException ex) {
-            dao.rollback();
-            throw ex;
-        }
-    }
 }
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountDaoWrapper.java b/account/src/main/java/com/ning/billing/account/dao/AccountDaoWrapper.java
new file mode 100644
index 0000000..9c819b5
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountDaoWrapper.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import java.util.List;
+import org.skife.jdbi.v2.Handle;
+import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.TransactionCallback;
+import org.skife.jdbi.v2.TransactionStatus;
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountChangeNotification;
+import com.ning.billing.account.api.AccountCreationNotification;
+import com.ning.billing.account.api.CustomField;
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.account.api.FieldStore;
+import com.ning.billing.account.api.Tag;
+import com.ning.billing.account.api.user.AccountChangeNotificationDefault;
+import com.ning.billing.account.api.user.AccountCreationEventDefault;
+import com.ning.billing.util.eventbus.EventBus;
+
+public class AccountDaoWrapper implements AccountDao {
+    private final AccountDao accountDao;
+    private final IDBI dbi; // needed for transaction support
+    private final EventBus eventBus;
+
+    @Inject
+    public AccountDaoWrapper(IDBI dbi, EventBus eventBus) {
+        this.dbi = dbi;
+        this.eventBus = eventBus;
+        this.accountDao = dbi.onDemand(AccountDao.class);
+    }
+
+    @Override
+    public Account getAccountByKey(final String key) {
+        return dbi.inTransaction(new TransactionCallback<Account>() {
+            @Override
+            public Account inTransaction(Handle conn, TransactionStatus status) throws Exception {
+                try {
+                    conn.begin();
+                    Account account = accountDao.getAccountByKey(key);
+
+                    if (account != null) {
+                        FieldStoreDao fieldStoreDao = conn.attach(FieldStoreDao.class);
+                        List<CustomField> fields = fieldStoreDao.load(account.getId().toString(), account.getObjectName());
+
+                        account.getFields().clear();
+                        if (fields != null) {
+                            for (CustomField field : fields) {
+                                account.getFields().setValue(field.getName(), field.getValue());
+                            }
+                        }
+
+                        TagStoreDao tagStoreDao = conn.attach(TagStoreDao.class);
+                        List<Tag> tags = tagStoreDao.load(account.getId().toString(), account.getObjectName());
+                        account.clearTags();
+
+                        if (tags != null) {
+                            account.addTags(tags);
+                        }
+                    }
+
+                    return account;
+                } catch (Throwable t) {
+                    return null;
+                }
+            }
+        });
+    }
+
+    @Override
+    public Account getById(final String id) {
+        return dbi.inTransaction(new TransactionCallback<Account>() {
+            @Override
+            public Account inTransaction(Handle conn, TransactionStatus status) throws Exception {
+                try {
+                    conn.begin();
+                    Account account = accountDao.getById(id);
+
+                    if (account != null) {
+                        FieldStoreDao fieldStoreDao = conn.attach(FieldStoreDao.class);
+                        List<CustomField> fields = fieldStoreDao.load(account.getId().toString(), account.getObjectName());
+
+                        account.getFields().clear();
+                        if (fields != null) {
+                            for (CustomField field : fields) {
+                                account.getFields().setValue(field.getName(), field.getValue());
+                            }
+                        }
+
+                        TagStoreDao tagStoreDao = conn.attach(TagStoreDao.class);
+                        List<Tag> tags = tagStoreDao.load(account.getId().toString(), account.getObjectName());
+                        account.clearTags();
+
+                        if (tags != null) {
+                            account.addTags(tags);
+                        }
+                    }
+
+                    return account;
+                } catch (Throwable t) {
+                    return null;
+                }
+            }
+        });
+    }
+
+    @Override
+    public List<Account> get() {
+        return accountDao.get();
+    }
+
+    @Override
+    public void test() {
+        accountDao.test();
+    }
+
+    @Override
+    public void save(final Account account) {
+        final String accountId = account.getId().toString();
+        final String objectType = DefaultAccount.OBJECT_TYPE;
+
+        dbi.inTransaction(new TransactionCallback<Void>() {
+            @Override
+            public Void inTransaction(Handle conn, TransactionStatus status) throws Exception {
+                try {
+                    conn.begin();
+
+                    AccountDao accountDao = conn.attach(AccountDao.class);
+                    Account currentAccount = accountDao.getById(accountId);
+                    accountDao.save(account);
+
+                    FieldStore fieldStore = account.getFields();
+                    FieldStoreDao fieldStoreDao = conn.attach(FieldStoreDao.class);
+                    fieldStoreDao.save(accountId, objectType, fieldStore.getEntityList());
+
+                    TagStoreDao tagStoreDao = conn.attach(TagStoreDao.class);
+                    tagStoreDao.save(accountId, objectType, account.getTagList());
+
+                    if (currentAccount == null) {
+                        AccountCreationNotification creationEvent = new AccountCreationEventDefault(account);
+                        eventBus.post(creationEvent);
+                    } else {
+                        AccountChangeNotification changeEvent = new AccountChangeNotificationDefault(account.getId(), currentAccount, account);
+                        if (changeEvent.hasChanges()) {
+                            eventBus.post(changeEvent);
+                        }
+                    }
+
+                    conn.commit();
+                } catch (Exception e) {
+                    conn.rollback();
+                    throw e;
+                }
+
+                return null;
+            }
+        });
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java b/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java
index e608f5e..fa3e8e5 100644
--- a/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java
@@ -16,37 +16,63 @@
 
 package com.ning.billing.account.dao;
 
-import com.google.inject.Inject;
-import com.ning.billing.account.api.ICustomField;
-import org.skife.jdbi.v2.IDBI;
-
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.util.List;
+import java.util.UUID;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlBatch;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+import com.ning.billing.account.api.CustomField;
+import com.ning.billing.account.api.StringCustomField;
 
-public class FieldStoreDao implements IFieldStoreDao {
-    private final IFieldStoreDao dao;
-
-    @Inject
-    public FieldStoreDao(IDBI dbi) {
-        dao = dbi.onDemand(IFieldStoreDao.class);
-    }
-
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(FieldStoreDao.CustomFieldMapper.class)
+public interface FieldStoreDao extends EntityCollectionDao<CustomField> {
     @Override
-    public void saveFields(String objectId, String objectType, List<ICustomField> fields) {
-        dao.saveFields(objectId, objectType, fields);
-    }
+    @SqlBatch
+    public void save(@Bind("objectId") final String objectId,
+                     @Bind("objectType") final String objectType,
+                     @CustomFieldBinder final List<CustomField> entities);
 
-    @Override
-    public void createFields(String objectId, String objectType,  List<ICustomField> fields) {
-        dao.createFields(objectId, objectType, fields);
-    }
 
-    @Override
-    public List<ICustomField> getFields(String objectId, String objectType) {
-        return dao.getFields(objectId, objectType);
+    public class CustomFieldMapper implements ResultSetMapper<CustomField> {
+        @Override
+        public CustomField map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID id = UUID.fromString(result.getString("id"));
+            String fieldName = result.getString("field_name");
+            String fieldValue = result.getString("field_value");
+            return new StringCustomField(id, fieldName, fieldValue);
+        }
     }
 
-    @Override
-    public void test() {
-        dao.test();
+    @BindingAnnotation(CustomFieldBinder.CustomFieldBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface CustomFieldBinder {
+        public static class CustomFieldBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<CustomFieldBinder, CustomField>() {
+                    public void bind(SQLStatement q, CustomFieldBinder bind, CustomField customField) {
+                        q.bind("id", customField.getId().toString());
+                        q.bind("fieldName", customField.getName());
+                        q.bind("fieldValue", customField.getValue());
+                    }
+                };
+            }
+        }
     }
 }
diff --git a/account/src/main/java/com/ning/billing/account/dao/FieldStoreDaoWrapper.java b/account/src/main/java/com/ning/billing/account/dao/FieldStoreDaoWrapper.java
new file mode 100644
index 0000000..68c0115
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/FieldStoreDaoWrapper.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import com.google.inject.Inject;
+import com.ning.billing.account.api.CustomField;
+import org.skife.jdbi.v2.IDBI;
+
+import java.util.List;
+
+public class FieldStoreDaoWrapper implements FieldStoreDao {
+    private final FieldStoreDao dao;
+
+    @Inject
+    public FieldStoreDaoWrapper(IDBI dbi) {
+        dao = dbi.onDemand(FieldStoreDao.class);
+    }
+
+    @Override
+    public void save(String objectId, String objectType, List<CustomField> entities) {
+        dao.save(objectId, objectType, entities);
+    }
+
+    @Override
+    public List<CustomField> load(String objectId, String objectType) {
+        return dao.load(objectId, objectType);
+    }
+
+    @Override
+    public void test() {
+        dao.test();
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/dao/TagDescriptionDao.java b/account/src/main/java/com/ning/billing/account/dao/TagDescriptionDao.java
new file mode 100644
index 0000000..2b361ff
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/TagDescriptionDao.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+import com.ning.billing.account.api.DefaultTag;
+import com.ning.billing.account.api.DefaultTagDescription;
+import com.ning.billing.account.api.TagDescription;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(TagDescriptionDao.TagDescriptionMapper.class)
+public interface TagDescriptionDao extends EntityDao<TagDescription> {
+    @Override
+    @SqlUpdate
+    public void save(@TagDescriptionBinder TagDescription entity);
+
+    public class TagDescriptionMapper implements ResultSetMapper<TagDescription> {
+        @Override
+        public TagDescription map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID id = UUID.fromString(result.getString("id"));
+            String name = result.getString("name");
+            String description = result.getString("description");
+            boolean processPayment = result.getBoolean("process_payment");
+            boolean generateInvoice = result.getBoolean("generate_invoice");
+            String createdBy = result.getString("created_by");
+            DateTime creationDate = new DateTime(result.getTimestamp("creation_date"));
+            return new DefaultTagDescription(id, name, description, processPayment, generateInvoice, createdBy, creationDate);
+        }
+    }
+
+    @BindingAnnotation(TagDescriptionBinder.TagDescriptionBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface TagDescriptionBinder {
+        public static class TagDescriptionBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<TagDescriptionBinder, TagDescription>() {
+                    public void bind(SQLStatement q, TagDescriptionBinder bind, TagDescription tagDescription) {
+                        q.bind("id", tagDescription.getId().toString());
+                        q.bind("name", tagDescription.getName());
+                        q.bind("createdBy", tagDescription.getCreatedBy());
+                        q.bind("creationDate", tagDescription.getCreationDate().toDate());
+                        q.bind("description", tagDescription.getDescription());
+                        q.bind("generateInvoice", tagDescription.getGenerateInvoice());
+                        q.bind("processPayment", tagDescription.getProcessPayment());
+                    }
+                };
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/account/src/main/java/com/ning/billing/account/dao/TagStoreDao.java b/account/src/main/java/com/ning/billing/account/dao/TagStoreDao.java
new file mode 100644
index 0000000..ce51954
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/TagStoreDao.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlBatch;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+import com.ning.billing.account.api.DefaultTag;
+import com.ning.billing.account.api.DefaultTagDescription;
+import com.ning.billing.account.api.Tag;
+import com.ning.billing.account.api.TagDescription;
+
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(TagStoreDao.TagMapper.class)
+public interface TagStoreDao extends EntityCollectionDao<Tag> {
+    @Override
+    @SqlBatch
+    public void save(@Bind("objectId") final String objectId,
+                     @Bind("objectType") final String objectType,
+                     @TagBinder final List<Tag> entities);
+
+    public class TagMapper implements ResultSetMapper<Tag> {
+        @Override
+        public Tag map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID tagDescriptionId = UUID.fromString(result.getString("tag_description_id"));
+            String name = result.getString("tag_description_name");
+            String description = result.getString("tag_description");
+            boolean processPayment = result.getBoolean("process_payment");
+            boolean generateInvoice = result.getBoolean("generate_invoice");
+            String createdBy = result.getString("created_by");
+            DateTime creationDate = new DateTime(result.getDate("creation_date"));
+            TagDescription tagDescription = new DefaultTagDescription(tagDescriptionId, name, description, processPayment, generateInvoice, createdBy, creationDate);
+
+            UUID id = UUID.fromString(result.getString("id"));
+            String addedBy = result.getString("added_by");
+            DateTime dateAdded = new DateTime(result.getTimestamp("date_added"));
+            return new DefaultTag(id, tagDescription, addedBy, dateAdded);
+        }
+    }
+
+    @BindingAnnotation(TagBinder.TagBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface TagBinder {
+        public static class TagBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<TagBinder, Tag>() {
+                    public void bind(SQLStatement q, TagBinder bind, Tag tag) {
+                        q.bind("id", tag.getId().toString());
+                        q.bind("tagDescriptionId", tag.getTagDescriptionId().toString());
+                        q.bind("dateAdded", tag.getDateAdded().toDate());
+                        q.bind("addedBy", tag.getAddedBy());
+                    }
+                };
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/account/src/main/java/com/ning/billing/account/dao/TagStoreDaoWrapper.java b/account/src/main/java/com/ning/billing/account/dao/TagStoreDaoWrapper.java
new file mode 100644
index 0000000..6fe4087
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/TagStoreDaoWrapper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import java.util.List;
+import org.skife.jdbi.v2.IDBI;
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Tag;
+
+public class TagStoreDaoWrapper implements TagStoreDao {
+    private final TagStoreDao dao;
+
+    @Inject
+    public TagStoreDaoWrapper(IDBI dbi) {
+        dao = dbi.onDemand(TagStoreDao.class);
+    }
+
+    @Override
+    public void save(String objectId, String objectType, List<Tag> entities) {
+        dao.save(objectId, objectType, entities);
+    }
+
+    @Override
+    public List<Tag> load(String objectId, String objectType) {
+        return dao.load(objectId, objectType);
+    }
+
+    @Override
+    public void test() {
+        dao.test();
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
index 1257928..5c191c2 100644
--- a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
+++ b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
@@ -16,49 +16,52 @@
 
 package com.ning.billing.account.glue;
 
-import org.skife.config.ConfigurationObjectFactory;
-
 import com.google.inject.AbstractModule;
-import com.ning.billing.account.api.AccountService;
 import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.account.api.IAccountService;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.user.DefaultAccountUserApi;
 import com.ning.billing.account.dao.AccountDao;
+import com.ning.billing.account.dao.AccountDaoWrapper;
 import com.ning.billing.account.dao.FieldStoreDao;
-import com.ning.billing.account.dao.IAccountDao;
-import com.ning.billing.account.dao.IFieldStoreDao;
+import com.ning.billing.account.dao.FieldStoreDaoWrapper;
+import com.ning.billing.account.dao.TagStoreDao;
+import com.ning.billing.account.dao.TagStoreDaoWrapper;
+import org.skife.config.ConfigurationObjectFactory;
 
 public class AccountModule extends AbstractModule {
 
-    protected void installConfig() {
-        final IAccountConfig config = new ConfigurationObjectFactory(System.getProperties()).build(IAccountConfig.class);
-        bind(IAccountConfig.class).toInstance(config);
+    private void installConfig() {
+        final AccountConfig config = new ConfigurationObjectFactory(System.getProperties()).build(AccountConfig.class);
+        bind(AccountConfig.class).toInstance(config);
     }
 
-    protected void installAccountDao() {
-        bind(IAccountDao.class).to(AccountDao.class).asEagerSingleton();
-//        bind(IAccountDaoSql.class).to(IAccountDaoSql.class).asEagerSingleton();
+    private void installAccountCore() {
+//        bind(IAccountService.class).to(Engine.class).asEagerSingleton();
+//        bind(Engine.class).asEagerSingleton();
     }
 
-    protected void installAccountUserApi() {
-        bind(IAccountUserApi.class).to(AccountUserApi.class).asEagerSingleton();
+    private void installAccountDao() {
+        bind(AccountDao.class).to(AccountDaoWrapper.class).asEagerSingleton();
     }
 
-    protected void installAccountService() {
-        bind(IAccountService.class).to(AccountService.class).asEagerSingleton();
+    private void installAccountUserApi() {
+        bind(AccountUserApi.class).to(DefaultAccountUserApi.class).asEagerSingleton();
     }
 
-    protected void installFieldStore() {
-        bind(IFieldStoreDao.class).to(FieldStoreDao.class).asEagerSingleton();
-    }
+//    private void installFieldStore() {
+//        bind(FieldStoreDao.class).to(FieldStoreDaoWrapper.class).asEagerSingleton();
+//    }
+//
+//    private void installTagStore() {
+//        bind(TagStoreDao.class).to(TagStoreDaoWrapper.class).asEagerSingleton();
+//    }
 
     @Override
     protected void configure() {
         installConfig();
+        installAccountCore();
         installAccountDao();
         installAccountUserApi();
-        installAccountService();
-        installFieldStore();
+//        installFieldStore();
+//        installTagStore();
     }
-
 }
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountDao.sql.stg
new file mode 100644
index 0000000..33d60b8
--- /dev/null
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountDao.sql.stg
@@ -0,0 +1,33 @@
+group AccountDaoSql;
+
+save() ::= <<
+    INSERT INTO accounts
+    (id, external_key, email, name, first_name_length, phone, currency, billing_cycle_day, payment_provider_name)
+    VALUES
+    (:id, :externalKey, :email, :name, :firstNameLength, :phone, :currency, :billingCycleDay, :paymentProviderName)
+    ON DUPLICATE KEY UPDATE
+      external_key = :externalKey, email = :email, name = :name, first_name_length = :firstNameLength,
+      phone = :phone, currency = :currency, payment_provider_name = :paymentProviderName;
+>>
+
+getAccountByKey() ::= <<
+    select id, external_key, email, name, first_name_length, phone, currency, billing_cycle_day, payment_provider_name
+    from accounts
+    where external_key = :externalKey;
+>>
+
+getById() ::= <<
+    select id, external_key, email, name, first_name_length, phone, currency, billing_cycle_day, payment_provider_name
+    from accounts
+    where id = :id;
+>>
+
+get() ::= <<
+    select id, external_key, email, name, first_name_length, phone, currency, billing_cycle_day, payment_provider_name
+    from accounts;
+>>
+
+test() ::= <<
+    select 1 from accounts;
+>>
+;
\ No newline at end of file
diff --git a/account/src/main/resources/com/ning/billing/account/dao/FieldStoreDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/FieldStoreDao.sql.stg
new file mode 100644
index 0000000..c995694
--- /dev/null
+++ b/account/src/main/resources/com/ning/billing/account/dao/FieldStoreDao.sql.stg
@@ -0,0 +1,20 @@
+group IFieldStoreDao;
+
+save() ::= <<
+  INSERT INTO custom_fields(id, object_id, object_type, field_name, field_value)
+  VALUES (:id, :objectId, :objectType, :fieldName, :fieldValue)
+  ON DUPLICATE KEY UPDATE
+    field_value = :fieldValue;
+>>
+
+load() ::= <<
+    SELECT id, field_name, field_value
+    FROM custom_fields
+    WHERE object_id = :objectId AND object_type = :objectType;
+>>
+
+test() ::= <<
+  SELECT 1 FROM custom_fields;
+>>
+;
+
diff --git a/account/src/main/resources/com/ning/billing/account/dao/TagDescriptionDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/TagDescriptionDao.sql.stg
new file mode 100644
index 0000000..bdde261
--- /dev/null
+++ b/account/src/main/resources/com/ning/billing/account/dao/TagDescriptionDao.sql.stg
@@ -0,0 +1,19 @@
+group TagDescriptionDao;
+
+save() ::= <<
+  INSERT INTO tag_descriptions(id, name, created_by, creation_date, description, generate_invoice, process_payment)
+  VALUES(:id, :name, :createdBy, :creationDate, :description, :generateInvoice, :processPayment)
+  ON DUPLICATE KEY UPDATE
+    name = :name, created_by = :createdBy, creation_date = :creationDate,
+    description := description, generate_invoice = :generateInvoice,
+    process_payment = :processPayment
+>>
+
+load() ::= <<
+  SELECT id, name, created_by, creation_date, description, generate_invoice, process_payment
+  FROM tag_descriptions
+  WHERE id = :id;
+>>
+;
+
+
diff --git a/account/src/main/resources/com/ning/billing/account/dao/TagStoreDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/TagStoreDao.sql.stg
new file mode 100644
index 0000000..3b53b2e
--- /dev/null
+++ b/account/src/main/resources/com/ning/billing/account/dao/TagStoreDao.sql.stg
@@ -0,0 +1,23 @@
+group TagStoreDao;
+
+save() ::= <<
+  INSERT INTO tags(id, tag_description_id, object_id, object_type, date_added, added_by)
+  VALUES (:id, :tagDescriptionId, :objectId, :objectType, :dateAdded, :addedBy)
+  ON DUPLICATE KEY UPDATE
+    tag_description_id = :tagDescriptionId, object_id = :objectId, object_type = :objectType,
+    date_added = :dateAdded, added_by = :addedBy;
+>>
+
+load() ::= <<
+    SELECT t.id, t.tag_description_id, t.object_id, t.object_type, t.date_added, t.added_by,
+           td.name AS tag_description_name, td.description AS tag_description, td.process_payment, td.generate_invoice,
+           td.created_by, td.creation_date
+    FROM tags t
+    INNER JOIN tag_descriptions td ON t.tag_description_id = td.id
+    WHERE t.object_id = :objectId AND t.object_type = :objectType;
+>>
+
+test() ::= <<
+  SELECT 1 FROM tags;
+>>
+;
\ No newline at end of file
diff --git a/account/src/main/resources/com/ning/billing/account/ddl.sql b/account/src/main/resources/com/ning/billing/account/ddl.sql
index 92f6bd0..9bc2a03 100644
--- a/account/src/main/resources/com/ning/billing/account/ddl.sql
+++ b/account/src/main/resources/com/ning/billing/account/ddl.sql
@@ -1,10 +1,18 @@
 DROP TABLE IF EXISTS accounts;
 CREATE TABLE accounts (
     id char(36) NOT NULL,
-    key_name varchar(128) NOT NULL,
-
+    external_key varchar(128) NULL,
+    email varchar(50) DEFAULT NULL,
+    name varchar(100) NOT NULL,
+    first_name_length int NOT NULL,
+    phone varchar(13) DEFAULT NULL,
+    currency char(3) NOT NULL,
+    billing_cycle_day int NOT NULL,
+    payment_provider_name varchar(20),
     PRIMARY KEY(id)
 ) ENGINE=innodb;
+CREATE UNIQUE INDEX accounts_external_key ON accounts(external_key);
+CREATE UNIQUE INDEX accounts_email ON accounts(email);
 
 DROP TABLE IF EXISTS custom_fields;
 CREATE TABLE custom_fields (
@@ -15,5 +23,31 @@ CREATE TABLE custom_fields (
   field_value varchar(255) NOT NULL,
   PRIMARY KEY(id)
 ) ENGINE=innodb;
+CREATE INDEX custom_fields_object_id_object_type ON custom_fields(object_id, object_type);
+CREATE UNIQUE INDEX custom_fields_unique ON custom_fields(object_id, object_type, field_name);
+
+DROP TABLE IF EXISTS tag_descriptions;
+CREATE TABLE tag_descriptions (
+  id char(36) NOT NULL,
+  name varchar(20) NOT NULL,
+  created_by varchar(50) NOT NULL,
+  creation_date datetime NOT NULL,
+  description varchar(200) NOT NULL,
+  generate_invoice boolean DEFAULT false,
+  process_payment boolean DEFAULT false,
+  PRIMARY KEY(id)
+) ENGINE=innodb;
+CREATE UNIQUE INDEX tag_descriptions_name ON tag_descriptions(name);
 
-CREATE INDEX custom_fields_object_id_object_type ON custom_fields(object_id, object_type);
\ No newline at end of file
+DROP TABLE IF EXISTS tags;
+CREATE TABLE tags (
+  id char(36) NOT NULL,
+  tag_description_id char(36) NOT NULL,
+  object_id char(36) NOT NULL,
+  object_type varchar(30) NOT NULL,
+  date_added datetime NOT NULL,
+  added_by varchar(50) NOT NULL,
+  PRIMARY KEY(id)
+) ENGINE = innodb;
+CREATE INDEX tags_by_object ON tags(object_id);
+CREATE UNIQUE INDEX tags_unique ON tags(tag_description_id, object_id);
\ No newline at end of file
diff --git a/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java b/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java
index e367ba0..52aa9db 100644
--- a/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java
+++ b/account/src/test/java/com/ning/billing/account/api/MockAccountUserApi.java
@@ -21,25 +21,20 @@ import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
 
-public class MockAccountUserApi implements IAccountUserApi {
-    private final CopyOnWriteArrayList<IAccount> accounts = new CopyOnWriteArrayList<IAccount>();
+public class MockAccountUserApi implements AccountUserApi {
+    private final CopyOnWriteArrayList<Account> accounts = new CopyOnWriteArrayList<Account>();
 
     @Override
-    public IAccount createAccount(IAccountData data) {
-        IAccount result = new Account().withKey(data.getKey())
-                                       .withName(data.getName())
-                                       .withEmail(data.getEmail())
-                                       .withPhone(data.getPhone())
-                                       .withBillCycleDay(data.getBillCycleDay())
-                                       .withCurrency(data.getCurrency());
+    public Account createAccount(AccountData data) {
+        Account result = new DefaultAccount(data);
         accounts.add(result);
         return result;
     }
 
     @Override
-    public IAccount getAccountByKey(String key) {
-        for (IAccount account : accounts) {
-            if (key.equals(account.getKey())) {
+    public Account getAccountByKey(String key) {
+        for (Account account : accounts) {
+            if (key.equals(account.getExternalKey())) {
                 return account;
             }
         }
@@ -47,8 +42,8 @@ public class MockAccountUserApi implements IAccountUserApi {
     }
 
     @Override
-    public IAccount getAccountFromId(UUID uid) {
-        for (IAccount account : accounts) {
+    public Account getAccountById(UUID uid) {
+        for (Account account : accounts) {
             if (uid.equals(account.getId())) {
                 return account;
             }
@@ -57,8 +52,12 @@ public class MockAccountUserApi implements IAccountUserApi {
     }
 
     @Override
-    public List<IAccount> getAccounts() {
-        return new ArrayList<IAccount>(accounts);
+    public List<Account> getAccounts() {
+        return new ArrayList<Account>(accounts);
     }
 
+    @Override
+    public void saveAccount(Account account) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
new file mode 100644
index 0000000..d191a0e
--- /dev/null
+++ b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.account.glue.AccountModuleMock;
+import com.ning.billing.util.eventbus.DefaultEventBusService;
+import com.ning.billing.util.eventbus.EventBusService;
+import org.apache.commons.io.IOUtils;
+import org.skife.jdbi.v2.IDBI;
+import org.testng.annotations.BeforeClass;
+
+import java.io.IOException;
+
+import static org.testng.Assert.fail;
+
+public abstract class AccountDaoTestBase {
+    //protected FieldStoreDao fieldStoreDao;
+    protected AccountDao accountDao;
+    protected IDBI dbi;
+
+    @BeforeClass(alwaysRun = true)
+    protected void setup() throws IOException {
+        // Healthcheck test to make sure MySQL is setup properly
+        try {
+            AccountModuleMock module = new AccountModuleMock();
+            final String ddl = IOUtils.toString(AccountDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
+            module.createDb(ddl);
+
+            final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
+
+            //fieldStoreDao = injector.getInstance(FieldStoreDao.class);
+            //fieldStoreDao.test();
+
+            dbi = injector.getInstance(IDBI.class);
+
+            accountDao = injector.getInstance(AccountDao.class);
+            accountDao.test();
+
+            EventBusService busService = injector.getInstance(EventBusService.class);
+            ((DefaultEventBusService) busService).startBus();
+        }
+        catch (Throwable t) {
+            fail(t.toString());
+        }
+    }
+}
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java b/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java
new file mode 100644
index 0000000..398df58
--- /dev/null
+++ b/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.dao;
+
+import java.util.UUID;
+import org.testng.annotations.Test;
+import com.ning.billing.account.api.DefaultFieldStore;
+import com.ning.billing.account.api.FieldStore;
+
+import static org.testng.Assert.assertEquals;
+
+@Test(groups={"account-dao"})
+public class TestFieldStore extends AccountDaoTestBase {
+    @Test
+    public void testFieldStore() {
+        UUID id = UUID.randomUUID();
+        String objectType = "Test widget";
+
+        FieldStore fieldStore = new DefaultFieldStore(id, objectType);
+
+        String fieldName = "TestField1";
+        String fieldValue = "Kitty Hawk";
+        fieldStore.setValue(fieldName, fieldValue);
+
+        FieldStoreDao fieldStoreDao = dbi.onDemand(FieldStoreDao.class);
+        fieldStoreDao.save(id.toString(), objectType, fieldStore.getEntityList());
+
+        fieldStore = DefaultFieldStore.create(id, objectType);
+        fieldStore.add(fieldStoreDao.load(id.toString(), objectType));
+
+        assertEquals(fieldStore.getValue(fieldName), fieldValue);
+
+        fieldValue = "Cape Canaveral";
+        fieldStore.setValue(fieldName, fieldValue);
+        assertEquals(fieldStore.getValue(fieldName), fieldValue);
+        fieldStoreDao.save(id.toString(), objectType, fieldStore.getEntityList());
+
+        fieldStore = DefaultFieldStore.create(id, objectType);
+        assertEquals(fieldStore.getValue(fieldName), null);
+        fieldStore.add(fieldStoreDao.load(id.toString(), objectType));
+
+        assertEquals(fieldStore.getValue(fieldName), fieldValue);
+    }
+}
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
index b18b600..33b67d8 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
@@ -16,96 +16,115 @@
 
 package com.ning.billing.account.dao;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.IOException;
 import java.util.List;
 import java.util.UUID;
-
-import org.apache.commons.io.IOUtils;
-import org.testng.annotations.BeforeClass;
+import org.joda.time.DateTime;
 import org.testng.annotations.Test;
-
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Stage;
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.glue.AccountModuleMock;
-
-@Test(groups = {"Account", "Account-DAO"})
-public class TestSimpleAccountDao {
-    private IAccountDao dao;
-
-    @BeforeClass(alwaysRun = true)
-    private void setup() throws IOException {
-        AccountModuleMock module = new AccountModuleMock();
-        final String ddl = IOUtils.toString(IAccountDaoSql.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
-        module.createDb(ddl);
-
-        // Healthcheck test to make sure MySQL is setup properly
-        try {
-            final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
-
-            dao = injector.getInstance(IAccountDao.class);
-            dao.test();
-        }
-        catch (Throwable t) {
-            fail(t.toString());
-        }
+import com.ning.billing.account.api.DefaultAccount;
+import com.ning.billing.account.api.DefaultTagDescription;
+import com.ning.billing.account.api.Tag;
+import com.ning.billing.account.api.TagDescription;
+import com.ning.billing.account.api.user.AccountBuilder;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.clock.DefaultClock;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = {"account-dao"})
+public class TestSimpleAccountDao extends AccountDaoTestBase {
+    private final String key = "test1234";
+    private final String firstName = "Wesley";
+    private final String email = "me@me.com";
+
+    private DefaultAccount createTestAccount() {
+        String thisKey = key + UUID.randomUUID().toString();
+        String lastName = UUID.randomUUID().toString();
+        String thisEmail = email + " " + UUID.randomUUID();
+        String name = firstName + " " + lastName;
+
+        int firstNameLength = firstName.length();
+        return new AccountBuilder().externalKey(thisKey).name(name).firstNameLength(firstNameLength)
+                                   .email(thisEmail).currency(Currency.USD).build();
     }
 
-    @Test(enabled=true, groups={"Account-DAO"})
     public void testBasic() {
 
-        IAccount a = new Account().withKey("foo");
-        dao.createAccount(a);
+        Account a = createTestAccount();
+        accountDao.save(a);
+        String key = a.getExternalKey();
 
-        IAccount r = dao.getAccountByKey("foo");
+        Account r = accountDao.getAccountByKey(key);
         assertNotNull(r);
-        assertEquals(r.getKey(), a.getKey());
+        assertEquals(r.getExternalKey(), a.getExternalKey());
 
-        r = dao.getAccountById(r.getId());
+        r = accountDao.getById(r.getId().toString());
         assertNotNull(r);
-        assertEquals(r.getKey(), a.getKey());
+        assertEquals(r.getExternalKey(), a.getExternalKey());
 
-        List<IAccount> all = dao.getAccounts();
+        List<Account> all = accountDao.get();
         assertNotNull(all);
         assertTrue(all.size() >= 1);
     }
 
     @Test
     public void testGetById() {
-        String key = "test1234";
-
-        IAccount account = Account.create().withKey(key);
+        Account account = createTestAccount();
         UUID id = account.getId();
+        String key = account.getExternalKey();
+        String name = account.getName();
+        int firstNameLength = account.getFirstNameLength();
 
-        dao.save(account);
+        accountDao.save(account);
 
-        account = dao.getAccountById(id);
+        account = accountDao.getById(id.toString());
         assertNotNull(account);
         assertEquals(account.getId(), id);
-        assertEquals(account.getKey(), key);
+        assertEquals(account.getExternalKey(), key);
+        assertEquals(account.getName(), name);
+        assertEquals(account.getFirstNameLength(), firstNameLength);
+
     }
 
     @Test
     public void testCustomFields() {
-        String key = "test45678";
-        IAccount account = Account.create().withKey(key);
-
+        Account account = createTestAccount();
         String fieldName = "testField1";
         String fieldValue = "testField1_value";
         account.setFieldValue(fieldName, fieldValue);
 
-        dao.save(account);
+        accountDao.save(account);
 
-        account = dao.getAccountByKey(key);
-        assertNotNull(account);
-        assertEquals(account.getKey(), key);
-        assertEquals(account.getFieldValue(fieldName), fieldValue);
+        Account thisAccount = accountDao.getAccountByKey(account.getExternalKey());
+        assertNotNull(thisAccount);
+        assertEquals(thisAccount.getExternalKey(), account.getExternalKey());
+        assertEquals(thisAccount.getFieldValue(fieldName), fieldValue);
+    }
+
+    @Test
+    public void testTags() {
+        Account account = createTestAccount();
+        TagDescription description = new DefaultTagDescription("Test Tag", "For testing only", true, true, "Test System", new DateTime());
+        TagDescriptionDao tagDescriptionDao = dbi.onDemand(TagDescriptionDao.class);
+        tagDescriptionDao.save(description);
+
+        String addedBy = "testTags()";
+        DateTime dateAdded = new DefaultClock().getUTCNow();
+        account.addTag(description, addedBy, dateAdded);
+        assertEquals(account.getTagList().size(), 1);
+        accountDao.save(account);
+
+        Account thisAccount = accountDao.getById(account.getId().toString());
+        List<Tag> tagList = thisAccount.getTagList();
+        assertEquals(tagList.size(), 1);
+        Tag tag = tagList.get(0);
+        assertEquals(tag.getName(), description.getName());
+        assertEquals(tag.getGenerateInvoice(), description.getGenerateInvoice());
+        assertEquals(tag.getProcessPayment(), description.getProcessPayment());
+        assertEquals(tag.getTagDescriptionId(), description.getId());
+        assertEquals(tag.getAddedBy(), addedBy);
+        assertEquals(tag.getDateAdded().compareTo(dateAdded), 0);
     }
 }
diff --git a/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java b/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java
index 7f92ad2..54a761e 100644
--- a/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java
+++ b/account/src/test/java/com/ning/billing/account/glue/AccountModuleMock.java
@@ -17,6 +17,7 @@
 package com.ning.billing.account.glue;
 
 import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.util.glue.EventBusModule;
 import org.skife.jdbi.v2.IDBI;
 
 import java.io.IOException;
@@ -33,5 +34,6 @@ public class AccountModuleMock extends AccountModule {
     protected void configure() {
         bind(IDBI.class).toInstance(helper.getDBI());
         super.configure();
+        install(new EventBusModule());
     }
 }
diff --git a/analytics/pom.xml b/analytics/pom.xml
index 5bd608a..692fded 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-analytics</artifactId>
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
index 7c5a6da..185289a 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountRecorder.java
@@ -17,8 +17,8 @@
 package com.ning.billing.analytics;
 
 import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.analytics.dao.BusinessAccountDao;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,20 +28,20 @@ public class BusinessAccountRecorder
     private static final Logger log = LoggerFactory.getLogger(BusinessAccountRecorder.class);
 
     private final BusinessAccountDao dao;
-    private final IAccountUserApi accountApi;
+    private final AccountUserApi accountApi;
 
     @Inject
-    public BusinessAccountRecorder(final BusinessAccountDao dao, final IAccountUserApi accountApi)
+    public BusinessAccountRecorder(final BusinessAccountDao dao, final AccountUserApi accountApi)
     {
         this.dao = dao;
         this.accountApi = accountApi;
     }
 
-    public void subscriptionCreated(final IAccount created)
+    public void subscriptionCreated(final Account created)
     {
     }
 
-    public void subscriptionUpdated(final IAccount updated)
+    public void subscriptionUpdated(final Account updated)
     {
     }
 }
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
index 71e3402..baacad8 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
@@ -17,14 +17,7 @@
 package com.ning.billing.analytics;
 
 import com.ning.billing.analytics.utils.Rounder;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.catalog.api.TimeUnit;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.user.Subscription;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
index e55bc8c..33b8f4d 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionTransitionRecorder.java
@@ -17,8 +17,8 @@
 package com.ning.billing.analytics;
 
 import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDao;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
@@ -36,10 +36,10 @@ public class BusinessSubscriptionTransitionRecorder
 
     private final BusinessSubscriptionTransitionDao dao;
     private final EntitlementUserApi entitlementApi;
-    private final IAccountUserApi accountApi;
+    private final AccountUserApi accountApi;
 
     @Inject
-    public BusinessSubscriptionTransitionRecorder(final BusinessSubscriptionTransitionDao dao, final EntitlementUserApi entitlementApi, final IAccountUserApi accountApi)
+    public BusinessSubscriptionTransitionRecorder(final BusinessSubscriptionTransitionDao dao, final EntitlementUserApi entitlementApi, final AccountUserApi accountApi)
     {
         this.dao = dao;
         this.entitlementApi = entitlementApi;
@@ -93,9 +93,9 @@ public class BusinessSubscriptionTransitionRecorder
         if (bundle != null) {
             transitionKey = bundle.getKey();
 
-            final IAccount account = accountApi.getAccountFromId(bundle.getAccountId());
+            final Account account = accountApi.getAccountById(bundle.getAccountId());
             if (account != null) {
-                accountKey = account.getKey();
+                accountKey = account.getExternalKey();
                 currency = account.getCurrency();
             }
         }
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
index 374f296..9db1b75 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessSubscriptionTransitionBinder.java
@@ -23,11 +23,7 @@ import org.skife.jdbi.v2.sqlobject.Binder;
 import org.skife.jdbi.v2.sqlobject.BinderFactory;
 import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
 
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
 import java.sql.Types;
 
 @BindingAnnotation(BusinessSubscriptionTransitionBinder.BstBinderFactory.class)
diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index d3563c6..b192698 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -17,31 +17,13 @@
 package com.ning.billing.analytics.api;
 
 import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
-import com.ning.billing.analytics.AnalyticsTestModule;
-import com.ning.billing.analytics.BusinessSubscription;
-import com.ning.billing.analytics.BusinessSubscriptionEvent;
-import com.ning.billing.analytics.BusinessSubscriptionTransition;
-import com.ning.billing.analytics.MockAccount;
-import com.ning.billing.analytics.MockDuration;
-import com.ning.billing.analytics.MockPhase;
-import com.ning.billing.analytics.MockPlan;
-import com.ning.billing.analytics.MockProduct;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.analytics.*;
 import com.ning.billing.analytics.dao.BusinessSubscriptionTransitionDao;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
-import com.ning.billing.entitlement.api.user.EntitlementUserApi;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionTransition;
-import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
+import com.ning.billing.entitlement.api.user.*;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.util.eventbus.EventBus;
@@ -65,7 +47,7 @@ public class TestAnalyticsService
     private static final String ACCOUNT_KEY = "pierre-1234";
 
     @Inject
-    private IAccountUserApi accountApi;
+    private AccountUserApi accountApi;
 
     @Inject
     private EntitlementUserApi entitlementApi;
@@ -88,6 +70,8 @@ public class TestAnalyticsService
     @BeforeClass(alwaysRun = true)
     public void startMysql() throws IOException, ClassNotFoundException, SQLException, EntitlementUserApiException
     {
+        bus.start();
+
         final String analyticsDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/analytics/ddl.sql"));
         // For bundles
         final String accountDdl = IOUtils.toString(BusinessSubscriptionTransitionDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
@@ -100,7 +84,7 @@ public class TestAnalyticsService
 
         // We need a bundle to retrieve the event key
         final MockAccount account = new MockAccount(UUID.randomUUID(), ACCOUNT_KEY, Currency.USD);
-        final IAccount storedAccount = accountApi.createAccount(account);
+        final Account storedAccount = accountApi.createAccount(account);
         final SubscriptionBundle bundle = entitlementApi.createBundleForAccount(storedAccount, KEY);
 
         // Verify we correctly initialized the account subsystem
@@ -108,7 +92,7 @@ public class TestAnalyticsService
         Assert.assertEquals(bundle.getKey(), KEY);
 
         // Create a subscription transition
-        final Product product = new MockProduct("platinium", "subscription", ProductCategory.BASE);
+        final Product product = new MockProduct("platinum", "subscription", ProductCategory.BASE);
         final Plan plan = new MockPlan("platinum-monthly", product);
         final PlanPhase phase = new MockPhase(PhaseType.EVERGREEN, plan, MockDuration.UNLIMITED(), 25.95);
         final UUID subscriptionId = UUID.randomUUID();
@@ -138,7 +122,7 @@ public class TestAnalyticsService
             requestedTransitionTime,
             BusinessSubscriptionEvent.subscriptionCreated(plan),
             null,
-            new BusinessSubscription(priceList, plan, phase, null, effectiveTransitionTime, Subscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
+            new BusinessSubscription(priceList, plan, phase, Currency.USD, effectiveTransitionTime, Subscription.SubscriptionState.ACTIVE, subscriptionId, bundle.getId())
         );
     }
 
@@ -156,7 +140,6 @@ public class TestAnalyticsService
 
         // Test the bus and make sure we can register our service
         try {
-            bus.start();
             service.registerForNotifications();
         }
         catch (Throwable t) {
diff --git a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
index 267c2bb..368b8c1 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/dao/TestAnalyticsDao.java
@@ -16,21 +16,9 @@
 
 package com.ning.billing.analytics.dao;
 
-import com.ning.billing.analytics.BusinessAccount;
-import com.ning.billing.analytics.BusinessSubscription;
-import com.ning.billing.analytics.BusinessSubscriptionEvent;
-import com.ning.billing.analytics.BusinessSubscriptionTransition;
-import com.ning.billing.analytics.MockDuration;
-import com.ning.billing.analytics.MockPhase;
-import com.ning.billing.analytics.MockPlan;
-import com.ning.billing.analytics.MockProduct;
+import com.ning.billing.analytics.*;
 import com.ning.billing.analytics.utils.Rounder;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.user.Subscription;
 import org.apache.commons.io.IOUtils;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
index 704b3da..dbb7f8a 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
@@ -17,12 +17,10 @@
 package com.ning.billing.analytics;
 
 import java.util.UUID;
-
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IFieldStore;
+import com.ning.billing.account.api.AccountData;
 import com.ning.billing.catalog.api.Currency;
 
-public class MockAccount implements IAccount
+public class MockAccount implements AccountData
 {
     private final UUID id;
     private final String accountKey;
@@ -36,61 +34,53 @@ public class MockAccount implements IAccount
     }
 
     @Override
-    public String getName()
-    {
-        throw new UnsupportedOperationException();
+    public int getFirstNameLength() {
+        return 0;
     }
 
     @Override
     public String getEmail()
     {
-        throw new UnsupportedOperationException();
+        return "test@test.com";
     }
 
     @Override
     public String getPhone()
     {
-        throw new UnsupportedOperationException();
+        return "408-555-6665";
     }
 
     @Override
-    public String getKey()
+    public String getExternalKey()
     {
         return accountKey;
     }
 
     @Override
-    public int getBillCycleDay()
-    {
-        throw new UnsupportedOperationException();
+    public String getName() {
+        return "firstName lastName";
     }
 
     @Override
-    public Currency getCurrency()
+    public int getBillCycleDay()
     {
-        return currency;
+        return 12;
     }
 
     @Override
-    public UUID getId()
+    public Currency getCurrency()
     {
-        return id;
-    }
-
-    @Override
-    public IFieldStore getFields() {
-        throw new UnsupportedOperationException();
+        return currency;
     }
 
     @Override
-    public String getFieldValue(final String fieldName)
-    {
-        throw new UnsupportedOperationException();
+    public String getPaymentProviderName() {
+        return "PayPal";
     }
 
     @Override
-    public void setFieldValue(final String fieldName, final String fieldValue)
+    public UUID getId()
     {
-        throw new UnsupportedOperationException();
+        return id;
     }
 }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
index 36f54f8..4982fe2 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockIAccountUserApi.java
@@ -16,44 +16,50 @@
 
 package com.ning.billing.analytics;
 
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
+
 import java.util.List;
 import java.util.UUID;
-
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountData;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.DefaultAccount;
 import com.ning.billing.catalog.api.Currency;
 
-public class MockIAccountUserApi implements IAccountUserApi
+public class MockIAccountUserApi implements AccountUserApi
 {
-    private final Account account;
+    private final AccountData account;
 
     public MockIAccountUserApi(final String accountKey, final Currency currency)
     {
-        account = new Account(UUID.randomUUID()).withKey(accountKey).withCurrency(currency);
+        account = new MockAccount(UUID.randomUUID(), accountKey, currency);
     }
 
     @Override
-    public IAccount createAccount(final IAccountData data)
+    public Account createAccount(final AccountData data)
     {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public IAccount getAccountByKey(final String key)
+    public void saveAccount(Account account) {
+        throw new NotImplementedException();
+    }
+
+    @Override
+    public Account getAccountByKey(final String key)
     {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public IAccount getAccountFromId(final UUID uid)
+    public Account getAccountById(final UUID uid)
     {
-        return account;
+        return new DefaultAccount(account);
     }
 
     @Override
-    public List<IAccount> getAccounts()
+    public List<Account> getAccounts()
     {
         throw new UnsupportedOperationException();
     }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
index 1fd1022..47ce151 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockIEntitlementUserApi.java
@@ -16,19 +16,18 @@
 
 package com.ning.billing.analytics;
 
-import com.ning.billing.account.api.IAccount;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.account.api.AccountData;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import org.joda.time.DateTime;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
 
 public class MockIEntitlementUserApi implements EntitlementUserApi
 {
@@ -94,7 +93,7 @@ public class MockIEntitlementUserApi implements EntitlementUserApi
     }
 
     @Override
-    public SubscriptionBundle createBundleForAccount(final IAccount account, final String bundleKey) throws EntitlementUserApiException
+    public SubscriptionBundle createBundleForAccount(final AccountData account, final String bundleKey) throws EntitlementUserApiException
     {
         throw new UnsupportedOperationException();
     }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
index af8e993..7eb9b44 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
@@ -16,14 +16,7 @@
 
 package com.ning.billing.analytics;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.InternationalPrice;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Price;
-import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.*;
 
 import java.math.BigDecimal;
 import java.util.Date;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
index 73b47ee..0e0809c 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
@@ -16,12 +16,10 @@
 
 package com.ning.billing.analytics;
 
-import com.ning.billing.catalog.api.BillingAlignment;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
 
 import java.util.Iterator;
 
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
index e6c2dfa..cff4ad7 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -22,7 +22,6 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionTransition;
-
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
index 819f46b..7bad790 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestAnalyticsListener.java
@@ -16,12 +16,7 @@
 
 package com.ning.billing.analytics;
 
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
 import com.ning.billing.entitlement.events.EntitlementEvent;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
index 73e7811..6c38854 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
@@ -16,12 +16,7 @@
 
 package com.ning.billing.analytics;
 
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.user.Subscription;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java
index 72574dd..5ea1950 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionEvent.java
@@ -16,11 +16,7 @@
 
 package com.ning.billing.analytics;
 
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.user.Subscription;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
index 5b7e3fe..592d20d 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscriptionTransition.java
@@ -16,11 +16,7 @@
 
 package com.ning.billing.analytics;
 
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.user.Subscription;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;

api/pom.xml 2(+1 -1)

diff --git a/api/pom.xml b/api/pom.xml
index 7f7f108..013feb9 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java b/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
new file mode 100644
index 0000000..879f642
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/AccountUserApi.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.List;
+import java.util.UUID;
+
+public interface AccountUserApi {
+
+    public Account createAccount(AccountData data);
+
+    public void saveAccount(Account account);
+
+    public Account getAccountByKey(String key);
+
+    public Account getAccountById(UUID uid);
+
+    public List<Account> getAccounts();
+}
diff --git a/api/src/main/java/com/ning/billing/account/api/ChangedField.java b/api/src/main/java/com/ning/billing/account/api/ChangedField.java
new file mode 100644
index 0000000..8bf2ef1
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/ChangedField.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import org.joda.time.DateTime;
+
+public interface ChangedField {
+    public DateTime getChangeDate();
+    public String getFieldName();
+    public String getOldValue();
+    public String getNewValue();
+}
diff --git a/api/src/main/java/com/ning/billing/account/api/CustomizableEntity.java b/api/src/main/java/com/ning/billing/account/api/CustomizableEntity.java
new file mode 100644
index 0000000..84254a1
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/CustomizableEntity.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+public interface CustomizableEntity extends Entity {
+    public String getFieldValue(String fieldName);
+
+    public void setFieldValue(String fieldName, String fieldValue);
+
+    public FieldStore getFields();
+
+    public String getObjectName();
+}
diff --git a/api/src/main/java/com/ning/billing/account/api/EntityCollection.java b/api/src/main/java/com/ning/billing/account/api/EntityCollection.java
new file mode 100644
index 0000000..7730656
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/EntityCollection.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.List;
+
+public interface EntityCollection<T extends Entity> {
+    public String getEntityKey(T entity);
+
+    public void clear();
+
+    public void add(T entity);
+
+    public void add(List<T> entities);
+
+    public void remove(T entity);
+
+    public List<T> getEntityList();
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/account/api/Tag.java b/api/src/main/java/com/ning/billing/account/api/Tag.java
new file mode 100644
index 0000000..82f0f2c
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/Tag.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.UUID;
+import org.joda.time.DateTime;
+
+public interface Tag extends Entity {
+    UUID getTagDescriptionId();
+
+    String getName();
+
+    boolean getProcessPayment();
+
+    boolean getGenerateInvoice();
+
+    String getAddedBy();
+
+    DateTime getDateAdded();
+}
diff --git a/api/src/main/java/com/ning/billing/account/api/TagDescription.java b/api/src/main/java/com/ning/billing/account/api/TagDescription.java
new file mode 100644
index 0000000..634a5ba
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/TagDescription.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import org.joda.time.DateTime;
+
+public interface TagDescription extends Entity {
+    String getName();
+
+    String getCreatedBy();
+
+    DateTime getCreationDate();
+
+    String getDescription();
+
+    boolean getGenerateInvoice();
+
+    boolean getProcessPayment();
+}
diff --git a/api/src/main/java/com/ning/billing/account/api/Taggable.java b/api/src/main/java/com/ning/billing/account/api/Taggable.java
new file mode 100644
index 0000000..fc77003
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/Taggable.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+import java.util.List;
+import org.joda.time.DateTime;
+
+public interface Taggable {
+    public List<Tag> getTagList();
+    public boolean hasTag(String tagName);
+    public void addTag(TagDescription description, String addedBy, DateTime dateAdded);
+    public void addTags(List<Tag> tags);
+    public void clearTags();
+    public void removeTag(TagDescription description);
+    public boolean generateInvoice();
+    public boolean processPayment();
+}
diff --git a/api/src/main/java/com/ning/billing/account/api/TagStore.java b/api/src/main/java/com/ning/billing/account/api/TagStore.java
new file mode 100644
index 0000000..e73e535
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/TagStore.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.account.api;
+
+public interface TagStore extends EntityCollection<Tag> {
+    public boolean processPayment();
+
+    public boolean generateInvoice();
+
+    public void remove(String tagName);
+
+    public boolean containsTag(String tagName);
+}
diff --git a/api/src/main/java/com/ning/billing/catalog/api/Catalog.java b/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
index f360eec..0fe2e25 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
@@ -47,7 +47,7 @@ public interface Catalog {
 
     public abstract void configureEffectiveDate(Date date);
 
-    public abstract String getCalalogName();
+    public abstract String getCatalogName();
 
     public abstract PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier) throws CatalogApiException;
 
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
index e92ee96..086bcd8 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
@@ -83,7 +83,7 @@ public interface BillingEvent extends Comparable<BillingEvent> {
      *
      * @return the billing mode for the current event
      */
-    public BillingMode getBillingMode();
+    public BillingModeType getBillingMode();
 
     /**
      *
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
index 7c6cabc..874a7bc 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/EntitlementBillingApi.java
@@ -16,21 +16,20 @@
 
 package com.ning.billing.entitlement.api.billing;
 
+import com.ning.billing.account.api.Account;
+import org.joda.time.DateTime;
+
 import java.util.List;
 import java.util.SortedSet;
 import java.util.UUID;
 
-import org.joda.time.DateTime;
-
-import com.ning.billing.account.api.IAccount;
-
 public interface EntitlementBillingApi {
 
     /**
      *
      * @return the list of accounts which have active subscriptions
      */
-    public List<IAccount> getActiveAccounts();
+    public List<Account> getActiveAccounts();
 
     /**
      *
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
index fc4425a..10f8591 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
@@ -18,10 +18,8 @@ package com.ning.billing.entitlement.api.user;
 
 import java.util.List;
 import java.util.UUID;
-
 import org.joda.time.DateTime;
-
-import com.ning.billing.account.api.IAccount;
+import com.ning.billing.account.api.AccountData;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PhaseType;
 
@@ -38,7 +36,7 @@ public interface EntitlementUserApi {
 
     public List<Subscription> getSubscriptionsForKey(String bundleKey);
 
-    public SubscriptionBundle createBundleForAccount(IAccount account, String bundleKey)
+    public SubscriptionBundle createBundleForAccount(AccountData account, String bundleKey)
         throws EntitlementUserApiException;
 
 
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index c94fc9d..8f13e06 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -16,14 +16,13 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.util.List;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import org.joda.time.DateTime;
+
+import java.util.List;
+import java.util.UUID;
 
 
 public interface Subscription {
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
index a6ecd91..f7c2e84 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
@@ -16,11 +16,9 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.util.UUID;
-
 import org.joda.time.DateTime;
 
-import com.ning.billing.catalog.api.BillingPeriod;
+import java.util.UUID;
 
 public interface SubscriptionBundle {
 
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
index 00e478f..517a7b8 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransition.java
@@ -16,14 +16,13 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.util.eventbus.EventBusNotification;
+import org.joda.time.DateTime;
+
+import java.util.UUID;
 
 public interface SubscriptionTransition extends EventBusNotification {
 
diff --git a/api/src/main/java/com/ning/billing/invoice/api/DefaultBillingEvent.java b/api/src/main/java/com/ning/billing/invoice/api/DefaultBillingEvent.java
index a4f6834..f18e106 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/DefaultBillingEvent.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/DefaultBillingEvent.java
@@ -20,8 +20,8 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.InternationalPrice;
-import com.ning.billing.entitlement.api.billing.BillingMode;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
 import org.joda.time.DateTime;
 
 import java.math.BigDecimal;
@@ -40,11 +40,11 @@ public class DefaultBillingEvent implements BillingEvent {
     private final InternationalPrice price;
     private final BillingPeriod billingPeriod;
     private final int billCycleDay;
-    private final BillingMode billingMode;
+    private final BillingModeType billingMode;
 
 
     public DefaultBillingEvent(UUID subscriptionId, DateTime startDate, String planName, String planPhaseName, InternationalPrice price,
-                        BillingPeriod billingPeriod, int billCycleDay, BillingMode billingMode) {
+                        BillingPeriod billingPeriod, int billCycleDay, BillingModeType billingMode) {
         this.subscriptionId = subscriptionId;
         this.startDate = startDate;
         this.planName = planName;
@@ -113,7 +113,7 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     @Override
-    public BillingMode getBillingMode() {
+    public BillingModeType getBillingMode() {
         return billingMode;
     }
 
diff --git a/api/src/main/java/com/ning/billing/invoice/api/Invoice.java b/api/src/main/java/com/ning/billing/invoice/api/Invoice.java
new file mode 100644
index 0000000..41d7adb
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/Invoice.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.ning.billing.catalog.api.Currency;
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+public interface Invoice {
+    boolean add(InvoiceItem item);
+
+    boolean add(List<InvoiceItem> items);
+
+    List<InvoiceItem> getItems();
+
+    int getNumberOfItems();
+
+    UUID getId();
+
+    UUID getAccountId();
+
+    DateTime getInvoiceDate();
+
+    DateTime getTargetDate();
+
+    Currency getCurrency();
+
+    DateTime getLastPaymentAttempt();
+
+    BigDecimal getAmountPaid();
+
+    BigDecimal getTotalAmount();
+
+    BigDecimal getAmountOutstanding();
+}
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceCreationNotification.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceCreationNotification.java
new file mode 100644
index 0000000..89c0d87
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceCreationNotification.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.eventbus.EventBusNotification;
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+public interface InvoiceCreationNotification extends EventBusNotification {
+    public UUID getInvoiceId();
+    public UUID getAccountId();
+    public BigDecimal getAmountOwed();
+    public Currency getCurrency();
+    public DateTime getInvoiceCreationDate();
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
new file mode 100644
index 0000000..bce002a
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.ning.billing.catalog.api.Currency;
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+public interface InvoiceItem extends Comparable<InvoiceItem> {
+    UUID getId();
+
+    UUID getInvoiceId();
+
+    UUID getSubscriptionId();
+
+    DateTime getStartDate();
+
+    DateTime getEndDate();
+
+    String getDescription();
+
+    BigDecimal getAmount();
+
+    BigDecimal getRate();
+
+    Currency getCurrency();
+
+    InvoiceItem asCredit(UUID invoiceId);
+
+    int compareTo(InvoiceItem invoiceItem);
+
+    void subtract(InvoiceItem that);
+
+    boolean duplicates(InvoiceItem that);
+
+    boolean cancels(InvoiceItem that);
+}
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java b/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java
new file mode 100644
index 0000000..6e9f57f
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoicePaymentApi.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.ning.billing.catalog.api.Currency;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+public interface InvoicePaymentApi {
+    public void paymentSuccessful(UUID invoiceId, BigDecimal amount, Currency currency, UUID paymentId);
+
+    public List<Invoice> getInvoicesByAccount(UUID accountId);
+
+    public Invoice getInvoice(UUID invoiceId);
+}
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
new file mode 100644
index 0000000..a32ba01
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import org.joda.time.DateTime;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+public interface InvoiceUserApi {
+    public List<UUID> getInvoicesForPayment(DateTime targetDate, int numberOfDays);
+
+    public List<Invoice> getInvoicesByAccount(UUID accountId);
+
+    public Invoice getInvoice(UUID invoiceId);
+
+    public void paymentAttemptFailed(UUID invoiceId, DateTime paymentAttemptDate);
+
+    public void paymentAttemptSuccessful(UUID invoiceId, DateTime paymentAttemptDate, BigDecimal paymentAmount);
+}
diff --git a/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java b/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java
index 105842b..759cc13 100644
--- a/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java
+++ b/api/src/main/java/com/ning/billing/lifecycle/LifecycleHandlerType.java
@@ -16,14 +16,14 @@
 
 package com.ning.billing.lifecycle;
 
+import com.google.common.collect.Lists;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.util.List;
 
-import com.google.common.collect.Lists;
-
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.METHOD)
 public @interface LifecycleHandlerType {
diff --git a/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java b/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java
index 1985465..0bddb7e 100644
--- a/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java
+++ b/api/src/main/java/com/ning/billing/util/eventbus/EventBus.java
@@ -16,8 +16,8 @@
 
 package com.ning.billing.util.eventbus;
 
-import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import com.google.common.eventbus.Subscribe;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 
 
 /**

beatrix/pom.xml 2(+1 -1)

diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index b211a46..07e2a57 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-beatrix</artifactId>
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
index 253e693..c0edf2c 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
@@ -16,18 +16,6 @@
 
 package com.ning.billing.beatrix.lifecycle;
 
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.common.base.Supplier;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
@@ -39,6 +27,13 @@ import com.ning.billing.lifecycle.KillbillService;
 import com.ning.billing.lifecycle.LifecycleHandlerType;
 import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
 import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel.Sequence;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 
 public class Lifecycle {
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
index b5fca46..a4a4ce2 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
@@ -17,28 +17,17 @@
 package com.ning.billing.beatrix.lifecycle;
 
 
+import com.ning.billing.lifecycle.KillbillService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.Modifier;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
 import java.util.jar.JarFile;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.ning.billing.lifecycle.KillbillService;
-
 public class ServiceFinder {
 
     private static final Logger log = LoggerFactory.getLogger(ServiceFinder.class);
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java b/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
index a01220e..69e6a0d 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
@@ -16,21 +16,16 @@
 
 package com.ning.billing.beatrix.lifecycle;
 
+import com.google.inject.*;
+import com.ning.billing.lifecycle.KillbillService;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Stage;
-import com.ning.billing.lifecycle.KillbillService;
-import com.ning.billing.lifecycle.LifecycleHandlerType;
-import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-
 
 public class TestLifecycle {
 

catalog/pom.xml 2(+1 -1)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index bf50441..ba9a714 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-catalog</artifactId>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
index 37d66f3..813ed2b 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
@@ -25,7 +25,6 @@ import com.ning.billing.config.CatalogConfig;
 import com.ning.billing.lifecycle.KillbillService;
 import com.ning.billing.lifecycle.LifecycleHandlerType;
 import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-import com.ning.billing.util.config.XMLLoader;
 
 public class DefaultCatalogService implements KillbillService, Provider<Catalog>, CatalogService {
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
index 16897bc..be3ea55 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
@@ -16,15 +16,15 @@
 
 package com.ning.billing.catalog;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
 import com.ning.billing.catalog.api.Duration;
 import com.ning.billing.catalog.api.TimeUnit;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> implements Duration {
 	@XmlElement(required=true)
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
index deca8b6..b53dcd3 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
@@ -16,24 +16,19 @@
 
 package com.ning.billing.catalog;
 
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Date;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.CurrencyValueNull;
-import com.ning.billing.catalog.api.InternationalPrice;
-import com.ning.billing.catalog.api.Price;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Date;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalog> implements InternationalPrice {
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
index 11154df..3620162 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
@@ -16,18 +16,6 @@
 
 package com.ning.billing.catalog;
 
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlID;
-import javax.xml.bind.annotation.XmlIDREF;
-
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
@@ -35,6 +23,11 @@ import com.ning.billing.catalog.api.Product;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.*;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements Plan {
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
index e12b90f..e086bfe 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
@@ -16,22 +16,16 @@
 
 package com.ning.billing.catalog;
 
-import java.net.URI;
+import com.ning.billing.catalog.api.*;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
+import com.ning.billing.util.config.ValidationErrors;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
-
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.InternationalPrice;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.util.config.ValidatingConfig;
-import com.ning.billing.util.config.ValidationError;
-import com.ning.billing.util.config.ValidationErrors;
+import java.net.URI;
 
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implements PlanPhase {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java
index 2021913..d9d26a6 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPrice.java
@@ -16,18 +16,17 @@
 
 package com.ning.billing.catalog;
 
-import java.math.BigDecimal;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.CurrencyValueNull;
 import com.ning.billing.catalog.api.Price;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import java.math.BigDecimal;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements Price {
 	@XmlElement(required=true)
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
index 785d173..04916ba 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
@@ -16,14 +16,6 @@
 
 package com.ning.billing.catalog;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlID;
-import javax.xml.bind.annotation.XmlIDREF;
-
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.Product;
@@ -31,6 +23,8 @@ import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.*;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implements PriceList  {
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
index fc86268..b876fa9 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
@@ -16,10 +16,6 @@
 
 package com.ning.billing.catalog;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.Product;
@@ -27,6 +23,10 @@ import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> {
 	@XmlElement(required=true, name="defaultPriceList")
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
index 500a4b0..79520ce 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
@@ -16,21 +16,14 @@
 
 package com.ning.billing.catalog;
 
-import java.net.URI;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlID;
-import javax.xml.bind.annotation.XmlIDREF;
-
 import com.ning.billing.catalog.api.Product;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.*;
+import java.net.URI;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implements Product {
 	private static final DefaultProduct[] EMPTY_PRODUCT_LIST = new DefaultProduct[0];
@@ -107,7 +100,7 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
 	
 	@Override
 	public void initialize(StandaloneCatalog catalog, URI sourceURI) {
-		catalogName = catalog.getCalalogName();
+		catalogName = catalog.getCatalogName();
 	}
 
 	@Override
diff --git a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
index 4b182ef..8702b6f 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
@@ -16,14 +16,13 @@
 
 package com.ning.billing.catalog.glue;
 
-import org.skife.config.ConfigurationObjectFactory;
-
 import com.google.inject.AbstractModule;
 import com.ning.billing.catalog.DefaultCatalogService;
 import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.io.ICatalogLoader;
 import com.ning.billing.catalog.io.VersionedCatalogLoader;
 import com.ning.billing.config.CatalogConfig;
+import org.skife.config.ConfigurationObjectFactory;
 
 public class CatalogModule extends AbstractModule {
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
index b383647..4ad78df 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
@@ -16,13 +16,6 @@
 
 package com.ning.billing.catalog.io;
 
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
 import com.google.inject.Inject;
 import com.ning.billing.catalog.StandaloneCatalog;
 import com.ning.billing.catalog.VersionedCatalog;
@@ -31,6 +24,13 @@ import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.config.UriAccessor;
 import com.ning.billing.util.config.XMLLoader;
 
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
 public class VersionedCatalogLoader implements ICatalogLoader  {
 	private static final Object PROTOCOL_FOR_FILE = "file";
 	private  final String XML_EXTENSION = ".xml";
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
index 72b6567..f667e17 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
@@ -16,13 +16,13 @@
 
 package com.ning.billing.catalog;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-
 import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class PriceListDefault extends DefaultPriceList {
 	
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java b/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
index 8ef2cb2..737373e 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
@@ -16,9 +16,9 @@
 
 package com.ning.billing.catalog.rules;
 
-import com.ning.billing.catalog.StandaloneCatalog;
 import com.ning.billing.catalog.DefaultPriceList;
 import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.StandaloneCatalog;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.PlanSpecifier;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
index 0c22d00..a340fdc 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
@@ -16,23 +16,18 @@
 
 package com.ning.billing.catalog.rules;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlIDREF;
-
-import com.ning.billing.catalog.StandaloneCatalog;
 import com.ning.billing.catalog.DefaultPriceList;
 import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public abstract class CaseChange<T>  extends ValidatingConfig<StandaloneCatalog> {
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
index fe46942..1a3b0b5 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
@@ -16,19 +16,15 @@
 
 package com.ning.billing.catalog.rules;
 
-import javax.xml.bind.annotation.XmlElement;
-
 import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.XmlElement;
+
 public abstract class CasePhase<T> extends CaseStandardNaming<T> {
 
 	@XmlElement(required=false)
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
index 5508c96..fbb9cab 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePriceList.java
@@ -16,14 +16,14 @@
 
 package com.ning.billing.catalog.rules;
 
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlIDREF;
-
 import com.ning.billing.catalog.DefaultPriceList;
 import com.ning.billing.catalog.DefaultProduct;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.ProductCategory;
 
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
 public class CasePriceList extends Case<DefaultPriceList> {
 
 	private DefaultPriceList toPriceList;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
index a0235de..cf61fcd 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseStandardNaming.java
@@ -16,14 +16,14 @@
 
 package com.ning.billing.catalog.rules;
 
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlIDREF;
-
 import com.ning.billing.catalog.DefaultPriceList;
 import com.ning.billing.catalog.DefaultProduct;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.ProductCategory;
 
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+
 public abstract class CaseStandardNaming<T> extends Case<T> {
 
 	@XmlElement(required=false, name="product")
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
index 40edb6b..54aa5c7 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
@@ -16,25 +16,17 @@
 
 package com.ning.billing.catalog.rules;
 
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingAlignment;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.IllegalPlanChange;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
-import com.ning.billing.catalog.api.PlanAlignmentCreate;
-import com.ning.billing.catalog.api.PlanChangeResult;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.util.config.ValidatingConfig;
-import com.ning.billing.util.config.ValidationErrors;
-
 @XmlAccessorType(XmlAccessType.NONE)
 public class PlanRules extends ValidatingConfig<StandaloneCatalog>  {
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
index 4ba7bc1..06b24bb 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
@@ -16,35 +16,18 @@
 
 package com.ning.billing.catalog;
 
-import java.net.URI;
-import java.util.Collection;
-import java.util.Date;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
-
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingAlignment;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.IllegalPlanChange;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
-import com.ning.billing.catalog.api.PlanAlignmentCreate;
-import com.ning.billing.catalog.api.PlanChangeResult;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.catalog.rules.PlanRules;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
+import javax.xml.bind.annotation.*;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Date;
+
 @XmlRootElement(name="catalog")
 @XmlAccessorType(XmlAccessType.NONE)
 public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> implements Catalog {
@@ -84,7 +67,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 	 * @see com.ning.billing.catalog.ICatalog#getCalalogName()
 	 */
 	@Override
-	public String getCalalogName() {
+	public String getCatalogName() {
 		return catalogName;
 	}
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
index 747e481..88a7dd4 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -15,32 +15,15 @@
  */
 package com.ning.billing.catalog;
 
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-
 import com.google.inject.Inject;
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingAlignment;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
-import com.ning.billing.catalog.api.PlanAlignmentCreate;
-import com.ning.billing.catalog.api.PlanChangeResult;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
+import java.net.URI;
+import java.util.*;
+
 public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implements Catalog {
 	
 	private StandaloneCatalog currentCatalog;
@@ -170,8 +153,8 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
 	}
 
 	@Override
-	public String getCalalogName() {
-		return currentCatalog.getCalalogName();
+	public String getCatalogName() {
+		return currentCatalog.getCatalogName();
 	}
 
 	@Override
diff --git a/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java b/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java
index 9094733..4367c9a 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/CreateCatalogSchema.java
@@ -16,13 +16,12 @@
 
 package com.ning.billing.catalog;
 
+import com.ning.billing.util.config.XMLSchemaGenerator;
+
 import java.io.File;
 import java.io.FileWriter;
 import java.io.Writer;
 
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.util.config.XMLSchemaGenerator;
-
 public class CreateCatalogSchema {
 
 	/**
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
index 3860561..9708b99 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
@@ -15,8 +15,18 @@
  */
 package com.ning.billing.catalog.io;
 
-import static org.testng.AssertJUnit.assertEquals;
+import com.google.common.io.Resources;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.VersionedCatalog;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
 
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URI;
@@ -25,19 +35,7 @@ import java.net.URL;
 import java.util.Iterator;
 import java.util.List;
 
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
-
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
-
-import com.google.common.io.Resources;
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.VersionedCatalog;
-import com.ning.billing.catalog.api.InvalidConfigException;
-import com.ning.billing.lifecycle.KillbillService.ServiceException;
-import com.ning.billing.util.clock.DefaultClock;
+import static org.testng.AssertJUnit.assertEquals;
 
 public class TestVersionedCatalogLoader {
 	private final VersionedCatalogLoader loader = new VersionedCatalogLoader(new DefaultClock());
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
index 3ec03d5..77f7248 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
@@ -16,11 +16,10 @@
 
 package com.ning.billing.catalog.io;
 
-import org.testng.annotations.Test;
-
 import com.google.common.io.Resources;
 import com.ning.billing.catalog.StandaloneCatalog;
 import com.ning.billing.util.config.XMLLoader;
+import org.testng.annotations.Test;
 
 public class TestXMLReader {
 
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
index 5c4975e..089c1e4 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
@@ -16,16 +16,12 @@
 
 package com.ning.billing.catalog;
 
-import java.util.Date;
-
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.catalog.rules.CaseCancelPolicy;
-import com.ning.billing.catalog.rules.CaseChangePlanAlignment;
-import com.ning.billing.catalog.rules.CaseChangePlanPolicy;
-import com.ning.billing.catalog.rules.CaseCreateAlignment;
-import com.ning.billing.catalog.rules.PlanRules;
+import com.ning.billing.catalog.rules.*;
+
+import java.util.Date;
 
 public class MockCatalog extends StandaloneCatalog {
 	private static final String[] PRODUCT_NAMES = new String[]{ "TestProduct1", "TestProduct2", "TestProduct3"};
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
index 1a4d8d9..5d1af74 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
@@ -16,11 +16,11 @@
 
 package com.ning.billing.catalog;
 
+import com.ning.billing.catalog.api.Currency;
+
 import java.math.BigDecimal;
 import java.util.Date;
 
-import com.ning.billing.catalog.api.Currency;
-
 public class MockInternationalPrice extends DefaultInternationalPrice {
 	
 	MockInternationalPrice() {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
index a9c3ffc..c00f1c4 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
@@ -16,23 +16,17 @@
 
 package com.ning.billing.catalog.rules;
 
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
+import org.testng.annotations.Test;
 
 import javax.xml.bind.annotation.XmlElement;
 
-import org.testng.annotations.Test;
-
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.catalog.rules.Case;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
 
 public class TestCase {
 
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
index bfc3f6d..af13162 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
@@ -16,25 +16,18 @@
 
 package com.ning.billing.catalog.rules;
 
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
-
-import javax.xml.bind.annotation.XmlElement;
-
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
+import javax.xml.bind.annotation.XmlElement;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
 
 public class TestCaseChange {
 	protected static class CaseChangeResult extends CaseChange<Result>  {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
index c9d2f22..fe505f4 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
@@ -16,21 +16,15 @@
 
 package com.ning.billing.catalog.rules;
 
-import javax.xml.bind.annotation.XmlElement;
-
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.*;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.catalog.rules.CasePhase;
+import javax.xml.bind.annotation.XmlElement;
 
 public class TestCasePhase {
 	protected class CaseResult extends CasePhase<Result>  {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
index 1d744e0..e41d506 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
@@ -16,26 +16,16 @@
 
 package com.ning.billing.catalog.rules;
 
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.api.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.IllegalPlanChange;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
-import com.ning.billing.catalog.api.PlanChangeResult;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
-
 public class TestPlanRules {
 	Logger log = LoggerFactory.getLogger(TestPlanRules.class);
 
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
index 93991e1..0f75459 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
@@ -15,19 +15,18 @@
  */
 package com.ning.billing.catalog;
 
-import java.math.BigDecimal;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Date;
-
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.config.ValidationErrors;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.util.config.ValidationErrors;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
 
 public class TestInternationalPrice {
 	private static final Logger log = LoggerFactory.getLogger(TestInternationalPrice.class);
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
index 4f14b48..4bfcf30 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
@@ -16,14 +16,13 @@
 
 package com.ning.billing.catalog;
 
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.util.config.ValidationErrors;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.util.config.ValidationErrors;
-
 public class TestPlanPhase {
 	Logger log = LoggerFactory.getLogger(TestPlanPhase.class);
 	
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
index d1f231e..09024ce 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
@@ -16,16 +16,17 @@
 
 package com.ning.billing.catalog;
 
-import static com.ning.billing.catalog.api.BillingPeriod.*;
-import static com.ning.billing.catalog.api.PhaseType.*;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
 import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.ProductCategory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static com.ning.billing.catalog.api.BillingPeriod.ANNUAL;
+import static com.ning.billing.catalog.api.BillingPeriod.MONTHLY;
+import static com.ning.billing.catalog.api.PhaseType.DISCOUNT;
+import static com.ning.billing.catalog.api.PhaseType.EVERGREEN;
 
 public class TestPriceListSet {
 	@Test(enabled=true)
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
index 08f6ebf..bc07e3e 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
@@ -15,25 +15,23 @@
  */
 package com.ning.billing.catalog;
 
-import static org.testng.AssertJUnit.assertEquals;
+import com.google.common.io.Resources;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.catalog.io.VersionedCatalogLoader;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
 
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.util.Date;
 
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
-
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
-
-import com.google.common.io.Resources;
-import com.ning.billing.catalog.api.InvalidConfigException;
-import com.ning.billing.catalog.io.VersionedCatalogLoader;
-import com.ning.billing.lifecycle.KillbillService.ServiceException;
-import com.ning.billing.util.clock.DefaultClock;
+import static org.testng.AssertJUnit.assertEquals;
 
 public class TestVersionedCatalog {
 	private final VersionedCatalogLoader loader = new VersionedCatalogLoader(new DefaultClock());
diff --git a/catalog/src/test/resources/WeaponsHire.xml b/catalog/src/test/resources/WeaponsHire.xml
index 740a903..01d7cb4 100644
--- a/catalog/src/test/resources/WeaponsHire.xml
+++ b/catalog/src/test/resources/WeaponsHire.xml
@@ -18,7 +18,7 @@
 <!-- 
 Use cases covered so far:
 	Tiered Product (Pistol/Shotgun/Assault-Rifle)
-	Multiple change plan policies 
+	Multiple changeEvent plan policies
 	Multiple PlanAlignment (see below, trial add-on alignments and rescue discount package)
 	Product transition rules
 	Add on (Scopes, Hoster)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 70f9b4b..7eed375 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
index d9ab5b3..083aef5 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
@@ -16,29 +16,18 @@
 
 package com.ning.billing.entitlement.alignment;
 
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.joda.time.DateTime;
-
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.CatalogService;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanAlignmentChange;
-import com.ning.billing.catalog.api.PlanAlignmentCreate;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  *
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java
index 08f1427..889d0ac 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/TimedPhase.java
@@ -16,9 +16,8 @@
 
 package com.ning.billing.entitlement.alignment;
 
-import org.joda.time.DateTime;
-
 import com.ning.billing.catalog.api.PlanPhase;
+import org.joda.time.DateTime;
 
 
 public final class TimedPhase {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
index 1704a0a..22fdd40 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
@@ -16,18 +16,16 @@
 
 package com.ning.billing.entitlement.api.billing;
 
-import java.util.List;
-import java.util.SortedSet;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
 import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
+import com.ning.billing.account.api.Account;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
-
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import org.joda.time.DateTime;
+
+import java.util.List;
+import java.util.SortedSet;
+import java.util.UUID;
 
 public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
 
@@ -40,7 +38,7 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
     }
 
     @Override
-    public List<IAccount> getActiveAccounts() {
+    public List<Account> getActiveAccounts() {
         return null;
     }
 
@@ -54,7 +52,7 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
     public void setChargedThroughDate(UUID subscriptionId, DateTime ctd) {
         SubscriptionData subscription = (SubscriptionData) dao.getSubscriptionFromId(subscriptionId);
         if (subscription == null) {
-            new EntitlementBillingApiException(String.format("Unknwon subscription %s", subscriptionId));
+            new EntitlementBillingApiException(String.format("Unknown subscription %s", subscriptionId));
         }
 
         SubscriptionBuilder builder = new SubscriptionBuilder(subscription)
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java
index d0897ed..c2f5878 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/test/DefaultEntitlementTestApi.java
@@ -16,14 +16,13 @@
 
 package com.ning.billing.entitlement.api.test;
 
-import java.util.UUID;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.inject.Inject;
 import com.ning.billing.config.EntitlementConfig;
 import com.ning.billing.entitlement.engine.core.EventNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.UUID;
 
 public class DefaultEntitlementTestApi implements EntitlementTestApi {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
index d79d514..135ce3e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
@@ -18,28 +18,22 @@ package com.ning.billing.entitlement.api.user;
 
 import java.util.List;
 import java.util.UUID;
-
 import org.joda.time.DateTime;
-
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
-import com.ning.billing.account.api.IAccount;
+import com.ning.billing.account.api.AccountData;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.entitlement.alignment.PlanAligner;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
-import com.ning.billing.util.clock.DefaultClock;
 import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.DefaultClock;
 
 public class DefaultEntitlementUserApi implements EntitlementUserApi {
 
@@ -84,7 +78,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
     }
 
     @Override
-    public SubscriptionBundle createBundleForAccount(IAccount account, String bundleName)
+    public SubscriptionBundle createBundleForAccount(AccountData account, String bundleName)
     throws EntitlementUserApiException {
         SubscriptionBundleData bundle = new SubscriptionBundleData(bundleName, account.getId());
         return dao.createSubscriptionBundle(bundle);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
index 1561aec..3b3ff73 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
@@ -16,26 +16,9 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.joda.time.DateTime;
-
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.CatalogService;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PriceList;
-import com.ning.billing.catalog.api.Product;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.PlanChangeResult;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
-import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.alignment.PlanAligner;
 import com.ning.billing.entitlement.alignment.TimedPhase;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
@@ -44,13 +27,13 @@ import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.phase.PhaseEvent;
 import com.ning.billing.entitlement.events.phase.PhaseEventData;
-import com.ning.billing.entitlement.events.user.ApiEventBuilder;
-import com.ning.billing.entitlement.events.user.ApiEventCancel;
-import com.ning.billing.entitlement.events.user.ApiEventChange;
-import com.ning.billing.entitlement.events.user.ApiEventCreate;
-import com.ning.billing.entitlement.events.user.ApiEventUncancel;
+import com.ning.billing.entitlement.events.user.*;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+
+import java.util.ArrayList;
+import java.util.List;
 
 public class SubscriptionApiService {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
index ad56168..8bdd584 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
@@ -16,13 +16,9 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.util.UUID;
-
 import org.joda.time.DateTime;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.entitlement.events.EntitlementEvent;
-import com.ning.billing.entitlement.events.user.ApiEventCreate;
+import java.util.UUID;
 
 public class SubscriptionBundleData implements SubscriptionBundle {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index 12333a2..669c77d 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -16,34 +16,21 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.ning.billing.ErrorCode;
-
-import com.ning.billing.catalog.api.ActionPolicy;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.CatalogApiException;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
 import com.ning.billing.entitlement.events.phase.PhaseEvent;
-import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.clock.Clock;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
 
 public class SubscriptionData implements Subscription {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java
index d69d4e2..66dfb88 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEvents.java
@@ -16,11 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
+import com.ning.billing.entitlement.events.EntitlementEvent;
+
 import java.util.LinkedList;
 import java.util.UUID;
 
-import com.ning.billing.entitlement.events.EntitlementEvent;
-
 public class SubscriptionEvents {
 
     public static final long INITIAL_VERSION = 1;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
index 48008bf..59d7c6e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
@@ -16,18 +16,17 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.lang.reflect.Field;
-import java.util.List;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
 import com.google.inject.Inject;
 import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.clock.Clock;
+import org.joda.time.DateTime;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.UUID;
 
 public class SubscriptionFactory {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
index 08cedf7..5a0eba0 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
@@ -16,16 +16,15 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
 import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
+import org.joda.time.DateTime;
+
+import java.util.UUID;
 
 public class SubscriptionTransitionData implements SubscriptionTransition {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
index 52fa9a4..cfeaca7 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
@@ -16,20 +16,6 @@
 
 package com.ning.billing.entitlement.engine.core;
 
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.inject.Inject;
@@ -37,6 +23,15 @@ import com.ning.billing.config.EntitlementConfig;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.util.clock.Clock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.*;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public abstract class ApiEventProcessorBase implements EventNotifier {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java
index c3c2f20..eba828e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/DefaultApiEventProcessor.java
@@ -16,15 +16,15 @@
 
 package com.ning.billing.entitlement.engine.core;
 
-import java.util.Collection;
-import java.util.List;
-
 import com.google.inject.Inject;
 import com.ning.billing.config.EntitlementConfig;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.util.clock.Clock;
 
+import java.util.Collection;
+import java.util.List;
+
 public class DefaultApiEventProcessor extends ApiEventProcessorBase {
 
     @Inject
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 89b4f2b..aed7937 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -16,14 +16,8 @@
 
 package com.ning.billing.entitlement.engine.core;
 
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.inject.Inject;
-import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.config.EntitlementConfig;
-
 import com.ning.billing.entitlement.alignment.PlanAligner;
 import com.ning.billing.entitlement.alignment.TimedPhase;
 import com.ning.billing.entitlement.api.EntitlementService;
@@ -45,7 +39,9 @@ import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.eventbus.EventBus;
 import com.ning.billing.util.eventbus.EventBus.EventBusException;
-import com.sun.org.apache.xml.internal.resolver.CatalogException;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class Engine implements EventListener, EntitlementService {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
index 10e0348..3470b74 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
@@ -16,13 +16,8 @@
 
 package com.ning.billing.entitlement.engine.dao;
 
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.skife.jdbi.v2.SQLStatement;
@@ -38,8 +33,12 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
 
 @ExternalizedSqlViaStringTemplate3()
 public interface BundleSqlDao extends Transactional<EventSqlDao>, CloseMe, Transmogrifier {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
index 835da51..6c87a40 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
@@ -16,16 +16,16 @@
 
 package com.ning.billing.entitlement.engine.dao;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.UUID;
-
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
 public interface EntitlementDao {
 
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
index 15f1e8c..3838845 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementSqlDao.java
@@ -16,35 +16,25 @@
 
 package com.ning.billing.entitlement.engine.dao;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
-import org.skife.jdbi.v2.DBI;
-import org.skife.jdbi.v2.Transaction;
-import org.skife.jdbi.v2.TransactionStatus;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.inject.Inject;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.config.EntitlementConfig;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
-import com.ning.billing.entitlement.api.user.SubscriptionData;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory;
+import com.ning.billing.entitlement.api.user.*;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
-import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.Hostname;
 import com.ning.billing.util.clock.Clock;
+import org.skife.jdbi.v2.DBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
 
 public class EntitlementSqlDao implements EntitlementDao {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
index a1e2670..704d722 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EventSqlDao.java
@@ -16,13 +16,15 @@
 
 package com.ning.billing.entitlement.engine.dao;
 
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
+import com.ning.billing.entitlement.events.EntitlementEvent;
+import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
+import com.ning.billing.entitlement.events.EventBaseBuilder;
+import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
+import com.ning.billing.entitlement.events.phase.PhaseEvent;
+import com.ning.billing.entitlement.events.phase.PhaseEventBuilder;
+import com.ning.billing.entitlement.events.phase.PhaseEventData;
+import com.ning.billing.entitlement.events.user.*;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.skife.jdbi.v2.SQLStatement;
@@ -38,23 +40,12 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
-import com.ning.billing.entitlement.events.EventBaseBuilder;
-import com.ning.billing.entitlement.events.EntitlementEvent;
-import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
-import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
-import com.ning.billing.entitlement.events.phase.PhaseEvent;
-import com.ning.billing.entitlement.events.phase.PhaseEventData;
-import com.ning.billing.entitlement.events.phase.PhaseEventBuilder;
-import com.ning.billing.entitlement.events.user.ApiEventBuilder;
-import com.ning.billing.entitlement.events.user.ApiEventCancel;
-import com.ning.billing.entitlement.events.user.ApiEventChange;
-import com.ning.billing.entitlement.events.user.ApiEventCreate;
-import com.ning.billing.entitlement.events.user.ApiEventPause;
-import com.ning.billing.entitlement.events.user.ApiEventResume;
-import com.ning.billing.entitlement.events.user.ApiEventType;
-import com.ning.billing.entitlement.events.user.ApiEventUncancel;
-import com.ning.billing.entitlement.events.user.ApiEvent;
-import com.ning.billing.entitlement.exceptions.EntitlementError;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
 
 @ExternalizedSqlViaStringTemplate3()
 public interface EventSqlDao extends Transactional<EventSqlDao>, CloseMe, Transmogrifier  {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
index 4a5312c..02f651d 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/SubscriptionSqlDao.java
@@ -16,13 +16,10 @@
 
 package com.ning.billing.entitlement.engine.dao;
 
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.skife.jdbi.v2.SQLStatement;
@@ -38,10 +35,12 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
-import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionData;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
 
 
 @ExternalizedSqlViaStringTemplate3()
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java
index cfbfd63..af74752 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EntitlementEvent.java
@@ -16,10 +16,10 @@
 
 package com.ning.billing.entitlement.events;
 
-import java.util.UUID;
-
 import org.joda.time.DateTime;
 
+import java.util.UUID;
+
 
 public interface EntitlementEvent extends EventLifecycle, Comparable<EntitlementEvent> {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
index d7a578c..d0db679 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBase.java
@@ -16,14 +16,11 @@
 
 package com.ning.billing.entitlement.events;
 
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
 import com.ning.billing.entitlement.events.user.ApiEvent;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
+import org.joda.time.DateTime;
+
+import java.util.UUID;
 
 public abstract class EventBase implements EntitlementEvent {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
index e003e35..104fbef 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventBaseBuilder.java
@@ -16,11 +16,10 @@
 
 package com.ning.billing.entitlement.events;
 
-import java.util.UUID;
-
+import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
 import org.joda.time.DateTime;
 
-import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
+import java.util.UUID;
 
 @SuppressWarnings("unchecked")
 public class EventBaseBuilder<T extends EventBaseBuilder<T>> {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java
index 0e9b226..ed2b042 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/EventLifecycle.java
@@ -16,10 +16,10 @@
 
 package com.ning.billing.entitlement.events;
 
-import java.util.UUID;
-
 import org.joda.time.DateTime;
 
+import java.util.UUID;
+
 public interface EventLifecycle {
 
     public enum EventLifecycleState {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java
index 873fb6d..be0ab6c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEventData.java
@@ -17,11 +17,10 @@
 package com.ning.billing.entitlement.events.phase;
 
 
-import org.joda.time.DateTime;
-
 import com.ning.billing.entitlement.alignment.TimedPhase;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.events.EventBase;
+import org.joda.time.DateTime;
 
 
 public class PhaseEventData extends EventBase implements PhaseEvent {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
index d6f390e..3f033a4 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
@@ -16,10 +16,10 @@
 
 package com.ning.billing.entitlement.events.user;
 
-import java.util.UUID;
-
-import org.joda.time.DateTime;
 import com.ning.billing.entitlement.events.EventBase;
+import org.joda.time.DateTime;
+
+import java.util.UUID;
 
 public class ApiEventBase extends EventBase implements ApiEvent {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index 4284181..1a9fffc 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -16,8 +16,6 @@
 
 package com.ning.billing.entitlement.glue;
 
-import org.skife.config.ConfigurationObjectFactory;
-
 import com.google.inject.AbstractModule;
 import com.ning.billing.config.EntitlementConfig;
 import com.ning.billing.entitlement.alignment.PlanAligner;
@@ -32,10 +30,11 @@ import com.ning.billing.entitlement.api.user.SubscriptionApiService;
 import com.ning.billing.entitlement.engine.core.DefaultApiEventProcessor;
 import com.ning.billing.entitlement.engine.core.Engine;
 import com.ning.billing.entitlement.engine.core.EventNotifier;
-import com.ning.billing.entitlement.engine.dao.EntitlementSqlDao;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
-import com.ning.billing.util.clock.DefaultClock;
+import com.ning.billing.entitlement.engine.dao.EntitlementSqlDao;
 import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.DefaultClock;
+import org.skife.config.ConfigurationObjectFactory;
 
 
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
index b14bf38..f76f775 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
@@ -16,20 +16,16 @@
 
 package com.ning.billing.entitlement.api;
 
-import java.util.EmptyStackException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Stack;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
 import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
 import com.google.common.eventbus.Subscribe;
 import com.ning.billing.entitlement.api.user.SubscriptionTransition;
 import com.ning.billing.util.eventbus.EventBus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
 
 public class ApiTestListener {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
index 9f1f69b..72d60aa 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
@@ -16,17 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.List;
 import java.util.UUID;
-
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,10 +29,8 @@ import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
-
 import com.google.inject.Injector;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IFieldStore;
+import com.ning.billing.account.api.AccountData;
 import com.ning.billing.catalog.DefaultCatalogService;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Catalog;
@@ -64,6 +56,11 @@ import com.ning.billing.util.clock.ClockMock;
 import com.ning.billing.util.eventbus.DefaultEventBusService;
 import com.ning.billing.util.eventbus.EventBusService;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
 
 public abstract class TestUserApiBase {
 
@@ -80,7 +77,7 @@ public abstract class TestUserApiBase {
     protected ClockMock clock;
     protected EventBusService busService;
 
-    protected IAccount account;
+    protected AccountData accountData;
     protected Catalog catalog;
     protected ApiTestListener testListener;
     protected SubscriptionBundle bundle;
@@ -136,8 +133,8 @@ public abstract class TestUserApiBase {
     protected abstract Injector getInjector();
 
     private void init() throws EntitlementUserApiException {
-        account = getAccount();
-        assertNotNull(account);
+        accountData = getAccountData();
+        assertNotNull(accountData);
 
         catalog = catalogService.getCatalog();
         assertNotNull(catalog);
@@ -161,7 +158,7 @@ public abstract class TestUserApiBase {
         ((MockEntitlementDao) dao).reset();
         try {
             busService.getEventBus().register(testListener);
-            bundle = entitlementApi.createBundleForAccount(account, "myDefaultBundle");
+            bundle = entitlementApi.createBundleForAccount(accountData, "myDefaultBundle");
         } catch (Exception e) {
             Assert.fail(e.getMessage());
         }
@@ -284,12 +281,20 @@ public abstract class TestUserApiBase {
         return result;
     }
 
-    protected IAccount getAccount() {
-        IAccount account = new IAccount() {
+    protected AccountData getAccountData() {
+        AccountData accountData = new AccountData() {
+            private final UUID id = UUID.randomUUID();
+
             @Override
             public String getName() {
-                return "accountName";
+                return "firstName lastName";
             }
+
+            @Override
+            public int getFirstNameLength() {
+                return "firstName".length();
+            }
+
             @Override
             public String getEmail() {
                 return "accountName@yahoo.com";
@@ -299,7 +304,7 @@ public abstract class TestUserApiBase {
                 return "4152876341";
             }
             @Override
-            public String getKey() {
+            public String getExternalKey() {
                 return "k123456";
             }
             @Override
@@ -310,26 +315,16 @@ public abstract class TestUserApiBase {
             public Currency getCurrency() {
                 return Currency.USD;
             }
-
             @Override
-            public UUID getId() {
-                return UUID.randomUUID();
+            public String getPaymentProviderName() {
+                return "Paypal";
             }
-
             @Override
-            public IFieldStore getFields() {
-                return null;
-            }
-
-            @Override
-            public String getFieldValue(String fieldName) {
-                return null;
+            public UUID getId() {
+                return id;
             }
-
-            @Override
-            public void setFieldValue(String fieldName, String fieldValue) {}
         };
-        return account;
+        return accountData;
     }
 
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
index 09a70f2..72e5556 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
@@ -16,24 +16,15 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.List;
-
+import com.ning.billing.catalog.api.*;
+import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.util.clock.DefaultClock;
 import org.joda.time.DateTime;
 import org.testng.Assert;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
-import com.ning.billing.util.clock.DefaultClock;
+import java.util.List;
+
+import static org.testng.Assert.*;
 
 public abstract class TestUserApiCancel extends TestUserApiBase {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
index 66cd35a..962a6ef 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
@@ -16,12 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
+import org.testng.annotations.Test;
 
 public class TestUserApiCancelMemory extends TestUserApiCancel {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java
index 83d4d8e..682fa06 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelSql.java
@@ -16,12 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.entitlement.glue.MockEngineModuleSql;
+import org.testng.annotations.Test;
 
 public class TestUserApiCancelSql extends TestUserApiCancel {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
index 14a46aa..76f6d44 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
@@ -16,28 +16,18 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.joda.time.DateTime;
-import org.testng.Assert;
-
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.user.ApiEvent;
 import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.testng.Assert.*;
 
 public abstract class TestUserApiChangePlan extends TestUserApiBase {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
index 341b9b6..173239c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
@@ -16,12 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
+import org.testng.annotations.Test;
 
 public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
index 2ccf83f..255e894 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
@@ -16,12 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.entitlement.glue.MockEngineModuleSql;
+import org.testng.annotations.Test;
 
 public class TestUserApiChangePlanSql extends TestUserApiChangePlan {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
index 7c14390..365374e 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
@@ -16,25 +16,17 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.List;
-
-import org.joda.time.DateTime;
-import org.testng.Assert;
-
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PriceListSet;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.phase.PhaseEvent;
 import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.Assert;
+
+import java.util.List;
+
+import static org.testng.Assert.*;
 
 public abstract class TestUserApiCreate extends TestUserApiBase {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
index d8a86c3..bff20db 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
@@ -16,12 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
+import org.testng.annotations.Test;
 
 public class TestUserApiCreateMemory extends TestUserApiCreate {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java
index 3ff899b..25996e2 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateSql.java
@@ -16,12 +16,11 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.entitlement.glue.MockEngineModuleSql;
+import org.testng.annotations.Test;
 
 public class TestUserApiCreateSql extends TestUserApiCreate {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
index 2476629..91ac96f 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
@@ -16,32 +16,22 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.Plan;
-import com.ning.billing.catalog.api.PlanPhase;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.*;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
 import com.ning.billing.entitlement.glue.MockEngineModuleSql;
 import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.testng.Assert.*;
 
 public class TestUserApiDemos extends TestUserApiBase {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
index bf7b717..d683244 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
@@ -16,20 +16,10 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-
-import java.util.UUID;
-
-import org.joda.time.DateTime;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.DefaultPriceListSet;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Duration;
 import com.ning.billing.catalog.api.PlanPhase;
@@ -37,6 +27,14 @@ import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
 import com.ning.billing.entitlement.glue.MockEngineModuleMemory;
 import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.UUID;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 
 public class TestUserApiError extends TestUserApiBase {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
index 69fcd08..7b600dd 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiScenarios.java
@@ -16,24 +16,21 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
-
-import org.joda.time.DateTime;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
 import com.ning.billing.entitlement.glue.MockEngineModuleSql;
 import com.ning.billing.util.clock.DefaultClock;
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
 
 public class TestUserApiScenarios extends TestUserApiBase {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java
index 434827a..83b981f 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/MockApiEventProcessorMemory.java
@@ -16,9 +16,6 @@
 
 package com.ning.billing.entitlement.engine.core;
 
-import java.util.Collection;
-import java.util.List;
-
 import com.google.inject.Inject;
 import com.ning.billing.config.EntitlementConfig;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
@@ -26,6 +23,9 @@ import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.clock.Clock;
 
+import java.util.Collection;
+import java.util.List;
+
 public class MockApiEventProcessorMemory extends ApiEventProcessorBase {
 
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
index f3f42f6..e9ff1bd 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoMemory.java
@@ -16,38 +16,22 @@
 
 package com.ning.billing.entitlement.engine.dao;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.TreeSet;
-import java.util.UUID;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.google.inject.Inject;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.catalog.api.TimeUnit;
 import com.ning.billing.config.EntitlementConfig;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionApiService;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionData;
-import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory;
+import com.ning.billing.entitlement.api.user.*;
 import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
 import com.ning.billing.entitlement.events.EventLifecycle.EventLifecycleState;
-import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.events.user.ApiEvent;
+import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.util.clock.Clock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
 
 public class MockEntitlementDaoMemory implements EntitlementDao, MockEntitlementDao {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
index 6f6d50d..2ebdea9 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
@@ -16,6 +16,10 @@
 
 package com.ning.billing.entitlement.engine.dao;
 
+import com.google.inject.Inject;
+import com.ning.billing.config.EntitlementConfig;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
+import com.ning.billing.util.clock.Clock;
 import org.skife.jdbi.v2.DBI;
 import org.skife.jdbi.v2.Transaction;
 import org.skife.jdbi.v2.TransactionStatus;
@@ -23,14 +27,6 @@ import org.skife.jdbi.v2.sqlobject.SqlUpdate;
 import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
 import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
 
-import com.google.inject.Inject;
-import com.ning.billing.catalog.api.Catalog;
-import com.ning.billing.catalog.api.CatalogService;
-import com.ning.billing.config.EntitlementConfig;
-import com.ning.billing.entitlement.api.user.SubscriptionApiService;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory;
-import com.ning.billing.util.clock.Clock;
-
 public class MockEntitlementDaoSql extends EntitlementSqlDao implements MockEntitlementDao {
 
     private final ResetSqlDao resetDao;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
index 75074ee..dc422a6 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
@@ -17,8 +17,8 @@
 package com.ning.billing.entitlement.glue;
 
 import com.ning.billing.catalog.glue.CatalogModule;
-import com.ning.billing.util.clock.ClockMock;
 import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
 import com.ning.billing.util.glue.EventBusModule;
 
 public class MockEngineModule extends EntitlementModule {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
index b8ef041..c6ce269 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
@@ -17,10 +17,10 @@
 package com.ning.billing.entitlement.glue;
 
 
-import com.ning.billing.entitlement.engine.core.MockApiEventProcessorMemory;
 import com.ning.billing.entitlement.engine.core.EventNotifier;
-import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoMemory;
+import com.ning.billing.entitlement.engine.core.MockApiEventProcessorMemory;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoMemory;
 
 public class MockEngineModuleMemory extends MockEngineModule {
     @Override
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
index afc8c06..f1cd237 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
@@ -16,15 +16,14 @@
 
 package com.ning.billing.entitlement.glue;
 
-import org.skife.config.ConfigurationObjectFactory;
-import org.skife.jdbi.v2.DBI;
-
 import com.ning.billing.dbi.DBIProvider;
 import com.ning.billing.dbi.DbiConfig;
-import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoSql;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
-import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoSql;
 import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.DBI;
 
 public class MockEngineModuleSql extends MockEngineModule {
 
diff --git a/entitlement/src/test/resources/testInput.xml b/entitlement/src/test/resources/testInput.xml
index 740a903..01d7cb4 100644
--- a/entitlement/src/test/resources/testInput.xml
+++ b/entitlement/src/test/resources/testInput.xml
@@ -18,7 +18,7 @@
 <!-- 
 Use cases covered so far:
 	Tiered Product (Pistol/Shotgun/Assault-Rifle)
-	Multiple change plan policies 
+	Multiple changeEvent plan policies
 	Multiple PlanAlignment (see below, trial add-on alignments and rescue discount package)
 	Product transition rules
 	Add on (Scopes, Hoster)

invoice/pom.xml 38(+37 -1)

diff --git a/invoice/pom.xml b/invoice/pom.xml
index 5bd70f4..8428ef0 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-invoice</artifactId>
@@ -29,20 +29,56 @@
             <artifactId>killbill-util</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-util</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>management</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>management-dbfiles</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
             <version>2.0</version>
         </dependency>
         <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.jdbi</groupId>
             <artifactId>jdbi</artifactId>
             <version>2.27</version>
         </dependency>
+        <dependency>
+            <groupId>org.antlr</groupId>
+            <artifactId>stringtemplate</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
     <build>
     </build>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java b/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java
new file mode 100644
index 0000000..b7bc657
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.google.inject.Inject;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+
+public class DefaultInvoiceService implements InvoiceService {
+    private static final String INVOICE_SERVICE_NAME = "invoice-service";
+    private final InvoiceUserApi userApi;
+    private final InvoicePaymentApi paymentApi;
+
+    @Inject
+    public DefaultInvoiceService(InvoiceUserApi userApi, InvoicePaymentApi paymentApi) {
+        this.userApi = userApi;
+        this.paymentApi = paymentApi;
+    }
+
+    @Override
+    public String getName() {
+        return INVOICE_SERVICE_NAME;
+    }
+
+    @Override
+    public InvoiceUserApi getUserApi() {
+        return userApi;
+    }
+
+    @Override
+    public InvoicePaymentApi getPaymentApi() {
+        return paymentApi;
+    }
+
+    @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.INIT_SERVICE)
+    public void initialize() {
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceUserApi.java
new file mode 100644
index 0000000..6b280ed
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/DefaultInvoiceUserApi.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.api;
+
+import com.google.inject.Inject;
+import com.ning.billing.invoice.dao.InvoiceDao;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.IDBI;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+public class DefaultInvoiceUserApi implements InvoiceUserApi {
+    private final InvoiceDao dao;
+
+    @Inject
+    public DefaultInvoiceUserApi(IDBI dbi) {
+        dao = dbi.onDemand(InvoiceDao.class);
+    }
+
+    @Override
+    public List<UUID> getInvoicesForPayment(DateTime targetDate, int numberOfDays) {
+        return dao.getInvoicesForPayment(targetDate.toDate(), numberOfDays);
+    }
+
+    @Override
+    public List<Invoice> getInvoicesByAccount(UUID accountId) {
+        return dao.getInvoicesByAccount(accountId.toString());
+    }
+
+    @Override
+    public Invoice getInvoice(UUID invoiceId) {
+        return dao.getInvoice(invoiceId.toString());
+    }
+
+    @Override
+    public void paymentAttemptFailed(UUID invoiceId, DateTime paymentAttemptDate) {
+        dao.notifyFailedPayment(invoiceId.toString(), paymentAttemptDate.toDate());
+    }
+
+    @Override
+    public void paymentAttemptSuccessful(UUID invoiceId, DateTime paymentAttemptDate, BigDecimal paymentAmount) {
+        dao.notifySuccessfulPayment(invoiceId.toString(), paymentAttemptDate.toDate(), paymentAmount);
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index 9abc12a..f238b86 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -16,32 +16,95 @@
 
 package com.ning.billing.invoice.dao;
 
-import com.ning.billing.invoice.model.Invoice;
-import org.skife.jdbi.v2.sqlobject.Bind;
-import org.skife.jdbi.v2.sqlobject.BindBean;
-import org.skife.jdbi.v2.sqlobject.SqlQuery;
-import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.*;
 import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
+import java.lang.annotation.*;
 import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 
 @ExternalizedSqlViaStringTemplate3()
-@RegisterMapper(InvoiceMapper.class)
+@RegisterMapper({UuidMapper.class, InvoiceDao.InvoiceMapper.class})
 public interface InvoiceDao {
     @SqlQuery
-    List<Invoice> getInvoicesByAccount(@Bind final String accountId);
+    List<Invoice> getInvoicesByAccount(@Bind("accountId") final String accountId);
 
     @SqlQuery
-    Invoice getInvoice(@Bind final String invoiceId);
+    Invoice getInvoice(@Bind("id") final String invoiceId);
 
     @SqlUpdate
-    void createInvoice(@BindBean final Invoice invoice);
+    void createInvoice(@InvoiceBinder final Invoice invoice);
 
-    @SqlUpdate
-    void addPayment(@Bind final String invoiceId, @Bind final BigDecimal paymentAmount);
+    @SqlQuery
+    List<Invoice> getInvoicesBySubscription(@Bind("subscriptionId") final String subscriptionId);
 
     @SqlQuery
-    int test();
+    List<UUID> getInvoicesForPayment(@Bind("targetDate") final Date targetDate,
+                                     @Bind("numberOfDays") final int numberOfDays);
+
+    @SqlUpdate
+    void notifySuccessfulPayment(@Bind("id") final String invoiceId,
+                                 @Bind("paymentDate") final Date paymentDate,
+                                 @Bind("paymentAmount") final BigDecimal paymentAmount);
+
+    @SqlUpdate
+    void notifyFailedPayment(@Bind("id") final String invoiceId,
+                             @Bind("paymentAttemptDate") final Date paymentAttemptDate);
+
+    @SqlUpdate
+    void test();
+
+    @BindingAnnotation(InvoiceBinder.InvoiceBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface InvoiceBinder {
+        public static class InvoiceBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<InvoiceBinder, Invoice>() {
+                    public void bind(SQLStatement q, InvoiceBinder bind, Invoice invoice) {
+                        q.bind("id", invoice.getId().toString());
+                        q.bind("accountId", invoice.getAccountId().toString());
+                        q.bind("invoiceDate", invoice.getInvoiceDate().toDate());
+                        q.bind("targetDate", invoice.getTargetDate().toDate());
+                        q.bind("amountPaid", invoice.getAmountPaid());
+                        q.bind("amountOutstanding", invoice.getAmountOutstanding());
+                        DateTime invoiceDate = invoice.getLastPaymentAttempt();
+                        q.bind("lastPaymentAttempt", invoiceDate == null ? null : invoiceDate.toDate());
+                        q.bind("currency", invoice.getCurrency().toString());
+                    }
+                };
+            }
+        }
+    }
+
+    public static class InvoiceMapper implements ResultSetMapper<Invoice> {
+        @Override
+        public Invoice map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID id = UUID.fromString(result.getString("id"));
+            UUID accountId = UUID.fromString(result.getString("account_id"));
+            DateTime invoiceDate = new DateTime(result.getTimestamp("invoice_date"));
+            DateTime targetDate = new DateTime(result.getTimestamp("target_date"));
+            BigDecimal amountPaid = result.getBigDecimal("amount_paid");
+            Timestamp lastPaymentAttemptTimeStamp = result.getTimestamp("last_payment_attempt");
+            DateTime lastPaymentAttempt = lastPaymentAttemptTimeStamp == null ? null : new DateTime(lastPaymentAttemptTimeStamp);
+            Currency currency = Currency.valueOf(result.getString("currency"));
+
+            return new DefaultInvoice(id, accountId, invoiceDate, targetDate, currency, lastPaymentAttempt, amountPaid, new ArrayList<InvoiceItem>());
+        }
+    }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoWrapper.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoWrapper.java
new file mode 100644
index 0000000..99a4a35
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.dao;
+
+import com.google.inject.Inject;
+import com.ning.billing.invoice.api.Invoice;
+import org.skife.jdbi.v2.IDBI;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+public class InvoiceDaoWrapper implements InvoiceDao {
+    private final InvoiceDao dao;
+
+    @Inject
+    public InvoiceDaoWrapper(IDBI dbi) {
+        this.dao = dbi.onDemand(InvoiceDao.class);
+    }
+
+    @Override
+    public List<Invoice> getInvoicesByAccount(final String accountId) {
+        return dao.getInvoicesByAccount(accountId);
+    }
+
+    @Override
+    public Invoice getInvoice(final String invoiceId) {
+        return dao.getInvoice(invoiceId);
+    }
+
+    @Override
+    public void createInvoice(final Invoice invoice) {
+        dao.createInvoice(invoice);
+    }
+
+    @Override
+    public List<Invoice> getInvoicesBySubscription(String subscriptionId) {
+        return dao.getInvoicesBySubscription(subscriptionId);
+    }
+
+    @Override
+    public List<UUID> getInvoicesForPayment(Date targetDate, int numberOfDays) {
+        return dao.getInvoicesForPayment(targetDate, numberOfDays);
+    }
+
+    @Override
+    public void notifySuccessfulPayment(String invoiceId, Date paymentDate, BigDecimal paymentAmount) {
+        dao.notifySuccessfulPayment(invoiceId, paymentDate, paymentAmount);
+    }
+
+    @Override
+    public void notifyFailedPayment(String invoiceId, Date paymentAttemptDate) {
+        dao.notifyFailedPayment(invoiceId, paymentAttemptDate);
+    }
+
+    @Override
+    public void test() {
+        dao.test();
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java
index 9de9f76..1bb41b3 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java
@@ -16,24 +16,82 @@
 
 package com.ning.billing.invoice.dao;
 
-import com.ning.billing.invoice.model.InvoiceItem;
-import com.ning.billing.invoice.model.InvoiceItemList;
-import org.skife.jdbi.v2.sqlobject.Bind;
-import org.skife.jdbi.v2.sqlobject.BindBean;
-import org.skife.jdbi.v2.sqlobject.SqlQuery;
-import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.*;
 import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import java.lang.annotation.*;
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
 
 @ExternalizedSqlViaStringTemplate3()
-@RegisterMapper(InvoiceItemMapper.class)
+@RegisterMapper(InvoiceItemDao.InvoiceItemMapper.class)
 public interface InvoiceItemDao {
     @SqlQuery
-    InvoiceItemList getInvoiceItemsByInvoice(@Bind final String invoiceId);
+    InvoiceItem getInvoiceItem(@Bind("id") final String invoiceItemId);
+
+    @SqlQuery
+    List<InvoiceItem> getInvoiceItemsByInvoice(@Bind("invoiceId") final String invoiceId);
+
+    @SqlQuery
+    List<InvoiceItem> getInvoiceItemsByAccount(@Bind("accountId") final String accountId);
 
     @SqlQuery
-    InvoiceItemList getInvoiceItemsByAccount(@Bind final String accountId);
+    List<InvoiceItem> getInvoiceItemsBySubscription(@Bind("subscriptionId") final String subscriptionId);
 
     @SqlUpdate
-    void createInvoiceItem(@BindBean final InvoiceItem invoiceItem);
+    void createInvoiceItem(@InvoiceItemBinder final InvoiceItem invoiceItem);
+
+    @SqlUpdate
+    void test();
+
+    @BindingAnnotation(InvoiceItemBinder.InvoiceItemBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface InvoiceItemBinder {
+        public static class InvoiceItemBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<InvoiceItemBinder, InvoiceItem>() {
+                    public void bind(SQLStatement q, InvoiceItemBinder bind, InvoiceItem item) {
+                        q.bind("id", item.getId().toString());
+                        q.bind("invoiceId", item.getInvoiceId().toString());
+                        q.bind("subscriptionId", item.getSubscriptionId().toString());
+                        q.bind("startDate", item.getStartDate().toDate());
+                        q.bind("endDate", item.getEndDate().toDate());
+                        q.bind("description", item.getDescription());
+                        q.bind("amount", item.getAmount());
+                        q.bind("rate", item.getRate());
+                        q.bind("currency", item.getCurrency().toString());
+                    }
+                };
+            }
+        }
+    }
+
+    public static class InvoiceItemMapper implements ResultSetMapper<InvoiceItem> {
+        @Override
+        public InvoiceItem map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID id = UUID.fromString(result.getString("id"));
+            UUID invoiceId = UUID.fromString(result.getString("invoice_id"));
+            UUID subscriptionId = UUID.fromString(result.getString("subscription_id"));
+            DateTime startDate = new DateTime(result.getTimestamp("start_date"));
+            DateTime endDate = new DateTime(result.getTimestamp("end_date"));
+            String description = result.getString("description");
+            BigDecimal amount = result.getBigDecimal("amount");
+            BigDecimal rate = result.getBigDecimal("rate");
+            Currency currency = Currency.valueOf(result.getString("currency"));
+
+            return new DefaultInvoiceItem(id, invoiceId, subscriptionId, startDate, endDate, description, amount, rate , currency);
+        }
+    }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDaoWrapper.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDaoWrapper.java
new file mode 100644
index 0000000..276785e
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDaoWrapper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.dao;
+
+import com.google.inject.Inject;
+import com.ning.billing.invoice.api.InvoiceItem;
+import org.skife.jdbi.v2.IDBI;
+
+import java.util.List;
+
+public class InvoiceItemDaoWrapper implements InvoiceItemDao {
+    private final InvoiceItemDao dao;
+
+    @Inject
+    public InvoiceItemDaoWrapper(IDBI dbi) {
+        dao = dbi.onDemand(InvoiceItemDao.class);
+    }
+
+    @Override
+    public InvoiceItem getInvoiceItem(String invoiceItemId) {
+        return dao.getInvoiceItem(invoiceItemId);
+    }
+
+    @Override
+    public List<InvoiceItem> getInvoiceItemsByInvoice(String invoiceId) {
+        return dao.getInvoiceItemsByInvoice(invoiceId);
+    }
+
+    @Override
+    public List<InvoiceItem> getInvoiceItemsByAccount(String accountId) {
+        return dao.getInvoiceItemsByAccount(accountId);
+    }
+
+    @Override
+    public List<InvoiceItem> getInvoiceItemsBySubscription(String subscriptionId) {
+        return dao.getInvoiceItemsBySubscription(subscriptionId);
+    }
+
+    @Override
+    public void createInvoiceItem(InvoiceItem invoiceItem) {
+        dao.createInvoiceItem(invoiceItem);
+    }
+
+    @Override
+    public void test() {
+        dao.test();
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/UuidMapper.java b/invoice/src/main/java/com/ning/billing/invoice/dao/UuidMapper.java
new file mode 100644
index 0000000..4affe3d
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/UuidMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.dao;
+
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+public class UuidMapper implements ResultSetMapper<UUID> {
+    @Override
+    public UUID map(final int index, ResultSet resultSet, StatementContext statementContext) throws SQLException {
+        return UUID.fromString(resultSet.getString(1));
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java b/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java
new file mode 100644
index 0000000..9318510
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.glue;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.invoice.api.DefaultInvoiceUserApi;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.invoice.dao.InvoiceDao;
+import com.ning.billing.invoice.dao.InvoiceDaoWrapper;
+import com.ning.billing.invoice.dao.InvoiceItemDao;
+import com.ning.billing.invoice.dao.InvoiceItemDaoWrapper;
+
+public class InvoiceModule extends AbstractModule {
+    private void installInvoiceDao() {
+        bind(InvoiceDao.class).to(InvoiceDaoWrapper.class).asEagerSingleton();
+    }
+
+    private void installInvoiceItemDao() {
+        bind(InvoiceItemDao.class).to(InvoiceItemDaoWrapper.class).asEagerSingleton();
+    }
+
+    protected void installInvoiceUserApi() {
+        bind(InvoiceUserApi.class).to(DefaultInvoiceUserApi.class).asEagerSingleton();
+    }
+
+    @Override
+    protected void configure() {
+        installInvoiceDao();
+        installInvoiceItemDao();
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java b/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java
index d141f27..949f711 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/BillingModeBase.java
@@ -21,7 +21,7 @@ import org.joda.time.DateTime;
 
 import java.math.BigDecimal;
 
-public abstract class BillingModeBase implements IBillingMode {
+public abstract class BillingModeBase implements BillingMode {
     @Override
     public BigDecimal calculateNumberOfBillingCycles(final DateTime startDate, final DateTime endDate, final DateTime targetDate, final int billingCycleDay, final BillingPeriod billingPeriod) throws InvalidDateSequenceException {
         if (endDate.isBefore(startDate)) {throw new InvalidDateSequenceException();}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
index 2dc32ce..54ca894 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
@@ -18,9 +18,11 @@ package com.ning.billing.invoice.model;
 
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.entitlement.api.billing.BillingMode;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.invoice.api.BillingEventSet;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
 import org.joda.time.DateTime;
 
 import java.math.BigDecimal;
@@ -29,15 +31,15 @@ import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 
-public class DefaultInvoiceGenerator implements IInvoiceGenerator {
+public class DefaultInvoiceGenerator implements InvoiceGenerator {
     @Override
     public Invoice generateInvoice(final UUID accountId, final BillingEventSet events, final InvoiceItemList existingItems, final DateTime targetDate, final Currency targetCurrency) {
-        if (events == null) {return new Invoice(accountId, targetCurrency);}
-        if (events.size() == 0) {return new Invoice(accountId, targetCurrency);}
+        if (events == null) {return new DefaultInvoice(accountId, targetDate, targetCurrency);}
+        if (events.size() == 0) {return new DefaultInvoice(accountId, targetDate, targetCurrency);}
 
-        Invoice invoice = new Invoice(accountId, targetCurrency);
-        InvoiceItemList currentItems = generateInvoiceItems(events, invoice.getInvoiceId(), targetDate, targetCurrency);
-        InvoiceItemList itemsToPost = reconcileInvoiceItems(invoice.getInvoiceId(), currentItems, existingItems);
+        DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, targetCurrency);
+        InvoiceItemList currentItems = generateInvoiceItems(events, invoice.getId(), targetDate, targetCurrency);
+        InvoiceItemList itemsToPost = reconcileInvoiceItems(invoice.getId(), currentItems, existingItems);
         invoice.add(itemsToPost);
 
         return invoice;
@@ -46,7 +48,7 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
     private InvoiceItemList reconcileInvoiceItems(final UUID invoiceId, final InvoiceItemList currentInvoiceItems, final InvoiceItemList existingInvoiceItems) {
         InvoiceItemList currentItems = new InvoiceItemList();
         for (InvoiceItem item : currentInvoiceItems) {
-            currentItems.add(new InvoiceItem(item, invoiceId));
+            currentItems.add(new DefaultInvoiceItem(item, invoiceId));
         }
 
         InvoiceItemList existingItems = (InvoiceItemList) existingInvoiceItems.clone();
@@ -112,7 +114,7 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
     private void processEvent(UUID invoiceId, BillingEvent event, List<InvoiceItem> items, DateTime targetDate, Currency targetCurrency) {
         BigDecimal rate = event.getPrice(targetCurrency);
         BigDecimal invoiceItemAmount = calculateInvoiceItemAmount(event, targetDate, rate);
-        IBillingMode billingMode = getBillingMode(event.getBillingMode());
+        BillingMode billingMode = getBillingMode(event.getBillingMode());
         DateTime billThroughDate = billingMode.calculateEffectiveEndDate(event.getEffectiveDate(), targetDate, event.getBillCycleDay(), event.getBillingPeriod());
 
         addInvoiceItem(invoiceId, items, event, billThroughDate, invoiceItemAmount, rate, targetCurrency);
@@ -121,7 +123,7 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
     private void processEvents(UUID invoiceId, BillingEvent firstEvent, BillingEvent secondEvent, List<InvoiceItem> items, DateTime targetDate, Currency targetCurrency) {
         BigDecimal rate = firstEvent.getPrice(targetCurrency);
         BigDecimal invoiceItemAmount = calculateInvoiceItemAmount(firstEvent, secondEvent, targetDate, rate);
-        IBillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
+        BillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
         DateTime billThroughDate = billingMode.calculateEffectiveEndDate(firstEvent.getEffectiveDate(), secondEvent.getEffectiveDate(), targetDate, firstEvent.getBillCycleDay(), firstEvent.getBillingPeriod());
 
         addInvoiceItem(invoiceId, items, firstEvent, billThroughDate, invoiceItemAmount, rate, targetCurrency);
@@ -129,13 +131,13 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
 
     private void addInvoiceItem(UUID invoiceId, List<InvoiceItem> items, BillingEvent event, DateTime billThroughDate, BigDecimal amount, BigDecimal rate, Currency currency) {
         if (!(amount.compareTo(BigDecimal.ZERO) == 0)) {
-            InvoiceItem item = new InvoiceItem(invoiceId, event.getSubscriptionId(), event.getEffectiveDate(), billThroughDate, event.getDescription(), amount, rate, currency);
+            DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, event.getSubscriptionId(), event.getEffectiveDate(), billThroughDate, event.getDescription(), amount, rate, currency);
             items.add(item);
         }
     }
 
     private BigDecimal calculateInvoiceItemAmount(BillingEvent event, DateTime targetDate, BigDecimal rate){
-        IBillingMode billingMode = getBillingMode(event.getBillingMode());
+        BillingMode billingMode = getBillingMode(event.getBillingMode());
         DateTime startDate = event.getEffectiveDate();
         int billingCycleDay = event.getBillCycleDay();
         BillingPeriod billingPeriod = event.getBillingPeriod();
@@ -151,7 +153,7 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
     }
 
     private BigDecimal calculateInvoiceItemAmount(BillingEvent firstEvent, BillingEvent secondEvent, DateTime targetDate, BigDecimal rate) {
-        IBillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
+        BillingMode billingMode = getBillingMode(firstEvent.getBillingMode());
         DateTime startDate = firstEvent.getEffectiveDate();
         int billingCycleDay = firstEvent.getBillCycleDay();
         BillingPeriod billingPeriod = firstEvent.getBillingPeriod();
@@ -168,8 +170,8 @@ public class DefaultInvoiceGenerator implements IInvoiceGenerator {
         }
     }
 
-    private IBillingMode getBillingMode(BillingMode billingMode) {
-        switch (billingMode) {
+    private BillingMode getBillingMode(BillingModeType billingModeType) {
+        switch (billingModeType) {
             case IN_ADVANCE:
                 return new InAdvanceBillingMode();
             default:
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
index 679c735..fb82f06 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceItemList.java
@@ -16,6 +16,8 @@
 
 package com.ning.billing.invoice.model;
 
+import com.ning.billing.invoice.api.InvoiceItem;
+
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg
index da2eade..b22f792 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg
@@ -1,24 +1,53 @@
 group InvoiceDao;
 
 getInvoicesByAccount() ::= <<
-  select * from invoices where account_id = :accountId order by invoiceDate asc;
+  SELECT id, account_id, invoice_date, target_date, currency, amount_paid, last_payment_attempt
+  FROM invoices
+  WHERE account_id = :accountId
+  ORDER BY invoice_date ASC;
+>>
+
+getInvoicesBySubscription() ::= <<
+  SELECT i.id, i.account_id, i.invoice_date, i.target_date, i.currency, i.amount_paid, i.last_payment_attempt
+  FROM invoices i
+  INNER JOIN invoice_items ii ON i.id = ii.invoice_id
+  WHERE ii.subscription_id = :subscriptionId;
+>>
+
+getInvoicesForPayment() ::= <<
+  SELECT i.id
+  FROM invoices i
+  INNER JOIN invoice_items ii ON i.id = ii.invoice_id
+  WHERE DATEDIFF(:targetDate, i.last_payment_attempt) >= :numberOfDays OR (i.last_payment_attempt IS NULL)
+  GROUP BY i.id, i.amount_paid
+  HAVING SUM(ii.amount) > (i.amount_paid);
 >>
 
 getInvoice() ::= <<
-  select * from invoices where invoice_id = :invoiceId;
+  SELECT id, account_id, invoice_date, target_date, currency, amount_paid, last_payment_attempt
+  FROM invoices
+  WHERE id = :id;
 >>
 
 createInvoice() ::= <<
-  INSERT INTO invoices(invoice_id, account_id, invoiceDate)
-  VALUES (:invoiceId, :accountId, :invoiceDate);
+  INSERT INTO invoices(id, account_id, invoice_date, target_date, currency, amount_paid, last_payment_attempt)
+  VALUES (:id, :accountId, :invoiceDate, :targetDate, :currency, :amountPaid, :lastPaymentAttempt);
+>>
+
+notifySuccessfulPayment() ::= <<
+  UPDATE invoices
+  SET amount_paid = amount_paid + :paymentAmount, last_payment_attempt = :paymentDate
+  WHERE id = :id;
 >>
 
-addPayment() ::= <<
-  UPDATE invoices SET amount_paid = amount_paid + :paymentAmount
-  WHERE invoice_id = :invoiceId;
+notifyFailedPayment() ::= <<
+  UPDATE invoices
+  SET last_payment_attempt = :paymentAttemptDate
+  WHERE id = :id;
 >>
 
 test() ::= <<
-  SELECT DISTINCT 1 FROM invoices;
+  SELECT 1
+  FROM invoices;
 >>
-;
+;
\ No newline at end of file
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg
index 479b4cf..ffd4cf9 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg
@@ -1,13 +1,37 @@
 group InvoiceItemDao;
 
+getInvoiceItem() ::= <<
+  SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+  FROM invoice_items
+  WHERE id = :id;
+>>
+
 getInvoiceItemsByInvoice() ::= <<
+  SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+  FROM invoice_items
+  WHERE invoice_id = :invoiceId;
 >>
 
 getInvoiceItemsByAccount() ::= <<
+  SELECT ii.id, ii.invoice_id, ii.subscription_id, ii.start_date, ii.end_date, ii.description, ii.amount, ii.rate, ii.currency
+  FROM invoice_items ii
+  INNER JOIN invoices i ON i.id = ii.invoice_id
+  WHERE i.account_id = :accountId;
+>>
+
+getInvoiceItemsBySubscription() ::= <<
+  SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
+  FROM invoice_items
+  WHERE subscription_id = :subscriptionId;
 >>
 
 createInvoiceItem() ::= <<
-  INSERT INTO invoice_items(invoice_item_id, subscription_id, start_date, end_date, description, amount, rate, currency)
-  VALUES(:invoiceItemId, :invoiceId, :subscriptionId, :startDate, :endDate, :description, :amount, :rate, :currency)
+  INSERT INTO invoice_items(id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency)
+  VALUES(:id, :invoiceId, :subscriptionId, :startDate, :endDate, :description, :amount, :rate, :currency)
+>>
+
+test() ::= <<
+  SELECT 1
+  FROM invoice_items;
 >>
 ;
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql b/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
index 1a851a0..3c25d8e 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
+++ b/invoice/src/main/resources/com/ning/billing/invoice/ddl.sql
@@ -1,7 +1,6 @@
 DROP TABLE IF EXISTS invoice_items;
 CREATE TABLE invoice_items (
-  id int(11) unsigned NOT NULL AUTO_INCREMENT,
-  invoice_item_id char(36) NOT NULL,
+  id char(36) NOT NULL,
   invoice_id char(36) NOT NULL,
   subscription_id char(36) NOT NULL,
   start_date datetime NOT NULL,
@@ -9,7 +8,7 @@ CREATE TABLE invoice_items (
   description varchar(100) NOT NULL,
   amount numeric(10,4) NOT NULL,
   rate numeric(10,4) NOT NULL,
-  currency varchar(5) NOT NULL,
+  currency char(3) NOT NULL,
   PRIMARY KEY(id)
 ) ENGINE=innodb;
 
@@ -17,18 +16,44 @@ CREATE INDEX invoice_items_subscription_id ON invoice_items(subscription_id ASC)
 
 DROP TABLE IF EXISTS invoices;
 CREATE TABLE invoices (
-  id int(11) unsigned NOT NULL AUTO_INCREMENT,
-  invoice_id char(36) NOT NULL,
+  id char(36) NOT NULL,
   account_id char(36) NOT NULL,
   invoice_date datetime NOT NULL,
+  target_date datetime NOT NULL,
+  currency char(3) NOT NULL,
   amount_paid numeric(10,4) NOT NULL DEFAULT 0,
-  amount_outstanding numeric(10,4) NOT NULL,
   last_payment_attempt datetime DEFAULT NULL,
   PRIMARY KEY(id)
 ) ENGINE=innodb;
 
 CREATE INDEX invoices_account_id ON invoices(account_id ASC);
-CREATE INDEX invoices_invoice_id ON invoices(invoice_id ASC);
+
+DROP TABLE IF EXISTS invoice_payments;
+CREATE TABLE invoice_payments (
+  id char(36) NOT NULL,
+  invoice_id char(36) NOT NULL,
+  payment_id char(36) NOT NULL,
+  payment_date datetime NOT NULL,
+  amount numeric(10,4) NOT NULL,
+  currency char(3) NOT NULL,
+  PRIMARY KEY(id)
+) ENGINE=innodb;
+CREATE UNIQUE INDEX invoice_payments_unique ON invoice_payments(invoice_id, payment_id);
+
+CREATE VIEW amount_remaining AS
+SELECT invoice_items.id,
+       SUM(invoice_items.amount) AS amount_owed
+FROM invoice_items
+GROUP BY invoice_items.id;
+
+CREATE VIEW invoices_for_payment AS
+SELECT i.id,
+       DATEDIFF(NOW(), MAX(i.last_payment_attempt)) AS days_due
+FROM invoices i
+LEFT JOIN amount_remaining ar ON i.id = ar.id
+WHERE (i.amount_paid < ar.amount_owed)
+      AND (i.last_payment_attempt IS NOT NULL)
+GROUP BY i.id;
 
 
 
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
index 5447094..0dd5d47 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
@@ -16,50 +16,263 @@
 
 package com.ning.billing.invoice.dao;
 
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.glue.InvoiceModuleMock;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import com.ning.billing.util.clock.DefaultClock;
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import static org.testng.Assert.*;
+
 @Test(groups = {"invoicing", "invoicing-dao"})
 public class InvoiceDaoTests {
-//    private final MysqlTestingHelper helper = new MysqlTestingHelper();
-//    private InvoiceDao dao;
-//
-//    @BeforeClass(alwaysRun = true)
-//    private void setup() {
-//        final String ddl = IOUtils.toString(InvoiceDao.class.getResourceAsStream("/ddl.sql"));
-//
-//        helper.startMysql();
-//        helper.initDb();
-//
-//        final IDBI dbi = helper.getDBI();
-//        dao = dbi.onDemand(EventDao.class);
-//
-//        // Healthcheck test to make sure MySQL is setup properly
-//        try {
-//            dao.test();
-//        }
-//        catch (Throwable t) {
-//            Assert.fail(t.toString());
-//        }
-//    }
-//
-//    @Test
-//    public void testCreationAndRetrievalByAccount() {
-//        InvoiceDao dao = dbi.onDemand(InvoiceDao.class);
-//        UUID accountId = UUID.randomUUID();
-//        Invoice invoice = new Invoice(accountId, Currency.USD);
-//        DateTime invoiceDate = invoice.getInvoiceDate();
-//
-//        dao.createInvoice(invoice);
-//
-//        List<Invoice> invoices = dao.getInvoicesByAccount(accountId.toString());
-//        assertNotNull(invoices);
-//        assertEquals(invoices.size(), 1);
-//        Invoice thisInvoice = invoices.get(0);
-//        assertEquals(invoice.getAccountId(), accountId);
-//        assertTrue(thisInvoice.getInvoiceDate().equals(invoiceDate));
-//        assertEquals(thisInvoice.getCurrency(), Currency.USD);
-//        assertEquals(thisInvoice.getNumberOfItems(), 0);
-//        assertTrue(thisInvoice.getTotalAmount().compareTo(BigDecimal.ZERO) == 0);
-//    }
+    private final int NUMBER_OF_DAY_BETWEEN_RETRIES = 8;
+
+    private final MysqlTestingHelper helper = new MysqlTestingHelper();
+    private InvoiceDao dao;
+    private InvoiceItemDao invoiceItemDao;
+
+    @BeforeClass()
+    private void setup() throws IOException {
+        // Health check test to make sure MySQL is setup properly
+        try {
+            InvoiceModuleMock module = new InvoiceModuleMock();
+            final String ddl = IOUtils.toString(InvoiceDaoWrapper.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
+            module.createDb(ddl);
+
+            final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
+
+            dao = injector.getInstance(InvoiceDaoWrapper.class);
+            dao.test();
+
+            invoiceItemDao = injector.getInstance(InvoiceItemDao.class);
+            invoiceItemDao.test();
+        }
+        catch (Throwable t) {
+            fail(t.toString());
+        }
+    }
+
+    @Test
+    public void testCreationAndRetrievalByAccount() {
+        UUID accountId = UUID.randomUUID();
+        Invoice invoice = new DefaultInvoice(accountId, new DefaultClock().getUTCNow(), Currency.USD);
+        DateTime invoiceDate = invoice.getInvoiceDate();
+
+        dao.createInvoice(invoice);
+
+        List<Invoice> invoices = dao.getInvoicesByAccount(accountId.toString());
+        assertNotNull(invoices);
+        assertEquals(invoices.size(), 1);
+        Invoice thisInvoice = invoices.get(0);
+        assertEquals(invoice.getAccountId(), accountId);
+        assertTrue(thisInvoice.getInvoiceDate().compareTo(invoiceDate) == 0);
+        assertEquals(thisInvoice.getCurrency(), Currency.USD);
+        assertEquals(thisInvoice.getNumberOfItems(), 0);
+        assertTrue(thisInvoice.getTotalAmount().compareTo(BigDecimal.ZERO) == 0);
+    }
+
+    @Test
+    public void testRetrievalForNonExistentInvoiceId() {
+        Invoice invoice = dao.getInvoice(UUID.randomUUID().toString());
+        assertNull(invoice);
+    }
+
+    @Test
+    public void testAddPayment() {
+        UUID accountId = UUID.randomUUID();
+        DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+        Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+        DateTime paymentAttemptDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
+        BigDecimal paymentAmount = new BigDecimal("14.0");
+
+        dao.createInvoice(invoice);
+        dao.notifySuccessfulPayment(invoice.getId().toString(), paymentAttemptDate.toDate(), paymentAmount);
+
+        invoice = dao.getInvoice(invoice.getId().toString());
+        assertEquals(invoice.getAmountPaid().compareTo(paymentAmount), 0);
+        assertTrue(invoice.getLastPaymentAttempt().equals(paymentAttemptDate));
+    }
+
+    @Test
+    public void testAddPaymentAttempt() {
+        UUID accountId = UUID.randomUUID();
+        DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+        Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+        DateTime paymentAttemptDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
+
+        dao.createInvoice(invoice);
+        dao.notifyFailedPayment(invoice.getId().toString(), paymentAttemptDate.toDate());
+
+        invoice = dao.getInvoice(invoice.getId().toString());
+        assertTrue(invoice.getLastPaymentAttempt().equals(paymentAttemptDate));
+    }
+
+    @Test
+    public void testGetInvoicesForPaymentWithNoResults() {
+        DateTime notionalDate = new DateTime();
+        DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+        
+        // determine the number of existing invoices available for payment (to avoid side effects from other tests)
+        List<UUID> invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        int existingInvoiceCount = invoices.size();
+        
+        UUID accountId = UUID.randomUUID();
+        Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+        dao.createInvoice(invoice);
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount);
+    }
+
+    // TODO: test invoices for payment with results
+    @Test
+    public void testGetInvoicesForPayment() {
+        List<UUID> invoices;
+        DateTime notionalDate = new DateTime();
+
+        // determine the number of existing invoices available for payment (to avoid side effects from other tests)
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        int existingInvoiceCount = invoices.size();
+
+        // create a new invoice with one item
+        UUID accountId = UUID.randomUUID();
+        DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+        Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+        dao.createInvoice(invoice);
+
+        UUID invoiceId = invoice.getId();
+        UUID subscriptionId = UUID.randomUUID();
+        DateTime endDate = targetDate.plusMonths(3);
+        BigDecimal rate = new BigDecimal("9.0");
+        BigDecimal amount = rate.multiply(new BigDecimal("3.0"));
+
+        DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, targetDate, endDate, "test", amount, rate, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item);
+
+        // ensure that the number of invoices for payment has increased by 1
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount + 1);
+
+        // attempt a payment; ensure that the number of invoices for payment has decreased by 1 (no retries for eight days)
+        dao.notifyFailedPayment(invoice.getId().toString(), notionalDate.toDate());
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount);
+
+        // advance clock by 8 days; ensure that number of invoices for payment has increased by 1 (retry)
+        notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount + 1);
+
+        // post successful partial payment; ensure that number of invoices for payment has decreased by 1
+        dao.notifySuccessfulPayment(invoiceId.toString(), notionalDate.toDate(), new BigDecimal("22.0000"));
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount);
+
+        // get invoice; verify amount paid is correct
+        invoice = dao.getInvoice(invoiceId.toString());
+        assertEquals(invoice.getAmountPaid().compareTo(new BigDecimal("22.0")), 0);
+
+        // advance clock eight days; ensure that number of invoices for payment has increased by 1 (retry)
+        notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount + 1);
+
+        // post completed payment; ensure that the number of invoices for payment has decreased by 1
+        dao.notifySuccessfulPayment(invoiceId.toString(), notionalDate.toDate(), new BigDecimal("5.0000"));
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount);
+
+        // get invoice; verify amount paid is correct
+        invoice = dao.getInvoice(invoiceId.toString());
+        assertEquals(invoice.getAmountPaid().compareTo(new BigDecimal("27.0")), 0);
+
+        // advance clock by 8 days; ensure that the number of invoices for payment hasn't changed
+        notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        assertEquals(invoices.size(), existingInvoiceCount);
+
+    }
+
+    @Test
+    public void testGetInvoicesBySubscription() {
+        UUID accountId = UUID.randomUUID();
+
+        UUID subscriptionId1 = UUID.randomUUID(); BigDecimal rate1 = new BigDecimal("17.0");
+        UUID subscriptionId2 = UUID.randomUUID(); BigDecimal rate2 = new BigDecimal("42.0");
+        UUID subscriptionId3 = UUID.randomUUID(); BigDecimal rate3 = new BigDecimal("3.0");
+        UUID subscriptionId4 = UUID.randomUUID(); BigDecimal rate4 = new BigDecimal("12.0");
+
+        DateTime targetDate = new DateTime(2011, 5, 23, 0, 0, 0, 0);
+
+
+        // create invoice 1 (subscriptions 1-4)
+        Invoice invoice1 = new DefaultInvoice(accountId, targetDate, Currency.USD);
+        dao.createInvoice(invoice1);
+
+        UUID invoiceId1 = invoice1.getId();
+
+        DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+        DateTime endDate = startDate.plusMonths(1);
+
+        DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoiceId1, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item1);
+
+        DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoiceId1, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item2);
+
+        DefaultInvoiceItem item3 = new DefaultInvoiceItem(invoiceId1, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item3);
+
+        DefaultInvoiceItem item4 = new DefaultInvoiceItem(invoiceId1, subscriptionId4, startDate, endDate, "test D", rate4, rate4, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item4);
+
+        // create invoice 2 (subscriptions 1-3)
+        DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+        dao.createInvoice(invoice);
+
+        UUID invoiceId2 = invoice.getId();
+
+        startDate = endDate;
+        endDate = startDate.plusMonths(1);
+
+        DefaultInvoiceItem item5 = new DefaultInvoiceItem(invoiceId2, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item5);
+
+        DefaultInvoiceItem item6 = new DefaultInvoiceItem(invoiceId2, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item6);
+
+        DefaultInvoiceItem item7 = new DefaultInvoiceItem(invoiceId2, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
+        invoiceItemDao.createInvoiceItem(item7);
+
+        // check that each subscription returns the correct number of invoices
+        List<Invoice> items1 = dao.getInvoicesBySubscription(subscriptionId1.toString());
+        assertEquals(items1.size(), 2);
+
+        List<Invoice> items2 = dao.getInvoicesBySubscription(subscriptionId2.toString());
+        assertEquals(items2.size(), 2);
+
+        List<Invoice> items3 = dao.getInvoicesBySubscription(subscriptionId3.toString());
+        assertEquals(items3.size(), 2);
 
+        List<Invoice> items4 = dao.getInvoicesBySubscription(subscriptionId4.toString());
+        assertEquals(items4.size(), 1);
+    }
+    
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
new file mode 100644
index 0000000..7e01ff2
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.dao;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.glue.InvoiceModuleMock;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import static org.testng.Assert.*;
+
+public class InvoiceItemDaoTests {
+    private InvoiceItemDaoWrapper dao;
+    private InvoiceDao invoiceDao;
+
+    @BeforeClass(alwaysRun = true)
+    private void setup() throws IOException {
+        InvoiceModuleMock module = new InvoiceModuleMock();
+        final String ddl = IOUtils.toString(InvoiceDaoWrapper.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
+        module.createDb(ddl);
+
+        // Healthcheck test to make sure MySQL is setup properly
+        try {
+            final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
+
+            dao = injector.getInstance(InvoiceItemDaoWrapper.class);
+            dao.test();
+
+            invoiceDao = injector.getInstance(InvoiceDaoWrapper.class);
+            invoiceDao.test();
+        }
+        catch (Throwable t) {
+            fail(t.toString());
+        }
+    }
+
+    @Test
+    public void testInvoiceItemCreation() {
+        UUID invoiceId = UUID.randomUUID();
+        UUID subscriptionId = UUID.randomUUID();
+        DateTime startDate = new DateTime(2011, 10, 1, 0, 0, 0, 0);
+        DateTime endDate = new DateTime(2011, 11, 1, 0, 0, 0, 0);
+        BigDecimal rate = new BigDecimal("20.00");
+
+        InvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", rate, rate, Currency.USD);
+        dao.createInvoiceItem(item);
+
+        InvoiceItem thisItem = dao.getInvoiceItem(item.getId().toString());
+        assertNotNull(thisItem);
+        assertEquals(thisItem.getId(), item.getId());
+        assertEquals(thisItem.getInvoiceId(), item.getInvoiceId());
+        assertEquals(thisItem.getSubscriptionId(), item.getSubscriptionId());
+        assertEquals(thisItem.getStartDate(), item.getStartDate());
+        assertEquals(thisItem.getEndDate(), item.getEndDate());
+        assertEquals(thisItem.getDescription(), item.getDescription());
+        assertEquals(thisItem.getAmount().compareTo(item.getAmount()), 0);
+        assertEquals(thisItem.getRate().compareTo(item.getRate()), 0);
+        assertEquals(thisItem.getCurrency(), item.getCurrency());
+    }
+
+    @Test
+    public void testGetInvoiceItemsBySubscriptionId() {
+        UUID subscriptionId = UUID.randomUUID();
+        DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+        BigDecimal rate = new BigDecimal("20.00");
+
+        for (int i = 0; i < 3; i++) {
+            UUID invoiceId = UUID.randomUUID();
+            DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate.plusMonths(i), startDate.plusMonths(i + 1), "test", rate, rate, Currency.USD);
+            dao.createInvoiceItem(item);
+        }
+
+        List<InvoiceItem> items = dao.getInvoiceItemsBySubscription(subscriptionId.toString());
+        assertEquals(items.size(), 3);
+    }
+
+    @Test
+    public void testGetInvoiceItemsByInvoiceId() {
+        UUID invoiceId = UUID.randomUUID();
+        DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+        BigDecimal rate = new BigDecimal("20.00");
+
+        for (int i = 0; i < 5; i++) {
+            UUID subscriptionId = UUID.randomUUID();
+            BigDecimal amount = rate.multiply(new BigDecimal(i + 1));
+            DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", amount, amount, Currency.USD);
+            dao.createInvoiceItem(item);
+        }
+
+        List<InvoiceItem> items = dao.getInvoiceItemsByInvoice(invoiceId.toString());
+        assertEquals(items.size(), 5);
+    }
+
+    @Test
+    public void testGetInvoiceItemsByAccountId() {
+        UUID accountId = UUID.randomUUID();
+        DateTime targetDate = new DateTime(2011, 5, 23, 0, 0, 0, 0);
+        DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
+
+        invoiceDao.createInvoice(invoice);
+
+        UUID invoiceId = invoice.getId();
+        DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+        BigDecimal rate = new BigDecimal("20.00");
+
+        UUID subscriptionId = UUID.randomUUID();
+        DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", rate, rate, Currency.USD);
+        dao.createInvoiceItem(item);
+
+        List<InvoiceItem> items = dao.getInvoiceItemsByAccount(accountId.toString());
+        assertEquals(items.size(), 1);
+    }
+}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java
new file mode 100644
index 0000000..7bccede
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.invoice.glue;
+
+import com.ning.billing.dbi.MysqlTestingHelper;
+import org.skife.jdbi.v2.IDBI;
+
+import java.io.IOException;
+
+public class InvoiceModuleMock extends InvoiceModule {
+    private final MysqlTestingHelper helper = new MysqlTestingHelper();
+
+    public void createDb(String ddl) throws IOException {
+        helper.startMysql();
+        helper.initDb(ddl);
+    }
+
+    @Override
+    public void configure() {
+        bind(IDBI.class).toInstance(helper.getDBI());
+        super.configure();
+    }
+}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
index 45f6e74..d01c470 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
@@ -18,11 +18,16 @@ package com.ning.billing.invoice.tests;
 
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.entitlement.api.billing.BillingMode;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
-import com.ning.billing.invoice.api.DefaultBillingEvent;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.invoice.api.BillingEventSet;
-import com.ning.billing.invoice.model.*;
+import com.ning.billing.invoice.api.DefaultBillingEvent;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
+import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.invoice.model.InvoiceItemList;
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
@@ -34,7 +39,7 @@ import static org.testng.Assert.assertNotNull;
 
 @Test(groups = {"invoicing", "invoiceGenerator"})
 public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
-    private final IInvoiceGenerator generator = new DefaultInvoiceGenerator();
+    private final InvoiceGenerator generator = new DefaultInvoiceGenerator();
 
     @Test
     public void testWithNullEventSetAndNullInvoiceSet() {
@@ -69,7 +74,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         String phaseName = "Build Space Laser";
         BillingEvent event = new DefaultBillingEvent(subscriptionId, startDate, planName, phaseName,
                                                new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
 
         events.add(event);
 
@@ -95,7 +100,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         BigDecimal rate = TEN;
         BillingEvent event = new DefaultBillingEvent(subscriptionId, startDate, planName, phaseName,
                                                new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
-                                               15, BillingMode.IN_ADVANCE);
+                                               15, BillingModeType.IN_ADVANCE);
 
         events.add(event);
 
@@ -121,13 +126,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         BillingEvent event1 = new DefaultBillingEvent(UUID.randomUUID(), buildDateTime(2011, 9, 1),
                                                "World Domination", "Build Space Laser",
                                                new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
         events.add(event1);
 
         BillingEvent event2 = new DefaultBillingEvent(UUID.randomUUID(), buildDateTime(2011, 10, 1),
                                                "Groceries", "Pick Up Milk",
                                                new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
         events.add(event2);
 
         InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -148,13 +153,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         BillingEvent event1 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 9, 1),
                                                "World Domination", "Build Space Laser",
                                                new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
         events.add(event1);
 
         BillingEvent event2 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 10, 15),
                                                "World Domination", "Incinerate James Bond",
                                                new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
-                                               15, BillingMode.IN_ADVANCE);
+                                               15, BillingModeType.IN_ADVANCE);
         events.add(event2);
 
         InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -186,19 +191,19 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         BillingEvent event1 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 9, 1),
                                                "World Domination", "Build Space Laser",
                                                new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
         events.add(event1);
 
         BillingEvent event2 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 10, 1),
                                                "World Domination", "Incinerate James Bond",
                                                new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
         events.add(event2);
 
         BillingEvent event3 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 11, 1),
                                                "World Domination", "Cackle Gleefully",
                                                new InternationalPriceMock(THIRTY), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
         events.add(event3);
 
         InvoiceItemList existingInvoiceItems = new InvoiceItemList();
@@ -222,11 +227,11 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         BillingEvent event1 = new DefaultBillingEvent(subscriptionId, startDate,
                                                "World Domination", "Build Space Laser",
                                                new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
-                                               1, BillingMode.IN_ADVANCE);
+                                               1, BillingModeType.IN_ADVANCE);
         events.add(event1);
 
         InvoiceItemList existingInvoiceItems = new InvoiceItemList();
-        InvoiceItem invoiceItem = new InvoiceItem(UUID.randomUUID(), subscriptionId, startDate, buildDateTime(2012, 1, 1), "",
+        InvoiceItem invoiceItem = new DefaultInvoiceItem(UUID.randomUUID(), subscriptionId, startDate, buildDateTime(2012, 1, 1), "",
                                                  rate.multiply(FOUR), rate, Currency.USD);
         existingInvoiceItems.add(invoiceItem);
 
@@ -395,7 +400,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
                                             BigDecimal rate, int billCycleDay) {
         return new DefaultBillingEvent(subscriptionId, startDate, planName, planPhaseName,
                                 new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
-                                billCycleDay, BillingMode.IN_ADVANCE);
+                                billCycleDay, BillingModeType.IN_ADVANCE);
 
     }
 
@@ -403,7 +408,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
                                                   BigDecimal rate, int billCycleDay) {
         return new DefaultBillingEvent(subscriptionId, startDate, planName, planPhaseName,
                                 new InternationalPriceMock(rate), BillingPeriod.ANNUAL,
-                                billCycleDay, BillingMode.IN_ADVANCE);
+                                billCycleDay, BillingModeType.IN_ADVANCE);
 
     }
 
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
index 2948557..14392a8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
@@ -16,7 +16,7 @@
 
 package com.ning.billing.invoice.tests.inAdvance;
 
-import com.ning.billing.invoice.model.IBillingMode;
+import com.ning.billing.invoice.model.BillingMode;
 import com.ning.billing.invoice.model.InAdvanceBillingMode;
 import com.ning.billing.invoice.tests.ProRationTestBase;
 import org.testng.annotations.Test;
@@ -24,7 +24,7 @@ import org.testng.annotations.Test;
 @Test(groups = {"invoicing", "proRation"})
 public abstract class ProRationInAdvanceTestBase extends ProRationTestBase {
     @Override
-    protected IBillingMode getBillingMode() {
+    protected BillingMode getBillingMode() {
         return new InAdvanceBillingMode();
     }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
index c57fe32..9de01bd 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
@@ -17,7 +17,7 @@
 package com.ning.billing.invoice.tests.inAdvance;
 
 import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.IBillingMode;
+import com.ning.billing.invoice.model.BillingMode;
 import com.ning.billing.invoice.model.InAdvanceBillingMode;
 import com.ning.billing.invoice.model.InvalidDateSequenceException;
 import com.ning.billing.invoice.tests.ProRationTestBase;
@@ -35,7 +35,7 @@ public class ValidationProRationTests extends ProRationTestBase {
     }
 
     @Override
-    protected IBillingMode getBillingMode() {
+    protected BillingMode getBillingMode() {
         return new InAdvanceBillingMode();
     }
 
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
index 835836e..174017b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
@@ -17,7 +17,7 @@
 package com.ning.billing.invoice.tests;
 
 import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.IBillingMode;
+import com.ning.billing.invoice.model.BillingMode;
 import com.ning.billing.invoice.model.InvalidDateSequenceException;
 import org.joda.time.DateTime;
 
@@ -27,7 +27,7 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.fail;
 
 public abstract class ProRationTestBase extends InvoicingTestBase{
-    protected abstract IBillingMode getBillingMode();
+    protected abstract BillingMode getBillingMode();
     protected abstract BillingPeriod getBillingPeriod();
 
     protected void testCalculateNumberOfBillingCycles(DateTime startDate, DateTime targetDate, int billingCycleDay, BigDecimal expectedValue) throws InvalidDateSequenceException {

payment/pom.xml 2(+1 -1)

diff --git a/payment/pom.xml b/payment/pom.xml
index eeecc49..e8e4e90 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-payment</artifactId>
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
index c0640d2..f01de5b 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
@@ -22,18 +22,18 @@ import java.util.UUID;
 import javax.annotation.Nullable;
 
 import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.payment.RequestProcessor;
 import com.ning.billing.payment.provider.PaymentProviderPlugin;
 import com.ning.billing.payment.provider.PaymentProviderPluginRegistry;
 
 public class DefaultPaymentApi implements PaymentApi {
     private final PaymentProviderPluginRegistry pluginRegistry;
-    private final IAccountUserApi accountUserApi;
+    private final AccountUserApi accountUserApi;
 
     @Inject
-    public DefaultPaymentApi(PaymentProviderPluginRegistry pluginRegistry, IAccountUserApi accountUserApi) {
+    public DefaultPaymentApi(PaymentProviderPluginRegistry pluginRegistry, AccountUserApi accountUserApi) {
         this.pluginRegistry = pluginRegistry;
         this.accountUserApi = accountUserApi;
     }
@@ -52,7 +52,7 @@ public class DefaultPaymentApi implements PaymentApi {
             paymentProviderName = null;
         }
         else {
-            final IAccount account = accountUserApi.getAccountFromId(UUID.fromString(accountKey));
+            final Account account = accountUserApi.getAccountById(UUID.fromString(accountKey));
             paymentProviderName = account.getFieldValue(RequestProcessor.PAYMENT_PROVIDER_KEY);
         }
 
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java
index d3e92d2..fe905a3 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/PaymentProviderPlugin.java
@@ -18,8 +18,8 @@ package com.ning.billing.payment.provider;
 
 import java.util.List;
 
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.invoice.model.Invoice;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.payment.PaymentInfo;
 import com.ning.billing.payment.PaymentProviderAccount;
 import com.ning.billing.payment.PaypalPaymentMethodInfo;
@@ -28,12 +28,12 @@ import com.ning.billing.payment.api.PaymentError;
 import com.ning.billing.payment.api.PaymentMethodInfo;
 
 public interface PaymentProviderPlugin {
-    Either<PaymentError, PaymentInfo> processInvoice(IAccount account, Invoice invoice);
+    Either<PaymentError, PaymentInfo> processInvoice(Account account, Invoice invoice);
     Either<PaymentError, PaymentInfo> getPaymentInfo(String paymentId);
-    Either<PaymentError, PaymentProviderAccount> createPaymentProviderAccount(IAccount account);
+    Either<PaymentError, PaymentProviderAccount> createPaymentProviderAccount(Account account);
     Either<PaymentError, PaymentMethodInfo> getPaymentMethodInfo(String paymentMethodId);
     Either<PaymentError, List<PaymentMethodInfo>> getPaymentMethods(String screenName);
-    Either<PaymentError, PaypalPaymentMethodInfo> addPaypalPaymentMethod(IAccount account, PaypalPaymentMethodInfo paypalPaymentMethod);
+    Either<PaymentError, PaypalPaymentMethodInfo> addPaypalPaymentMethod(Account account, PaypalPaymentMethodInfo paypalPaymentMethod);
     Either<PaymentError, Void> updatePaymentGateway(String accountKey);
 
 }
diff --git a/payment/src/main/java/com/ning/billing/payment/RequestProcessor.java b/payment/src/main/java/com/ning/billing/payment/RequestProcessor.java
index 6e33ffb..54ca415 100644
--- a/payment/src/main/java/com/ning/billing/payment/RequestProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/RequestProcessor.java
@@ -18,9 +18,9 @@ package com.ning.billing.payment;
 
 import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
-import com.ning.billing.invoice.model.Invoice;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.payment.api.Either;
 import com.ning.billing.payment.api.PaymentError;
 import com.ning.billing.payment.provider.PaymentProviderPlugin;
@@ -30,12 +30,12 @@ import com.ning.billing.util.eventbus.EventBus.EventBusException;
 
 public class RequestProcessor {
     public static final String PAYMENT_PROVIDER_KEY = "paymentProvider";
-    private final IAccountUserApi accountUserApi;
+    private final AccountUserApi accountUserApi;
     private final PaymentProviderPluginRegistry pluginRegistry;
     private final EventBus eventBus;
 
     @Inject
-    public RequestProcessor(IAccountUserApi accountUserApi,
+    public RequestProcessor(AccountUserApi accountUserApi,
                             PaymentProviderPluginRegistry pluginRegistry,
                             EventBus eventBus) {
         this.accountUserApi = accountUserApi;
@@ -45,7 +45,7 @@ public class RequestProcessor {
 
     @Subscribe
     public void receiveInvoice(Invoice invoice) throws EventBusException {
-        final IAccount account = accountUserApi.getAccountFromId(invoice.getAccountId());
+        final Account account = accountUserApi.getAccountById(invoice.getAccountId());
         final String paymentProviderName = account.getFieldValue(PAYMENT_PROVIDER_KEY);
         final PaymentProviderPlugin plugin = pluginRegistry.getPlugin(paymentProviderName);
 
@@ -56,7 +56,7 @@ public class RequestProcessor {
 
     @Subscribe
     public void receivePaymentInfoRequest(PaymentInfoRequest paymentInfoRequest) throws EventBusException {
-        final IAccount account = accountUserApi.getAccountFromId(paymentInfoRequest.getAccountId());
+        final Account account = accountUserApi.getAccountById(paymentInfoRequest.getAccountId());
         final String paymentProviderName = account.getFieldValue(PAYMENT_PROVIDER_KEY);
         final PaymentProviderPlugin plugin = pluginRegistry.getPlugin(paymentProviderName);
 
diff --git a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
index 39724b4..88db00d 100644
--- a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -21,8 +21,8 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.invoice.model.Invoice;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.payment.PaymentInfo;
 import com.ning.billing.payment.PaymentProviderAccount;
 import com.ning.billing.payment.PaypalPaymentMethodInfo;
@@ -34,7 +34,7 @@ public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
     private final Map<String, PaymentInfo> payments = new ConcurrentHashMap<String, PaymentInfo>();
 
     @Override
-    public Either<PaymentError, PaymentInfo> processInvoice(IAccount account, Invoice invoice) {
+    public Either<PaymentError, PaymentInfo> processInvoice(Account account, Invoice invoice) {
         PaymentInfo payment = new PaymentInfo.Builder().setId(UUID.randomUUID().toString()).build();
 
         payments.put(payment.getId(), payment);
@@ -54,7 +54,7 @@ public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
     }
 
     @Override
-    public Either<PaymentError, PaymentProviderAccount> createPaymentProviderAccount(IAccount account) {
+    public Either<PaymentError, PaymentProviderAccount> createPaymentProviderAccount(Account account) {
         // TODO
         return Either.left(new PaymentError("unknown", "Not implemented"));
     }
@@ -72,7 +72,7 @@ public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
     }
 
     @Override
-    public Either<PaymentError, PaypalPaymentMethodInfo> addPaypalPaymentMethod(IAccount account, PaypalPaymentMethodInfo paypalPaymentMethod) {
+    public Either<PaymentError, PaypalPaymentMethodInfo> addPaypalPaymentMethod(Account account, PaypalPaymentMethodInfo paypalPaymentMethod) {
         // TODO
         return Either.left(new PaymentError("unknown", "Not implemented"));
     }
diff --git a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModule.java b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModule.java
index 9516c33..4b96dce 100644
--- a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModule.java
+++ b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModule.java
@@ -19,7 +19,7 @@ package com.ning.billing.payment.setup;
 import org.apache.commons.collections.MapUtils;
 
 import com.google.common.collect.ImmutableMap;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.account.api.MockAccountUserApi;
 import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
 import com.ning.billing.util.eventbus.EventBus;
@@ -39,6 +39,6 @@ public class PaymentTestModule extends PaymentModule {
     protected void configure() {
         super.configure();
         bind(EventBus.class).to(MemoryEventBus.class).asEagerSingleton();
-        bind(IAccountUserApi.class).to(MockAccountUserApi.class).asEagerSingleton();
+        bind(AccountUserApi.class).to(MockAccountUserApi.class).asEagerSingleton();
     }
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java b/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java
index d74c959..00be061 100644
--- a/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java
+++ b/payment/src/test/java/com/ning/billing/payment/TestPaymentProvider.java
@@ -36,11 +36,12 @@ import org.testng.annotations.Test;
 
 import com.google.inject.Inject;
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.IAccount;
-import com.ning.billing.account.api.IAccountUserApi;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.DefaultAccount;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.model.Invoice;
-import com.ning.billing.invoice.model.InvoiceItem;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.payment.api.PaymentError;
 import com.ning.billing.payment.setup.PaymentTestModule;
 import com.ning.billing.util.eventbus.EventBus;
@@ -53,7 +54,7 @@ public class TestPaymentProvider {
     @Inject
     private RequestProcessor invoiceProcessor;
     @Inject
-    private IAccountUserApi accountUserApi;
+    private AccountUserApi accountUserApi;
     private MockPaymentInfoReceiver paymentInfoReceiver;
 
     @BeforeMethod(alwaysRun = true)
@@ -70,13 +71,13 @@ public class TestPaymentProvider {
         eventBus.stop();
     }
 
-    protected IAccount getTestAccount() {
-        return accountUserApi.createAccount(new Account());
+    protected Account getTestAccount() {
+        return accountUserApi.createAccount(new DefaultAccount());
     }
 
     @Test
     public void testSimpleInvoice() throws Exception {
-        final IAccount account = getTestAccount();
+        final Account account = getTestAccount();
         final UUID subscriptionUuid = UUID.randomUUID();
         final UUID invoiceUuid = UUID.randomUUID();
         final DateTime now = new DateTime();
@@ -89,7 +90,7 @@ public class TestPaymentProvider {
                                                      new BigDecimal("1"),
                                                      Currency.USD);
         final List<InvoiceItem> lineItems = Arrays.asList(lineItem);
-        final Invoice invoice = new Invoice(account.getId(), lineItems, Currency.USD);
+        final Invoice invoice = new DefaultInvoice(account.getId(), lineItems, Currency.USD);
 
         eventBus.post(invoice);
         await().atMost(1, MINUTES).until(new Callable<Boolean>() {

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index fcb837e..a3d4b5b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
     <groupId>com.ning.billing</groupId>
     <artifactId>killbill</artifactId>
     <packaging>pom</packaging>
-    <version>0.0.17-SNAPSHOT</version>
+    <version>0.0.18-SNAPSHOT</version>
     <name>killbill</name>
     <description>Library for managing recurring subscriptions and the associated billing</description>
     <url>http://github.com/ning/killbill</url>

util/pom.xml 2(+1 -1)

diff --git a/util/pom.xml b/util/pom.xml
index c7b6110..ad4848e 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.0.17-SNAPSHOT</version>
+        <version>0.0.18-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-util</artifactId>
diff --git a/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java b/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java
index 8d61ba5..5db2ac3 100644
--- a/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java
+++ b/util/src/main/java/com/ning/billing/util/clock/DefaultClock.java
@@ -16,13 +16,12 @@
 
 package com.ning.billing.util.clock;
 
-import java.util.ArrayList;
-import java.util.List;
-
+import com.ning.billing.catalog.api.Duration;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
-import com.ning.billing.catalog.api.Duration;
+import java.util.ArrayList;
+import java.util.List;
 
 public class DefaultClock implements Clock {
 
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidationError.java b/util/src/main/java/com/ning/billing/util/config/ValidationError.java
index 33af867..cd1ae4d 100644
--- a/util/src/main/java/com/ning/billing/util/config/ValidationError.java
+++ b/util/src/main/java/com/ning/billing/util/config/ValidationError.java
@@ -15,10 +15,10 @@
  */
 package com.ning.billing.util.config;
 
-import java.net.URI;
-
 import org.slf4j.Logger;
 
+import java.net.URI;
+
 
 public class ValidationError {
 	private final String description;
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java b/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
index 19e4270..c8145d2 100644
--- a/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
+++ b/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
@@ -16,11 +16,11 @@
 
 package com.ning.billing.util.config;
 
+import org.slf4j.Logger;
+
 import java.net.URI;
 import java.util.ArrayList;
 
-import org.slf4j.Logger;
-
 public class ValidationErrors extends ArrayList<ValidationError>{
 	private static final long serialVersionUID = 1L;
 
diff --git a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
index 9ed3bce..d0487b8 100644
--- a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
+++ b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
@@ -16,9 +16,10 @@
 
 package com.ning.billing.util.config;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
 
 import javax.xml.XMLConstants;
 import javax.xml.bind.JAXBContext;
@@ -28,12 +29,9 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
-
-import com.ning.billing.catalog.api.InvalidConfigException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
 
 public class XMLLoader {
 	public static Logger log = LoggerFactory.getLogger(XMLLoader.class);
diff --git a/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java b/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java
index d7f876d..259736d 100644
--- a/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java
+++ b/util/src/main/java/com/ning/billing/util/eventbus/MemoryEventBus.java
@@ -16,16 +16,15 @@
 
 package com.ning.billing.util.eventbus;
 
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicBoolean;
-
+import com.google.common.eventbus.AsyncEventBus;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.eventbus.AsyncEventBus;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 public class MemoryEventBus implements EventBus {
 
diff --git a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
index 127f0b6..0fb473d 100644
--- a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
+++ b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
@@ -16,13 +16,12 @@
 
 package com.ning.billing.util.clock;
 
-import java.util.ArrayList;
-import java.util.List;
-
+import com.ning.billing.catalog.api.Duration;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
-import com.ning.billing.catalog.api.Duration;
+import java.util.ArrayList;
+import java.util.List;
 
 // STEPH should really be in tests but not accessible from other sub modules
 public class ClockMock extends DefaultClock {
diff --git a/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java b/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
index 30b8ee3..6721ee8 100644
--- a/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
+++ b/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
@@ -16,23 +16,19 @@
 
 package com.ning.billing.util.config;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
 
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.Date;
-
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
 
-import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
-
-import com.ning.billing.catalog.api.InvalidConfigException;
+import static org.testng.Assert.assertEquals;
 
 
 public class TestXMLLoader {
diff --git a/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java b/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java
index 02f7261..1419b8f 100644
--- a/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java
+++ b/util/src/test/java/com/ning/billing/util/eventbus/TestEventBus.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.util.eventbus;
 
+import com.google.common.eventbus.Subscribe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -23,8 +24,6 @@ import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import com.google.common.eventbus.Subscribe;
-
 public class TestEventBus {
 
     private static final Logger log = LoggerFactory.getLogger(TestEventBus.class);