Search in sources :

Example 96 with Invoice

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);
}
Also used : DefaultAccount(org.killbill.billing.account.api.DefaultAccount) Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) DateTime(org.joda.time.DateTime) Test(org.testng.annotations.Test)

Example 97 with Invoice

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"));
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) Entitlement(org.killbill.billing.entitlement.api.Entitlement) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) LocalDate(org.joda.time.LocalDate) Test(org.testng.annotations.Test)

Example 98 with Invoice

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);
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) DefaultPlanPhasePriceOverride(org.killbill.billing.catalog.DefaultPlanPhasePriceOverride) Invoice(org.killbill.billing.invoice.api.Invoice) ArrayList(java.util.ArrayList) Plan(org.killbill.billing.catalog.api.Plan) StaticCatalog(org.killbill.billing.catalog.api.StaticCatalog) SimplePlanDescriptor(org.killbill.billing.catalog.api.SimplePlanDescriptor) DefaultSimplePlanDescriptor(org.killbill.billing.catalog.api.user.DefaultSimplePlanDescriptor) DefaultSimplePlanDescriptor(org.killbill.billing.catalog.api.user.DefaultSimplePlanDescriptor) BigDecimal(java.math.BigDecimal) Entitlement(org.killbill.billing.entitlement.api.Entitlement) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride) DefaultPlanPhasePriceOverride(org.killbill.billing.catalog.DefaultPlanPhasePriceOverride) Test(org.testng.annotations.Test)

Example 99 with Invoice

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);
}
Also used : DefaultAccount(org.killbill.billing.account.api.DefaultAccount) Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) DateTime(org.joda.time.DateTime) Test(org.testng.annotations.Test)

Example 100 with Invoice

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;
}
Also used : Usage(org.killbill.billing.catalog.api.Usage) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) Invoice(org.killbill.billing.invoice.api.Invoice) HashMap(java.util.HashMap) Function(com.google.common.base.Function) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) List(java.util.List) UUID(java.util.UUID)

Aggregations

Invoice (org.killbill.billing.invoice.api.Invoice)245 Test (org.testng.annotations.Test)190 LocalDate (org.joda.time.LocalDate)165 BigDecimal (java.math.BigDecimal)148 UUID (java.util.UUID)105 DefaultInvoice (org.killbill.billing.invoice.model.DefaultInvoice)96 Account (org.killbill.billing.account.api.Account)84 DateTime (org.joda.time.DateTime)73 DefaultEntitlement (org.killbill.billing.entitlement.api.DefaultEntitlement)70 InvoiceItem (org.killbill.billing.invoice.api.InvoiceItem)57 ArrayList (java.util.ArrayList)50 BillingEventSet (org.killbill.billing.junction.BillingEventSet)48 ExpectedInvoiceItemCheck (org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck)45 MockPlan (org.killbill.billing.catalog.MockPlan)45 MockPlanPhase (org.killbill.billing.catalog.MockPlanPhase)45 MockBillingEventSet (org.killbill.billing.invoice.MockBillingEventSet)44 FixedPriceInvoiceItem (org.killbill.billing.invoice.model.FixedPriceInvoiceItem)43 Plan (org.killbill.billing.catalog.api.Plan)41 RecurringInvoiceItem (org.killbill.billing.invoice.model.RecurringInvoiceItem)40 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)39