use of org.killbill.billing.invoice.dao.InvoiceItemModelDao in project killbill by killbill.
the class TestWithoutZeroUsageItems method testConsumableInArrearWithExtraZeroItems.
@Test(groups = "slow")
public void testConsumableInArrearWithExtraZeroItems() throws Exception {
// We take april as it has 30 days (easier to play with BCD)
// Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
clock.setDay(new LocalDate(2012, 4, 1));
final AccountData accountData = getAccountData(1);
final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
accountChecker.checkAccount(account.getId(), accountData, callContext);
//
// CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE, NextEvent.BLOCK NextEvent.INVOICE
//
final DefaultEntitlement bpSubscription = createBaseEntitlementAndCheckForCompletion(account.getId(), "bundleKey", "Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
// Check bundle after BP got created otherwise we get an error from auditApi.
subscriptionChecker.checkSubscriptionCreated(bpSubscription.getId(), internalCallContext);
invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 4, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
//
// ADD ADD_ON ON THE SAME DAY
//
final DefaultEntitlement aoSubscription = addAOEntitlementAndCheckForCompletion(bpSubscription.getBundleId(), "Bullets", ProductCategory.ADD_ON, BillingPeriod.NO_BILLING_PERIOD, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.NULL_INVOICE);
recordUsageData(aoSubscription.getId(), "tracking-1", "bullets", new LocalDate(2012, 4, 1), 99L, callContext);
recordUsageData(aoSubscription.getId(), "tracking-2", "bullets", new LocalDate(2012, 4, 15), 100L, callContext);
busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.NULL_INVOICE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addDays(30);
assertListenerStatus();
Invoice curInvoice = invoiceChecker.checkInvoice(account.getId(), 2, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2013, 5, 1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")), new ExpectedInvoiceItemCheck(new LocalDate(2012, 4, 1), new LocalDate(2012, 5, 1), InvoiceItemType.USAGE, new BigDecimal("5.90")));
invoiceChecker.checkTrackingIds(curInvoice, ImmutableSet.of("tracking-1", "tracking-2"), internalCallContext);
// No $0 invoice
busHandler.pushExpectedEvents(NextEvent.NULL_INVOICE);
clock.addMonths(1);
assertListenerStatus();
// Insert Manually $0 USAGE items for the period 2012-5-1 -> 2012-6-1 to check this does not cause any issues
final DateTime catalogEffectiveDate = curInvoice.getInvoiceItems().get(0).getCatalogEffectiveDate();
final InvoiceModelDao invoiceForPreviousBehavior = new InvoiceModelDao(UUID.randomUUID(), clock.getUTCNow(), account.getId(), null, new LocalDate(2012, 5, 1), new LocalDate(2012, 5, 1), Currency.USD, false, InvoiceStatus.COMMITTED, false);
invoiceForPreviousBehavior.addInvoiceItem(new InvoiceItemModelDao(UUID.randomUUID(), clock.getUTCNow(), InvoiceItemType.USAGE, invoiceForPreviousBehavior.getId(), account.getId(), null, aoSubscription.getBundleId(), aoSubscription.getId(), "", "Bullets", "bullets-usage-in-arrear", "bullets-usage-in-arrear-evergreen", "bullets-usage-in-arrear-usage", catalogEffectiveDate, new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), BigDecimal.ZERO, BigDecimal.ZERO, Currency.USD, null, 0, "{\"tier\":1,\"tierUnit\":\"bullets\",\"tierPrice\":2.95,\"tierBlockSize\":100,\"quantity\":0,\"amount\":5.90}"));
busHandler.pushExpectedEvents(NextEvent.INVOICE);
insertInvoiceItems(invoiceForPreviousBehavior);
assertListenerStatus();
recordUsageData(aoSubscription.getId(), "tracking-3", "bullets", new LocalDate(2012, 6, 1), 50L, callContext);
recordUsageData(aoSubscription.getId(), "tracking-4", "bullets", new LocalDate(2012, 6, 16), 300L, callContext);
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addMonths(1);
assertListenerStatus();
curInvoice = invoiceChecker.checkInvoice(account.getId(), 4, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 1), new LocalDate(2012, 7, 1), InvoiceItemType.USAGE, new BigDecimal("11.80")));
invoiceChecker.checkTrackingIds(curInvoice, ImmutableSet.of("tracking-3", "tracking-4"), internalCallContext);
// Should be ignored because this is outside of optimization range (org.killbill.invoice.readMaxRawUsagePreviousPeriod = 2) => we will only look for items > 2012-7-1 - 2 months = 2012-5-1
recordUsageData(aoSubscription.getId(), "tracking-5", "bullets", new LocalDate(2012, 4, 30), 100L, callContext);
// Should be invoiced from past period
recordUsageData(aoSubscription.getId(), "tracking-6", "bullets", new LocalDate(2012, 5, 1), 199L, callContext);
// New usage for this past period
recordUsageData(aoSubscription.getId(), "tracking-7", "bullets", new LocalDate(2012, 7, 1), 50L, callContext);
recordUsageData(aoSubscription.getId(), "tracking-8", "bullets", new LocalDate(2012, 7, 16), 300L, callContext);
// Remove old data, should be ignored by the system because readMaxRawUsagePreviousPeriod = 2, so:
// * Last endDate invoiced is 2012-7-1 => Anything 2 period prior that will be ignored => Anything prior 2012-5-1 should be ignored
removeUsageData(aoSubscription.getId(), "bullets", new LocalDate(2012, 4, 15));
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addMonths(1);
assertListenerStatus();
curInvoice = invoiceChecker.checkInvoice(account.getId(), 5, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.USAGE, new BigDecimal("5.90")), new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 1), new LocalDate(2012, 8, 1), InvoiceItemType.USAGE, new BigDecimal("11.80")));
invoiceChecker.checkTrackingIds(curInvoice, ImmutableSet.of("tracking-6", "tracking-7", "tracking-8"), internalCallContext);
}
use of org.killbill.billing.invoice.dao.InvoiceItemModelDao in project killbill by killbill.
the class TestInvoiceDispatcher method testWithParking.
@Test(groups = "slow")
public void testWithParking() throws InvoiceApiException, AccountApiException, CatalogApiException, SubscriptionBaseApiException, TagDefinitionApiException {
final UUID accountId = account.getId();
final BillingEventSet events = new MockBillingEventSet();
final Plan plan = MockPlan.createBicycleNoTrialEvergreen1USD();
final PlanPhase planPhase = MockPlanPhase.create1USDMonthlyEvergreen();
final DateTime effectiveDate = clock.getUTCNow().minusDays(1);
final Currency currency = Currency.USD;
final BigDecimal fixedPrice = null;
events.add(invoiceUtil.createMockBillingEvent(account, subscription, effectiveDate, plan, planPhase, fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1, BillingMode.IN_ADVANCE, "", 1L, SubscriptionBaseTransitionType.CREATE));
Mockito.when(billingApi.getBillingEventsForAccountAndUpdateAccountBCD(Mockito.<UUID>any(), Mockito.<DryRunArguments>any(), Mockito.<LocalDate>any(), Mockito.<InternalCallContext>any())).thenReturn(events);
final LocalDate target = internalCallContext.toLocalDate(effectiveDate);
final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, subscriptionApi, invoiceDao, internalCallContextFactory, invoicePluginDispatcher, locker, bus, notificationQueueService, invoiceConfig, clock, invoiceOptimizer, parkedAccountsManager);
// Verify initial tags state for account
Assert.assertTrue(tagUserApi.getTagsForAccount(accountId, true, callContext).isEmpty());
// Create chaos on disk
final InvoiceModelDao invoiceModelDao = new InvoiceModelDao(accountId, target, target, currency, false);
final InvoiceItemModelDao invoiceItemModelDao1 = new InvoiceItemModelDao(clock.getUTCNow(), InvoiceItemType.RECURRING, invoiceModelDao.getId(), accountId, subscription.getBundleId(), subscription.getId(), "Bad data", null, plan.getName(), planPhase.getName(), null, null, effectiveDate.toLocalDate(), effectiveDate.plusMonths(1).toLocalDate(), BigDecimal.TEN, BigDecimal.ONE, currency, null);
final InvoiceItemModelDao invoiceItemModelDao2 = new InvoiceItemModelDao(clock.getUTCNow(), InvoiceItemType.RECURRING, invoiceModelDao.getId(), accountId, subscription.getBundleId(), subscription.getId(), "Bad data", null, plan.getName(), planPhase.getName(), null, null, effectiveDate.plusDays(1).toLocalDate(), effectiveDate.plusMonths(1).toLocalDate(), BigDecimal.TEN, BigDecimal.ONE, currency, null);
invoiceModelDao.addInvoiceItem(invoiceItemModelDao1);
invoiceModelDao.addInvoiceItem(invoiceItemModelDao2);
invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceModelDao), events, ImmutableSet.of(), context);
try {
dispatcher.processAccountFromNotificationOrBusEvent(accountId, target, new DryRunFutureDateArguments(), false, context);
Assert.fail();
} catch (final InvoiceApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
Assert.assertTrue(e.getCause().getMessage().startsWith("Double billing detected"));
}
// Dry-run: no side effect on disk
Assert.assertEquals(invoiceDao.getInvoicesByAccount(false, context).size(), 1);
Assert.assertTrue(tagUserApi.getTagsForAccount(accountId, true, callContext).isEmpty());
try {
dispatcher.processAccountFromNotificationOrBusEvent(accountId, target, null, false, context);
Assert.fail();
} catch (final InvoiceApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
Assert.assertTrue(e.getCause().getMessage().startsWith("Double billing detected"));
}
Assert.assertEquals(invoiceDao.getInvoicesByAccount(false, context).size(), 1);
// No dry-run: account is parked
final List<Tag> tags = tagUserApi.getTagsForAccount(accountId, false, callContext);
Assert.assertEquals(tags.size(), 1);
Assert.assertEquals(tags.get(0).getTagDefinitionId(), SystemTags.PARK_TAG_DEFINITION_ID);
// isApiCall=false
final Invoice nullInvoice1 = dispatcher.processAccountFromNotificationOrBusEvent(accountId, target, null, false, context);
Assert.assertNull(nullInvoice1);
// No dry-run and isApiCall=true
try {
dispatcher.processAccount(true, accountId, target, null, false, context);
Assert.fail();
} catch (final InvoiceApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
Assert.assertTrue(e.getCause().getMessage().startsWith("Double billing detected"));
}
// Idempotency
Assert.assertEquals(invoiceDao.getInvoicesByAccount(false, context).size(), 1);
Assert.assertEquals(tagUserApi.getTagsForAccount(accountId, false, callContext), tags);
// Fix state
dbi.withHandle(new HandleCallback<Void>() {
@Override
public Void withHandle(final Handle handle) throws Exception {
handle.execute("delete from invoices");
handle.execute("delete from invoice_items");
return null;
}
});
// Dry-run and isApiCall=false: still parked
final Invoice nullInvoice2 = dispatcher.processAccountFromNotificationOrBusEvent(accountId, target, new DryRunFutureDateArguments(), false, context);
Assert.assertNull(nullInvoice2);
// Dry-run and isApiCall=true: call goes through
final Invoice invoice1 = dispatcher.processAccount(true, accountId, target, new DryRunFutureDateArguments(), false, context);
Assert.assertNotNull(invoice1);
Assert.assertEquals(invoiceDao.getInvoicesByAccount(false, context).size(), 0);
// Dry-run: still parked
Assert.assertEquals(tagUserApi.getTagsForAccount(accountId, false, callContext).size(), 1);
// No dry-run and isApiCall=true: call goes through
final Invoice invoice2 = dispatcher.processAccount(true, accountId, target, null, false, context);
Assert.assertNotNull(invoice2);
Assert.assertEquals(invoiceDao.getInvoicesByAccount(false, context).size(), 1);
// No dry-run: now unparked
Assert.assertEquals(tagUserApi.getTagsForAccount(accountId, false, callContext).size(), 0);
Assert.assertEquals(tagUserApi.getTagsForAccount(accountId, true, callContext).size(), 1);
}
use of org.killbill.billing.invoice.dao.InvoiceItemModelDao in project killbill by killbill.
the class TestWithBCDUpdate method testBCDUpgradeMigrationPath_0_20_to_0_22.
@Test(groups = "slow")
public void testBCDUpgradeMigrationPath_0_20_to_0_22() throws Exception {
// Change to false to verify new behavior
final boolean checkMigrationFrom_0_20_to_0_22 = true;
final DateTime initialDate = new DateTime(2018, 6, 21, 0, 13, 42, 0, testTimeZone);
clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(21));
assertNotNull(account);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("pistol-monthly-notrial");
busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
// We will realign the BCD on the 15 as we create the subscription - ignoring the account setting on 21.
final UUID entitlementId = entitlementApi.createBaseEntitlement(account.getId(), new DefaultEntitlementSpecifier(spec, null, null, null), null, null, null, false, false, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final Invoice firstInvoice = invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2018, 6, 21), new LocalDate(2018, 7, 21), InvoiceItemType.RECURRING, new BigDecimal("19.95")));
// Set BCD to be the 1
subscriptionBaseInternalApi.updateBCD(entitlementId, 1, new LocalDate(2018, 7, 1), internalCallContext);
if (checkMigrationFrom_0_20_to_0_22) {
final InvoiceModelDao invoiceForRepair_0_20 = new InvoiceModelDao(UUID.randomUUID(), clock.getUTCNow(), account.getId(), null, clock.getUTCToday(), clock.getUTCToday(), Currency.USD, false, InvoiceStatus.COMMITTED, false);
final UUID originalRecuringItemId = firstInvoice.getInvoiceItems().get(0).getId();
final InvoiceItemModelDao repair = new InvoiceItemModelDao(invoiceForRepair_0_20.getCreatedDate(), InvoiceItemType.REPAIR_ADJ, invoiceForRepair_0_20.getId(), account.getId(), UUID.randomUUID(), entitlementId, null, null, null, null, null, null, new LocalDate(2018, 7, 1), new LocalDate(2018, 7, 21), new BigDecimal("-13.30"), new BigDecimal("-13.30"), account.getCurrency(), originalRecuringItemId);
final InvoiceItemModelDao recurring = new InvoiceItemModelDao(invoiceForRepair_0_20.getCreatedDate(), InvoiceItemType.RECURRING, invoiceForRepair_0_20.getId(), account.getId(), UUID.randomUUID(), entitlementId, "", "Pistol", "pistol-monthly-notrial", "pistol-monthly-notrial-evergreen", null, null, new LocalDate(2018, 7, 1), new LocalDate(2018, 8, 1), new BigDecimal("19.95"), new BigDecimal("19.95"), account.getCurrency(), null);
invoiceForRepair_0_20.addInvoiceItem(repair);
invoiceForRepair_0_20.addInvoiceItem(recurring);
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
insertInvoiceItems(invoiceForRepair_0_20);
assertListenerStatus();
}
// With existing 0_20 data, nothing will be re-generated -> shows new behavior is compatible with old data
if (checkMigrationFrom_0_20_to_0_22) {
busHandler.pushExpectedEvents(NextEvent.BCD_CHANGE, NextEvent.NULL_INVOICE);
} else {
busHandler.pushExpectedEvents(NextEvent.BCD_CHANGE, NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
}
// Verify next month
// 2018-7-1
clock.addDays(10);
assertListenerStatus();
if (!checkMigrationFrom_0_20_to_0_22) {
invoiceChecker.checkInvoice(account.getId(), 2, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2018, 7, 21), new LocalDate(2018, 8, 1), InvoiceItemType.RECURRING, new BigDecimal("7.08")));
}
}
use of org.killbill.billing.invoice.dao.InvoiceItemModelDao in project killbill by killbill.
the class TestIntegrationInvoiceWithRepairLogic method testRegressionFor170.
// This is a beatrix level test matching our invoice TestDefaultInvoiceGenerator#testRegressionFor170
@Test(groups = "slow")
public void testRegressionFor170() throws Exception {
final DateTime initialDate = new DateTime(2013, 6, 15, 0, 0, 0, 0, testTimeZone);
final LocalDate startDate = initialDate.toLocalDate();
clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(15));
assertNotNull(account);
add_AUTO_PAY_OFF_Tag(account.getId(), ObjectType.ACCOUNT);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("pistol-monthly-notrial");
busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.CREATE, NextEvent.INVOICE);
final UUID entitlementId = entitlementApi.createBaseEntitlement(account.getId(), new DefaultEntitlementSpecifier(spec, null, null, null), null, startDate, startDate, false, false, ImmutableList.<PluginProperty>of(), callContext);
final Entitlement bpEntitlement = entitlementApi.getEntitlementForId(entitlementId, callContext);
assertListenerStatus();
final Invoice invoice = invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2013, 6, 15), new LocalDate(2013, 7, 15), InvoiceItemType.RECURRING, new BigDecimal("19.95")));
add_AUTO_INVOICING_OFF_Tag(account.getId(), ObjectType.ACCOUNT);
final UUID linkedItemId = invoice.getInvoiceItems().get(0).getId();
final InvoiceModelDao repairInvoice = new InvoiceModelDao(UUID.randomUUID(), clock.getUTCNow(), account.getId(), null, startDate, startDate, Currency.USD, false, InvoiceStatus.COMMITTED, false);
final InvoiceItemModelDao wrongRepair = new InvoiceItemModelDao(repairInvoice.getCreatedDate(), InvoiceItemType.REPAIR_ADJ, repairInvoice.getId(), repairInvoice.getAccountId(), bpEntitlement.getBundleId(), bpEntitlement.getBaseEntitlementId(), null, null, null, null, null, null, new LocalDate(2013, 6, 21), new LocalDate(2013, 6, 26), new BigDecimal("-3.33"), new BigDecimal("19.95"), account.getCurrency(), linkedItemId);
repairInvoice.addInvoiceItem(wrongRepair);
busHandler.pushExpectedEvents(NextEvent.INVOICE_ADJUSTMENT, NextEvent.INVOICE);
insertInvoiceItems(repairInvoice);
assertListenerStatus();
// Prior the change introduced in 6338109f8cdc7, this is what the code would have generated
final InvoiceModelDao prevBehaviorInvoice = new InvoiceModelDao(UUID.randomUUID(), clock.getUTCNow(), account.getId(), null, startDate, startDate, Currency.USD, false, InvoiceStatus.COMMITTED, false);
final InvoiceItemModelDao prevRecurring = new InvoiceItemModelDao(initialDate, InvoiceItemType.RECURRING, prevBehaviorInvoice.getId(), prevBehaviorInvoice.getAccountId(), bpEntitlement.getBundleId(), entitlementId, "", "Pistol", "pistol-monthly-notrial", "pistol-monthly-notrial-evergreen", null, null, new LocalDate(2013, 6, 15), new LocalDate(2013, 7, 15), new BigDecimal("19.85"), new BigDecimal("19.95"), account.getCurrency(), null);
final InvoiceItemModelDao prevRepair1 = new InvoiceItemModelDao(prevBehaviorInvoice.getCreatedDate(), InvoiceItemType.REPAIR_ADJ, prevBehaviorInvoice.getId(), prevBehaviorInvoice.getAccountId(), bpEntitlement.getBundleId(), bpEntitlement.getBaseEntitlementId(), null, null, null, null, null, null, new LocalDate(2013, 6, 15), new LocalDate(2013, 6, 21), new BigDecimal("-3.99"), new BigDecimal("19.95"), account.getCurrency(), linkedItemId);
final InvoiceItemModelDao prevRepair2 = new InvoiceItemModelDao(prevBehaviorInvoice.getCreatedDate(), InvoiceItemType.REPAIR_ADJ, prevBehaviorInvoice.getId(), prevBehaviorInvoice.getAccountId(), bpEntitlement.getBundleId(), bpEntitlement.getBaseEntitlementId(), null, null, null, null, null, null, new LocalDate(2013, 6, 26), new LocalDate(2013, 7, 15), new BigDecimal("-12.63"), new BigDecimal("19.95"), account.getCurrency(), linkedItemId);
prevBehaviorInvoice.addInvoiceItem(prevRecurring);
prevBehaviorInvoice.addInvoiceItem(prevRepair1);
prevBehaviorInvoice.addInvoiceItem(prevRepair2);
busHandler.pushExpectedEvents(NextEvent.INVOICE);
insertInvoiceItems(prevBehaviorInvoice);
assertListenerStatus();
// Nothing to generate - new behavior is compatible with older behavior
busHandler.pushExpectedEvents(NextEvent.NULL_INVOICE);
remove_AUTO_INVOICING_OFF_Tag(account.getId(), ObjectType.ACCOUNT);
assertListenerStatus();
checkNoMoreInvoiceToGenerate(account);
}
use of org.killbill.billing.invoice.dao.InvoiceItemModelDao in project killbill by killbill.
the class TestIntegrationWithDifferentBillingPeriods method testPauseResumeAnnualWithInvoicingOffMigrationPath_0_20_to_0_22.
@Test(groups = "slow")
public void testPauseResumeAnnualWithInvoicingOffMigrationPath_0_20_to_0_22() throws Exception {
// We take april as it has 30 days (easier to play with BCD)
final LocalDate today = new LocalDate(2012, 4, 1);
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
// Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
final String productName = "Shotgun";
//
// CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE, NextEvent.BLOCK NextEvent.INVOICE
//
final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, BillingPeriod.ANNUAL, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
assertNotNull(bpEntitlement);
assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext).size(), 1);
assertEquals(bpEntitlement.getSubscriptionBase().getCurrentPlan().getRecurringBillingPeriod(), BillingPeriod.ANNUAL);
// Move out of trials for interesting invoices adjustments
busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addDays(31);
assertListenerStatus();
// Auto invoice off
busHandler.pushExpectedEvents(NextEvent.TAG);
tagUserApi.addTag(account.getId(), ObjectType.ACCOUNT, ControlTagType.AUTO_INVOICING_OFF.getId(), callContext);
assertListenerStatus();
// 2012-5-12
clock.addDays(10);
busHandler.pushExpectedEvents(NextEvent.BLOCK);
entitlementApi.pause(bpEntitlement.getBundleId(), clock.getUTCNow().toLocalDate(), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// 2012-6-4
clock.addDays(23);
busHandler.pushExpectedEvents(NextEvent.BLOCK);
entitlementApi.resume(bpEntitlement.getBundleId(), clock.getUTCNow().toLocalDate(), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// /
List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext);
assertEquals(invoices.size(), 2);
final Invoice secondInvoice = invoices.get(1);
final UUID originalRecuringItemId = secondInvoice.getInvoiceItems().get(0).getId();
final InvoiceModelDao invoiceForRepair_0_20 = new InvoiceModelDao(UUID.randomUUID(), clock.getUTCNow(), account.getId(), null, clock.getUTCToday(), clock.getUTCToday(), Currency.USD, false, InvoiceStatus.COMMITTED, false);
final InvoiceItemModelDao repair = new InvoiceItemModelDao(invoiceForRepair_0_20.getCreatedDate(), InvoiceItemType.REPAIR_ADJ, invoiceForRepair_0_20.getId(), account.getId(), UUID.randomUUID(), bpEntitlement.getId(), null, null, null, null, null, null, new LocalDate(2012, 5, 12), new LocalDate(2013, 5, 1), new BigDecimal("-2327.62"), new BigDecimal("-2327.62"), account.getCurrency(), originalRecuringItemId);
final InvoiceItemModelDao recurring = new InvoiceItemModelDao(invoiceForRepair_0_20.getCreatedDate(), InvoiceItemType.RECURRING, invoiceForRepair_0_20.getId(), account.getId(), UUID.randomUUID(), bpEntitlement.getId(), "", "Shotgun", "shotgun-monthly", "shotgun-monthly-evergreen", null, null, new LocalDate(2012, 6, 4), new LocalDate(2013, 6, 1), new BigDecimal("2380.22"), new BigDecimal("2380.22"), account.getCurrency(), null);
invoiceForRepair_0_20.addInvoiceItem(repair);
invoiceForRepair_0_20.addInvoiceItem(recurring);
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
insertInvoiceItems(invoiceForRepair_0_20);
assertListenerStatus();
//
// We should not generate any invoice, instead, we generate a new invoice with 2 canceling items
//
// busHandler.pushExpectedEvents(NextEvent.TAG, NextEvent.NULL_INVOICE);
busHandler.pushExpectedEvents(NextEvent.TAG, NextEvent.INVOICE);
tagUserApi.removeTag(account.getId(), ObjectType.ACCOUNT, ControlTagType.AUTO_INVOICING_OFF.getId(), callContext);
assertListenerStatus();
invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext);
assertEquals(invoices.size(), 4);
ImmutableList<ExpectedInvoiceItemCheck> toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 4), new LocalDate(2013, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("2380.22")), // Cancels similar item previously added from 0_22
new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 4), new LocalDate(2013, 6, 1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-2380.22")));
invoiceChecker.checkInvoice(invoices.get(3).getId(), callContext, toBeChecked);
checkNoMoreInvoiceToGenerate(account);
}
Aggregations