use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestIntegrationParentInvoice method testParentInvoiceItemAdjustmentPaidInvoice.
// Scenario 2: Follow up Invoice Item Adjustment on PAID invoice
@Test(groups = "slow")
public void testParentInvoiceItemAdjustmentPaidInvoice() throws Exception {
final int billingDay = 14;
final DateTime initialCreationDate = new DateTime(2014, 5, 15, 0, 0, 0, 0, testTimeZone);
// set clock to the initial start date
clock.setTime(initialCreationDate);
final Account parentAccount = createAccountWithNonOsgiPaymentMethod(getAccountData(billingDay));
final Account childAccount = createAccountWithNonOsgiPaymentMethod(getChildAccountData(billingDay, parentAccount.getId(), true));
// CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
createBaseEntitlementAndCheckForCompletion(childAccount.getId(), "bundleKey1", "Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
// ---- trial period ----
// Moving a day the NotificationQ calls the commitInvoice. No payment is expected because balance is 0
busHandler.pushExpectedEvents(NextEvent.INVOICE);
clock.addDays(1);
assertListenerStatus();
// ---- recurring period ----
// Move through time and verify new parent Invoice. No payments are expected.
busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE);
clock.addDays(29);
assertListenerStatus();
// move one day to have parent invoice paid
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addDays(1);
assertListenerStatus();
final List<Invoice> parentInvoices = invoiceUserApi.getInvoicesByAccount(parentAccount.getId(), false, callContext);
final List<Invoice> childInvoices = invoiceUserApi.getInvoicesByAccount(childAccount.getId(), false, callContext);
// get last child invoice
Invoice childInvoice = childInvoices.get(1);
assertEquals(childInvoice.getNumberOfItems(), 1);
// Second Parent invoice over Recurring period
assertEquals(parentInvoices.size(), 2);
Invoice parentInvoice = parentInvoices.get(1);
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.COMMITTED);
assertTrue(parentInvoice.isParentInvoice());
assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
assertEquals(parentInvoice.getChargedAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
// issue a $10 adj in a paid invoice
busHandler.pushExpectedEvents(NextEvent.INVOICE_ADJUSTMENT);
invoiceUserApi.insertInvoiceItemAdjustment(childAccount.getId(), childInvoice.getId(), childInvoice.getInvoiceItems().get(0).getId(), clock.getToday(childAccount.getTimeZone()), BigDecimal.TEN, childAccount.getCurrency(), "test adjustment", callContext);
assertListenerStatus();
// expected child invoice
// RECURRING : $ 249.95
// ITEM_ADJ : $ -10
// CBA_ADJ : $ +10
childInvoice = invoiceUserApi.getInvoice(childInvoice.getId(), callContext);
assertEquals(childInvoice.getNumberOfItems(), 3);
assertEquals(childInvoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(childInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
assertEquals(childInvoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.ITEM_ADJ);
assertEquals(childInvoice.getInvoiceItems().get(1).getAmount().compareTo(BigDecimal.valueOf(-10)), 0);
assertEquals(childInvoice.getInvoiceItems().get(2).getInvoiceItemType(), InvoiceItemType.CBA_ADJ);
assertEquals(childInvoice.getInvoiceItems().get(2).getAmount().compareTo(BigDecimal.valueOf(10)), 0);
// check parent invoices
parentInvoice = invoiceUserApi.getInvoice(parentInvoice.getId(), callContext);
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getPaidAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
assertEquals(parentInvoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.PARENT_SUMMARY);
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestCatalogRetireElements method testRetirePriceList.
@Test(groups = "slow")
public void testRetirePriceList() throws Exception {
// Catalog v1 starts in 2011-01-01
// Catalog v2 starts in 2015-12-01
// Catalog v3 starts in 2016-01-01
final LocalDate today = new LocalDate(2015, 11, 1);
// Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
clock.setDay(today);
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
//accountUserApi.createAccount(getAccountData(1), callContext);
final String productName = "Pistol";
final BillingPeriod term = BillingPeriod.MONTHLY;
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, term, "SpecialDiscount", null);
busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
final Entitlement bpEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, "externalKey", null, null, null, false, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertNotNull(bpEntitlement);
assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext).size(), 1);
// Move out a month.
busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addMonths(1);
assertListenerStatus();
// Move out a month.
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addMonths(1);
assertListenerStatus();
try {
entitlementApi.createBaseEntitlement(account.getId(), spec, "externalKey2", null, null, null, false, ImmutableList.<PluginProperty>of(), callContext);
// force to fail is there is not an exception
fail();
} catch (final EntitlementApiException e) {
assertTrue(e.getLocalizedMessage().startsWith("Could not find any product named 'Pistol'"));
}
// Move out a month and verify 'Pistol' plan continue working as expected.
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addMonths(1);
assertListenerStatus();
// Move out a month.
busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.NULL_INVOICE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addMonths(1);
assertListenerStatus();
final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext);
assertEquals(invoices.size(), 5);
assertTrue(invoices.get(0).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-trial"));
assertTrue(invoices.get(1).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-discount"));
assertTrue(invoices.get(2).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-discount"));
assertTrue(invoices.get(3).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-discount"));
assertTrue(invoices.get(4).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-evergreen"));
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestIntegrationWithCatalogUpdate method testWithPriceOverride.
@Test(groups = "slow")
public void testWithPriceOverride() throws Exception {
// Create a per-tenant catalog with one plan
final SimplePlanDescriptor desc1 = new DefaultSimplePlanDescriptor("bar-monthly", "Bar", ProductCategory.BASE, account.getCurrency(), BigDecimal.TEN, BillingPeriod.MONTHLY, 0, TimeUnit.UNLIMITED, ImmutableList.<String>of());
catalogUserApi.addSimplePlan(desc1, init, testCallContext);
StaticCatalog catalog = catalogUserApi.getCurrentCatalog("dummy", testCallContext);
assertEquals(catalog.getCurrentPlans().size(), 1);
final Plan plan = catalog.getCurrentPlans().iterator().next();
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("bar-monthly", null);
final List<PlanPhasePriceOverride> overrides = new ArrayList<PlanPhasePriceOverride>();
overrides.add(new DefaultPlanPhasePriceOverride(plan.getFinalPhase().getName(), account.getCurrency(), null, BigDecimal.ONE));
final Entitlement baseEntitlement = createEntitlement(spec, overrides, true);
List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, testCallContext);
assertEquals(invoices.size(), 1);
assertEquals(invoices.get(0).getChargedAmount().compareTo(BigDecimal.ONE), 0);
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
clock.addMonths(1);
assertListenerStatus();
invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, testCallContext);
assertEquals(invoices.size(), 2);
assertEquals(invoices.get(1).getChargedAmount().compareTo(BigDecimal.ONE), 0);
// Change plan to original (non overridden plan)
busHandler.pushExpectedEvents(NextEvent.CHANGE, NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
baseEntitlement.changePlan(spec, null, ImmutableList.<PluginProperty>of(), testCallContext);
assertListenerStatus();
invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, testCallContext);
assertEquals(invoices.size(), 3);
// 10 (recurring) - 1 (repair)
assertEquals(invoices.get(2).getChargedAmount().compareTo(new BigDecimal("9.00")), 0);
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestIntegrationParentInvoice method testParentInvoiceGeneration.
@Test(groups = "slow")
public void testParentInvoiceGeneration() throws Exception {
final int billingDay = 14;
final DateTime initialCreationDate = new DateTime(2015, 5, 15, 0, 0, 0, 0, testTimeZone);
// set clock to the initial start date
clock.setTime(initialCreationDate);
log.info("Beginning test with BCD of " + billingDay);
final Account parentAccount = createAccountWithNonOsgiPaymentMethod(getAccountData(billingDay));
final Account child1Account = createAccountWithNonOsgiPaymentMethod(getChildAccountData(billingDay, parentAccount.getId(), true));
final Account child2Account = createAccountWithNonOsgiPaymentMethod(getChildAccountData(billingDay, parentAccount.getId(), true));
// CREATE SUBSCRIPTIONS AND EXPECT BOTH EVENTS EACH: NextEvent.CREATE NextEvent.INVOICE
createBaseEntitlementAndCheckForCompletion(child1Account.getId(), "bundleKey1", "Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
createBaseEntitlementAndCheckForCompletion(child2Account.getId(), "bundleKey2", "Pistol", ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
// First Parent invoice over TRIAL period
List<Invoice> parentInvoices = invoiceUserApi.getInvoicesByAccount(parentAccount.getId(), false, callContext);
assertEquals(parentInvoices.size(), 1);
Invoice parentInvoice = parentInvoices.get(0);
assertEquals(parentInvoice.getNumberOfItems(), 2);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
// Moving a day the NotificationQ calls the commitInvoice. No payment is expected
busHandler.pushExpectedEvents(NextEvent.INVOICE);
clock.addDays(1);
assertListenerStatus();
// reload parent invoice
parentInvoice = invoiceUserApi.getInvoice(parentInvoice.getId(), callContext);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.COMMITTED);
// Move through time and verify new parent Invoice. No payments are expected yet.
busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.PHASE, NextEvent.INVOICE, NextEvent.INVOICE);
clock.addDays(29);
assertListenerStatus();
// Second Parent invoice over Recurring period
parentInvoices = invoiceUserApi.getInvoicesByAccount(parentAccount.getId(), false, callContext);
assertEquals(parentInvoices.size(), 2);
parentInvoice = parentInvoices.get(1);
assertEquals(parentInvoice.getNumberOfItems(), 2);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
// balance is 0 because parent invoice status is DRAFT
assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
// total 279.95
assertEquals(parentInvoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.PARENT_SUMMARY);
assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
assertEquals(parentInvoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.PARENT_SUMMARY);
assertEquals(parentInvoice.getInvoiceItems().get(1).getAmount().compareTo(BigDecimal.valueOf(29.95)), 0);
// Check Child Balance. It should be > 0 here because Parent invoice is unpaid yet.
List<Invoice> child1Invoices = invoiceUserApi.getInvoicesByAccount(child1Account.getId(), false, callContext);
assertEquals(child1Invoices.size(), 2);
// child balance is 0 because parent invoice status is DRAFT at this point
assertEquals(child1Invoices.get(1).getBalance().compareTo(BigDecimal.ZERO), 0);
// Moving a day the NotificationQ calls the commitInvoice. Payment is expected.
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
clock.addDays(1);
assertListenerStatus();
parentInvoice = invoiceUserApi.getInvoice(parentInvoice.getId(), callContext);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.COMMITTED);
// Check Child Balance. It should be = 0 because parent invoice had already paid.
child1Invoices = invoiceUserApi.getInvoicesByAccount(child1Account.getId(), false, callContext);
assertEquals(child1Invoices.size(), 2);
assertTrue(parentInvoice.getBalance().compareTo(BigDecimal.ZERO) == 0);
assertTrue(child1Invoices.get(1).getBalance().compareTo(BigDecimal.ZERO) == 0);
// load children invoice items
final List<InvoiceItem> childrenInvoiceItems = invoiceUserApi.getInvoiceItemsByParentInvoice(parentInvoice.getId(), callContext);
assertEquals(childrenInvoiceItems.size(), 2);
assertEquals(childrenInvoiceItems.get(0).getAccountId(), child1Account.getId());
assertEquals(childrenInvoiceItems.get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
assertEquals(childrenInvoiceItems.get(1).getAccountId(), child2Account.getId());
assertEquals(childrenInvoiceItems.get(1).getAmount().compareTo(BigDecimal.valueOf(29.95)), 0);
// loading children items from non parent account should return empty list
assertEquals(invoiceUserApi.getInvoiceItemsByParentInvoice(child1Invoices.get(1).getId(), callContext).size(), 0);
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class UsageInvoiceItemGenerator method extractPerSubscriptionExistingInArrearUsageItems.
private Map<UUID, List<InvoiceItem>> extractPerSubscriptionExistingInArrearUsageItems(final Map<String, Usage> knownUsage, @Nullable final List<Invoice> existingInvoices) {
if (existingInvoices == null || existingInvoices.isEmpty()) {
return ImmutableMap.of();
}
final Map<UUID, List<InvoiceItem>> result = new HashMap<UUID, List<InvoiceItem>>();
final Iterable<InvoiceItem> usageInArrearItems = Iterables.concat(Iterables.transform(existingInvoices, new Function<Invoice, Iterable<InvoiceItem>>() {
@Override
public Iterable<InvoiceItem> apply(final Invoice input) {
return Iterables.filter(input.getInvoiceItems(), new Predicate<InvoiceItem>() {
@Override
public boolean apply(final InvoiceItem input) {
if (input.getInvoiceItemType() == InvoiceItemType.USAGE) {
final Usage usage = knownUsage.get(input.getUsageName());
return usage.getBillingMode() == BillingMode.IN_ARREAR;
}
return false;
}
});
}
}));
for (final InvoiceItem cur : usageInArrearItems) {
List<InvoiceItem> perSubscriptionUsageItems = result.get(cur.getSubscriptionId());
if (perSubscriptionUsageItems == null) {
perSubscriptionUsageItems = new LinkedList<InvoiceItem>();
result.put(cur.getSubscriptionId(), perSubscriptionUsageItems);
}
perSubscriptionUsageItems.add(cur);
}
return result;
}
Aggregations