killbill-aplcache
Changes
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceDraft.java 219(+219 -0)
Details
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceDraft.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceDraft.java
new file mode 100644
index 0000000..e223f22
--- /dev/null
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceDraft.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2014-2017 Groupon, Inc
+ * Copyright 2014-2017 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.beatrix.integration;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.killbill.billing.ObjectType;
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.api.TestApiListener.NextEvent;
+import org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.entitlement.api.DefaultEntitlement;
+import org.killbill.billing.invoice.api.Invoice;
+import org.killbill.billing.invoice.api.InvoiceItemType;
+import org.killbill.billing.invoice.api.InvoiceStatus;
+import org.killbill.billing.invoice.api.InvoiceUserApi;
+import org.killbill.billing.util.api.TagApiException;
+import org.killbill.billing.util.api.TagDefinitionApiException;
+import org.killbill.billing.util.api.TagUserApi;
+import org.killbill.billing.util.tag.ControlTagType;
+import org.killbill.billing.util.tag.Tag;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Inject;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+public class TestIntegrationWithAutoInvoiceDraft extends TestIntegrationBase {
+
+ @Inject
+ private InvoiceUserApi invoiceApi;
+
+ @Inject
+ private TagUserApi tagApi;
+
+ private Account account;
+ private String productName;
+ private BillingPeriod term;
+
+ @Override
+ @BeforeMethod(groups = "slow")
+ public void beforeMethod() throws Exception {
+ super.beforeMethod();
+ account = createAccountWithNonOsgiPaymentMethod(getAccountData(25));
+ assertNotNull(account);
+ productName = "Shotgun";
+ term = BillingPeriod.MONTHLY;
+ }
+
+
+ @Test(groups = "slow")
+ public void testBasic() throws Exception {
+ clock.setTime(new DateTime(2017, 6, 16, 18, 24, 42, 0));
+ add_AUTO_INVOICING_DRAFT_Tag(account.getId(), ObjectType.ACCOUNT);
+
+ final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK);
+ assertNotNull(bpEntitlement);
+
+ List<Invoice> invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
+ assertEquals(invoices.size(), 1);
+ final Invoice trialInvoice = invoices.get(0);
+ assertEquals(trialInvoice.getStatus(), InvoiceStatus.DRAFT);
+
+ busHandler.pushExpectedEvent(NextEvent.INVOICE);
+ invoiceApi.commitInvoice(trialInvoice.getId(), callContext);
+ assertListenerStatus();
+
+ // Move out of TRIAL
+ busHandler.pushExpectedEvents(NextEvent.PHASE);
+ clock.addDays(30);
+ assertListenerStatus();
+
+ invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
+ assertEquals(invoices.size(), 2);
+
+ final Invoice firstNonTrialInvoice = invoices.get(1);
+ assertEquals(firstNonTrialInvoice.getStatus(), InvoiceStatus.DRAFT);
+
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+ invoiceApi.commitInvoice(firstNonTrialInvoice.getId(), callContext);
+ assertListenerStatus();
+
+
+ busHandler.pushExpectedEvents(NextEvent.TAG);
+ remove_AUTO_INVOICING_DRAFT_Tag(account.getId(), ObjectType.ACCOUNT);
+ assertListenerStatus();
+
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+ clock.addMonths(1);
+ assertListenerStatus();
+
+ invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
+ assertEquals(invoices.size(), 3);
+
+
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+ clock.addMonths(1);
+ assertListenerStatus();
+
+ invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
+ assertEquals(invoices.size(), 4);
+ }
+
+
+ @Test(groups = "slow")
+ public void testWithExistingDraftInvoice() throws Exception {
+ clock.setTime(new DateTime(2017, 6, 16, 18, 24, 42, 0));
+ add_AUTO_INVOICING_DRAFT_Tag(account.getId(), ObjectType.ACCOUNT);
+
+ final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK);
+ assertNotNull(bpEntitlement);
+
+ List<Invoice> invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
+ assertEquals(invoices.size(), 1);
+ final Invoice trialInvoice = invoices.get(0);
+ assertEquals(trialInvoice.getStatus(), InvoiceStatus.DRAFT);
+
+ busHandler.pushExpectedEvent(NextEvent.INVOICE);
+ invoiceApi.commitInvoice(trialInvoice.getId(), callContext);
+ assertListenerStatus();
+
+ // Move out of TRIAL
+ busHandler.pushExpectedEvents(NextEvent.PHASE);
+ clock.addDays(30);
+ assertListenerStatus();
+
+ invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
+ assertEquals(invoices.size(), 2);
+
+ // Check firstNonTrialInvoice is still in DRAFT
+ final Invoice firstNonTrialInvoice = invoices.get(1);
+ assertEquals(firstNonTrialInvoice.getStatus(), InvoiceStatus.DRAFT);
+ assertEquals(firstNonTrialInvoice.getInvoiceDate(), new LocalDate(2017, 07, 16));
+
+
+ final List<ExpectedInvoiceItemCheck> toBeChecked = new ArrayList<ExpectedInvoiceItemCheck>();
+ toBeChecked.add(new ExpectedInvoiceItemCheck(new LocalDate(2017, 7, 16), new LocalDate(2017, 7, 25), InvoiceItemType.RECURRING, new BigDecimal("74.99")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+ toBeChecked.clear();
+
+ // Check account balance is still reflected as Zero
+ final BigDecimal accountBalance = invoiceApi.getAccountBalance(account.getId(), callContext);
+ assertEquals(accountBalance.compareTo(BigDecimal.ZERO), 0);
+
+ busHandler.pushExpectedEvents(NextEvent.TAG);
+ remove_AUTO_INVOICING_DRAFT_Tag(account.getId(), ObjectType.ACCOUNT);
+ assertListenerStatus();
+
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+ clock.addMonths(1);
+ assertListenerStatus();
+
+ invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
+ assertEquals(invoices.size(), 3);
+
+ // Check prev invoice is still in DRAFT
+ assertEquals(invoices.get(1).getStatus(), InvoiceStatus.DRAFT);
+
+ // Check most recent invoice is COMMITTED
+ assertEquals(invoices.get(2).getStatus(), InvoiceStatus.COMMITTED);
+
+ // Verify most recent invoice *only* contains the items for the period 2017-07-25 -> 2017-08-25 (and not 2017-07-16 -> 2017-07-25 from the DRAFT invoice)
+ toBeChecked.add(new ExpectedInvoiceItemCheck(new LocalDate(2017, 7, 25), new LocalDate(2017, 8, 25), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
+ invoiceChecker.checkInvoice(invoices.get(2).getId(), callContext, toBeChecked);
+ toBeChecked.clear();
+
+ // Finally commit second invoice
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+ invoiceApi.commitInvoice(firstNonTrialInvoice.getId(), callContext);
+ assertListenerStatus();
+
+ final BigDecimal accountBalance2 = invoiceApi.getAccountBalance(account.getId(), callContext);
+ assertEquals(accountBalance2.compareTo(BigDecimal.ZERO), 0);
+
+ }
+
+
+ private void add_AUTO_INVOICING_DRAFT_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
+ add_account_Tag(id, ControlTagType.AUTO_INVOICING_DRAFT, type);
+ }
+
+ private void add_account_Tag(final UUID id, final ControlTagType controlTagType, final ObjectType type) throws TagDefinitionApiException, TagApiException {
+ busHandler.pushExpectedEvent(NextEvent.TAG);
+ tagApi.addTag(id, type, controlTagType.getId(), callContext);
+ assertListenerStatus();
+ final List<Tag> tags = tagApi.getTagsForObject(id, type, false, callContext);
+ assertEquals(tags.size(), 1);
+ }
+
+ private void remove_AUTO_INVOICING_DRAFT_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
+ tagApi.removeTag(id, type, ControlTagType.AUTO_INVOICING_DRAFT.getId(), callContext);
+ }
+
+}
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
index e3825da..5b5d4c2 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
@@ -145,56 +145,6 @@ public class TestIntegrationWithAutoInvoiceOffTag extends TestIntegrationBase {
assertEquals(invoices.size(), 3); // Only one additional invoice generated
}
-
- @Test(groups = "slow")
- public void testAutoInvoiceDraftAccount() throws Exception {
- clock.setTime(new DateTime(2017, 6, 16, 18, 24, 42, 0));
- add_AUTO_INVOICING_DRAFT_Tag(account.getId(), ObjectType.ACCOUNT);
-
- final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK);
- assertNotNull(bpEntitlement);
-
- List<Invoice> invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
- assertEquals(invoices.size(), 1);
- final Invoice trialInvoice = invoices.get(0);
- assertEquals(trialInvoice.getStatus(), InvoiceStatus.DRAFT);
-
- busHandler.pushExpectedEvent(NextEvent.INVOICE);
- invoiceApi.commitInvoice(trialInvoice.getId(), callContext);
- assertListenerStatus();
-
- // Move out of TRIAL
- busHandler.pushExpectedEvents(NextEvent.PHASE);
- clock.addDays(30);
- assertListenerStatus();
-
- invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
- assertEquals(invoices.size(), 2);
-
- final Invoice firstNonTrialInvoice = invoices.get(1);
- assertEquals(firstNonTrialInvoice.getStatus(), InvoiceStatus.DRAFT);
-
- busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
- invoiceApi.commitInvoice(firstNonTrialInvoice.getId(), callContext);
- assertListenerStatus();
-
-
- busHandler.pushExpectedEvents(NextEvent.TAG);
- remove_AUTO_INVOICING_DRAFT_Tag(account.getId(), ObjectType.ACCOUNT);
- assertListenerStatus();
-
- busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
- clock.addMonths(1);
- assertListenerStatus();
-
- invoices = invoiceApi.getInvoicesByAccount(account.getId(), false, callContext);
- assertEquals(invoices.size(), 3);
- }
-
- private void add_AUTO_INVOICING_DRAFT_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
- add_account_Tag(id, ControlTagType.AUTO_INVOICING_DRAFT, type);
- }
-
private void add_AUTO_INVOICING_OFF_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
add_account_Tag(id, ControlTagType.AUTO_INVOICING_OFF, type);
}
@@ -207,10 +157,6 @@ public class TestIntegrationWithAutoInvoiceOffTag extends TestIntegrationBase {
assertEquals(tags.size(), 1);
}
- private void remove_AUTO_INVOICING_DRAFT_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
- tagApi.removeTag(id, type, ControlTagType.AUTO_INVOICING_DRAFT.getId(), callContext);
- }
-
private void remove_AUTO_INVOICING_OFF_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
tagApi.removeTag(id, type, ControlTagType.AUTO_INVOICING_OFF.getId(), callContext);
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
index 5a7f3ce..05c5e9f 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
@@ -347,6 +347,7 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
notifyOfParentInvoiceCreation(entitySqlDaoWrapperFactory, invoiceModelDao, context);
}
+ // We always add the future notifications when the callbackDateTimePerSubscriptions is not empty (incl. DRAFT invoices containing RECURRING items created using AUTO_INVOICING_DRAFT feature)
notifyOfFutureBillingEvents(entitySqlDaoWrapperFactory, invoiceModelDao.getAccountId(), callbackDateTimePerSubscriptions, context);
}