diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
new file mode 100644
index 0000000..d0b97bf
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
@@ -0,0 +1,561 @@
+/*
+ * 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.junction.plumbing.billing;
+
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.MockCatalogService;
+import com.ning.billing.catalog.api.BillingAlignment;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+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.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.Price;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.PriceListSet;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionEvent;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.BillingEventSet;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.api.DefaultBlockingState;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.dao.ObjectType;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
+
+public class TestBillingApi {
+
+ class MockPrice implements InternationalPrice {
+ private final BigDecimal price;
+
+ public MockPrice(String val) {
+ price = new BigDecimal(val);
+ }
+
+ @Override
+ public boolean isZero() {
+ return price.compareTo(BigDecimal.ZERO) == 0;
+ }
+
+ @Override
+ public Price[] getPrices() {
+ return new Price[]{
+ new Price() {
+
+ @Override
+ public Currency getCurrency() {
+ return Currency.USD;
+ }
+
+ @Override
+ public BigDecimal getValue() throws CurrencyValueNull {
+ return price;
+ }
+
+ }
+ };
+ }
+
+ @Override
+ public BigDecimal getPrice(Currency currency) throws CatalogApiException {
+ return price;
+ }
+ };
+
+ private static final String DISABLED_BUNDLE = "disabled-bundle";
+ private static final String CLEAR_BUNDLE = "clear-bundle";
+
+ private static final UUID eventId = new UUID(0L,0L);
+ private static final UUID subId = new UUID(1L,0L);
+ private static final UUID bunId = new UUID(2L,0L);
+
+ private CatalogService catalogService;
+ private List<SubscriptionBundle> bundles;
+ private List<Subscription> subscriptions;
+
+ private List<SubscriptionEvent> subscriptionTransitions;
+ private EntitlementUserApi entitlementApi;
+
+ private BlockingCalculator blockCalculator = new BlockingCalculator(null) {
+ @Override
+ public void insertBlockingEvents(SortedSet<BillingEvent> billingEvents) {
+
+ }
+
+ };
+
+
+
+ private Clock clock;
+ private Subscription subscription;
+ private DateTime subscriptionStartDate;
+ private Plan subscriptionPlan;
+ private TagUserApi tagApi;
+
+ @BeforeSuite(groups={"fast", "slow"})
+ public void setup() throws ServiceException {
+ catalogService = new MockCatalogService(new MockCatalog());
+ clock = new ClockMock();
+ }
+
+ @BeforeMethod(groups={"fast", "slow"})
+ public void setupEveryTime() {
+ bundles = new ArrayList<SubscriptionBundle>();
+ final SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+ ((ZombieControl)bundle).addResult("getId", bunId);
+
+ //new SubscriptionBundleData( eventId,"TestKey", subId, clock.getUTCNow().minusDays(4), null);
+ bundles.add(bundle);
+
+
+ subscriptionTransitions = new LinkedList<SubscriptionEvent>();
+ subscriptions = new LinkedList<Subscription>();
+
+ subscriptionStartDate = clock.getUTCNow().minusDays(3);
+ subscription = new MockSubscription() {
+ @Override
+ public List<SubscriptionEvent> getBillingTransitions() {
+ return subscriptionTransitions;
+ }
+
+ @Override
+ public Plan getCurrentPlan() {
+ return subscriptionPlan;
+ }
+
+ @Override
+ public UUID getId() {
+ return subId;
+ }
+
+ @Override
+ public UUID getBundleId() {
+ return bunId;
+ }
+
+ @Override
+ public DateTime getStartDate() {
+ return subscriptionStartDate;
+ }
+
+
+ };
+
+ subscriptions.add(subscription);
+
+ entitlementApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+ ((ZombieControl) entitlementApi).addResult("getBundlesForAccount", bundles);
+ ((ZombieControl) entitlementApi).addResult("getSubscriptionsForBundle", subscriptions);
+ ((ZombieControl) entitlementApi).addResult("getSubscriptionFromId", subscription);
+ ((ZombieControl) entitlementApi).addResult("getBundleFromId", bundle);
+ ((ZombieControl) entitlementApi).addResult("getBaseSubscription", subscription);
+
+ tagApi = mock(TagUserApi.class);
+
+ assertTrue(true);
+ }
+
+ @Test(enabled=true, groups="fast")
+ public void testBillingEventsEmpty() {
+ UUID accountId = UUID.randomUUID();
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl) account).addResult("getId", accountId).addResult("getCurrency", Currency.USD);
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ ((ZombieControl) accountApi).addResult("getAccountById", account);
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator, catalogService, tagApi);
+
+ SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
+ Assert.assertEquals(events.size(), 0);
+ }
+
+ @Test(enabled=true, groups="fast")
+ public void testBillingEventsNoBillingPeriod() throws CatalogApiException {
+ DateTime now = clock.getUTCNow();
+ DateTime then = now.minusDays(1);
+ Plan nextPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+ PlanPhase nextPhase = nextPlan.getAllPhases()[0]; // The trial has no billing period
+ PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+
+ SubscriptionEvent t = new MockSubscriptionEvent(
+ eventId, subId, bunId, then, now, null, null, null, null, SubscriptionState.ACTIVE,
+ nextPlan.getName(), nextPhase.getName(),
+ nextPriceList.getName(), 1L,null,
+ SubscriptionTransitionType.CREATE, 0, null);
+
+ subscriptionTransitions.add(t);
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl)account).addResult("getBillCycleDay", 32);
+ ((ZombieControl)account).addResult("getCurrency", Currency.USD);
+ ((ZombieControl)account).addResult("getId", UUID.randomUUID());
+ ((ZombieControl)accountApi).addResult("getAccountById", account);
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator, catalogService, tagApi);
+ SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
+
+ checkFirstEvent(events, nextPlan, 32, subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString());
+ }
+
+ @Test(enabled=false, groups="fast")
+ public void testBillingEventsAnnual() throws CatalogApiException {
+ DateTime now = clock.getUTCNow();
+ DateTime then = now.minusDays(1);
+ Plan nextPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+ PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+ PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+ SubscriptionEvent t = new MockSubscriptionEvent(
+ eventId, subId, bunId, then, now, null, null, null, null, SubscriptionState.ACTIVE,
+ nextPlan.getName(), nextPhase.getName(),
+ nextPriceList.getName(), 1L,null,
+ SubscriptionTransitionType.CREATE, 0, null);
+
+ subscriptionTransitions.add(t);
+
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl)account).addResult("getBillCycleDay", 1).addResult("getTimeZone", DateTimeZone.UTC)
+ .addResult("getCurrency", Currency.USD);
+
+ ((MockCatalog)catalogService.getFullCatalog()).setBillingAlignment(BillingAlignment.SUBSCRIPTION);
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ ((ZombieControl)accountApi).addResult("getAccountById", account);
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator, catalogService, tagApi);
+ SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
+
+ checkFirstEvent(events, nextPlan, subscription.getStartDate().plusDays(30).getDayOfMonth(), subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString());
+ }
+
+ @Test(enabled=true, groups="fast")
+ public void testBillingEventsMonthly() throws CatalogApiException {
+ DateTime now = clock.getUTCNow();
+ DateTime then = now.minusDays(1);
+ Plan nextPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+ PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+ PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+
+ SubscriptionEvent t = new MockSubscriptionEvent(
+ eventId, subId, bunId, then, now, null, null, null, null, SubscriptionState.ACTIVE,
+ nextPlan.getName(), nextPhase.getName(),
+ nextPriceList.getName(), 1L,null,
+ SubscriptionTransitionType.CREATE, 0, null);
+
+
+ subscriptionTransitions.add(t);
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl)account).addResult("getBillCycleDay", 32);
+ ((ZombieControl)account).addResult("getCurrency", Currency.USD);
+ ((ZombieControl)account).addResult("getId", UUID.randomUUID());
+ ((ZombieControl)accountApi).addResult("getAccountById", account);
+
+ ((MockCatalog)catalogService.getFullCatalog()).setBillingAlignment(BillingAlignment.ACCOUNT);
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator, catalogService, tagApi);
+
+ SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
+
+ checkFirstEvent(events, nextPlan, 32, subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString());
+ }
+
+ @Test(enabled=false, groups="fast")
+ public void testBillingEventsAddOn() throws CatalogApiException {
+ DateTime now = clock.getUTCNow();
+ DateTime then = now.minusDays(1);
+ Plan nextPlan = catalogService.getFullCatalog().findPlan("Horn1USD", now);
+ PlanPhase nextPhase = nextPlan.getAllPhases()[0];
+ PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+
+ SubscriptionEvent t = new MockSubscriptionEvent(
+ eventId, subId, bunId, then, now, null, null, null, null, SubscriptionState.ACTIVE,
+ nextPlan.getName(), nextPhase.getName(),
+ nextPriceList.getName(), 1L,null,
+ SubscriptionTransitionType.CREATE, 0, null);
+
+ subscriptionTransitions.add(t);
+
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl)account).addResult("getBillCycleDay", 1).addResult("getTimeZone", DateTimeZone.UTC);
+ ((ZombieControl)account).addResult("getCurrency", Currency.USD);
+ ((ZombieControl)account).addResult("getId", UUID.randomUUID());
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ ((ZombieControl)accountApi).addResult("getAccountById", account);
+
+ ((MockCatalog)catalogService.getFullCatalog()).setBillingAlignment(BillingAlignment.BUNDLE);
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator, catalogService, tagApi);
+ subscriptionPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+
+ SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
+
+ checkFirstEvent(events, nextPlan, subscription.getStartDate().plusDays(30).getDayOfMonth(), subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString());
+ }
+
+ @Test(enabled=true, groups="fast")
+ public void testBillingEventsWithBlock() throws CatalogApiException {
+ DateTime now = clock.getUTCNow();
+ DateTime then = now.minusDays(1);
+ Plan nextPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+ PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+ PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+
+
+ SubscriptionEvent t = new MockSubscriptionEvent(
+ eventId, subId, bunId, then, now, null, null, null, null, SubscriptionState.ACTIVE,
+ nextPlan.getName(), nextPhase.getName(),
+ nextPriceList.getName(), 1L,null,
+ SubscriptionTransitionType.CREATE, 0, null);
+
+ subscriptionTransitions.add(t);
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl)account).addResult("getBillCycleDay", 32);
+ ((ZombieControl)account).addResult("getCurrency", Currency.USD);
+ ((ZombieControl)accountApi).addResult("getAccountById", account);
+ ((ZombieControl)account).addResult("getId", UUID.randomUUID());
+
+ ((MockCatalog)catalogService.getFullCatalog()).setBillingAlignment(BillingAlignment.ACCOUNT);
+
+ final SortedSet<BlockingState> blockingStates = new TreeSet<BlockingState>();
+ blockingStates.add(new DefaultBlockingState(bunId,DISABLED_BUNDLE, Blockable.Type.SUBSCRIPTION_BUNDLE, "test", true, true, true, now.plusDays(1)));
+ blockingStates.add(new DefaultBlockingState(bunId,CLEAR_BUNDLE, Blockable.Type.SUBSCRIPTION_BUNDLE, "test", false, false, false, now.plusDays(2)));
+
+ BlockingCalculator blockingCal = new BlockingCalculator(new BlockingApi() {
+
+ @Override
+ public <T extends Blockable> void setBlockingState(BlockingState state) {}
+
+ @Override
+ public BlockingState getBlockingStateFor(UUID overdueableId) {
+ return null;
+ }
+
+ @Override
+ public BlockingState getBlockingStateFor(Blockable overdueable) {
+ return null;
+ }
+
+ @Override
+ public SortedSet<BlockingState> getBlockingHistory(UUID overdueableId) {
+ if(overdueableId == bunId) {
+ return blockingStates;
+ }
+ return new TreeSet<BlockingState>();
+ }
+
+ @Override
+ public SortedSet<BlockingState> getBlockingHistory(Blockable overdueable) {
+ return new TreeSet<BlockingState>();
+ }
+ });
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockingCal, catalogService, tagApi);
+ SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
+
+ Assert.assertEquals(events.size(), 3);
+ Iterator<BillingEvent> it = events.iterator();
+
+ checkEvent(it.next(), nextPlan, 32, subId, now, nextPhase, SubscriptionTransitionType.CREATE.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+ checkEvent(it.next(), nextPlan, 32, subId, now.plusDays(1), nextPhase, SubscriptionTransitionType.CANCEL.toString(), new MockPrice("0"), new MockPrice("0"));
+ checkEvent(it.next(), nextPlan, 32, subId, now.plusDays(2), nextPhase, SubscriptionTransitionType.RE_CREATE.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+
+ }
+
+ @Test(enabled=true, groups="fast")
+ public void testBillingEventsAutoInvoicingOffAccount() throws CatalogApiException {
+ DateTime now = clock.getUTCNow();
+ DateTime then = now.minusDays(1);
+ Plan nextPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+ PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+ PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+
+ SubscriptionEvent t = new MockSubscriptionEvent(
+ eventId, subId, bunId, then, now, null, null, null, null, SubscriptionState.ACTIVE,
+ nextPlan.getName(), nextPhase.getName(),
+ nextPriceList.getName(), 1L,null,
+ SubscriptionTransitionType.CREATE, 0, null);
+
+
+ subscriptionTransitions.add(t);
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl)account).addResult("getBillCycleDay", 32);
+ ((ZombieControl)account).addResult("getCurrency", Currency.USD);
+ ((ZombieControl)account).addResult("getId", UUID.randomUUID());
+ ((ZombieControl)accountApi).addResult("getAccountById", account);
+
+ Map<String, Tag> tags = new HashMap<String, Tag>();
+ Tag aioTag = mock(Tag.class);
+ when(aioTag.getTagDefinitionName()).thenReturn(ControlTagType.AUTO_INVOICING_OFF.name());
+ tags.put(ControlTagType.AUTO_INVOICING_OFF.name(),aioTag);
+ when(tagApi.getTags(account.getId(), ObjectType.ACCOUNT)).thenReturn(tags);
+ assertEquals(tagApi.getTags(account.getId(), ObjectType.ACCOUNT), tags);
+
+ ((MockCatalog)catalogService.getFullCatalog()).setBillingAlignment(BillingAlignment.ACCOUNT);
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator, catalogService, tagApi);
+
+ BillingEventSet events = api.getBillingEventsForAccountAndUpdateAccountBCD(account.getId());
+
+ assertEquals(events.isAccountAutoInvoiceOff(), true);
+ assertEquals(events.size(),0);
+ }
+
+
+ @Test(enabled=true, groups="fast")
+ public void testBillingEventsAutoInvoicingOffBundle() throws CatalogApiException {
+ DateTime now = clock.getUTCNow();
+ DateTime then = now.minusDays(1);
+ Plan nextPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+ PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+ PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+
+ SubscriptionEvent t = new MockSubscriptionEvent(
+ eventId, subId, bunId, then, now, null, null, null, null, SubscriptionState.ACTIVE,
+ nextPlan.getName(), nextPhase.getName(),
+ nextPriceList.getName(), 1L,null,
+ SubscriptionTransitionType.CREATE, 0, null);
+
+
+ subscriptionTransitions.add(t);
+
+ AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+ Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+ ((ZombieControl)account).addResult("getBillCycleDay", 32);
+ ((ZombieControl)account).addResult("getCurrency", Currency.USD);
+ ((ZombieControl)account).addResult("getId", UUID.randomUUID());
+ ((ZombieControl)accountApi).addResult("getAccountById", account);
+
+ Map<String, Tag> tags = new HashMap<String, Tag>();
+ Tag aioTag = mock(Tag.class);
+ when(aioTag.getTagDefinitionName()).thenReturn(ControlTagType.AUTO_INVOICING_OFF.name());
+ tags.put(ControlTagType.AUTO_INVOICING_OFF.name(),aioTag);
+ when(tagApi.getTags(bunId, ObjectType.BUNDLE)).thenReturn(tags);
+
+ ((MockCatalog)catalogService.getFullCatalog()).setBillingAlignment(BillingAlignment.ACCOUNT);
+
+ BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+ CallContextFactory factory = new DefaultCallContextFactory(clock);
+ BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator, catalogService, tagApi);
+
+ BillingEventSet events = api.getBillingEventsForAccountAndUpdateAccountBCD(account.getId());
+
+ assertEquals(events.getSubscriptionAndBundleIdsWithAutoInvoiceOff().size(), 1);
+ assertEquals(events.getSubscriptionAndBundleIdsWithAutoInvoiceOff().get(0), subId);
+ assertEquals(events.size(),0);
+ }
+
+ private void checkFirstEvent(SortedSet<BillingEvent> events, Plan nextPlan,
+ int BCD, UUID id, DateTime time, PlanPhase nextPhase, String desc) throws CatalogApiException {
+ Assert.assertEquals(events.size(), 1);
+ checkEvent(events.first(), nextPlan,
+ BCD, id, time, nextPhase, desc, nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+ }
+
+ private void checkEvent(BillingEvent event, Plan nextPlan,
+ int BCD, UUID id, DateTime time, PlanPhase nextPhase, String desc, InternationalPrice fixedPrice, InternationalPrice recurringPrice) throws CatalogApiException {
+ if(fixedPrice != null) {
+ Assert.assertEquals(fixedPrice.getPrice(Currency.USD), event.getFixedPrice());
+ } else {
+ assertNull(event.getFixedPrice());
+ }
+
+ if(recurringPrice != null) {
+ Assert.assertEquals(recurringPrice.getPrice(Currency.USD), event.getRecurringPrice());
+ } else {
+ assertNull(event.getRecurringPrice());
+ }
+
+ Assert.assertEquals(BCD, event.getBillCycleDay());
+ Assert.assertEquals(id, event.getSubscription().getId());
+ Assert.assertEquals(time, event.getEffectiveDate());
+ Assert.assertEquals(nextPhase, event.getPlanPhase());
+ Assert.assertEquals(nextPlan, event.getPlan());
+ Assert.assertEquals(nextPhase.getBillingPeriod(), event.getBillingPeriod());
+ Assert.assertEquals(BillingModeType.IN_ADVANCE, event.getBillingMode());
+ Assert.assertEquals(desc, event.getTransitionType().toString());
+ }
+}