killbill-aplcache
Changes
invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java 15(+8 -7)
Details
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
index af66de0..f6726f6 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
@@ -50,6 +50,7 @@ import org.killbill.billing.util.currency.KillBillMoney;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import static org.killbill.billing.invoice.generator.InvoiceDateUtils.calculateNumberOfWholeBillingPeriods;
@@ -90,12 +91,12 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
return accountItemTree.getResultingItemList();
}
- private List<InvoiceItem> processRecurringBillingEvents(final UUID invoiceId, final UUID accountId, final BillingEventSet events,
+ private void processRecurringBillingEvents(final UUID invoiceId, final UUID accountId, final BillingEventSet events,
final LocalDate targetDate, final Currency currency, final List<InvoiceItem> proposedItems,
final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate) throws InvoiceApiException {
if (events.size() == 0) {
- return proposedItems;
+ return;
}
// Pretty-print the generated invoice items from the junction events
@@ -121,10 +122,11 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
log.info(logStringBuilder.toString());
- return proposedItems;
+ return;
}
- private List<InvoiceItem> processFixedBillingEvents(final UUID invoiceId, final UUID accountId, final BillingEventSet events, final LocalDate targetDate, final Currency currency, final List<InvoiceItem> proposedItems) {
+ @VisibleForTesting
+ void processFixedBillingEvents(final UUID invoiceId, final UUID accountId, final BillingEventSet events, final LocalDate targetDate, final Currency currency, final List<InvoiceItem> proposedItems) {
final AccountDateAndTimeZoneContext dateAndTimeZoneContext = events.getAccountDateAndTimeZoneContext();
@@ -144,11 +146,10 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
if (prevItem != null) {
proposedItems.add(prevItem);
}
- return proposedItems;
}
-
- private boolean isSameDayAndSameSubscription(final InvoiceItem prevComputedFixedItem, final BillingEvent currentBillingEvent, final AccountDateAndTimeZoneContext dateAndTimeZoneContext) {
+ @VisibleForTesting
+ boolean isSameDayAndSameSubscription(final InvoiceItem prevComputedFixedItem, final BillingEvent currentBillingEvent, final AccountDateAndTimeZoneContext dateAndTimeZoneContext) {
final LocalDate curLocalEffectiveDate = dateAndTimeZoneContext.computeLocalDateFromFixedAccountOffset(currentBillingEvent.getEffectiveDate());
if (prevComputedFixedItem != null && /* If we have computed a previous item */
prevComputedFixedItem.getStartDate().compareTo(curLocalEffectiveDate) == 0 && /* The current billing event happens at the same date */
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java
new file mode 100644
index 0000000..fc2d83a
--- /dev/null
+++ b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2014-2016 Groupon, Inc
+ * Copyright 2014-2016 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.invoice.generator;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.catalog.DefaultPrice;
+import org.killbill.billing.catalog.MockInternationalPrice;
+import org.killbill.billing.catalog.MockPlan;
+import org.killbill.billing.catalog.MockPlanPhase;
+import org.killbill.billing.catalog.api.BillingMode;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.Plan;
+import org.killbill.billing.catalog.api.PlanPhase;
+import org.killbill.billing.invoice.InvoiceTestSuiteNoDB;
+import org.killbill.billing.invoice.MockBillingEventSet;
+import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.api.InvoiceItemType;
+import org.killbill.billing.invoice.model.FixedPriceInvoiceItem;
+import org.killbill.billing.junction.BillingEvent;
+import org.killbill.billing.junction.BillingEventSet;
+import org.killbill.billing.subscription.api.SubscriptionBase;
+import org.killbill.billing.subscription.api.SubscriptionBaseTransitionType;
+import org.killbill.billing.util.AccountDateAndTimeZoneContext;
+import org.killbill.billing.util.timezone.DefaultAccountDateAndTimeZoneContext;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteNoDB {
+
+ private Account account;
+ private SubscriptionBase subscription;
+ private AccountDateAndTimeZoneContext dateAndTimeZoneContext;
+
+ @Override
+ @BeforeMethod(groups = "fast")
+ public void beforeMethod() {
+ super.beforeMethod();
+
+ try {
+ account = invoiceUtil.createAccount(callContext);
+ subscription = invoiceUtil.createSubscription();
+ dateAndTimeZoneContext = new DefaultAccountDateAndTimeZoneContext(new DateTime("2016-01-08T03:01:01.000Z"), DateTimeZone.UTC);
+ } catch (final Exception e) {
+ Assert.fail(e.getMessage());
+ }
+ }
+
+ @Test(groups = "fast")
+ public void testIsSameDayAndSameSubscriptionWithNullPrevEvent() {
+
+ final Plan plan = new MockPlan("my-plan");
+
+ final BigDecimal fixedPriceAmount = BigDecimal.TEN;
+ final MockInternationalPrice fixedPrice = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount, Currency.USD));
+ final PlanPhase phase = new MockPlanPhase(null, fixedPrice, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final InvoiceItem prevInvoiceItem = null;
+
+ final BillingEvent event = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-02-01"),
+ plan, phase,
+ fixedPriceAmount, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 1L,
+ SubscriptionBaseTransitionType.CREATE);
+
+ assertFalse(fixedAndRecurringInvoiceItemGenerator.isSameDayAndSameSubscription(prevInvoiceItem, event, dateAndTimeZoneContext));
+ }
+
+ @Test(groups = "fast")
+ public void testIsSameDayAndSameSubscriptionWithDifferentSubscriptionId() {
+
+ final Plan plan = new MockPlan("my-plan");
+
+ final LocalDate invoiceItemDate = new LocalDate("2016-01-08");
+ final BigDecimal fixedPriceAmount = BigDecimal.TEN;
+ final MockInternationalPrice fixedPrice = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount, Currency.USD));
+ final PlanPhase phase = new MockPlanPhase(null, fixedPrice, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final UUID invoiceId = UUID.randomUUID();
+ final InvoiceItem prevInvoiceItem = new FixedPriceInvoiceItem(invoiceId, account.getId(), UUID.randomUUID(), UUID.randomUUID(), plan.getName(),
+ phase.getName(), invoiceItemDate, fixedPriceAmount, Currency.USD);
+
+ final BillingEvent event = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan, phase,
+ fixedPriceAmount, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 1L,
+ SubscriptionBaseTransitionType.CREATE);
+
+ assertFalse(fixedAndRecurringInvoiceItemGenerator.isSameDayAndSameSubscription(prevInvoiceItem, event, dateAndTimeZoneContext));
+ }
+
+ @Test(groups = "fast")
+ public void testIsSameDayAndSameSubscriptionWithDifferentDate() {
+
+ final Plan plan = new MockPlan("my-plan");
+
+ final LocalDate invoiceItemDate = new LocalDate("2016-01-08");
+ final BigDecimal fixedPriceAmount = BigDecimal.TEN;
+ final MockInternationalPrice fixedPrice = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount, Currency.USD));
+ final PlanPhase phase = new MockPlanPhase(null, fixedPrice, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final UUID invoiceId = UUID.randomUUID();
+ final InvoiceItem prevInvoiceItem = new FixedPriceInvoiceItem(invoiceId, account.getId(), subscription.getBundleId(), subscription.getId(), plan.getName(),
+ phase.getName(), invoiceItemDate, fixedPriceAmount, Currency.USD);
+
+ final BillingEvent event = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-02-01"),
+ plan, phase,
+ fixedPriceAmount, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 1L,
+ SubscriptionBaseTransitionType.CREATE);
+
+ assertFalse(fixedAndRecurringInvoiceItemGenerator.isSameDayAndSameSubscription(prevInvoiceItem, event, dateAndTimeZoneContext));
+ }
+
+ @Test(groups = "fast")
+ public void testIsSameDayAndSameSubscriptionWithSameDateAndSubscriptionId() {
+
+ final Plan plan = new MockPlan("my-plan");
+
+ final LocalDate invoiceItemDate = new LocalDate("2016-01-08");
+ final BigDecimal fixedPriceAmount = BigDecimal.TEN;
+ final MockInternationalPrice fixedPrice = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount, Currency.USD));
+ final PlanPhase phase = new MockPlanPhase(null, fixedPrice, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final UUID invoiceId = UUID.randomUUID();
+ final InvoiceItem prevInvoiceItem = new FixedPriceInvoiceItem(invoiceId, account.getId(), subscription.getBundleId(), subscription.getId(), plan.getName(),
+ phase.getName(), invoiceItemDate, fixedPriceAmount, Currency.USD);
+
+ final BillingEvent event = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan, phase,
+ fixedPriceAmount, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 1L,
+ SubscriptionBaseTransitionType.CREATE);
+
+ assertTrue(fixedAndRecurringInvoiceItemGenerator.isSameDayAndSameSubscription(prevInvoiceItem, event, dateAndTimeZoneContext));
+ }
+
+ @Test(groups = "fast")
+ public void testProcessFixedBillingEventsWithCancellationOnSameDay() {
+
+ final LocalDate targetDate = new LocalDate("2016-01-08");
+
+ final UUID invoiceId = UUID.randomUUID();
+ final BillingEventSet events = new MockBillingEventSet();
+
+ final BigDecimal fixedPriceAmount = BigDecimal.TEN;
+ final MockInternationalPrice fixedPrice = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount, Currency.USD));
+ final Plan plan = new MockPlan("my-plan");
+ final PlanPhase phase = new MockPlanPhase(null, fixedPrice, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final BillingEvent event1 = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan, phase,
+ fixedPriceAmount, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 1L,
+ SubscriptionBaseTransitionType.CREATE);
+ events.add(event1);
+
+
+ final BillingEvent event2 = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan, phase,
+ null, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 2L,
+ SubscriptionBaseTransitionType.CANCEL);
+ events.add(event2);
+
+ final List<InvoiceItem> proposedItems = new ArrayList<InvoiceItem>();
+ fixedAndRecurringInvoiceItemGenerator.processFixedBillingEvents(invoiceId, account.getId(), events, targetDate, Currency.USD, proposedItems);
+ assertTrue(proposedItems.isEmpty());
+ }
+
+ @Test(groups = "fast")
+ public void testProcessFixedBillingEventsWithCancellationOnNextDay() {
+
+ final LocalDate targetDate = new LocalDate("2016-01-08");
+
+ final UUID invoiceId = UUID.randomUUID();
+ final BillingEventSet events = new MockBillingEventSet();
+
+ final BigDecimal fixedPriceAmount = BigDecimal.TEN;
+ final MockInternationalPrice fixedPrice = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount, Currency.USD));
+ final Plan plan = new MockPlan("my-plan");
+ final PlanPhase phase = new MockPlanPhase(null, fixedPrice, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final BillingEvent event1 = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan, phase,
+ fixedPriceAmount, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 1L,
+ SubscriptionBaseTransitionType.CREATE);
+ events.add(event1);
+
+
+ final BillingEvent event2 = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-09"),
+ plan, phase,
+ null, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 2L,
+ SubscriptionBaseTransitionType.CANCEL);
+ events.add(event2);
+
+ final List<InvoiceItem> proposedItems = new ArrayList<InvoiceItem>();
+ fixedAndRecurringInvoiceItemGenerator.processFixedBillingEvents(invoiceId, account.getId(), events, targetDate, Currency.USD, proposedItems);
+ assertEquals(proposedItems.size(), 1);
+ assertEquals(proposedItems.get(0).getInvoiceItemType(), InvoiceItemType.FIXED);
+ assertEquals(proposedItems.get(0).getAmount(), fixedPriceAmount);
+ }
+
+
+ @Test(groups = "fast")
+ public void testProcessFixedBillingEventsWithMultipleChangeOnSameDay() {
+
+ final LocalDate targetDate = new LocalDate("2016-01-08");
+
+ final UUID invoiceId = UUID.randomUUID();
+ final BillingEventSet events = new MockBillingEventSet();
+
+ final BigDecimal fixedPriceAmount1 = BigDecimal.TEN;
+ final MockInternationalPrice fixedPrice1 = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount1, Currency.USD));
+ final Plan plan1 = new MockPlan("my-plan1");
+ final PlanPhase planPhase1 = new MockPlanPhase(null, fixedPrice1, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final BillingEvent event1 = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan1, planPhase1,
+ fixedPriceAmount1, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 1L,
+ SubscriptionBaseTransitionType.CREATE);
+ events.add(event1);
+
+
+
+ final BigDecimal fixedPriceAmount2 = null;
+ final MockInternationalPrice fixedPrice2 = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount2, Currency.USD));
+ final Plan plan2 = new MockPlan("my-plan2");
+ final PlanPhase planPhase2 = new MockPlanPhase(null, fixedPrice2, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final BillingEvent event2 = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan2, planPhase2,
+ fixedPriceAmount2, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 2L,
+ SubscriptionBaseTransitionType.CHANGE);
+ events.add(event2);
+
+
+ final BigDecimal fixedPriceAmount3 = BigDecimal.ONE;
+ final MockInternationalPrice fixedPrice3 = new MockInternationalPrice(new DefaultPrice(fixedPriceAmount3, Currency.USD));
+ final Plan plan3 = new MockPlan("my-plan3");
+ final PlanPhase planPhase3 = new MockPlanPhase(null, fixedPrice3, BillingPeriod.NO_BILLING_PERIOD, PhaseType.TRIAL);
+
+ final BillingEvent event3 = invoiceUtil.createMockBillingEvent(account, subscription, new DateTime("2016-01-08"),
+ plan3, planPhase3,
+ fixedPriceAmount3, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1,
+ BillingMode.IN_ADVANCE, "Billing Event Desc", 3L,
+ SubscriptionBaseTransitionType.CHANGE);
+ events.add(event3);
+
+ final List<InvoiceItem> proposedItems = new ArrayList<InvoiceItem>();
+ fixedAndRecurringInvoiceItemGenerator.processFixedBillingEvents(invoiceId, account.getId(), events, targetDate, Currency.USD, proposedItems);
+ assertEquals(proposedItems.size(), 1);
+ assertEquals(proposedItems.get(0).getInvoiceItemType(), InvoiceItemType.FIXED);
+ assertEquals(proposedItems.get(0).getAmount(), fixedPriceAmount3);
+ }
+
+}
\ No newline at end of file
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/glue/TestInvoiceModuleNoDB.java b/invoice/src/test/java/org/killbill/billing/invoice/glue/TestInvoiceModuleNoDB.java
index 10c58c2..a2f5751 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/glue/TestInvoiceModuleNoDB.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/glue/TestInvoiceModuleNoDB.java
@@ -34,6 +34,7 @@ import org.killbill.billing.currency.api.CurrencyConversionException;
import org.killbill.billing.currency.api.Rate;
import org.killbill.billing.invoice.dao.InvoiceDao;
import org.killbill.billing.invoice.dao.MockInvoiceDao;
+import org.killbill.billing.mock.api.MockAccountUserApi;
import org.killbill.billing.mock.glue.MockNonEntityDaoModule;
import org.killbill.billing.platform.api.KillbillConfigSource;
import org.mockito.Mockito;
@@ -55,7 +56,7 @@ public class TestInvoiceModuleNoDB extends TestInvoiceModule {
install(new MockNonEntityDaoModule(configSource));
bind(AccountInternalApi.class).toInstance(Mockito.mock(AccountInternalApi.class));
- bind(AccountUserApi.class).toInstance(Mockito.mock(AccountUserApi.class));
+ bind(AccountUserApi.class).to(MockAccountUserApi.class);
installCurrencyConversionApi();
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
index c360655..4e2d5f6 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
@@ -224,8 +224,10 @@ public class TestInvoiceHelper {
public SubscriptionBase createSubscription() throws SubscriptionBaseApiException {
final UUID uuid = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
final SubscriptionBase subscription = Mockito.mock(SubscriptionBase.class);
Mockito.when(subscription.getId()).thenReturn(uuid);
+ Mockito.when(subscription.getBundleId()).thenReturn(bundleId);
Mockito.when(subscriptionApi.getSubscriptionFromId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscription);
return subscription;
}
@@ -329,7 +331,6 @@ public class TestInvoiceHelper {
final Account mockAccount = Mockito.mock(Account.class);
Mockito.when(mockAccount.getTimeZone()).thenReturn(DateTimeZone.UTC);
- final Account accountOrMockAcount = account != null ? account : mockAccount;
return new BillingEvent() {
@Override
public int getBillCycleDayLocal() {