killbill-memoizeit
Changes
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java 3(+2 -1)
invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java 17(+10 -7)
invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java 11(+6 -5)
invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java 20(+11 -9)
invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg 34(+34 -0)
invoice/src/main/resources/org/killbill/billing/invoice/migration/V20181129164135__tracking_ids.sql 15(+15 -0)
Details
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
index 88bd103..65e9c2e 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
@@ -53,6 +53,7 @@ import org.killbill.billing.payment.api.TransactionStatus;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@@ -720,7 +721,7 @@ public class TestIntegrationInvoiceWithRepairLogic extends TestIntegrationBase {
newItems.add(recurring3);
newItems.add(repair3);
shellInvoice.addInvoiceItems(newItems);
- invoiceDao.createInvoice(shellInvoice, new FutureAccountNotifications(), internalCallContext);
+ invoiceDao.createInvoice(shellInvoice, ImmutableSet.of(), new FutureAccountNotifications(), internalCallContext);
// Move ahead one month, verify nothing from previous data was generated
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java b/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
index ccc5669..f47254c 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
@@ -58,6 +58,7 @@ import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
public class InvoiceApiHelper {
@@ -115,7 +116,7 @@ public class InvoiceApiHelper {
invoiceModelDaos.add(invoiceModelDao);
}
- final List<InvoiceItemModelDao> createdInvoiceItems = dao.createInvoices(invoiceModelDaos, internalCallContext);
+ final List<InvoiceItemModelDao> createdInvoiceItems = dao.createInvoices(invoiceModelDaos, ImmutableSet.of(), internalCallContext);
success = true;
return fromInvoiceItemModelDao(createdInvoiceItems);
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 90f3637..30aa18d 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -85,6 +85,7 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
@@ -468,7 +469,7 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
}));
migrationInvoice.addInvoiceItems(itemModelDaos);
- dao.createInvoices(ImmutableList.<InvoiceModelDao>of(migrationInvoice), internalCallContext);
+ dao.createInvoices(ImmutableList.<InvoiceModelDao>of(migrationInvoice), ImmutableSet.of(), internalCallContext);
return migrationInvoice.getId();
}
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 cc48631..9acff42 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
@@ -305,18 +305,21 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
@Override
public void createInvoice(final InvoiceModelDao invoice,
+ final Set<InvoiceTrackingModelDao> trackingIds,
final FutureAccountNotifications callbackDateTimePerSubscriptions,
final InternalCallContext context) {
- createInvoices(ImmutableList.<InvoiceModelDao>of(invoice), callbackDateTimePerSubscriptions, context);
+ createInvoices(ImmutableList.<InvoiceModelDao>of(invoice), trackingIds, callbackDateTimePerSubscriptions, context);
}
@Override
public List<InvoiceItemModelDao> createInvoices(final List<InvoiceModelDao> invoices,
+ final Set<InvoiceTrackingModelDao> trackingIds,
final InternalCallContext context) {
- return createInvoices(invoices, new FutureAccountNotifications(), context);
+ return createInvoices(invoices, trackingIds, new FutureAccountNotifications(), context);
}
private List<InvoiceItemModelDao> createInvoices(final Iterable<InvoiceModelDao> invoices,
+ final Set<InvoiceTrackingModelDao> trackingIds,
final FutureAccountNotifications callbackDateTimePerSubscriptions,
final InternalCallContext context) {
// Track invoices that are being created
@@ -418,6 +421,13 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
notifyBusOfInvoiceAdjustment(entitySqlDaoWrapperFactory, adjustedInvoiceId, accountId, context.getUserToken(), context);
}
}
+
+
+ if (trackingIds != null && !trackingIds.isEmpty()) {
+ final InvoiceTrackingSqlDao trackingIdsSqlDao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
+ trackingIdsSqlDao.create(trackingIds, context);
+ }
+
return createdInvoiceItems;
}
});
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
index e7c7790..0c45abb 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
@@ -21,6 +21,7 @@ package org.killbill.billing.invoice.dao;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -40,10 +41,13 @@ import org.killbill.billing.util.entity.dao.EntityDao;
public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceApiException> {
void createInvoice(final InvoiceModelDao invoice,
+ final Set<InvoiceTrackingModelDao> trackingIds,
final FutureAccountNotifications callbackDateTimePerSubscriptions,
final InternalCallContext context);
- List<InvoiceItemModelDao> createInvoices(final List<InvoiceModelDao> invoices, final InternalCallContext context);
+ List<InvoiceItemModelDao> createInvoices(final List<InvoiceModelDao> invoices,
+ final Set<InvoiceTrackingModelDao> trackingIds,
+ final InternalCallContext context);
public void setFutureAccountNotificationsForEmptyInvoice(final UUID accountId, final FutureAccountNotifications callbackDateTimePerSubscriptions,
final InternalCallContext context);
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingModelDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingModelDao.java
new file mode 100644
index 0000000..764ef17
--- /dev/null
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingModelDao.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 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.dao;
+
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.killbill.billing.util.UUIDs;
+import org.killbill.billing.util.dao.TableName;
+import org.killbill.billing.util.entity.Entity;
+import org.killbill.billing.util.entity.dao.EntityModelDao;
+import org.killbill.billing.util.entity.dao.EntityModelDaoBase;
+
+import com.google.common.base.Objects;
+
+public class InvoiceTrackingModelDao extends EntityModelDaoBase implements EntityModelDao<Entity> {
+
+ private String trackingId;
+ private UUID invoiceId;
+ private UUID subscriptionId;
+ private LocalDate recordDate;
+
+ public InvoiceTrackingModelDao() { /* For the DAO mapper */ }
+
+
+ public InvoiceTrackingModelDao(final String trackingId,final UUID invoiceId, final UUID subscriptionId, final LocalDate recordDate) {
+ this(UUIDs.randomUUID(), null, trackingId, invoiceId, subscriptionId, recordDate);
+ }
+
+ public InvoiceTrackingModelDao(final UUID id, @Nullable final DateTime createdDate, final String trackingId,
+ final UUID invoiceId, final UUID subscriptionId, final LocalDate recordDate) {
+ super(id, createdDate, createdDate);
+ this.trackingId = trackingId;
+ this.invoiceId = invoiceId;
+ this.subscriptionId = subscriptionId;
+ this.recordDate = recordDate;
+ }
+
+ public String getTrackingId() {
+ return trackingId;
+ }
+
+ public void setTrackingId(final String trackingId) {
+ this.trackingId = trackingId;
+ }
+
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ public void setInvoiceId(final UUID invoiceId) {
+ this.invoiceId = invoiceId;
+ }
+
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ public void setSubscriptionId(final UUID subscriptionId) {
+ this.subscriptionId = subscriptionId;
+ }
+
+ public LocalDate getRecordDate() {
+ return recordDate;
+ }
+
+ public void setRecordDate(final LocalDate recordDate) {
+ this.recordDate = recordDate;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof InvoiceTrackingModelDao)) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ final InvoiceTrackingModelDao that = (InvoiceTrackingModelDao) o;
+ return Objects.equal(trackingId, that.trackingId) &&
+ Objects.equal(invoiceId, that.invoiceId) &&
+ Objects.equal(subscriptionId, that.subscriptionId) &&
+ Objects.equal(recordDate, that.recordDate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), trackingId, invoiceId, subscriptionId, recordDate);
+ }
+
+ @Override
+ public String toString() {
+ return "InvoiceTrackingModelDao{" +
+ "trackingId='" + trackingId + '\'' +
+ ", invoiceId=" + invoiceId +
+ ", subscriptionId=" + subscriptionId +
+ ", recordDate=" + recordDate +
+ '}';
+ }
+
+ @Override
+ public TableName getTableName() {
+ return TableName.INVOICE_TRACKING_IDS;
+ }
+
+
+ @Override
+ public TableName getHistoryTableName() {
+ return null;
+ }
+
+}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.java
new file mode 100644
index 0000000..469200c
--- /dev/null
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 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.dao;
+
+import java.util.Date;
+import java.util.List;
+
+import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.util.callcontext.InternalTenantContextBinder;
+import org.killbill.billing.util.entity.Entity;
+import org.killbill.billing.util.entity.dao.EntitySqlDao;
+import org.killbill.commons.jdbi.binder.SmartBindBean;
+import org.killbill.commons.jdbi.template.KillBillSqlDaoStringTemplate;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlBatch;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+
+@KillBillSqlDaoStringTemplate
+public interface InvoiceTrackingSqlDao extends EntitySqlDao<InvoiceTrackingModelDao, Entity> {
+
+ @SqlBatch
+ void create(@SmartBindBean Iterable<InvoiceTrackingModelDao> trackings,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlQuery
+ List<InvoiceTrackingModelDao> getTrackingsByDateRange(@Bind("startDate") final Date startDate,
+ @Bind("endDate") final Date endDate,
+ @SmartBindBean final InternalTenantContext context);
+
+}
+
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java
index 2e46d79..fa8da71 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/DefaultInvoiceGenerator.java
@@ -36,16 +36,17 @@ import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoiceStatus;
+import org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceGeneratorResult;
import org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates;
import org.killbill.billing.invoice.model.DefaultInvoice;
import org.killbill.billing.junction.BillingEventSet;
import org.killbill.billing.util.config.definition.InvoiceConfig;
import org.killbill.clock.Clock;
-import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
@@ -77,7 +78,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
final Currency targetCurrency,
final InternalCallContext context) throws InvoiceApiException {
if ((events == null) || (events.size() == 0) || events.isAccountAutoInvoiceOff()) {
- return new InvoiceWithMetadata(null, ImmutableMap.<UUID, SubscriptionFutureNotificationDates>of());
+ return new InvoiceWithMetadata(null, ImmutableSet.of(), ImmutableMap.<UUID, SubscriptionFutureNotificationDates>of());
}
validateTargetDate(targetDate, context);
@@ -91,11 +92,11 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates = new HashMap<UUID, SubscriptionFutureNotificationDates>();
- final List<InvoiceItem> fixedAndRecurringItems = recurringInvoiceItemGenerator.generateItems(account, invoice.getId(), events, existingInvoices, adjustedTargetDate, targetCurrency, perSubscriptionFutureNotificationDates, context);
- invoice.addInvoiceItems(fixedAndRecurringItems);
+ final InvoiceGeneratorResult fixedAndRecurringItems = recurringInvoiceItemGenerator.generateItems(account, invoice.getId(), events, existingInvoices, adjustedTargetDate, targetCurrency, perSubscriptionFutureNotificationDates, context);
+ invoice.addInvoiceItems(fixedAndRecurringItems.getItems());
- final List<InvoiceItem> usageItems = usageInvoiceItemGenerator.generateItems(account, invoice.getId(), events, existingInvoices, adjustedTargetDate, targetCurrency, perSubscriptionFutureNotificationDates, context);
- invoice.addInvoiceItems(usageItems);
+ final InvoiceGeneratorResult usageItemsWithTrackingIds = usageInvoiceItemGenerator.generateItems(account, invoice.getId(), events, existingInvoices, adjustedTargetDate, targetCurrency, perSubscriptionFutureNotificationDates, context);
+ invoice.addInvoiceItems(usageItemsWithTrackingIds.getItems());
if (targetInvoiceId != null) {
final Invoice originalInvoice = Iterables.tryFind(existingInvoices, new Predicate<Invoice>() {
@@ -108,7 +109,9 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
invoice.addInvoiceItems(originalInvoice.getInvoiceItems());
}
- return new InvoiceWithMetadata(invoice.getInvoiceItems().isEmpty() ? null : invoice, perSubscriptionFutureNotificationDates);
+ return new InvoiceWithMetadata(invoice.getInvoiceItems().isEmpty() ? null : invoice,
+ usageItemsWithTrackingIds.getTrackingIds(),
+ perSubscriptionFutureNotificationDates);
}
private void validateTargetDate(final LocalDate targetDate, final InternalTenantContext context) throws InvoiceApiException {
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 afc6032..9756bff 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
@@ -59,6 +59,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Range;
@@ -82,10 +83,10 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
this.clock = clock;
}
- public List<InvoiceItem> generateItems(final ImmutableAccountData account, final UUID invoiceId, final BillingEventSet eventSet,
- @Nullable final Iterable<Invoice> existingInvoices, final LocalDate targetDate,
- final Currency targetCurrency, final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
- final InternalCallContext internalCallContext) throws InvoiceApiException {
+ public InvoiceGeneratorResult generateItems(final ImmutableAccountData account, final UUID invoiceId, final BillingEventSet eventSet,
+ @Nullable final Iterable<Invoice> existingInvoices, final LocalDate targetDate,
+ final Currency targetCurrency, final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
+ final InternalCallContext internalCallContext) throws InvoiceApiException {
final Multimap<UUID, LocalDate> createdItemsPerDayPerSubscription = LinkedListMultimap.<UUID, LocalDate>create();
final AccountItemTree accountItemTree = new AccountItemTree(account.getId(), invoiceId);
@@ -118,7 +119,7 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator
final List<InvoiceItem> resultingItems = accountItemTree.getResultingItemList();
safetyBounds(resultingItems, createdItemsPerDayPerSubscription, internalCallContext);
- return resultingItems;
+ return new InvoiceGeneratorResult(resultingItems, ImmutableSet.of());
}
private void processRecurringBillingEvents(final UUID invoiceId, final UUID accountId, final BillingEventSet events,
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java
index c5db403..fb7f0d5 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceItemGenerator.java
@@ -20,6 +20,7 @@ package org.killbill.billing.invoice.generator;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -32,15 +33,38 @@ import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceApiException;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates;
+import org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingIds;
import org.killbill.billing.junction.BillingEventSet;
import org.slf4j.Logger;
public abstract class InvoiceItemGenerator {
- public abstract List<InvoiceItem> generateItems(final ImmutableAccountData account, final UUID invoiceId, final BillingEventSet eventSet,
- @Nullable final Iterable<Invoice> existingInvoices, final LocalDate targetDate,
- final Currency targetCurrency, Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
- final InternalCallContext context) throws InvoiceApiException;
+
+ public abstract InvoiceGeneratorResult generateItems(final ImmutableAccountData account, final UUID invoiceId, final BillingEventSet eventSet,
+ @Nullable final Iterable<Invoice> existingInvoices, final LocalDate targetDate,
+ final Currency targetCurrency, Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
+ final InternalCallContext context) throws InvoiceApiException;
+
+
+ public static class InvoiceGeneratorResult {
+ private final List<InvoiceItem> items;
+ private final Set<TrackingIds> trackingIds;
+
+ public InvoiceGeneratorResult(final List<InvoiceItem> items, final Set<TrackingIds> trackingIds) {
+ this.items = items;
+ this.trackingIds = trackingIds;
+ }
+
+ public List<InvoiceItem> getItems() {
+ return items;
+ }
+
+ public Set<TrackingIds> getTrackingIds() {
+ return trackingIds;
+ }
+ }
+
+
public static class InvoiceItemGeneratorLogger {
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java
index 9425e0c..fc7b7cc 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/InvoiceWithMetadata.java
@@ -17,10 +17,9 @@
package org.killbill.billing.invoice.generator;
-import java.math.BigDecimal;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -40,9 +39,12 @@ public class InvoiceWithMetadata {
private DefaultInvoice invoice;
- public InvoiceWithMetadata(final DefaultInvoice originalInvoice, final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates) {
+ private final Set<TrackingIds> trackingIds;
+
+ public InvoiceWithMetadata(final DefaultInvoice originalInvoice, final Set<TrackingIds> trackingIds, final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates) {
this.invoice = originalInvoice;
this.perSubscriptionFutureNotificationDates = perSubscriptionFutureNotificationDates;
+ this.trackingIds = trackingIds;
build();
}
@@ -80,6 +82,40 @@ public class InvoiceWithMetadata {
});
}
+ public Set<TrackingIds> getTrackingIds() {
+ return trackingIds;
+ }
+
+ public static class TrackingIds {
+ private final String trackingId;
+ private final UUID invoiceId;
+ private final UUID subscriptionId;
+ private final LocalDate recordDate;
+
+ public TrackingIds(final String trackingId, final UUID invoiceId, final UUID subscriptionId, final LocalDate recordDate) {
+ this.trackingId = trackingId;
+ this.invoiceId = invoiceId;
+ this.subscriptionId = subscriptionId;
+ this.recordDate = recordDate;
+ }
+
+ public String getTrackingId() {
+ return trackingId;
+ }
+
+ public UUID getInvoiceId() {
+ return invoiceId;
+ }
+
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ public LocalDate getRecordDate() {
+ return recordDate;
+ }
+ }
+
public static class SubscriptionFutureNotificationDates {
private final BillingMode recurringBillingMode;
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
index 5fd4826..ea05a90 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/UsageInvoiceItemGenerator.java
@@ -54,6 +54,7 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
@@ -71,15 +72,16 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
this.invoiceConfig = invoiceConfig;
}
+
@Override
- public List<InvoiceItem> generateItems(final ImmutableAccountData account,
- final UUID invoiceId,
- final BillingEventSet eventSet,
- @Nullable final Iterable<Invoice> existingInvoices,
- final LocalDate targetDate,
- final Currency targetCurrency,
- final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates,
- final InternalCallContext internalCallContext) throws InvoiceApiException {
+ public InvoiceGeneratorResult generateItems(final ImmutableAccountData account,
+ final UUID invoiceId,
+ final BillingEventSet eventSet,
+ @Nullable final Iterable<Invoice> existingInvoices,
+ final LocalDate targetDate,
+ final Currency targetCurrency,
+ final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates,
+ final InternalCallContext internalCallContext) throws InvoiceApiException {
final Map<UUID, List<InvoiceItem>> perSubscriptionInArrearUsageItems = extractPerSubscriptionExistingInArrearUsageItems(eventSet.getUsages(), existingInvoices);
try {
// Pretty-print the generated invoice items from the junction events
@@ -143,7 +145,7 @@ public class UsageInvoiceItemGenerator extends InvoiceItemGenerator {
invoiceItemGeneratorLogger.logItems();
- return items;
+ return new InvoiceGeneratorResult(items, ImmutableSet.of());
} catch (final CatalogApiException e) {
throw new InvoiceApiException(e);
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
index 0483ab4..d461199 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -69,6 +69,7 @@ import org.killbill.billing.invoice.dao.InvoiceItemModelDao;
import org.killbill.billing.invoice.dao.InvoiceModelDao;
import org.killbill.billing.invoice.dao.InvoiceModelDaoHelper;
import org.killbill.billing.invoice.dao.InvoiceParentChildModelDao;
+import org.killbill.billing.invoice.dao.InvoiceTrackingModelDao;
import org.killbill.billing.invoice.generator.InvoiceGenerator;
import org.killbill.billing.invoice.generator.InvoiceWithMetadata;
import org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates;
@@ -204,7 +205,7 @@ public class InvoiceDispatcher {
final ImmutableAccountData account = accountApi.getImmutableAccountDataById(accountId, context);
- commitInvoiceAndSetFutureNotifications(account, null, notificationsBuilder.build(), context);
+ commitInvoiceAndSetFutureNotifications(account, null, ImmutableSet.of(), notificationsBuilder.build(), context);
} catch (final SubscriptionBaseApiException e) {
log.warn("Failed handling SubscriptionBase change.",
@@ -537,7 +538,7 @@ public class InvoiceDispatcher {
log.warn("Ignoring rescheduleDate='{}', delayed scheduling is unsupported in dry-run", rescheduleDate);
} else {
final FutureAccountNotifications futureAccountNotifications = createNextFutureNotificationDate(rescheduleDate, billingEvents, internalCallContext);
- commitInvoiceAndSetFutureNotifications(account, null, futureAccountNotifications, internalCallContext);
+ commitInvoiceAndSetFutureNotifications(account, null, ImmutableSet.of(), futureAccountNotifications, internalCallContext);
}
return null;
}
@@ -560,7 +561,7 @@ public class InvoiceDispatcher {
final BusInternalEvent event = new DefaultNullInvoiceEvent(accountId, clock.getUTCToday(),
internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId(), internalCallContext.getUserToken());
- commitInvoiceAndSetFutureNotifications(account, null, futureAccountNotifications, internalCallContext);
+ commitInvoiceAndSetFutureNotifications(account, null, ImmutableSet.of(), futureAccountNotifications, internalCallContext);
postEvent(event);
}
return null;
@@ -604,8 +605,14 @@ public class InvoiceDispatcher {
final List<InvoiceItemModelDao> invoiceItemModelDaos = transformToInvoiceModelDao(invoice.getInvoiceItems());
invoiceModelDao.addInvoiceItems(invoiceItemModelDaos);
+
+ final Set<InvoiceTrackingModelDao> trackingIds = new HashSet<>();
+ for (InvoiceWithMetadata.TrackingIds cur : invoiceWithMetadata.getTrackingIds()) {
+ trackingIds.add(new InvoiceTrackingModelDao(cur.getTrackingId(), cur.getInvoiceId(), cur.getSubscriptionId(), cur.getRecordDate()));
+ }
+
// Commit invoice on disk
- commitInvoiceAndSetFutureNotifications(account, invoiceModelDao, futureAccountNotifications, internalCallContext);
+ commitInvoiceAndSetFutureNotifications(account, invoiceModelDao, trackingIds, futureAccountNotifications, internalCallContext);
success = true;
try {
@@ -618,7 +625,7 @@ public class InvoiceDispatcher {
} finally {
// Make sure we always set future notifications in case of errors
if (!isDryRun && !success) {
- commitInvoiceAndSetFutureNotifications(account, null, futureAccountNotifications, internalCallContext);
+ commitInvoiceAndSetFutureNotifications(account, null, ImmutableSet.of(), futureAccountNotifications, internalCallContext);
}
if (isDryRun || success) {
@@ -791,11 +798,12 @@ public class InvoiceDispatcher {
private void commitInvoiceAndSetFutureNotifications(final ImmutableAccountData account,
@Nullable final InvoiceModelDao invoiceModelDao,
+ final Set<InvoiceTrackingModelDao> trackingIds,
final FutureAccountNotifications futureAccountNotifications,
final InternalCallContext context) {
final boolean isThereAnyItemsLeft = invoiceModelDao != null && !invoiceModelDao.getInvoiceItems().isEmpty();
if (isThereAnyItemsLeft) {
- invoiceDao.createInvoice(invoiceModelDao, futureAccountNotifications, context);
+ invoiceDao.createInvoice(invoiceModelDao, trackingIds, futureAccountNotifications, context);
} else {
invoiceDao.setFutureAccountNotificationsForEmptyInvoice(account.getId(), futureAccountNotifications, context);
}
@@ -1095,7 +1103,7 @@ public class InvoiceDispatcher {
List<InvoiceModelDao> invoices = new ArrayList<InvoiceModelDao>();
invoices.add(draftParentInvoice);
log.info("Adding new itemId='{}', amount='{}' on existing DRAFT invoiceId='{}'", parentInvoiceItem.getId(), childInvoiceAmount, draftParentInvoice.getId());
- invoiceDao.createInvoices(invoices, parentContext);
+ invoiceDao.createInvoices(invoices, ImmutableSet.of(), parentContext);
} else {
if (shouldIgnoreChildInvoice(childInvoice, childInvoiceAmount)) {
return;
@@ -1107,7 +1115,7 @@ public class InvoiceDispatcher {
draftParentInvoice.addInvoiceItem(new InvoiceItemModelDao(parentInvoiceItem));
log.info("Adding new itemId='{}', amount='{}' on new DRAFT invoiceId='{}'", parentInvoiceItem.getId(), childInvoiceAmount, draftParentInvoice.getId());
- invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(draftParentInvoice), parentContext);
+ invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(draftParentInvoice), ImmutableSet.of(), parentContext);
}
// save parent child invoice relation
@@ -1203,7 +1211,7 @@ public class InvoiceDispatcher {
parentSummaryInvoiceItem.getId(),
null);
parentInvoiceModelDao.addInvoiceItem(new InvoiceItemModelDao(adj));
- invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(parentInvoiceModelDao), parentContext);
+ invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(parentInvoiceModelDao), ImmutableSet.of(), parentContext);
return;
}
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg
new file mode 100644
index 0000000..1cd5116
--- /dev/null
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg
@@ -0,0 +1,34 @@
+import "org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg"
+
+tableName() ::= "invoice_tracking_ids"
+
+tableFields(prefix) ::= <<
+ <prefix>tracking_id
+, <prefix>invoice_id
+, <prefix>subscription_id
+, <prefix>record_date
+, <prefix>created_by
+, <prefix>created_date
+>>
+
+tableValues() ::= <<
+ :trackingId
+, :invoiceId
+, :subscriptionId
+, :recordDate
+, :userName
+, :createdDate
+>>
+
+getTrackingsByDateRange() ::= <<
+select
+ <allTableFields("")>
+from <tableName()>
+where
+record_date >= :startDate
+and record_date \< :endDate
+and <accountRecordIdField("")> = :accountRecordId
+<AND_CHECK_TENANT("")>
+<defaultOrderBy("")>
+;
+>>
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql b/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql
index 128c664..3719c53 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/ddl.sql
@@ -1,5 +1,22 @@
/*! SET default_storage_engine=INNODB */;
+DROP TABLE IF EXISTS invoice_tracking_ids;
+CREATE TABLE invoice_tracking_ids (
+ record_id serial unique,
+ id varchar(36) NOT NULL,
+ tracking_id varchar(128) NOT NULL,
+ invoice_id varchar(36) NOT NULL,
+ subscription_id varchar(36),
+ record_date date NOT NULL,
+ created_by varchar(50) NOT NULL,
+ created_date datetime NOT NULL,
+ account_record_id bigint /*! unsigned */ not null,
+ tenant_record_id bigint /*! unsigned */ not null default 0,
+ PRIMARY KEY(record_id)
+) /*! CHARACTER SET utf8 COLLATE utf8_bin */;
+CREATE INDEX invoice_tracking_tenant_account_date_idx ON invoice_tracking_ids(tenant_record_id, account_record_id, record_date);
+
+
DROP TABLE IF EXISTS invoice_items;
CREATE TABLE invoice_items (
record_id serial unique,
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/migration/V20181129164135__tracking_ids.sql b/invoice/src/main/resources/org/killbill/billing/invoice/migration/V20181129164135__tracking_ids.sql
new file mode 100644
index 0000000..d540f70
--- /dev/null
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/migration/V20181129164135__tracking_ids.sql
@@ -0,0 +1,15 @@
+DROP TABLE IF EXISTS invoice_tracking_ids;
+CREATE TABLE invoice_tracking_ids (
+ record_id serial unique,
+ id varchar(36) NOT NULL,
+ tracking_id varchar(128) NOT NULL,
+ invoice_id varchar(36) NOT NULL,
+ subscription_id varchar(36),
+ record_date date NOT NULL,
+ created_by varchar(50) NOT NULL,
+ created_date datetime NOT NULL,
+ account_record_id bigint /*! unsigned */ not null,
+ tenant_record_id bigint /*! unsigned */ not null default 0,
+ PRIMARY KEY(record_id)
+) /*! CHARACTER SET utf8 COLLATE utf8_bin */;
+CREATE INDEX invoice_tracking_tenant_account_date_idx ON invoice_tracking_ids(tenant_record_id, account_record_id, record_date);
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
index 32499df..2833ec5 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
@@ -25,6 +25,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import org.joda.time.LocalDate;
@@ -62,6 +63,7 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
@Override
public void createInvoice(final InvoiceModelDao invoice,
+ final Set<InvoiceTrackingModelDao> trackingIds,
final FutureAccountNotifications callbackDateTimePerSubscriptions, final InternalCallContext context) {
synchronized (monitor) {
storeInvoice(invoice, context);
@@ -81,7 +83,7 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
}
@Override
- public List<InvoiceItemModelDao> createInvoices(final List<InvoiceModelDao> invoiceModelDaos, final InternalCallContext context) {
+ public List<InvoiceItemModelDao> createInvoices(final List<InvoiceModelDao> invoiceModelDaos, final Set<InvoiceTrackingModelDao> trackingIds, final InternalCallContext context) {
synchronized (monitor) {
final List<InvoiceItemModelDao> createdItems = new LinkedList<InvoiceItemModelDao>();
for (final InvoiceModelDao invoice : invoiceModelDaos) {
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java
index bc02e39..a36be45 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java
@@ -80,6 +80,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import static org.killbill.billing.invoice.TestInvoiceHelper.FIVE;
import static org.killbill.billing.invoice.TestInvoiceHelper.TEN;
@@ -822,7 +823,7 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
final InvoiceModelDao invoiceForExternalCharge = new InvoiceModelDao(accountId, clock.getUTCToday(), clock.getUTCToday(), Currency.USD, false);
final InvoiceItemModelDao externalCharge = new InvoiceItemModelDao(new ExternalChargeInvoiceItem(invoiceForExternalCharge.getId(), accountId, bundleId, description, clock.getUTCToday(), clock.getUTCToday(), new BigDecimal("15.0"), Currency.USD, null));
invoiceForExternalCharge.addInvoiceItem(externalCharge);
- final InvoiceItemModelDao charge = invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceForExternalCharge), context).get(0);
+ final InvoiceItemModelDao charge = invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceForExternalCharge), ImmutableSet.of(), context).get(0);
InvoiceModelDao newInvoice = invoiceDao.getById(charge.getInvoiceId(), context);
List<InvoiceItemModelDao> items = newInvoice.getInvoiceItems();
@@ -859,7 +860,7 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
final InvoiceModelDao draftInvoiceForExternalCharge = new InvoiceModelDao(accountId, clock.getUTCToday(), clock.getUTCToday(), Currency.USD, false, InvoiceStatus.DRAFT);
final InvoiceItemModelDao externalCharge = new InvoiceItemModelDao(new ExternalChargeInvoiceItem(draftInvoiceForExternalCharge.getId(), accountId, bundleId, description, clock.getUTCToday(), clock.getUTCToday(), new BigDecimal("15.0"), Currency.USD, null));
draftInvoiceForExternalCharge.addInvoiceItem(externalCharge);
- final InvoiceItemModelDao charge = invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(draftInvoiceForExternalCharge), context).get(0);
+ final InvoiceItemModelDao charge = invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(draftInvoiceForExternalCharge), ImmutableSet.of(), context).get(0);
InvoiceModelDao newInvoice = invoiceDao.getById(charge.getInvoiceId(), context);
List<InvoiceItemModelDao> items = newInvoice.getInvoiceItems();
@@ -1783,7 +1784,7 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
invoiceModelDao.getCurrency(),
null);
invoiceModelDao.addInvoiceItem(new InvoiceItemModelDao(invoiceItem));
- return invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceModelDao), context).get(0);
+ return invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceModelDao), ImmutableSet.of(), context).get(0);
}
@Test(groups = "slow")
@@ -1815,7 +1816,7 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
InvoiceItem parentInvoiceItem = new ParentInvoiceItem(UUID.randomUUID(), today, parentInvoice.getId(), parentAccountId, childAccountId, BigDecimal.TEN, account.getCurrency(), "");
parentInvoice.addInvoiceItem(new InvoiceItemModelDao(parentInvoiceItem));
- invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(parentInvoice), context);
+ invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(parentInvoice), ImmutableSet.of(), context);
final InvoiceModelDao parentDraftInvoice = invoiceDao.getParentDraftInvoice(parentAccountId, context);
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceTrackingSqlDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceTrackingSqlDao.java
new file mode 100644
index 0000000..82d390c
--- /dev/null
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceTrackingSqlDao.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 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.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.LocalDate;
+import org.killbill.billing.invoice.InvoiceTestSuiteWithEmbeddedDB;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TestInvoiceTrackingSqlDao extends InvoiceTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testBasicTrackingIds() {
+ final InvoiceTrackingSqlDao dao = dbi.onDemand(InvoiceTrackingSqlDao.class);
+
+ LocalDate startRange = new LocalDate(2018, 8, 1);
+ LocalDate endRange = new LocalDate(2018, 11, 23);
+
+ final UUID invoiceId1 = UUID.randomUUID();
+ final UUID invoiceId2 = UUID.randomUUID();
+ final UUID subscriptionId = UUID.randomUUID();
+
+ // Before desired range
+ final InvoiceTrackingModelDao input0 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId0", invoiceId1, subscriptionId, startRange.minusDays(1));
+
+ final InvoiceTrackingModelDao input1 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId1", invoiceId1, subscriptionId, startRange);
+ final InvoiceTrackingModelDao input2 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId2", invoiceId1, subscriptionId, new LocalDate(2018, 8, 5));
+ final InvoiceTrackingModelDao input3 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId3", invoiceId2, subscriptionId, new LocalDate(2018, 9, 1));
+
+ // After desired range
+ final InvoiceTrackingModelDao input4 = new InvoiceTrackingModelDao(UUID.randomUUID(), clock.getUTCNow(), "trackingId4", invoiceId1, subscriptionId, endRange);
+
+ final List<InvoiceTrackingModelDao> inputs = new ArrayList<>();
+ inputs.add(input0);
+ inputs.add(input1);
+ inputs.add(input2);
+ inputs.add(input3);
+ inputs.add(input4);
+
+ dao.create(inputs, internalCallContext);
+
+ final List<InvoiceTrackingModelDao> result = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
+ Assert.assertEquals(result.size(), 3);
+
+ Assert.assertEquals(result.get(0).getTrackingId(), "trackingId1");
+ Assert.assertEquals(result.get(0).getInvoiceId(), invoiceId1);
+ Assert.assertEquals(result.get(0).getRecordDate(), startRange);
+ Assert.assertEquals(result.get(0).getSubscriptionId(), subscriptionId);
+
+ Assert.assertEquals(result.get(1).getTrackingId(), "trackingId2");
+ Assert.assertEquals(result.get(1).getInvoiceId(), invoiceId1);
+ Assert.assertEquals(result.get(1).getRecordDate(), new LocalDate(2018, 8, 5));
+ Assert.assertEquals(result.get(1).getSubscriptionId(), subscriptionId);
+
+ Assert.assertEquals(result.get(2).getTrackingId(), "trackingId3");
+ Assert.assertEquals(result.get(2).getInvoiceId(), invoiceId2);
+ Assert.assertEquals(result.get(2).getRecordDate(), new LocalDate(2018, 9, 1));
+ Assert.assertEquals(result.get(2).getSubscriptionId(), subscriptionId);
+
+ }
+}
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
index 68fcade..e95e5db 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestFixedAndRecurringInvoiceItemGenerator.java
@@ -347,7 +347,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate.plusMonths(threshold),
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext).size(), 1);
+ internalCallContext).getItems().size(), 1);
// Simulate a big catch-up on that day
for (int i = threshold; i < 2 * threshold; i++) {
@@ -377,7 +377,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate.plusMonths(2 * threshold),
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
@@ -436,7 +436,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
// There will be one proposed, but because it will match one of ones in the existing list and we don't repair, it won't be returned
assertEquals(generatedItems.size(), 0);
}
@@ -497,7 +497,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
@@ -557,7 +557,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
assertEquals(generatedItems.size(), 2);
assertTrue(generatedItems.get(0) instanceof RecurringInvoiceItem);
assertEquals(generatedItems.get(0).getStartDate(), new LocalDate("2016-01-01"));
@@ -636,7 +636,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
// Maybe we could auto-fix-it one day?
// assertEquals(generatedItems.size(), 1);
@@ -713,7 +713,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
assertEquals(generatedItems.size(), 1);
assertTrue(generatedItems.get(0) instanceof RecurringInvoiceItem);
assertEquals(generatedItems.get(0).getStartDate(), new LocalDate("2016-01-01"));
@@ -793,7 +793,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
@@ -863,7 +863,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
@@ -899,7 +899,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
@@ -936,7 +936,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
@@ -992,7 +992,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
@@ -1081,7 +1081,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
assertTrue(generatedItems.isEmpty());
}
@@ -1166,7 +1166,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
assertTrue(generatedItems.isEmpty());
}
@@ -1252,7 +1252,7 @@ public class TestFixedAndRecurringInvoiceItemGenerator extends InvoiceTestSuiteN
startDate,
account.getCurrency(),
new HashMap<UUID, SubscriptionFutureNotificationDates>(),
- internalCallContext);
+ internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestInvoiceWithMetadata.java b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestInvoiceWithMetadata.java
index ef9d691..d20db05 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestInvoiceWithMetadata.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestInvoiceWithMetadata.java
@@ -46,6 +46,7 @@ import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import com.google.common.collect.ImmutableSet;
public class TestInvoiceWithMetadata extends InvoiceTestSuiteNoDB {
@@ -122,7 +123,7 @@ public class TestInvoiceWithMetadata extends InvoiceTestSuiteNoDB {
perSubscriptionFutureNotificationDates.put(subscription.getId(), subscriptionFutureNotificationDates);
- final InvoiceWithMetadata invoiceWithMetadata = new InvoiceWithMetadata(originalInvoice, perSubscriptionFutureNotificationDates);
+ final InvoiceWithMetadata invoiceWithMetadata = new InvoiceWithMetadata(originalInvoice, ImmutableSet.of(), perSubscriptionFutureNotificationDates);
// We generate an invoice with one item, invoicing for $0
final Invoice resultingInvoice = invoiceWithMetadata.getInvoice();
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java b/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java
index 7d0c111..98f4fad 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/proRations/InvoiceTestUtils.java
@@ -47,6 +47,7 @@ import org.mockito.Mockito;
import org.testng.Assert;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
public class InvoiceTestUtils {
@@ -108,7 +109,7 @@ public class InvoiceTestUtils {
final InvoiceModelDao invoiceModelDao = new InvoiceModelDao(invoice);
invoiceModelDao.addInvoiceItems(invoiceModelItems);
- invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceModelDao), internalCallContext);
+ invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceModelDao), ImmutableSet.of(), internalCallContext);
return invoice;
}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java
index b994b58..bdbc878 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceDispatcher.java
@@ -60,6 +60,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
public class TestInvoiceDispatcher extends InvoiceTestSuiteWithEmbeddedDB {
@@ -197,7 +198,7 @@ public class TestInvoiceDispatcher extends InvoiceTestSuiteWithEmbeddedDB {
invoiceModelDao.addInvoiceItem(invoiceItemModelDao1);
invoiceModelDao.addInvoiceItem(invoiceItemModelDao2);
- invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceModelDao), context);
+ invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(invoiceModelDao), ImmutableSet.of(), context);
try {
dispatcher.processAccountFromNotificationOrBusEvent(accountId, target, new DryRunFutureDateArguments(), false, context);
diff --git a/util/src/main/java/org/killbill/billing/util/dao/TableName.java b/util/src/main/java/org/killbill/billing/util/dao/TableName.java
index f1f51a0..5e6e068 100644
--- a/util/src/main/java/org/killbill/billing/util/dao/TableName.java
+++ b/util/src/main/java/org/killbill/billing/util/dao/TableName.java
@@ -35,6 +35,7 @@ public enum TableName {
INVOICE_ITEMS("invoice_items", ObjectType.INVOICE_ITEM),
INVOICE_PAYMENTS("invoice_payments", ObjectType.INVOICE_PAYMENT),
INVOICES("invoices", ObjectType.INVOICE),
+ INVOICE_TRACKING_IDS("invoice_tracking_ids"),
INVOICE_PARENT_CHILDREN("invoice_parent_children"),
NODE_INFOS("node_infos"),
PAYMENT_ATTEMPT_HISTORY("payment_attempt_history"),
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntityModelDaoBase.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntityModelDaoBase.java
index 69d6647..47d50a1 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntityModelDaoBase.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntityModelDaoBase.java
@@ -23,7 +23,6 @@ import org.joda.time.DateTime;
import org.killbill.billing.entity.EntityBase;
public class EntityModelDaoBase extends EntityBase {
-
private Long recordId;
private Long accountRecordId;
private Long tenantRecordId;