killbill-aplcache

- remove InternationalPrice from billing events; pass values

3/8/2012 4:37:33 PM

Details

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 2628b36..f11e5b4 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
@@ -16,6 +16,7 @@
 
 package com.ning.billing.entitlement.api.billing;
 
+import com.ning.billing.catalog.api.Currency;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.BillingPeriod;
@@ -25,6 +26,8 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionTransition.SubscriptionTransitionType;
 
+import java.math.BigDecimal;
+
 public interface BillingEvent extends Comparable<BillingEvent> {
 
     /**
@@ -82,13 +85,19 @@ public interface BillingEvent extends Comparable<BillingEvent> {
      * 
      * @return the fixed price for the phase
      */
-    public InternationalPrice getFixedPrice();
+    public BigDecimal getFixedPrice();
 
     /**
      * 
      * @return the recurring price for the phase
      */
-    public InternationalPrice getRecurringPrice();
+    public BigDecimal getRecurringPrice();
+
+    /**
+     *
+     * @return the currency for the account being invoiced
+     */
+    public Currency getCurrency();
 
 	/**
 	 * @return the transition type of the underlying subscription event that triggered this
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index cc9fc20..4dcf09f 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -140,7 +140,8 @@ public enum ErrorCode {
     INVOICE_ACCOUNT_ID_INVALID(4001, "No account could be retrieved for id %s"),
     INVOICE_INVALID_TRANSITION(4002, "Transition did not contain a subscription id."),
     INVOICE_NO_ACCOUNT_ID_FOR_SUBSCRIPTION_ID(4003, "No account id was retrieved for subscription id %s"),
-    INVOICE_INVALID_DATE_SEQUENCE(4004, "Date sequence was invalid. Start Date: %s; End Date: %s; Target Date: %s")
+    INVOICE_INVALID_DATE_SEQUENCE(4004, "Date sequence was invalid. Start Date: %s; End Date: %s; Target Date: %s"),
+    INVOICE_TARGET_DATE_TOO_FAR_IN_THE_FUTURE(4005, "The target date was too far in the future. Target Date: %s")
     ;
 
     private int code;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
index 11c5a79..043a8fd 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
@@ -16,35 +16,34 @@
 
 package com.ning.billing.entitlement.api.billing;
 
+import com.ning.billing.catalog.api.CatalogApiException;
 import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
-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.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionTransition;
 import com.ning.billing.entitlement.api.user.SubscriptionTransition.SubscriptionTransitionType;
 
-public class DefaultBillingEvent implements BillingEvent {
-	Logger log = LoggerFactory.getLogger(DefaultBillingEvent.class);
+import java.math.BigDecimal;
 
+public class DefaultBillingEvent implements BillingEvent {
     final private int billCycleDay;
     final private Subscription subscription;
     final private DateTime effectiveDate;
     final private PlanPhase planPhase;
     final private Plan plan;
-    final private InternationalPrice fixedPrice;
-    final private InternationalPrice recurringPrice;
+    final private BigDecimal fixedPrice;
+    final private BigDecimal recurringPrice;
+    final private Currency currency;
     final private String description;
     final private BillingModeType billingModeType;
     final private BillingPeriod billingPeriod;
     final private SubscriptionTransitionType type;
 
-    public DefaultBillingEvent(SubscriptionTransition transition, Subscription subscription, int billCycleDay) {
+    public DefaultBillingEvent(SubscriptionTransition transition, Subscription subscription, int billCycleDay, Currency currency) throws CatalogApiException {
         this.billCycleDay = billCycleDay;
         this.subscription = subscription;
         effectiveDate = transition.getEffectiveTransitionTime();
@@ -53,9 +52,10 @@ public class DefaultBillingEvent implements BillingEvent {
         plan = (transition.getTransitionType() != SubscriptionTransitionType.CANCEL) ?
                 transition.getNextPlan() : transition.getPreviousPlan();
         fixedPrice = (transition.getNextPhase() == null) ? null :
-        		transition.getNextPhase().getFixedPrice();
+        		transition.getNextPhase().getFixedPrice().getPrice(currency);
         recurringPrice = (transition.getNextPhase() == null) ? null :
-        	transition.getNextPhase().getRecurringPrice();
+        	transition.getNextPhase().getRecurringPrice().getPrice(currency);
+        this.currency = currency;
         description = transition.getTransitionType().toString();
         billingModeType = BillingModeType.IN_ADVANCE;
         billingPeriod =  (transition.getTransitionType() != SubscriptionTransitionType.CANCEL) ?
@@ -64,14 +64,17 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     // Intended for test only
-    public DefaultBillingEvent(Subscription subscription, DateTime effectiveDate, Plan plan, PlanPhase planPhase, InternationalPrice fixedPrice,
-            InternationalPrice recurringPrice, BillingPeriod billingPeriod, int billCycleDay, BillingModeType billingModeType, String description, SubscriptionTransitionType type) {
+    public DefaultBillingEvent(Subscription subscription, DateTime effectiveDate, Plan plan, PlanPhase planPhase,
+                               BigDecimal fixedPrice, BigDecimal recurringPrice, Currency currency,
+                               BillingPeriod billingPeriod, int billCycleDay, BillingModeType billingModeType,
+                               String description, SubscriptionTransitionType type) {
         this.subscription = subscription;
         this.effectiveDate = effectiveDate;
         this.plan = plan;
         this.planPhase = planPhase;
         this.fixedPrice = fixedPrice;
         this.recurringPrice = recurringPrice;
+        this.currency = currency;
         this.billingPeriod = billingPeriod;
         this.billCycleDay = billCycleDay;
         this.billingModeType = billingModeType;
@@ -137,16 +140,21 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     @Override
-    public InternationalPrice getFixedPrice() {
+    public BigDecimal getFixedPrice() {
         return fixedPrice;
     }
 
     @Override
-    public InternationalPrice getRecurringPrice() {
+    public BigDecimal getRecurringPrice() {
         return recurringPrice;
     }
 
     @Override
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    @Override
     public SubscriptionTransitionType getTransitionType() {
         return type;
     }
@@ -159,25 +167,26 @@ public class DefaultBillingEvent implements BillingEvent {
         sb.append("phase = ").append(planPhase.getName()).append(", ");
         sb.append("effectiveDate = ").append(effectiveDate.toString()).append(", ");
         sb.append("billCycleDay = ").append(billCycleDay).append(", ");
-        sb.append("recurringPrice(USD) = ");
+        sb.append("recurringPrice = ");
 
         try {
-            sb.append(recurringPrice.getPrice(Currency.USD).toString());
+            sb.append(recurringPrice.toString());
         } catch (Exception e) {
             sb.append("null");
         }
 
         sb.append(", ");
-        sb.append("fixedPrice(USD) = ");
+        sb.append("fixedPrice = ");
 
         try {
-            sb.append(fixedPrice.getPrice(Currency.USD).toString());
+            sb.append(fixedPrice.toString());
         } catch (Exception e) {
             sb.append("null");
         }
 
         sb.append(", ");
 
+        sb.append("currency = ").append(currency.toString()).append(", ");
         sb.append("billingPeriod = ").append(billingPeriod.toString());
         sb.append("}");
 
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 788cda1..7739ba7 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
@@ -22,6 +22,7 @@ import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.UUID;
 
+import com.ning.billing.catalog.api.Currency;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
@@ -70,6 +71,8 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
     @Override
     public SortedSet<BillingEvent> getBillingEventsForAccount(
             final UUID accountId) {
+        Account account = accountApi.getAccountById(accountId);
+        Currency currency = account.getCurrency();
 
         List<SubscriptionBundle> bundles = entitlementDao.getSubscriptionBundleForAccount(accountId);
         SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();
@@ -79,7 +82,7 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
         	for (final Subscription subscription: subscriptions) {
         		for (final SubscriptionTransition transition : subscription.getAllTransitions()) {
         			try {
-        				BillingEvent event = new DefaultBillingEvent(transition, subscription, calculateBcd(bundle, subscription, transition, accountId));
+        				BillingEvent event = new DefaultBillingEvent(transition, subscription, calculateBcd(bundle, subscription, transition, accountId), currency);
         				result.add(event);
         			} catch (CatalogApiException e) {
         				log.error("Failing to identify catalog components while creating BillingEvent from transition: " +
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultBillingEvent.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultBillingEvent.java
index fc3362a..4766a08 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultBillingEvent.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultBillingEvent.java
@@ -34,7 +34,6 @@ import com.ning.billing.catalog.MockPlan;
 import com.ning.billing.catalog.MockPlanPhase;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.InternationalPrice;
 import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
@@ -126,7 +125,6 @@ public class TestDefaultBillingEvent {
 
 
 	private BillingEvent createEvent(Subscription sub, DateTime effectiveDate, SubscriptionTransitionType type) {
-		InternationalPrice zeroPrice = new MockInternationalPrice(new DefaultPrice(BigDecimal.ZERO, Currency.USD));
 		int billCycleDay = 1;
 
 		Plan shotgun = new MockPlan();
@@ -134,7 +132,7 @@ public class TestDefaultBillingEvent {
 
 		return new DefaultBillingEvent(sub , effectiveDate,
 				shotgun, shotgunMonthly,
-				zeroPrice, null, BillingPeriod.NO_BILLING_PERIOD, billCycleDay,
+				BigDecimal.ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, billCycleDay,
 				BillingModeType.IN_ADVANCE, "Test Event 1", type);
 	}
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
index 21ed6fa..28e5f3f 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
@@ -127,8 +127,14 @@ public class TestDefaultEntitlementBillingApi {
         dao = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementDao.class);
         ((ZombieControl) dao).addResult("getSubscriptionBundleForAccount", new ArrayList<SubscriptionBundle>());
 
+        UUID accountId = UUID.randomUUID();
+        Account account = new BrainDeadAccount();
+        ((ZombieControl) account).addResult("getId", accountId);
+
 		AccountUserApi accountApi = new BrainDeadAccountUserApi() ;
-		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
+        ((ZombieControl) accountApi).addResult("getAccountById", account);
+
+		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao, accountApi, catalogService);
 		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
 		Assert.assertEquals(events.size(), 0);
 	}
@@ -148,10 +154,17 @@ public class TestDefaultEntitlementBillingApi {
 
 			@Override
 			public Account getAccountById(UUID accountId) {
-				return new BrainDeadAccount(){@Override
-				public int getBillCycleDay() {
-					return 32;
-				}};
+				return new BrainDeadAccount(){
+                    @Override
+                    public int getBillCycleDay() {
+                        return 32;
+                    }
+
+                    @Override
+                    public Currency getCurrency() {
+                        return Currency.USD;
+                    }
+                };
 			}} ;
 		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
 		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
@@ -159,7 +172,7 @@ public class TestDefaultEntitlementBillingApi {
 	}
 
     @Test(enabled=true, groups="fast")
-	public void testBillingEventsAnual() throws CatalogApiException {
+	public void testBillingEventsAnnual() throws CatalogApiException {
 		DateTime now = clock.getUTCNow();
 		DateTime then = now.minusDays(1);
 		Plan nextPlan = catalogService.getFullCatalog().findPlan("shotgun-annual", now);
@@ -170,7 +183,9 @@ public class TestDefaultEntitlementBillingApi {
 		transitions.add(t);
 
 		Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
-		((ZombieControl)account).addResult("getBillCycleDay", 1).addResult("getTimeZone", DateTimeZone.UTC);
+		((ZombieControl)account).addResult("getBillCycleDay", 1).addResult("getTimeZone", DateTimeZone.UTC)
+                                .addResult("getCurrency", Currency.USD);
+
 
 		AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
 		((ZombieControl)accountApi).addResult("getAccountById", account);
@@ -195,10 +210,17 @@ public class TestDefaultEntitlementBillingApi {
 
 			@Override
 			public Account getAccountById(UUID accountId) {
-				return new BrainDeadAccount(){@Override
-				public int getBillCycleDay() {
-					return 32;
-				}};
+				return new BrainDeadAccount(){
+                    @Override
+				    public int getBillCycleDay() {
+					    return 32;
+				    }
+
+                    @Override
+                    public Currency getCurrency() {
+                        return Currency.USD;
+                    }
+                };
 			}} ;
 		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
 		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
@@ -218,6 +240,7 @@ public class TestDefaultEntitlementBillingApi {
 
 		Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
 		((ZombieControl)account).addResult("getBillCycleDay", 1).addResult("getTimeZone", DateTimeZone.UTC);
+        ((ZombieControl)account).addResult("getCurrency", Currency.USD);
 
 		AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
 		((ZombieControl)accountApi).addResult("getAccountById", account);
@@ -233,10 +256,10 @@ public class TestDefaultEntitlementBillingApi {
 		Assert.assertEquals(events.size(), 1);
 		BillingEvent event = events.first();
 		if(nextPhase.getFixedPrice() != null) {
-			Assert.assertEquals(nextPhase.getFixedPrice().getPrice(Currency.USD), event.getFixedPrice().getPrice(Currency.USD));
+			Assert.assertEquals(nextPhase.getFixedPrice().getPrice(Currency.USD), event.getFixedPrice());
 		}
 		if(nextPhase.getRecurringPrice() != null) {
-			Assert.assertEquals(nextPhase.getRecurringPrice().getPrice(Currency.USD), event.getRecurringPrice().getPrice(Currency.USD));
+			Assert.assertEquals(nextPhase.getRecurringPrice().getPrice(Currency.USD), event.getRecurringPrice());
 		}
 
 		Assert.assertEquals(BCD, event.getBillCycleDay());
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
index d888c14..788cf2d 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserCustomFieldsSql.java
@@ -16,15 +16,10 @@
 
 package com.ning.billing.entitlement.api.user;
 
-import static org.testng.Assert.assertNotNull;
-
-import java.util.ArrayList;
 import java.util.List;
-import java.util.UUID;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
 
 import org.joda.time.DateTime;
 import org.testng.Assert;
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 b8d9e39..e4af118 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
@@ -19,10 +19,8 @@ package com.ning.billing.invoice.model;
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
 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.Duration;
-import com.ning.billing.catalog.api.InternationalPrice;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.invoice.api.Invoice;
@@ -30,6 +28,7 @@ import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.util.clock.Clock;
 import org.joda.time.DateTime;
+import org.joda.time.Months;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
@@ -42,6 +41,7 @@ import javax.annotation.Nullable;
 public class DefaultInvoiceGenerator implements InvoiceGenerator {
     private static final int ROUNDING_MODE = InvoicingConfiguration.getRoundingMode();
     private static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
+    public static final String NUMBER_OF_MONTHS = "com.ning.billing.invoice.maxNumberOfMonthsInFuture";
 
     private final Clock clock;
 
@@ -62,6 +62,8 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
             return null;
         }
 
+        validateTargetDate(targetDate);
+
         Collections.sort(events);
 
         List<InvoiceItem> existingItems = new ArrayList<InvoiceItem>();
@@ -97,7 +99,18 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
         }
     }
 
+    private void validateTargetDate(DateTime targetDate) throws InvoiceApiException {
+        String maximumNumberOfMonthsValue = System.getProperty(NUMBER_OF_MONTHS);
+        int maximumNumberOfMonths= (maximumNumberOfMonthsValue == null) ? 36 : Integer.parseInt(maximumNumberOfMonthsValue);
+
+        if (Months.monthsBetween(clock.getUTCNow(), targetDate).getMonths() > maximumNumberOfMonths) {
+            throw new InvoiceApiException(ErrorCode.INVOICE_TARGET_DATE_TOO_FAR_IN_THE_FUTURE, targetDate.toString());
+        }
+    }
+
     private DateTime adjustTargetDate(final List<Invoice> existingInvoices, final DateTime targetDate) {
+        if (existingInvoices == null) {return targetDate;}
+
         DateTime maxDate = targetDate;
 
         for (Invoice invoice : existingInvoices) {
@@ -192,16 +205,9 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
                 }
 
                 for (RecurringInvoiceItemData itemDatum : itemData) {
-                    InternationalPrice price = thisEvent.getRecurringPrice();
-                    if (price != null) {
-                        BigDecimal rate;
-
-                        try {
-                            rate = thisEvent.getRecurringPrice().getPrice(currency);
-                        } catch (CatalogApiException e) {
-                            throw new InvoiceApiException(e, ErrorCode.CAT_NO_PRICE_FOR_CURRENCY, currency.toString());
-                        }
+                    BigDecimal rate = thisEvent.getRecurringPrice();
 
+                    if (rate != null) {
                         BigDecimal amount = itemDatum.getNumberOfCycles().multiply(rate).setScale(NUMBER_OF_DECIMALS, ROUNDING_MODE);
 
                         RecurringInvoiceItem recurringItem = new RecurringInvoiceItem(invoiceId, thisEvent.getSubscription().getId(),
@@ -232,23 +238,19 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
         if (thisEvent.getEffectiveDate().isAfter(targetDate)) {
             return null;
         } else {
-            FixedPriceInvoiceItem fixedPriceInvoiceItem = null;
-
-            if (thisEvent.getFixedPrice() != null) {
-                try {
-                    Duration duration = thisEvent.getPlanPhase().getDuration();
-                    DateTime endDate = duration.addToDateTime(thisEvent.getEffectiveDate());
-                    BigDecimal fixedPrice = thisEvent.getFixedPrice().getPrice(currency);
-                    fixedPriceInvoiceItem = new FixedPriceInvoiceItem(invoiceId, thisEvent.getSubscription().getId(),
-                            thisEvent.getPlan().getName(), thisEvent.getPlanPhase().getName(),
-                            thisEvent.getEffectiveDate(), endDate, fixedPrice, currency,
-                            clock.getUTCNow());
-                } catch (CatalogApiException e) {
-                    throw new InvoiceApiException(e, ErrorCode.CAT_NO_PRICE_FOR_CURRENCY, currency.toString());
-                }
+            BigDecimal fixedPrice = thisEvent.getFixedPrice();
+
+            if (fixedPrice != null) {
+                Duration duration = thisEvent.getPlanPhase().getDuration();
+                DateTime endDate = duration.addToDateTime(thisEvent.getEffectiveDate());
+
+                return new FixedPriceInvoiceItem(invoiceId, thisEvent.getSubscription().getId(),
+                                                 thisEvent.getPlan().getName(), thisEvent.getPlanPhase().getName(),
+                                                 thisEvent.getEffectiveDate(), endDate, fixedPrice, currency,
+                                                 clock.getUTCNow());
+            } else {
+                return null;
             }
-
-            return fixedPriceInvoiceItem;
         }
     }
 }
\ No newline at end of file
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 dbe271b..07dd93b 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
@@ -22,6 +22,7 @@ import com.ning.billing.catalog.MockInternationalPrice;
 import com.ning.billing.catalog.MockPlan;
 import com.ning.billing.catalog.MockPlanPhase;
 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.PhaseType;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
@@ -502,10 +503,11 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
      *
      */
     @Test
-    public void testInvoiceGenerationForImmediateChanges() throws InvoiceApiException {
+    public void testInvoiceGenerationForImmediateChanges() throws InvoiceApiException, CatalogApiException {
         UUID accountId = UUID.randomUUID();
         List<Invoice> invoiceList = new ArrayList<Invoice>();
         DateTime targetDate = new DateTime(2011, 2, 16, 0, 0, 0, 0);
+        Currency currency = Currency.USD;
 
         // generate first invoice
         DefaultPrice price1 = new DefaultPrice(TEN, Currency.USD);
@@ -518,7 +520,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
 
         DateTime effectiveDate1 = new DateTime(2011, 2, 1, 0, 0, 0, 0);
         BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan1, phase1, null,
-                recurringPrice, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
+                recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
                 "testEvent1", SubscriptionTransitionType.CREATE);
 
         BillingEventSet events = new BillingEventSet();
@@ -536,7 +538,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
 
         DateTime effectiveDate2 = new DateTime(2011, 2, 15, 0, 0, 0, 0);
         BillingEvent event2 = new DefaultBillingEvent(subscription, effectiveDate2, plan2, phase2, null,
-                recurringPrice2, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
+                recurringPrice2.getPrice(currency), currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
                 "testEvent2", SubscriptionTransitionType.CREATE);
         events.add(event2);
 
@@ -557,7 +559,8 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
     }
 
     @Test
-    public void testInvoiceForFreeTrial() throws InvoiceApiException {
+    public void testInvoiceForFreeTrial() throws InvoiceApiException, CatalogApiException {
+        Currency currency = Currency.USD;
         DefaultPrice price = new DefaultPrice(BigDecimal.ZERO, Currency.USD);
         MockInternationalPrice recurringPrice = new MockInternationalPrice(price);
         MockPlanPhase phase = new MockPlanPhase(recurringPrice, null);
@@ -568,7 +571,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         DateTime effectiveDate = buildDateTime(2011, 1, 1);
 
         BillingEvent event = new DefaultBillingEvent(subscription, effectiveDate, plan, phase, null,
-                recurringPrice, BillingPeriod.MONTHLY, 15, BillingModeType.IN_ADVANCE,
+                recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 15, BillingModeType.IN_ADVANCE,
                 "testEvent", SubscriptionTransitionType.CREATE);
         BillingEventSet events = new BillingEventSet();
         events.add(event);
@@ -582,7 +585,9 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
     }
 
     @Test
-    public void testInvoiceForFreeTrialWithRecurringDiscount() throws InvoiceApiException {
+    public void testInvoiceForFreeTrialWithRecurringDiscount() throws InvoiceApiException, CatalogApiException {
+        Currency currency = Currency.USD;
+
         DefaultPrice zeroPrice = new DefaultPrice(BigDecimal.ZERO, Currency.USD);
         MockInternationalPrice fixedPrice = new MockInternationalPrice(zeroPrice);
         MockPlanPhase phase1 = new MockPlanPhase(null, fixedPrice);
@@ -598,8 +603,8 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         ((ZombieControl) subscription).addResult("getId", UUID.randomUUID());
         DateTime effectiveDate1 = buildDateTime(2011, 1, 1);
 
-        BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan, phase1, fixedPrice,
-                null, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
+        BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan, phase1, fixedPrice.getPrice(currency),
+                null, currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
                 "testEvent1", SubscriptionTransitionType.CREATE);
         BillingEventSet events = new BillingEventSet();
         events.add(event1);
@@ -614,7 +619,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
 
         DateTime effectiveDate2 = effectiveDate1.plusDays(30);
         BillingEvent event2 = new DefaultBillingEvent(subscription, effectiveDate2, plan, phase2, null,
-                recurringPrice, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
+                recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
                 "testEvent2", SubscriptionTransitionType.CHANGE);
         events.add(event2);
 
@@ -640,7 +645,8 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
     }
 
     @Test
-    public void testMixedModeInvoicePersistence() throws InvoiceApiException {
+    public void testMixedModeInvoicePersistence() throws InvoiceApiException, CatalogApiException {
+        Currency currency = Currency.USD;
         DefaultPrice zeroPrice = new DefaultPrice(BigDecimal.ZERO, Currency.USD);
         MockInternationalPrice fixedPrice = new MockInternationalPrice(zeroPrice);
         MockPlanPhase phase1 = new MockPlanPhase(null, fixedPrice);
@@ -656,15 +662,16 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         ((ZombieControl) subscription).addResult("getId", UUID.randomUUID());
         DateTime effectiveDate1 = buildDateTime(2011, 1, 1);
 
-        BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan, phase1, fixedPrice,
-                null, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
+        BillingEvent event1 = new DefaultBillingEvent(subscription, effectiveDate1, plan, phase1,
+                fixedPrice.getPrice(currency), null, currency,
+                BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
                 "testEvent1", SubscriptionTransitionType.CREATE);
         BillingEventSet events = new BillingEventSet();
         events.add(event1);
 
         DateTime effectiveDate2 = effectiveDate1.plusDays(30);
         BillingEvent event2 = new DefaultBillingEvent(subscription, effectiveDate2, plan, phase2, null,
-                recurringPrice, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
+                recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
                 "testEvent2", SubscriptionTransitionType.CHANGE);
         events.add(event2);
 
@@ -680,79 +687,4 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         assertEquals(savedInvoice.getNumberOfItems(), 2);
         assertEquals(savedInvoice.getTotalAmount().compareTo(cheapAmount), 0);
     }
-
-//    @Test
-//    public void testCancellationWithMultipleBillingPeriodsFollowing() throws InvoiceApiException {
-//        UUID accountId = UUID.randomUUID();
-//
-//        BigDecimal fixedValue = FIVE;
-//        DefaultPrice fixedAmount = new DefaultPrice(fixedValue, Currency.USD);
-//        MockInternationalPrice fixedPrice = new MockInternationalPrice(fixedAmount);
-//        MockPlanPhase plan1phase1 = new MockPlanPhase(null, fixedPrice);
-//
-//        BigDecimal trialValue = new BigDecimal("9.95");
-//        DefaultPrice trialAmount = new DefaultPrice(trialValue, Currency.USD);
-//        MockInternationalPrice trialPrice = new MockInternationalPrice(trialAmount);
-//        MockPlanPhase plan2phase1 = new MockPlanPhase(trialPrice, null);
-//
-//        BigDecimal discountValue = new BigDecimal("24.95");
-//        DefaultPrice discountAmount = new DefaultPrice(discountValue, Currency.USD);
-//        MockInternationalPrice discountPrice = new MockInternationalPrice(discountAmount);
-//        MockPlanPhase plan2phase2 = new MockPlanPhase(discountPrice, null);
-//
-//        MockPlan plan1 = new MockPlan();
-//        MockPlan plan2 = new MockPlan();
-//        Subscription subscription = new MockSubscription();
-//        DateTime effectiveDate1 = buildDateTime(2011, 1, 1);
-//
-//        BillingEvent creationEvent = new DefaultBillingEvent(subscription, effectiveDate1, plan1, plan1phase1, fixedPrice,
-//                                                     null, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
-//                                                     "trial", SubscriptionTransitionType.CREATE);
-//        BillingEventSet events = new BillingEventSet();
-//        events.add(creationEvent);
-//
-//        InvoiceItemList existingItems;
-//
-//        existingItems = new InvoiceItemList(invoiceDao.getInvoiceItemsByAccount(accountId));
-//        Invoice invoice1 = generator.generateInvoice(accountId, events, existingItems, effectiveDate1, Currency.USD);
-//
-//        assertNotNull(invoice1);
-//        assertEquals(invoice1.getNumberOfItems(), 1);
-//        assertEquals(invoice1.getTotalAmount().compareTo(fixedValue), 0);
-//        invoiceDao.create(invoice1);
-//
-//        DateTime effectiveDate2 = effectiveDate1.plusSeconds(1);
-//        BillingEvent changeEvent = new DefaultBillingEvent(subscription, effectiveDate2, plan2, plan2phase1, null,
-//                                                     trialPrice, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
-//                                                     "discount", SubscriptionTransitionType.CHANGE);
-//        events.add(changeEvent);
-//
-//        existingItems = new InvoiceItemList(invoiceDao.getInvoiceItemsByAccount(accountId));
-//        Invoice invoice2 = generator.generateInvoice(accountId, events, existingItems, effectiveDate2, Currency.USD);
-//        assertNotNull(invoice2);
-//        assertEquals(invoice2.getNumberOfItems(), 2);
-//        assertEquals(invoice2.getTotalAmount().compareTo(trialValue), 0);
-//        invoiceDao.create(invoice2);
-//
-//        DateTime effectiveDate3 = effectiveDate2.plusMonths(1);
-//        BillingEvent phaseEvent = new DefaultBillingEvent(subscription, effectiveDate3, plan2, plan2phase2, null,
-//                                                     discountPrice, BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
-//                                                     "discount", SubscriptionTransitionType.PHASE);
-//        events.add(phaseEvent);
-//
-//        existingItems = new InvoiceItemList(invoiceDao.getInvoiceItemsByAccount(accountId));
-//        Invoice invoice3 = generator.generateInvoice(accountId, events, existingItems, effectiveDate3, Currency.USD);
-//        assertNotNull(invoice3);
-//        assertEquals(invoice3.getNumberOfItems(), 1);
-//        assertEquals(invoice3.getTotalAmount().compareTo(discountValue), 0);
-//        invoiceDao.create(invoice3);
-//
-//        DateTime effectiveDate4 = effectiveDate3.plusMonths(1);
-//        existingItems = new InvoiceItemList(invoiceDao.getInvoiceItemsByAccount(accountId));
-//        Invoice invoice4 = generator.generateInvoice(accountId, events, existingItems, effectiveDate4, Currency.USD);
-//        assertNotNull(invoice4);
-//        assertEquals(invoice4.getNumberOfItems(), 1);
-//        assertEquals(invoice4.getTotalAmount().compareTo(discountValue), 0);
-//        invoiceDao.create(invoice4);
-//    }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
index 987dd4d..4546a8c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -17,6 +17,7 @@
 package com.ning.billing.invoice;
 
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -57,6 +58,7 @@ import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.bus.BusService;
 import com.ning.billing.util.globallocker.GlobalLocker;
+import sun.security.util.BigInt;
 
 @Guice(modules = {MockModule.class})
 public class TestInvoiceDispatcher {
@@ -123,13 +125,15 @@ public class TestInvoiceDispatcher {
 	    	Plan plan = MockPlan.createBicycleNoTrialEvergreen1USD();
 	    	PlanPhase planPhase = MockPlanPhase.create1USDMonthlyEvergreen();
 			DateTime effectiveDate = new DateTime().minusDays(1);
-			InternationalPrice reccurringPrice = MockInternationalPrice.create1USD();
-			InternationalPrice fixedPrice = null;
-			events.add(new DefaultBillingEvent(subscription, effectiveDate,plan,planPhase, fixedPrice , reccurringPrice, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,"", SubscriptionTransitionType.CREATE));
+            Currency currency = Currency.USD;
+			BigDecimal fixedPrice = null;
+			events.add(new DefaultBillingEvent(subscription, effectiveDate,plan, planPhase,
+                                               fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
+                                               BillingModeType.IN_ADVANCE, "", SubscriptionTransitionType.CREATE));
+
 	    	EntitlementBillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
 	    	((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccount", events);
-	    	
-	    	
+
 	    	DateTime target = new DateTime();
 	    	
 	    	InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountUserApi, entitlementBillingApi, invoiceDao, locker);
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 8e5637c..30e3884 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
@@ -22,6 +22,7 @@ import com.ning.billing.catalog.MockInternationalPrice;
 import com.ning.billing.catalog.MockPlan;
 import com.ning.billing.catalog.MockPlanPhase;
 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.PhaseType;
 import com.ning.billing.catalog.api.Plan;
@@ -36,12 +37,15 @@ import com.ning.billing.entitlement.api.user.SubscriptionTransition.Subscription
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.model.BillingEventSet;
+import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.InvoiceGenerator;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.DefaultClock;
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
@@ -57,12 +61,12 @@ import static org.testng.Assert.assertNull;
 
 @Test(groups = {"fast", "invoicing", "invoiceGenerator"})
 public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
+    private final Clock clock = new DefaultClock();
     private final InvoiceGenerator generator;
 
-    @Inject
-    public DefaultInvoiceGeneratorTests(InvoiceGenerator generator) {
+    public DefaultInvoiceGeneratorTests() {
         super();
-        this.generator = generator;
+        this.generator = new DefaultInvoiceGenerator(clock);
     }
 
     @Test
@@ -84,7 +88,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testWithSingleMonthlyEvent() throws InvoiceApiException {
+    public void testWithSingleMonthlyEvent() throws InvoiceApiException, CatalogApiException {
         BillingEventSet events = new BillingEventSet();
 
         Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
@@ -108,7 +112,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testWithSingleMonthlyEventWithLeadingProRation() throws InvoiceApiException {
+    public void testWithSingleMonthlyEventWithLeadingProRation() throws InvoiceApiException, CatalogApiException {
         BillingEventSet events = new BillingEventSet();
 
         Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
@@ -134,7 +138,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testTwoMonthlySubscriptionsWithAlignedBillingDates() throws InvoiceApiException {
+    public void testTwoMonthlySubscriptionsWithAlignedBillingDates() throws InvoiceApiException, CatalogApiException {
         BillingEventSet events = new BillingEventSet();
 
         Plan plan1 = new MockPlan();
@@ -163,7 +167,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testOnePlan_TwoMonthlyPhases_ChangeImmediate() throws InvoiceApiException {
+    public void testOnePlan_TwoMonthlyPhases_ChangeImmediate() throws InvoiceApiException, CatalogApiException {
         BillingEventSet events = new BillingEventSet();
 
         Plan plan1 = new MockPlan();
@@ -200,7 +204,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testOnePlan_ThreeMonthlyPhases_ChangeEOT() throws InvoiceApiException {
+    public void testOnePlan_ThreeMonthlyPhases_ChangeEOT() throws InvoiceApiException, CatalogApiException {
         BillingEventSet events = new BillingEventSet();
 
         Plan plan1 = new MockPlan();
@@ -231,7 +235,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testSingleEventWithExistingInvoice() throws InvoiceApiException {
+    public void testSingleEventWithExistingInvoice() throws InvoiceApiException, CatalogApiException {
         BillingEventSet events = new BillingEventSet();
 
         Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
@@ -257,7 +261,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testMultiplePlansWithUtterChaos() throws InvoiceApiException {
+    public void testMultiplePlansWithUtterChaos() throws InvoiceApiException, CatalogApiException {
         // plan 1: change of phase from trial to discount followed by immediate cancellation; (covers phase change, cancel, pro-ration)
         // plan 2: single plan that moves from trial to discount to evergreen; BCD = 10 (covers phase change)
         // plan 3: change of term from monthly (BCD = 20) to annual (BCD = 31; immediate)
@@ -418,7 +422,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testZeroDollarEvents() throws InvoiceApiException {
+    public void testZeroDollarEvents() throws InvoiceApiException, CatalogApiException {
         Plan plan = new MockPlan();
         PlanPhase planPhase = createMockMonthlyPlanPhase(ZERO);
         BillingEventSet events = new BillingEventSet();
@@ -431,7 +435,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testEndDateIsCorrect() throws InvoiceApiException {
+    public void testEndDateIsCorrect() throws InvoiceApiException, CatalogApiException {
         Plan plan = new MockPlan();
         PlanPhase planPhase = createMockMonthlyPlanPhase(ZERO);
         BillingEventSet events = new BillingEventSet();
@@ -464,13 +468,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
         BillingEvent event1 = new DefaultBillingEvent(subscription, new DateTime("2012-01-1T00:00:00.000-08:00"),
                                                       plan, phase1,
-                                                      zeroPrice, null, BillingPeriod.NO_BILLING_PERIOD, 1,
+                                                      ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
                                                       BillingModeType.IN_ADVANCE, "Test Event 1",
                                                       SubscriptionTransitionType.CREATE);
 
         BillingEvent event2 = new DefaultBillingEvent(subscription, changeDate,
                                                       plan, phase2,
-                                                      zeroPrice, null, BillingPeriod.NO_BILLING_PERIOD, 1,
+                                                      ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
                                                       BillingModeType.IN_ADVANCE, "Test Event 2",
                                                       SubscriptionTransitionType.PHASE);
 
@@ -490,7 +494,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
    }
 
     @Test
-    public void testMixedModeLifeCycle() throws InvoiceApiException {
+    public void testMixedModeLifeCycle() throws InvoiceApiException, CatalogApiException {
         // create a subscription with a fixed price and recurring price
         Plan plan1 = new MockPlan();
         BigDecimal monthlyRate = FIVE;
@@ -525,7 +529,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testFixedModePlanChange() throws InvoiceApiException {
+    public void testFixedModePlanChange() throws InvoiceApiException, CatalogApiException {
         // create a subscription with a fixed price and recurring price
         Plan plan1 = new MockPlan();
         BigDecimal fixedCost1 = TEN;
@@ -563,7 +567,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     @Test
-    public void testNutsFailure() throws InvoiceApiException {
+    public void testNutsFailure() throws InvoiceApiException, CatalogApiException {
         BillingEventSet events = new BillingEventSet();
         UUID subscriptionId = UUID.randomUUID();
         UUID accountId = UUID.randomUUID();
@@ -614,7 +618,17 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         targetDate = targetDate.plusMonths(6);
         Invoice invoice4 = generator.generateInvoice(accountId, events, invoiceList, targetDate, Currency.USD);
         assertNotNull(invoice4);
-        assertEquals(invoice4.getNumberOfItems(), 17);
+        assertEquals(invoice4.getNumberOfItems(), 7);
+    }
+
+    @Test(expectedExceptions = {InvoiceApiException.class})
+    public void testTargetDateRestrictionFailure() throws InvoiceApiException, CatalogApiException {
+        DateTime targetDate = DateTime.now().plusMonths(60);
+        BillingEventSet events = new BillingEventSet();
+        Plan plan1 = new MockPlan();
+        PlanPhase phase1 = createMockMonthlyPlanPhase(null, ZERO, PhaseType.TRIAL);
+        events.add(createBillingEvent(UUID.randomUUID(), DateTime.now(), plan1, phase1, 1));
+        generator.generateInvoice(UUID.randomUUID(), events, null, targetDate, Currency.USD);
     }
 
     private MockPlanPhase createMockMonthlyPlanPhase() {
@@ -646,12 +660,14 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     }
 
     private DefaultBillingEvent createBillingEvent(final UUID subscriptionId, final DateTime startDate,
-                                                   final Plan plan, final PlanPhase planPhase, final int billCycleDay) {
+                                                   final Plan plan, final PlanPhase planPhase, final int billCycleDay) throws CatalogApiException {
         Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(subscriptionId));
+        Currency currency = Currency.USD;
 
         return new DefaultBillingEvent(sub, startDate, plan, planPhase,
-                                       planPhase.getFixedPrice(),
-                                       planPhase.getRecurringPrice(), planPhase.getBillingPeriod(),
+                                       planPhase.getFixedPrice() == null ? null : planPhase.getFixedPrice().getPrice(currency),
+                                       planPhase.getRecurringPrice() == null ? null : planPhase.getRecurringPrice().getPrice(currency),
+                                       currency, planPhase.getBillingPeriod(),
                                        billCycleDay, BillingModeType.IN_ADVANCE,"Test", SubscriptionTransitionType.CREATE);
     }
 
diff --git a/invoice/src/test/resources/resource.properties b/invoice/src/test/resources/resource.properties
new file mode 100644
index 0000000..4e66149
--- /dev/null
+++ b/invoice/src/test/resources/resource.properties
@@ -0,0 +1 @@
+com.ning.billing.invoice.maxNumberOfMonthsInFuture = 36
\ No newline at end of file