killbill-memoizeit
Changes
beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyNotificationPlugin.java 2(+1 -1)
beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java 2(+1 -1)
beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java 2(+1 -1)
invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java 9(+6 -3)
NEWS 2(+2 -0)
osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java 12(+11 -1)
osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java 36(+35 -1)
osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java 41(+40 -1)
payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java 33(+25 -8)
payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java 25(+24 -1)
payment/src/test/java/com/ning/billing/payment/provider/TestDefaultNoOpPaymentInfoPlugin.java 7(+4 -3)
pom.xml 2(+1 -1)
util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java 151(+151 -0)
Details
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
index 9fd099b..c26cb32 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
@@ -33,6 +33,8 @@ import com.ning.billing.account.api.AccountEmail;
import com.ning.billing.account.api.DefaultAccount;
import com.ning.billing.account.api.DefaultAccountEmail;
import com.ning.billing.account.api.MutableAccountData;
+import com.ning.billing.callcontext.InternalCallContext;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.mock.MockAccountBuilder;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.CustomFieldApiException;
@@ -40,6 +42,7 @@ import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.audit.ChangeType;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
import com.ning.billing.util.customfield.CustomField;
import com.ning.billing.util.customfield.StringCustomField;
import com.ning.billing.util.customfield.dao.CustomFieldModelDao;
@@ -83,6 +86,39 @@ public class TestAccountDao extends AccountTestSuiteWithEmbeddedDB {
Assert.assertEquals(auditLogsForAccount.get(0).getChangeType(), ChangeType.INSERT);
}
+ @Test(groups = "slow", description = "Test Account: verify audits")
+ public void testAudits() throws AccountApiException {
+ // Special test to verify audits - they are handled a bit differently due to the account record id (see EntitySqlDaoWrapperInvocationHandler#insertAudits)
+ final AccountModelDao account1 = createTestAccount();
+ accountDao.create(account1, internalCallContext);
+ final Long account1RecordId = nonEntityDao.retrieveAccountRecordIdFromObject(account1.getId(), ObjectType.ACCOUNT, null);
+ final InternalCallContext internalCallContext1 = new InternalCallContext(internalCallContext, account1RecordId);
+
+ // Verify audits via account record id
+ final DefaultAccountAuditLogs auditLogsForAccount1ViaAccountRecordId1 = auditDao.getAuditLogsForAccountRecordId(AuditLevel.FULL, internalCallContext1);
+ Assert.assertEquals(auditLogsForAccount1ViaAccountRecordId1.getAuditLogsForAccount().size(), 1);
+ Assert.assertEquals(auditLogsForAccount1ViaAccountRecordId1.getAuditLogsForAccount().get(0).getChangeType(), ChangeType.INSERT);
+
+ // Add an entry in the account_history table to make sure we pick up the right
+ // record id / target record id / account record id in the audit_log table
+ accountDao.updatePaymentMethod(account1.getId(), UUID.randomUUID(), internalCallContext1);
+
+ final AccountModelDao account2 = createTestAccount();
+ accountDao.create(account2, internalCallContext);
+ final Long account2RecordId = nonEntityDao.retrieveAccountRecordIdFromObject(account2.getId(), ObjectType.ACCOUNT, null);
+ final InternalTenantContext internalTenantContext2 = new InternalCallContext(internalCallContext, account2RecordId);
+
+ // Verify audits via account record id
+ final DefaultAccountAuditLogs auditLogsForAccount2ViaAccountRecordId = auditDao.getAuditLogsForAccountRecordId(AuditLevel.FULL, internalTenantContext2);
+ Assert.assertEquals(auditLogsForAccount2ViaAccountRecordId.getAuditLogsForAccount().size(), 1);
+ Assert.assertEquals(auditLogsForAccount2ViaAccountRecordId.getAuditLogsForAccount().get(0).getChangeType(), ChangeType.INSERT);
+
+ final DefaultAccountAuditLogs auditLogsForAccount1ViaAccountRecordId2 = auditDao.getAuditLogsForAccountRecordId(AuditLevel.FULL, internalCallContext1);
+ Assert.assertEquals(auditLogsForAccount1ViaAccountRecordId2.getAuditLogsForAccount().size(), 2);
+ Assert.assertEquals(auditLogsForAccount1ViaAccountRecordId2.getAuditLogsForAccount().get(0).getChangeType(), ChangeType.INSERT);
+ Assert.assertEquals(auditLogsForAccount1ViaAccountRecordId2.getAuditLogsForAccount().get(1).getChangeType(), ChangeType.UPDATE);
+ }
+
// Simple test to ensure long phone numbers can be stored
@Test(groups = "slow", description = "Test Account DAO: long numbers")
public void testLongPhoneNumber() throws AccountApiException {
@@ -129,7 +165,7 @@ public class TestAccountDao extends AccountTestSuiteWithEmbeddedDB {
final Tag tag = new DescriptiveTag(tagDefinition.getId(), ObjectType.ACCOUNT, account.getId(), internalCallContext.getCreatedDate());
tagDao.create(new TagModelDao(tag), internalCallContext);
- final List<TagModelDao> tags = tagDao.getTagsForObject(account.getId(), ObjectType.ACCOUNT, internalCallContext);
+ final List<TagModelDao> tags = tagDao.getTagsForObject(account.getId(), ObjectType.ACCOUNT, false, internalCallContext);
Assert.assertEquals(tags.size(), 1);
Assert.assertEquals(tags.get(0).getTagDefinitionId(), tagDefinition.getId());
Assert.assertEquals(tags.get(0).getObjectId(), account.getId());
diff --git a/api/src/main/java/com/ning/billing/callcontext/InternalCallContext.java b/api/src/main/java/com/ning/billing/callcontext/InternalCallContext.java
index fb83e76..ae6e1c9 100644
--- a/api/src/main/java/com/ning/billing/callcontext/InternalCallContext.java
+++ b/api/src/main/java/com/ning/billing/callcontext/InternalCallContext.java
@@ -62,6 +62,12 @@ public class InternalCallContext extends InternalTenantContext {
callContext.getUpdatedDate());
}
+ public InternalCallContext(final InternalCallContext context, final Long accountRecordId) {
+ this(context.getTenantRecordId(), accountRecordId, context.getUserToken(), context.getCreatedBy(), context.getCallOrigin(),
+ context.getContextUserType(), context.getReasonCode(), context.getComments(), context.getCreatedDate(),
+ context.getUpdatedDate());
+ }
+
// TODO should not be needed if all services are using internal API
// Unfortunately not true as some APIs ae hidden in object -- e.g OverdueStateApplicator is doing subscription.cancelEntitlementWithDateOverrideBillingPolicy
public CallContext toCallContext(final UUID tenantId) {
diff --git a/api/src/main/java/com/ning/billing/entity/EntityBase.java b/api/src/main/java/com/ning/billing/entity/EntityBase.java
index b0f4fea..06c2cc2 100644
--- a/api/src/main/java/com/ning/billing/entity/EntityBase.java
+++ b/api/src/main/java/com/ning/billing/entity/EntityBase.java
@@ -45,7 +45,7 @@ public abstract class EntityBase implements Entity {
}
public EntityBase(final EntityBase target) {
- this.id = UUID.randomUUID();
+ this.id = target.getId();
this.createdDate = target.getCreatedDate();
this.updatedDate = target.getUpdatedDate();
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyNotificationPlugin.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyNotificationPlugin.java
index 77eb9b2..1f12d13 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyNotificationPlugin.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestJrubyNotificationPlugin.java
@@ -57,7 +57,7 @@ public class TestJrubyNotificationPlugin extends TestOSGIBase {
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(4));
assertTrue(busHandler.isCompleted(2 * DELAY));
- final List<Tag> tags = tagUserApi.getTagsForAccount(account.getId(), callContext);
+ final List<Tag> tags = tagUserApi.getTagsForAccount(account.getId(), false, callContext);
Assert.assertEquals(tags.size(), 1);
//final Tag tag = tags.get(0);
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
index 80fbf5a..ab97c53 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
@@ -147,7 +147,7 @@ public class TestIntegrationWithAutoInvoiceOffTag extends TestIntegrationBase {
busHandler.pushExpectedEvent(NextEvent.TAG);
tagApi.addTag(id, type, ControlTagType.AUTO_INVOICING_OFF.getId(), callContext);
assertListenerStatus();
- final List<Tag> tags = tagApi.getTagsForObject(id, type, callContext);
+ final List<Tag> tags = tagApi.getTagsForObject(id, type, false, callContext);
assertEquals(tags.size(), 1);
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java
index 06bae39..7816769 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java
@@ -270,7 +270,7 @@ public class TestIntegrationWithAutoPayOff extends TestIntegrationBase {
tagApi.addTag(id, type, ControlTagType.AUTO_PAY_OFF.getId(), callContext);
assertListenerStatus();
- final List<Tag> tags = tagApi.getTagsForObject(id, type, callContext);
+ final List<Tag> tags = tagApi.getTagsForObject(id, type, false, callContext);
assertEquals(tags.size(), 1);
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestTagApi.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestTagApi.java
index 6fe6a54..663612b 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestTagApi.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestTagApi.java
@@ -59,15 +59,15 @@ public class TestTagApi extends TestIntegrationBase {
tagUserApi.addTag(account.getId(), ObjectType.ACCOUNT, ControlTagType.AUTO_PAY_OFF.getId(), callContext);
assertListenerStatus();
- List<Tag> tags = tagUserApi.getTagsForAccount(account.getId(), callContext);
+ List<Tag> tags = tagUserApi.getTagsForAccount(account.getId(), false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
- tags = tagUserApi.getTagsForObject(account.getId(), ObjectType.ACCOUNT, callContext);
+ tags = tagUserApi.getTagsForObject(account.getId(), ObjectType.ACCOUNT, false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
- tags = tagUserApi.getTagsForAccountType(account.getId(), ObjectType.ACCOUNT, callContext);
+ tags = tagUserApi.getTagsForAccountType(account.getId(), ObjectType.ACCOUNT, false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
}
@@ -109,15 +109,15 @@ public class TestTagApi extends TestIntegrationBase {
tagUserApi.addTag(invoice.getId(), ObjectType.INVOICE, tagDefinition.getId(), callContext);
assertListenerStatus();
- List<Tag> tags = tagUserApi.getTagsForAccount(account.getId(), callContext);
+ List<Tag> tags = tagUserApi.getTagsForAccount(account.getId(), false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
- tags = tagUserApi.getTagsForObject(invoice.getId(), ObjectType.INVOICE, callContext);
+ tags = tagUserApi.getTagsForObject(invoice.getId(), ObjectType.INVOICE, false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
- tags = tagUserApi.getTagsForAccountType(account.getId(), ObjectType.INVOICE, callContext);
+ tags = tagUserApi.getTagsForAccountType(account.getId(), ObjectType.INVOICE, false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
@@ -128,15 +128,15 @@ public class TestTagApi extends TestIntegrationBase {
tagUserApi.addTag(account.getId(), ObjectType.ACCOUNT, ControlTagType.AUTO_PAY_OFF.getId(), callContext);
assertListenerStatus();
- tags = tagUserApi.getTagsForAccount(account.getId(), callContext);
+ tags = tagUserApi.getTagsForAccount(account.getId(), false, callContext);
Assert.assertEquals(tags.size(), 3);
checkTagsExists(tags);
- tags = tagUserApi.getTagsForObject(invoice.getId(), ObjectType.INVOICE, callContext);
+ tags = tagUserApi.getTagsForObject(invoice.getId(), ObjectType.INVOICE, false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
- tags = tagUserApi.getTagsForAccountType(account.getId(), ObjectType.INVOICE, callContext);
+ tags = tagUserApi.getTagsForAccountType(account.getId(), ObjectType.INVOICE, false, callContext);
Assert.assertEquals(tags.size(), 2);
checkTagsExists(tags);
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java b/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java
index 1099bf6..9d71eb5 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java
@@ -16,7 +16,6 @@
package com.ning.billing.beatrix.util;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -46,14 +45,12 @@ import com.ning.billing.subscription.engine.dao.SubscriptionEventSqlDao;
import com.ning.billing.subscription.engine.dao.SubscriptionSqlDao;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForAccount;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
+import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.dao.NonEntityDao;
import com.ning.billing.util.entity.Entity;
import com.ning.billing.util.entity.dao.EntityModelDao;
@@ -85,15 +82,14 @@ public class AuditChecker {
*/
public void checkAccountCreated(final Account account, final CallContext context) {
- AuditLogsForAccount result = auditUserApi.getAuditLogsForAccount(account.getId(), AuditLevel.FULL, context);
- checkAuditLog(ChangeType.INSERT, context, result.getAccountAuditLogs().get(0), account.getId(), AccountSqlDao.class, true, true);
- checkAuditLog(ChangeType.UPDATE, context, result.getAccountAuditLogs().get(1), account.getId(), AccountSqlDao.class, true, true);
+ final AccountAuditLogs result = auditUserApi.getAccountAuditLogs(account.getId(), AuditLevel.FULL, context);
+ checkAuditLog(ChangeType.INSERT, context, result.getAuditLogsForAccount().get(0), account.getId(), AccountSqlDao.class, true, true);
+ checkAuditLog(ChangeType.UPDATE, context, result.getAuditLogsForAccount().get(1), account.getId(), AccountSqlDao.class, true, true);
}
public void checkPaymentCreated(final Payment payment, final CallContext context) {
- AuditLogsForPayments result = getAuditLogsForPayment(payment, context);
- Assert.assertEquals(result.getPaymentsAuditLogs().size(), 1);
- final List<AuditLog> paymentLogs = result.getPaymentsAuditLogs().get(payment.getId());
+ final AccountAuditLogs result = auditUserApi.getAccountAuditLogs(payment.getAccountId(), AuditLevel.FULL, context);
+ final List<AuditLog> paymentLogs = result.getAuditLogsForPayment(payment.getId());
Assert.assertEquals(paymentLogs.size(), 2);
checkAuditLog(ChangeType.INSERT, context, paymentLogs.get(0), payment.getId(), PaymentSqlDao.class, true, false);
checkAuditLog(ChangeType.UPDATE, context, paymentLogs.get(1), payment.getId(), PaymentSqlDao.class, true, false);
@@ -105,16 +101,16 @@ public class AuditChecker {
// Pass the call callcontext used to create the bundle
public void checkBundleCreated(final UUID bundleId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- Assert.assertEquals(auditLogsForBundles.getBundlesAuditLogs().keySet().size(), 1);
- checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.getBundlesAuditLogs().get(bundleId).get(0), bundleId, BundleSqlDao.class, false, false);
+ final List<AuditLog> auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
+ Assert.assertTrue(auditLogsForBundles.size() >= 1);
+ checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.get(0), bundleId, BundleSqlDao.class, false, false);
}
// Pass the call callcontext used to update the bundle
public void checkBundleUpdated(final UUID bundleId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- Assert.assertEquals(auditLogsForBundles.getBundlesAuditLogs().keySet().size(), 1);
- checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.getBundlesAuditLogs().get(bundleId).get(auditLogsForBundles.getBundlesAuditLogs().get(bundleId).size() - 1), bundleId, BundleSqlDao.class, false, false);
+ final List<AuditLog> auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
+ Assert.assertTrue(auditLogsForBundles.size() > 1);
+ checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.get(auditLogsForBundles.size() - 1), bundleId, BundleSqlDao.class, false, false);
}
/**
@@ -123,19 +119,17 @@ public class AuditChecker {
// Pass the call callcontext used to create the subscription
public void checkSubscriptionCreated(final UUID bundleId, final UUID subscriptionId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- Assert.assertEquals(auditLogsForBundles.getSubscriptionsAuditLogs().keySet().size(), 1);
- checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).get(0), subscriptionId, SubscriptionSqlDao.class, false, true);
+ final List<AuditLog> auditLogsForSubscription = getAuditLogsForSubscription(bundleId, subscriptionId, context);
+ Assert.assertTrue(auditLogsForSubscription.size() >= 1);
+ checkAuditLog(ChangeType.INSERT, context, auditLogsForSubscription.get(0), subscriptionId, SubscriptionSqlDao.class, false, true);
}
// Pass the call callcontext used to update the subscription
public void checkSubscriptionUpdated(final UUID bundleId, final UUID subscriptionId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
-
- Assert.assertEquals(auditLogsForBundles.getSubscriptionsAuditLogs().keySet().size(), 1);
- Assert.assertEquals(auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).size(), 2);
- checkAuditLog(ChangeType.INSERT, auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).get(0));
- checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).get(1), subscriptionId, SubscriptionSqlDao.class, false, false);
+ final List<AuditLog> auditLogsForSubscription = getAuditLogsForSubscription(bundleId, subscriptionId, context);
+ Assert.assertEquals(auditLogsForSubscription.size(), 2);
+ checkAuditLog(ChangeType.INSERT, auditLogsForSubscription.get(0));
+ checkAuditLog(ChangeType.UPDATE, context, auditLogsForSubscription.get(1), subscriptionId, SubscriptionSqlDao.class, false, false);
}
/**
@@ -144,24 +138,17 @@ public class AuditChecker {
// Pass the call callcontext used to create the subscription event
public void checkSubscriptionEventCreated(final UUID bundleId, final UUID subscriptionEventId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.getSubscriptionEventsAuditLogs().get(subscriptionEventId).get(0), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
+ final List<AuditLog> auditLogsForSubscriptionEvent = getAuditLogsForSubscriptionEvent(bundleId, subscriptionEventId, context);
+ Assert.assertEquals(auditLogsForSubscriptionEvent.size(), 1);
+ checkAuditLog(ChangeType.INSERT, context, auditLogsForSubscriptionEvent.get(0), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
}
// Pass the call callcontext used to update the subscription event
public void checkSubscriptionEventUpdated(final UUID bundleId, final UUID subscriptionEventId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- checkAuditLog(ChangeType.INSERT, auditLogsForBundles.getSubscriptionEventsAuditLogs().get(subscriptionEventId).get(0));
- checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.getSubscriptionEventsAuditLogs().get(subscriptionEventId).get(1), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
- }
-
- /**
- * ******************************************** PAYMENT *******************************************************
- */
-
- private AuditLogsForPayments getAuditLogsForPayment(final Payment payment, final CallContext context) {
- AuditLogsForPayments results = auditUserApi.getAuditLogsForPayments(Collections.singletonList(payment), AuditLevel.FULL, context);
- return results;
+ final List<AuditLog> auditLogsForSubscriptionEvent = getAuditLogsForSubscriptionEvent(bundleId, subscriptionEventId, context);
+ Assert.assertEquals(auditLogsForSubscriptionEvent.size(), 2);
+ checkAuditLog(ChangeType.INSERT, auditLogsForSubscriptionEvent.get(0));
+ checkAuditLog(ChangeType.UPDATE, context, auditLogsForSubscriptionEvent.get(1), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
}
/**
@@ -169,32 +156,53 @@ public class AuditChecker {
*/
public void checkInvoiceCreated(final Invoice invoice, final CallContext context) {
- AuditLogsForInvoices result = getAuditLogForInvoice(invoice, context);
- Assert.assertEquals(result.getInvoiceAuditLogs().keySet().size(), 1);
- final List<AuditLog> invoiceLogs = result.getInvoiceAuditLogs().get(invoice.getId());
+ final List<AuditLog> invoiceLogs = getAuditLogForInvoice(invoice, context);
Assert.assertEquals(invoiceLogs.size(), 1);
checkAuditLog(ChangeType.INSERT, context, invoiceLogs.get(0), invoice.getId(), InvoiceSqlDao.class, false, false);
- Assert.assertEquals(result.getInvoiceItemsAuditLogs().keySet().size(), invoice.getInvoiceItems().size());
for (InvoiceItem cur : invoice.getInvoiceItems()) {
- final List<AuditLog> auditLogs = result.getInvoiceItemsAuditLogs().get(cur.getId());
+ final List<AuditLog> auditLogs = getAuditLogForInvoiceItem(cur, context);
Assert.assertEquals(auditLogs.size(), 1);
checkAuditLog(ChangeType.INSERT, context, auditLogs.get(0), cur.getId(), InvoiceItemSqlDao.class, false, false);
}
}
- private AuditLogsForBundles getAuditLogsForBundle(final UUID bundleId, final CallContext context) {
+ private List<AuditLog> getAuditLogsForBundle(final UUID bundleId, final TenantContext context) {
+ try {
+ final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context);
+ return auditUserApi.getAccountAuditLogs(bundle.getAccountId(), AuditLevel.FULL, context).getAuditLogsForBundle(bundle.getId());
+ } catch (final SubscriptionApiException e) {
+ Assert.fail(e.toString());
+ return null;
+ }
+ }
+
+ private List<AuditLog> getAuditLogsForSubscription(final UUID bundleId, final UUID subscriptionId, final TenantContext context) {
try {
final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context);
- return auditUserApi.getAuditLogsForBundles(Collections.singletonList(bundle), AuditLevel.FULL, context);
- } catch (SubscriptionApiException e) {
+ return auditUserApi.getAccountAuditLogs(bundle.getAccountId(), AuditLevel.FULL, context).getAuditLogsForSubscription(subscriptionId);
+ } catch (final SubscriptionApiException e) {
Assert.fail(e.toString());
return null;
}
}
- private AuditLogsForInvoices getAuditLogForInvoice(final Invoice invoice, final CallContext context) {
- return auditUserApi.getAuditLogsForInvoices(Collections.singletonList(invoice), AuditLevel.FULL, context);
+ private List<AuditLog> getAuditLogsForSubscriptionEvent(final UUID bundleId, final UUID subscriptionEventId, final TenantContext context) {
+ try {
+ final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context);
+ return auditUserApi.getAccountAuditLogs(bundle.getAccountId(), AuditLevel.FULL, context).getAuditLogsForSubscriptionEvent(subscriptionEventId);
+ } catch (final SubscriptionApiException e) {
+ Assert.fail(e.toString());
+ return null;
+ }
+ }
+
+ private List<AuditLog> getAuditLogForInvoice(final Invoice invoice, final TenantContext context) {
+ return auditUserApi.getAccountAuditLogs(invoice.getAccountId(), AuditLevel.FULL, context).getAuditLogsForInvoice(invoice.getId());
+ }
+
+ private List<AuditLog> getAuditLogForInvoiceItem(final InvoiceItem invoiceItem, final TenantContext context) {
+ return auditUserApi.getAccountAuditLogs(invoiceItem.getAccountId(), AuditLevel.FULL, context).getAuditLogsForInvoiceItem(invoiceItem.getId());
}
private void checkAuditLog(final ChangeType insert, final AuditLog auditLog) {
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 6d0feb4..d3b627f 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -147,7 +147,7 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
@Override
public Invoice getInvoiceByNumber(final Integer number, final TenantContext context) throws InvoiceApiException {
- // TODO (PIERRE) Populate accountRecordId in callcontext
+ // The account record id will be populated in the DAO
return new DefaultInvoice(dao.getByNumber(number, internalCallContextFactory.createInternalTenantContext(context)));
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index 1ea4350..754b74d 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -43,6 +43,7 @@ import com.ning.billing.invoice.api.InvoicePaymentType;
import com.ning.billing.invoice.api.user.DefaultInvoiceAdjustmentEvent;
import com.ning.billing.invoice.notification.NextBillingDatePoster;
import com.ning.billing.util.cache.CacheControllerDispatcher;
+import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.dao.NonEntityDao;
import com.ning.billing.util.entity.dao.EntityDaoBase;
import com.ning.billing.util.entity.dao.EntitySqlDao;
@@ -71,6 +72,7 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
private final NextBillingDatePoster nextBillingDatePoster;
private final PersistentBus eventBus;
+ private final InternalCallContextFactory internalCallContextFactory;
private final InvoiceDaoHelper invoiceDaoHelper;
private final CBADao cbaDao;
@@ -80,10 +82,12 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
final PersistentBus eventBus,
final Clock clock,
final CacheControllerDispatcher cacheControllerDispatcher,
- final NonEntityDao nonEntityDao) {
+ final NonEntityDao nonEntityDao,
+ final InternalCallContextFactory internalCallContextFactory) {
super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao), InvoiceSqlDao.class);
this.nextBillingDatePoster = nextBillingDatePoster;
this.eventBus = eventBus;
+ this.internalCallContextFactory = internalCallContextFactory;
this.invoiceDaoHelper = new InvoiceDaoHelper();
this.cbaDao = new CBADao();
}
@@ -180,7 +184,12 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
if (invoice == null) {
throw new InvoiceApiException(ErrorCode.INVOICE_NUMBER_NOT_FOUND, number.longValue());
}
- invoiceDaoHelper.populateChildren(invoice, entitySqlDaoWrapperFactory, context);
+
+ // The context may not contain the account record id at this point - we couldn't do it in the API above
+ // as we couldn't get access to the invoice object until now.
+ final InternalTenantContext contextWithAccountRecordId = internalCallContextFactory.createInternalTenantContext(invoice.getAccountId(), context);
+ invoiceDaoHelper.populateChildren(invoice, entitySqlDaoWrapperFactory, contextWithAccountRecordId);
+
return invoice;
}
});
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoHelper.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoHelper.java
index 54965fd..801eaf7 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoHelper.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoHelper.java
@@ -19,6 +19,8 @@ package com.ning.billing.invoice.dao;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -40,11 +42,11 @@ import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap.Builder;
public class InvoiceDaoHelper {
-
/**
* Find amounts to adjust for individual items, if not specified.
* The user gives us a list of items to adjust associated with a given amount (how much to refund per invoice item).
@@ -57,7 +59,6 @@ public class InvoiceDaoHelper {
* @param context the tenant callcontext
* @return the final mapping between invoice item ids and amount to refund
* @throws com.ning.billing.invoice.api.InvoiceApiException
- *
*/
public Map<UUID, BigDecimal> computeItemAdjustments(final String invoiceId,
final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory,
@@ -98,12 +99,10 @@ public class InvoiceDaoHelper {
return invoiceItemIdsWithAmountsBuilder.build();
}
-
/**
- * @param invoiceItem item we are adjusting
- * @param requestedPositiveAmountToAdjust
- * amount we are adjusting for that item
- * @param invoiceItems list of all invoice items on this invoice
+ * @param invoiceItem item we are adjusting
+ * @param requestedPositiveAmountToAdjust amount we are adjusting for that item
+ * @param invoiceItems list of all invoice items on this invoice
* @return the amount we should really adjust based on whether or not the item got repaired
*/
private BigDecimal computeItemAdjustmentAmount(final UUID invoiceItem, final BigDecimal requestedPositiveAmountToAdjust, final List<InvoiceItemModelDao> invoiceItems) {
@@ -155,13 +154,11 @@ public class InvoiceDaoHelper {
return requestedPositiveAmount;
}
-
public List<InvoiceModelDao> getUnpaidInvoicesByAccountFromTransaction(final UUID accountId, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final LocalDate upToDate, final InternalTenantContext context) {
final List<InvoiceModelDao> invoices = getAllInvoicesByAccountFromTransaction(entitySqlDaoWrapperFactory, context);
return getUnpaidInvoicesByAccountFromTransaction(invoices, upToDate);
}
-
public List<InvoiceModelDao> getUnpaidInvoicesByAccountFromTransaction(final List<InvoiceModelDao> invoices, @Nullable final LocalDate upToDate) {
final Collection<InvoiceModelDao> unpaidInvoices = Collections2.filter(invoices, new Predicate<InvoiceModelDao>() {
@Override
@@ -224,11 +221,11 @@ public class InvoiceDaoHelper {
}
public void populateChildren(final InvoiceModelDao invoice, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
- getInvoiceItemsWithinTransaction(invoice, entitySqlDaoWrapperFactory, context);
- getInvoicePaymentsWithinTransaction(invoice, entitySqlDaoWrapperFactory, context);
+ getInvoiceItemsWithinTransaction(ImmutableList.<InvoiceModelDao>of(invoice), entitySqlDaoWrapperFactory, context);
+ getInvoicePaymentsWithinTransaction(ImmutableList.<InvoiceModelDao>of(invoice), entitySqlDaoWrapperFactory, context);
}
- public void populateChildren(final List<InvoiceModelDao> invoices, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
+ public void populateChildren(final Iterable<InvoiceModelDao> invoices, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
getInvoiceItemsWithinTransaction(invoices, entitySqlDaoWrapperFactory, context);
getInvoicePaymentsWithinTransaction(invoices, entitySqlDaoWrapperFactory, context);
}
@@ -244,37 +241,49 @@ public class InvoiceDaoHelper {
return amount == null ? BigDecimal.ZERO : amount;
}
- private void getInvoiceItemsWithinTransaction(final List<InvoiceModelDao> invoices, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
- for (final InvoiceModelDao invoice : invoices) {
- getInvoiceItemsWithinTransaction(invoice, entitySqlDaoWrapperFactory, context);
- }
- }
-
- private void getInvoiceItemsWithinTransaction(final InvoiceModelDao invoice, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
- final String invoiceId = invoice.getId().toString();
+ private void getInvoiceItemsWithinTransaction(final Iterable<InvoiceModelDao> invoices, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
+ final InvoiceItemSqlDao invoiceItemSqlDao = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class);
+ final List<InvoiceItemModelDao> invoiceItemsForAccount = invoiceItemSqlDao.getByAccountRecordId(context);
- final InvoiceItemSqlDao transInvoiceItemSqlDao = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class);
- final List<InvoiceItemModelDao> items = transInvoiceItemSqlDao.getInvoiceItemsByInvoice(invoiceId, context);
- invoice.addInvoiceItems(items);
- }
+ final Map<UUID, List<InvoiceItemModelDao>> invoiceItemsPerInvoiceId = new HashMap<UUID, List<InvoiceItemModelDao>>();
+ for (final InvoiceItemModelDao item : invoiceItemsForAccount) {
+ if (invoiceItemsPerInvoiceId.get(item.getInvoiceId()) == null) {
+ invoiceItemsPerInvoiceId.put(item.getInvoiceId(), new LinkedList<InvoiceItemModelDao>());
+ }
+ invoiceItemsPerInvoiceId.get(item.getInvoiceId()).add(item);
+ }
- private void getInvoicePaymentsWithinTransaction(final List<InvoiceModelDao> invoices, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
for (final InvoiceModelDao invoice : invoices) {
- getInvoicePaymentsWithinTransaction(invoice, entitySqlDaoWrapperFactory, context);
+ // Make sure to set invoice items to a non-null value
+ final List<InvoiceItemModelDao> invoiceItemsForInvoice = Objects.firstNonNull(invoiceItemsPerInvoiceId.get(invoice.getId()), ImmutableList.<InvoiceItemModelDao>of());
+ invoice.addInvoiceItems(invoiceItemsForInvoice);
}
}
- private void getInvoicePaymentsWithinTransaction(final InvoiceModelDao invoice, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
+ private void getInvoicePaymentsWithinTransaction(final Iterable<InvoiceModelDao> invoices, final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory, final InternalTenantContext context) {
final InvoicePaymentSqlDao invoicePaymentSqlDao = entitySqlDaoWrapperFactory.become(InvoicePaymentSqlDao.class);
- final String invoiceId = invoice.getId().toString();
- final List<InvoicePaymentModelDao> invoicePayments = invoicePaymentSqlDao.getPaymentsForInvoice(invoiceId, context);
- for (final InvoicePaymentModelDao cur : invoicePayments) {
- if (cur.getCurrency() != cur.getProcessedCurrency()) {
- // If any entry is set with a different processed currency, we use it as a processed currency.
- invoice.setProcessedCurrency(cur.getProcessedCurrency());
- break;
+ final List<InvoicePaymentModelDao> invoicePaymentsForAccount = invoicePaymentSqlDao.getByAccountRecordId(context);
+
+ final Map<UUID, List<InvoicePaymentModelDao>> invoicePaymentsPerInvoiceId = new HashMap<UUID, List<InvoicePaymentModelDao>>();
+ for (final InvoicePaymentModelDao invoicePayment : invoicePaymentsForAccount) {
+ if (invoicePaymentsPerInvoiceId.get(invoicePayment.getInvoiceId()) == null) {
+ invoicePaymentsPerInvoiceId.put(invoicePayment.getInvoiceId(), new LinkedList<InvoicePaymentModelDao>());
+ }
+ invoicePaymentsPerInvoiceId.get(invoicePayment.getInvoiceId()).add(invoicePayment);
+ }
+
+ for (final InvoiceModelDao invoice : invoices) {
+ // Make sure to set payments to a non-null value
+ final List<InvoicePaymentModelDao> invoicePaymentsForInvoice = Objects.firstNonNull(invoicePaymentsPerInvoiceId.get(invoice.getId()), ImmutableList.<InvoicePaymentModelDao>of());
+ invoice.addPayments(invoicePaymentsForInvoice);
+
+ for (final InvoicePaymentModelDao invoicePayment : invoicePaymentsForInvoice) {
+ if (invoicePayment.getCurrency() != invoicePayment.getProcessedCurrency()) {
+ // If any entry is set with a different processed currency, we use it as a processed currency.
+ invoice.setProcessedCurrency(invoicePayment.getProcessedCurrency());
+ break;
+ }
}
}
- invoice.addPayments(invoicePayments);
}
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
index 00d3c1e..9dc4d55 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
@@ -30,6 +30,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.ning.billing.account.api.Account;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.InvoiceTestSuiteWithEmbeddedDB;
import com.ning.billing.invoice.api.Invoice;
@@ -70,7 +71,8 @@ public class TestDefaultInvoiceMigrationApi extends InvoiceTestSuiteWithEmbedded
Assert.assertNotNull(migrationInvoiceId);
//Double check it was created and values are correct
- final InvoiceModelDao invoice = invoiceDao.getById(migrationInvoiceId, internalCallContext);
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(accountId, callContext);
+ final InvoiceModelDao invoice = invoiceDao.getById(migrationInvoiceId, internalTenantContext);
Assert.assertNotNull(invoice);
Assert.assertEquals(invoice.getAccountId(), accountId);
@@ -111,8 +113,9 @@ public class TestDefaultInvoiceMigrationApi extends InvoiceTestSuiteWithEmbedded
// ACCOUNT balance should reflect total of migration and non-migration invoices
@Test(groups = "slow")
public void testBalance() throws InvoiceApiException {
- final InvoiceModelDao migrationInvoice = invoiceDao.getById(migrationInvoiceId, internalCallContext);
- final InvoiceModelDao regularInvoice = invoiceDao.getById(regularInvoiceId, internalCallContext);
+ final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(accountId, callContext);
+ final InvoiceModelDao migrationInvoice = invoiceDao.getById(migrationInvoiceId, internalTenantContext);
+ final InvoiceModelDao regularInvoice = invoiceDao.getById(regularInvoiceId, internalTenantContext);
final BigDecimal balanceOfAllInvoices = InvoiceModelDaoHelper.getBalance(migrationInvoice).add(InvoiceModelDaoHelper.getBalance(regularInvoice));
final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
index 683f296..634eb14 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
@@ -346,12 +346,12 @@ public class TestDefaultInvoiceUserApi extends InvoiceTestSuiteWithEmbeddedDB {
public void testAddRemoveWrittenOffTag() throws InvoiceApiException, TagApiException {
invoiceUserApi.tagInvoiceAsWrittenOff(invoiceId, callContext);
- List<Tag> tags = tagUserApi.getTagsForObject(invoiceId, ObjectType.INVOICE, callContext);
+ List<Tag> tags = tagUserApi.getTagsForObject(invoiceId, ObjectType.INVOICE, false, callContext);
assertEquals(tags.size(), 1);
assertEquals(tags.get(0).getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId());
invoiceUserApi.tagInvoiceAsNotWrittenOff(invoiceId, callContext);
- tags = tagUserApi.getTagsForObject(invoiceId, ObjectType.INVOICE, callContext);
+ tags = tagUserApi.getTagsForObject(invoiceId, ObjectType.INVOICE, false, callContext);
assertEquals(tags.size(), 0);
}
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
index 2ad6556..0488412 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
@@ -712,7 +712,6 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
assertEquals(cbaAfterRefund.compareTo(expectedCba), 0);
}
-
}
@Test(groups = "slow")
@@ -1412,14 +1411,14 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
// Verify scenario - no CBA should have been used
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 10.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 10.00, 10.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 10.00, 10.00, context);
// Delete the CBA on invoice 1
invoiceDao.deleteCBA(accountId, invoice1.getId(), creditBalanceAdjInvoiceItem1.getId(), context);
// Verify the result
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 0.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 0.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 0.00, context);
}
@Test(groups = "slow")
@@ -1470,16 +1469,16 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
// Verify scenario - half of the CBA should have been used
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 5.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00);
- invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00, context);
+ invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00, context);
// Refund Payment before we can deleted CBA
invoiceDao.createRefund(paymentId, new BigDecimal("10.0"), false, ImmutableMap.<UUID, BigDecimal>of(), UUID.randomUUID(), context);
// Verify all three invoices were affected
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 0.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 5.00, 5.00);
- invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 5.00, 5.00, context);
+ invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00, context);
}
@Test(groups = "slow")
@@ -1507,7 +1506,6 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
invoiceUtil.createInvoiceItem(repairAdjInvoiceItem, context);
invoiceUtil.createInvoiceItem(creditBalanceAdjInvoiceItem1, context);
-
final BigDecimal paymentAmount = new BigDecimal("10.00");
final UUID paymentId = UUID.randomUUID();
@@ -1545,17 +1543,17 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
// Verify scenario - all CBA should have been used
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 0.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00);
- invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00);
- invoiceUtil.verifyInvoice(invoice3.getId(), 0.00, -5.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00, context);
+ invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00, context);
+ invoiceUtil.verifyInvoice(invoice3.getId(), 0.00, -5.00, context);
invoiceDao.createRefund(paymentId, paymentAmount, false, ImmutableMap.<UUID, BigDecimal>of(), UUID.randomUUID(), context);
// Verify all three invoices were affected
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 0.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 10.00, 10.00);
- invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00);
- invoiceUtil.verifyInvoice(invoice3.getId(), 0.00, -5.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 10.00, 10.00, context);
+ invoiceUtil.verifyInvoice(invoice2.getId(), 0.00, -5.00, context);
+ invoiceUtil.verifyInvoice(invoice3.getId(), 0.00, -5.00, context);
}
@Test(groups = "slow")
@@ -1580,7 +1578,7 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
// Verify scenario
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 10.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00, context);
// Delete the CBA on invoice 1
try {
@@ -1592,6 +1590,6 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
// Verify the result
Assert.assertEquals(invoiceDao.getAccountCBA(accountId, context).doubleValue(), 10.00);
- invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00);
+ invoiceUtil.verifyInvoice(invoice1.getId(), 0.00, 10.00, context);
}
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
index e64ddeb..17c2f2c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
@@ -82,7 +82,6 @@ import com.google.common.collect.ImmutableMap;
public class TestInvoiceHelper {
-
public static final Currency accountCurrency = Currency.USD;
public static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
@@ -131,7 +130,6 @@ public class TestInvoiceHelper {
public static final BigDecimal THREE_HUNDRED_AND_SIXTY_FIVE = new BigDecimal("365.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal THREE_HUNDRED_AND_SIXTY_SIX = new BigDecimal("366.0").setScale(NUMBER_OF_DECIMALS);
-
private final InvoiceGenerator generator;
private final BillingInternalApi billingApi;
private final AccountInternalApi accountApi;
@@ -149,7 +147,6 @@ public class TestInvoiceHelper {
private final InvoicePaymentSqlDao invoicePaymentSqlDao;
private final InvoiceItemSqlDao invoiceItemSqlDao;
-
@Inject
public TestInvoiceHelper(final InvoiceGenerator generator, final IDBI dbi,
final BillingInternalApi billingApi, final AccountInternalApi accountApi, final AccountUserApi accountUserApi, final SubscriptionBaseInternalApi subscriptionApi, final BusService busService,
@@ -283,8 +280,8 @@ public class TestInvoiceHelper {
}
}
- public void verifyInvoice(final UUID invoiceId, final double balance, final double cbaAmount) throws InvoiceApiException {
- final InvoiceModelDao invoice = invoiceDao.getById(invoiceId, internalCallContext);
+ public void verifyInvoice(final UUID invoiceId, final double balance, final double cbaAmount, final InternalTenantContext context) throws InvoiceApiException {
+ final InvoiceModelDao invoice = invoiceDao.getById(invoiceId, context);
Assert.assertEquals(InvoiceModelDaoHelper.getBalance(invoice).doubleValue(), balance);
Assert.assertEquals(InvoiceModelDaoHelper.getCBAAmount(invoice).doubleValue(), cbaAmount);
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
index e408af4..21507b8 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
@@ -20,12 +20,9 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import javax.annotation.Nullable;
-
import com.ning.billing.account.api.Account;
import com.ning.billing.entitlement.api.SubscriptionBundle;
import com.ning.billing.invoice.api.Invoice;
@@ -34,16 +31,11 @@ import com.ning.billing.invoice.api.InvoiceItemType;
import com.ning.billing.invoice.api.InvoicePayment;
import com.ning.billing.payment.api.Payment;
import com.ning.billing.payment.api.Refund;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
public class AccountTimelineJson {
@@ -95,35 +87,14 @@ public class AccountTimelineJson {
return tmp.toString();
}
-
public AccountTimelineJson(final Account account, final List<Invoice> invoices, final List<Payment> payments,
- final List<SubscriptionBundle> bundlesTimeline, final Multimap<UUID, Refund> refundsByPayment,
- final Multimap<UUID, InvoicePayment> chargebacksByPayment, @Nullable final AuditLogsForInvoices invoicesAuditLogs,
- @Nullable final AuditLogsForPayments paymentsAuditLogs, @Nullable final AuditLogsForRefunds refundsAuditLogs,
- @Nullable final AuditLogsForInvoicePayments chargebacksAuditLogs, @Nullable final AuditLogsForBundles bundlesAuditLogs) {
- this(account, invoices, payments, bundlesTimeline, refundsByPayment, chargebacksByPayment,
- invoicesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : invoicesAuditLogs.getInvoiceAuditLogs(),
- invoicesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : invoicesAuditLogs.getInvoiceItemsAuditLogs(),
- paymentsAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : paymentsAuditLogs.getPaymentsAuditLogs(),
- refundsAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : refundsAuditLogs.getRefundsAuditLogs(),
- chargebacksAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : chargebacksAuditLogs.getInvoicePaymentsAuditLogs(),
- bundlesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : bundlesAuditLogs.getBundlesAuditLogs(),
- bundlesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : bundlesAuditLogs.getSubscriptionsAuditLogs(),
- bundlesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : bundlesAuditLogs.getSubscriptionEventsAuditLogs());
- }
-
- public AccountTimelineJson(final Account account, final List<Invoice> invoices, final List<Payment> payments, final List<SubscriptionBundle> bundles,
- final Multimap<UUID, Refund> refundsByPayment, final Multimap<UUID, InvoicePayment> chargebacksByPayment,
- final Map<UUID, List<AuditLog>> invoiceAuditLogs, final Map<UUID, List<AuditLog>> invoiceItemsAuditLogs,
- final Map<UUID, List<AuditLog>> paymentsAuditLogs, final Map<UUID, List<AuditLog>> refundsAuditLogs,
- final Map<UUID, List<AuditLog>> chargebacksAuditLogs, final Map<UUID, List<AuditLog>> bundlesAuditLogs,
- final Map<UUID, List<AuditLog>> subscriptionsAuditLogs, final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs) {
+ final List<SubscriptionBundle> bundles, final Multimap<UUID, Refund> refundsByPayment,
+ final Multimap<UUID, InvoicePayment> chargebacksByPayment, final AccountAuditLogs accountAuditLogs) {
this.account = new AccountJson(account, null, null);
this.bundles = new LinkedList<BundleJson>();
for (final SubscriptionBundle bundle : bundles) {
- final List<AuditLog> bundleAuditLogs = bundlesAuditLogs.get(bundle.getId());
- final BundleJson jsonWithSubscriptions = new BundleJson(bundle, bundleAuditLogs,
- subscriptionsAuditLogs, subscriptionEventsAuditLogs);
+ final List<AuditLog> bundleAuditLogs = accountAuditLogs.getAuditLogsForBundle(bundle.getId());
+ final BundleJson jsonWithSubscriptions = new BundleJson(bundle, accountAuditLogs);
this.bundles.add(jsonWithSubscriptions);
}
@@ -133,43 +104,41 @@ public class AccountTimelineJson {
for (final Invoice invoice : invoices) {
for (final InvoiceItem invoiceItem : invoice.getInvoiceItems()) {
if (InvoiceItemType.CREDIT_ADJ.equals(invoiceItem.getInvoiceItemType())) {
- final List<AuditLog> auditLogs = invoiceItemsAuditLogs.get(invoiceItem.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForInvoiceItem(invoiceItem.getId());
credits.add(new CreditJson(invoice, invoiceItem, auditLogs));
}
}
}
// Create now the invoice json objects
for (final Invoice invoice : invoices) {
- final List<AuditLog> auditLogs = invoiceAuditLogs.get(invoice.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForInvoice(invoice.getId());
this.invoices.add(new InvoiceJson(invoice,
- getBundleExternalKey(invoice, bundles),
- credits,
- auditLogs));
+ getBundleExternalKey(invoice, bundles),
+ credits,
+ auditLogs));
}
this.payments = new LinkedList<PaymentJson>();
for (final Payment payment : payments) {
final List<RefundJson> refunds = new ArrayList<RefundJson>();
for (final Refund refund : refundsByPayment.get(payment.getId())) {
- final List<AuditLog> auditLogs = refundsAuditLogs.get(refund.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForRefund(refund.getId());
// TODO add adjusted invoice items?
refunds.add(new RefundJson(refund, null, auditLogs));
}
final List<ChargebackJson> chargebacks = new ArrayList<ChargebackJson>();
for (final InvoicePayment chargeback : chargebacksByPayment.get(payment.getId())) {
- final List<AuditLog> auditLogs = chargebacksAuditLogs.get(chargeback.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForChargeback(chargeback.getId());
chargebacks.add(new ChargebackJson(payment.getAccountId(), chargeback, auditLogs));
}
- final int nbOfPaymentAttempts = payment.getAttempts().size();
- final String status = payment.getPaymentStatus().toString();
- final List<AuditLog> auditLogs = paymentsAuditLogs.get(payment.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForPayment(payment.getId());
this.payments.add(new PaymentJson(payment,
getBundleExternalKey(payment.getInvoiceId(), invoices, bundles),
refunds,
- chargebacks,
- auditLogs));
+ chargebacks,
+ auditLogs));
}
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
index da1a3e8..c3cae9c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
@@ -18,15 +18,13 @@ package com.ning.billing.jaxrs.json;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
import javax.annotation.Nullable;
import com.ning.billing.entitlement.api.Subscription;
import com.ning.billing.entitlement.api.SubscriptionBundle;
import com.ning.billing.entitlement.api.SubscriptionEvent;
-import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -71,26 +69,21 @@ public class BundleJson extends JsonBase {
return externalKey;
}
- public BundleJson(final SubscriptionBundle bundle, final List<AuditLog> auditLogs,
- final Map<UUID, List<AuditLog>> subscriptionsAuditLogs, final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs) {
- super(toAuditLogJson(auditLogs));
+ public BundleJson(final SubscriptionBundle bundle, @Nullable final AccountAuditLogs accountAuditLogs) {
+ super(toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForBundle(bundle.getId())));
this.accountId = bundle.getAccountId().toString();
this.bundleId = bundle.getId().toString();
this.externalKey = bundle.getExternalKey();
this.subscriptions = new LinkedList<SubscriptionJson>();
for (final Subscription cur : bundle.getSubscriptions()) {
-
final ImmutableList<SubscriptionEvent> events = ImmutableList.<SubscriptionEvent>copyOf(Collections2.filter(bundle.getTimeline().getSubscriptionEvents(), new Predicate<SubscriptionEvent>() {
@Override
public boolean apply(@Nullable final SubscriptionEvent input) {
return input.getEntitlementId().equals(cur.getId());
}
}));
- this.subscriptions.add(new SubscriptionJson(cur,
- events,
- (subscriptionsAuditLogs != null ? subscriptionsAuditLogs.get(cur.getId()) : null),
- subscriptionEventsAuditLogs));
+ this.subscriptions.add(new SubscriptionJson(cur, events, accountAuditLogs));
}
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
index 3958225..b3ed9d8 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
@@ -19,8 +19,6 @@ package com.ning.billing.jaxrs.json;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
import javax.annotation.Nullable;
@@ -28,6 +26,7 @@ import org.joda.time.LocalDate;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.audit.AuditLog;
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -80,9 +79,8 @@ public class InvoiceJson extends JsonBase {
this.items = items;
}
-
- public InvoiceJson(final Invoice input, @Nullable final List<AuditLog> auditLogs) {
- this(input, null, null, auditLogs);
+ public InvoiceJson(final Invoice input) {
+ this(input, false, null);
}
public InvoiceJson(final Invoice input, final String bundleKeys, final List<CreditJson> credits, final List<AuditLog> auditLogs) {
@@ -91,11 +89,13 @@ public class InvoiceJson extends JsonBase {
input.getBalance(), input.getAccountId().toString(), bundleKeys, credits, null, toAuditLogJson(auditLogs));
}
- public InvoiceJson(final Invoice input, @Nullable final List<AuditLog> invoiceAuditLogs, @Nullable final Map<UUID, List<AuditLog>> invoiceItemsAuditLogs) {
- super(toAuditLogJson(invoiceAuditLogs));
+ public InvoiceJson(final Invoice input, final boolean withItems, @Nullable final AccountAuditLogs accountAuditLogs) {
+ super(toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForInvoice(input.getId())));
this.items = new ArrayList<InvoiceItemJson>(input.getInvoiceItems().size());
- for (final InvoiceItem item : input.getInvoiceItems()) {
- this.items.add(new InvoiceItemJson(item, invoiceItemsAuditLogs == null ? null : invoiceItemsAuditLogs.get(item.getId())));
+ if (withItems) {
+ for (final InvoiceItem item : input.getInvoiceItems()) {
+ this.items.add(new InvoiceItemJson(item, accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForInvoiceItem(item.getId())));
+ }
}
this.amount = input.getChargedAmount();
this.currency = input.getCurrency().toString();
@@ -199,7 +199,7 @@ public class InvoiceJson extends JsonBase {
if (amount != null ? amount.compareTo(that.amount) != 0 : that.amount != null) {
return false;
}
- if (balance != null ? balance.compareTo(that.balance) != 0: that.balance != null) {
+ if (balance != null ? balance.compareTo(that.balance) != 0 : that.balance != null) {
return false;
}
if (bundleKeys != null ? !bundleKeys.equals(that.bundleKeys) : that.bundleKeys != null) {
@@ -226,7 +226,7 @@ public class InvoiceJson extends JsonBase {
if (items != null ? !items.equals(that.items) : that.items != null) {
return false;
}
- if (refundAdj != null ? refundAdj.compareTo(that.refundAdj) != 0: that.refundAdj != null) {
+ if (refundAdj != null ? refundAdj.compareTo(that.refundAdj) != 0 : that.refundAdj != null) {
return false;
}
if (targetDate != null ? targetDate.compareTo(that.targetDate) != 0 : that.targetDate != null) {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
index ad23683..dfaca55 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
@@ -18,8 +18,6 @@ package com.ning.billing.jaxrs.json;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
import javax.annotation.Nullable;
@@ -31,7 +29,7 @@ import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.entitlement.api.Subscription;
import com.ning.billing.entitlement.api.SubscriptionEvent;
-import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -313,12 +311,10 @@ public class SubscriptionJson extends JsonBase {
this.newEvents = newEvents;
}
-
public SubscriptionJson(final Subscription subscription,
final List<SubscriptionEvent> subscriptionEvents,
- final List<AuditLog> subscriptionAuditLogs,
- final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs) {
- super(toAuditLogJson(subscriptionAuditLogs));
+ @Nullable final AccountAuditLogs accountAuditLogs) {
+ super(toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForSubscription(subscription.getId())));
this.startDate = subscription.getEffectiveStartDate();
this.productName = subscription.getLastActiveProduct().getName();
this.productCategory = subscription.getLastActiveProductCategory().name();
@@ -334,20 +330,20 @@ public class SubscriptionJson extends JsonBase {
this.externalKey = subscription.getExternalKey();
this.events = subscriptionEvents != null ? new LinkedList<EventSubscriptionJson>() : null;
if (events != null) {
- for (SubscriptionEvent cur : subscriptionEvents) {
+ for (final SubscriptionEvent cur : subscriptionEvents) {
final BillingPeriod billingPeriod = cur.getNextBillingPeriod() != null ? cur.getNextBillingPeriod() : cur.getPrevBillingPeriod();
final Product product = cur.getNextProduct() != null ? cur.getNextProduct() : cur.getPrevProduct();
final PriceList priceList = cur.getNextPriceList() != null ? cur.getNextPriceList() : cur.getPrevPriceList();
final PlanPhase phase = cur.getNextPhase() != null ? cur.getNextPhase() : cur.getPrevPhase();
this.events.add(new EventSubscriptionJson(cur.getId().toString(),
- billingPeriod != null ? billingPeriod.toString() : null,
- cur.getRequestedDate(),
- cur.getEffectiveDate(),
- product != null ? product.getName() : null,
- priceList != null ? priceList.getName() : null,
- cur.getSubscriptionEventType().toString(),
- phase != null ? phase.getName() : null,
- (subscriptionEventsAuditLogs != null ? toAuditLogJson(subscriptionEventsAuditLogs.get(cur.getId())) : null)));
+ billingPeriod != null ? billingPeriod.toString() : null,
+ cur.getRequestedDate(),
+ cur.getEffectiveDate(),
+ product != null ? product.getName() : null,
+ priceList != null ? priceList.getName() : null,
+ cur.getSubscriptionEventType().toString(),
+ phase != null ? phase.getName() : null,
+ toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForSubscriptionEvent(cur.getId()))));
}
}
this.newEvents = null;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index a210318..eb44ad3 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -90,11 +90,7 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.entity.Pagination;
@@ -231,7 +227,7 @@ public class AccountResource extends JaxRsResourceBase {
final Collection<BundleJson> result = Collections2.transform(bundles, new Function<SubscriptionBundle, BundleJson>() {
@Override
public BundleJson apply(final SubscriptionBundle input) {
- return new BundleJson(input, null, null, null);
+ return new BundleJson(input, null);
}
});
return Response.status(Status.OK).entity(result).build();
@@ -322,15 +318,12 @@ public class AccountResource extends JaxRsResourceBase {
// Get the invoices
final List<Invoice> invoices = invoiceApi.getInvoicesByAccount(account.getId(), tenantContext);
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(invoices, auditMode.getLevel(), tenantContext);
// Get the payments
final List<Payment> payments = paymentApi.getAccountPayments(accountId, tenantContext);
- final AuditLogsForPayments paymentsAuditLogs = auditUserApi.getAuditLogsForPayments(payments, auditMode.getLevel(), tenantContext);
// Get the refunds
final List<Refund> refunds = paymentApi.getAccountRefunds(account, tenantContext);
- final AuditLogsForRefunds refundsAuditLogs = auditUserApi.getAuditLogsForRefunds(refunds, auditMode.getLevel(), tenantContext);
final Multimap<UUID, Refund> refundsByPayment = ArrayListMultimap.<UUID, Refund>create();
for (final Refund refund : refunds) {
refundsByPayment.put(refund.getPaymentId(), refund);
@@ -338,7 +331,6 @@ public class AccountResource extends JaxRsResourceBase {
// Get the chargebacks
final List<InvoicePayment> chargebacks = invoicePaymentApi.getChargebacksByAccountId(accountId, tenantContext);
- final AuditLogsForInvoicePayments chargebacksAuditLogs = auditUserApi.getAuditLogsForInvoicePayments(chargebacks, auditMode.getLevel(), tenantContext);
final Multimap<UUID, InvoicePayment> chargebacksByPayment = ArrayListMultimap.<UUID, InvoicePayment>create();
for (final InvoicePayment chargeback : chargebacks) {
chargebacksByPayment.put(chargeback.getPaymentId(), chargeback);
@@ -346,12 +338,13 @@ public class AccountResource extends JaxRsResourceBase {
// Get the bundles
final List<SubscriptionBundle> bundles = subscriptionApi.getSubscriptionBundlesForAccountId(account.getId(), tenantContext);
- final AuditLogsForBundles bundlesAuditLogs = auditUserApi.getAuditLogsForBundles(bundles, auditMode.getLevel(), tenantContext);
+
+ // Get all audit logs
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
final AccountTimelineJson json = new AccountTimelineJson(account, invoices, payments, bundles,
refundsByPayment, chargebacksByPayment,
- invoicesAuditLogs, paymentsAuditLogs, refundsAuditLogs,
- chargebacksAuditLogs, bundlesAuditLogs);
+ accountAuditLogs);
return Response.status(Status.OK).entity(json).build();
}
@@ -392,7 +385,6 @@ public class AccountResource extends JaxRsResourceBase {
return Response.status(Status.OK).build();
}
-
/*
* ************************** INVOICE CBA REBALANCING ********************************
*/
@@ -421,7 +413,7 @@ public class AccountResource extends JaxRsResourceBase {
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + INVOICES)
@Produces(APPLICATION_JSON)
- public Response getInvoices(@PathParam("accountId") final String accountId,
+ public Response getInvoices(@PathParam("accountId") final String accountIdString,
@QueryParam(QUERY_INVOICE_WITH_ITEMS) @DefaultValue("false") final boolean withItems,
@QueryParam(QUERY_UNPAID_INVOICES_ONLY) @DefaultValue("false") final boolean unpaidInvoicesOnly,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@@ -429,35 +421,22 @@ public class AccountResource extends JaxRsResourceBase {
final TenantContext tenantContext = context.createContext(request);
// Verify the account exists
- accountUserApi.getAccountById(UUID.fromString(accountId), tenantContext);
-
+ final UUID accountId = UUID.fromString(accountIdString);
+ accountUserApi.getAccountById(accountId, tenantContext);
final List<Invoice> invoices = unpaidInvoicesOnly ?
- new ArrayList<Invoice>(invoiceApi.getUnpaidInvoicesByAccountId(UUID.fromString(accountId), null, tenantContext)) :
- invoiceApi.getInvoicesByAccount(UUID.fromString(accountId), tenantContext);
-
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(invoices, auditMode.getLevel(), tenantContext);
+ new ArrayList<Invoice>(invoiceApi.getUnpaidInvoicesByAccountId(accountId, null, tenantContext)) :
+ invoiceApi.getInvoicesByAccount(accountId, tenantContext);
- if (withItems) {
- final List<InvoiceJson> result = new LinkedList<InvoiceJson>();
- for (final Invoice invoice : invoices) {
- result.add(new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()),
- invoicesAuditLogs.getInvoiceItemsAuditLogs()));
- }
-
- return Response.status(Status.OK).entity(result).build();
- } else {
- final List<InvoiceJson> result = new LinkedList<InvoiceJson>();
- for (final Invoice invoice : invoices) {
- result.add(new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId())));
- }
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
- return Response.status(Status.OK).entity(result).build();
+ final List<InvoiceJson> result = new LinkedList<InvoiceJson>();
+ for (final Invoice invoice : invoices) {
+ result.add(new InvoiceJson(invoice, withItems, accountAuditLogs));
}
- }
+ return Response.status(Status.OK).entity(result).build();
+ }
/*
* ************************** PAYMENTS ********************************
@@ -500,7 +479,6 @@ public class AccountResource extends JaxRsResourceBase {
return Response.status(Status.OK).build();
}
-
@POST
@Path("/{accountId:" + UUID_PATTERN + "}/" + PAYMENT_METHODS)
@Consumes(APPLICATION_JSON)
@@ -580,7 +558,6 @@ public class AccountResource extends JaxRsResourceBase {
return Response.status(Status.OK).build();
}
-
/*
* ************************** CHARGEBACKS ********************************
*/
@@ -598,7 +575,6 @@ public class AccountResource extends JaxRsResourceBase {
return Response.status(Response.Status.OK).entity(chargebacksJson).build();
}
-
/*
* ************************** REFUNDS ********************************
*/
@@ -622,7 +598,6 @@ public class AccountResource extends JaxRsResourceBase {
return Response.status(Status.OK).entity(result).build();
}
-
/*
* ************************** OVERDUE ********************************
*/
@@ -687,10 +662,12 @@ public class AccountResource extends JaxRsResourceBase {
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String accountIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+ @QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
@javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, context.createContext(request));
+ final UUID accountId = UUID.fromString(accountIdString);
+ return super.getTags(accountId, accountId, auditMode, includedDeleted, context.createContext(request));
}
@POST
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
index 91dcf0e..a29f632 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
@@ -58,6 +58,7 @@ import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TenantContext;
import com.google.inject.Inject;
@@ -91,10 +92,9 @@ public class BundleResource extends JaxRsResourceBase {
@Produces(APPLICATION_JSON)
public Response getBundle(@PathParam("bundleId") final String bundleId,
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
-
final UUID id = UUID.fromString(bundleId);
final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(id, context.createContext(request));
- final BundleJson json = new BundleJson(bundle, null, null, null);
+ final BundleJson json = new BundleJson(bundle, null);
return Response.status(Status.OK).entity(json).build();
}
@@ -103,7 +103,7 @@ public class BundleResource extends JaxRsResourceBase {
public Response getBundleByKey(@QueryParam(QUERY_EXTERNAL_KEY) final String externalKey,
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
final SubscriptionBundle bundle = subscriptionApi.getActiveSubscriptionBundleForExternalKey(externalKey, context.createContext(request));
- final BundleJson json = new BundleJson(bundle, null, null, null);
+ final BundleJson json = new BundleJson(bundle, null);
return Response.status(Status.OK).entity(json).build();
}
@@ -131,11 +131,11 @@ public class BundleResource extends JaxRsResourceBase {
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response resumeBundle(@PathParam(ID_PARAM_NAME) final String id,
- @QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
- @HeaderParam(HDR_CREATED_BY) final String createdBy,
- @HeaderParam(HDR_REASON) final String reason,
- @HeaderParam(HDR_COMMENT) final String comment,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException, EntitlementApiException {
+ @QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
+ @HeaderParam(HDR_CREATED_BY) final String createdBy,
+ @HeaderParam(HDR_REASON) final String reason,
+ @HeaderParam(HDR_COMMENT) final String comment,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException, EntitlementApiException {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final UUID bundleId = UUID.fromString(id);
@@ -185,10 +185,14 @@ public class BundleResource extends JaxRsResourceBase {
@GET
@Path("/{bundleId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String bundleIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, context.createContext(request));
+ @QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, SubscriptionApiException {
+ final UUID bundleId = UUID.fromString(bundleIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context.createContext(request));
+ return super.getTags(bundle.getAccountId(), bundleId, auditMode, includedDeleted, tenantContext);
}
@PUT
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
index 449a023..dbd5d85 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
@@ -18,8 +18,6 @@ package com.ning.billing.jaxrs.resources;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@@ -38,7 +36,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
-import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,13 +67,12 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
+import com.ning.billing.util.audit.AccountAuditLogs;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@@ -109,7 +105,6 @@ public class InvoiceResource extends JaxRsResourceBase {
this.invoiceNotifier = invoiceNotifier;
}
-
@GET
@Path("/{invoiceId:" + UUID_PATTERN + "}/")
@Produces(APPLICATION_JSON)
@@ -119,19 +114,12 @@ public class InvoiceResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException {
final TenantContext tenantContext = context.createContext(request);
final Invoice invoice = invoiceApi.getInvoice(UUID.fromString(invoiceId), tenantContext);
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(ImmutableList.<Invoice>of(invoice),
- auditMode.getLevel(),
- tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(invoice.getAccountId(), auditMode.getLevel(), tenantContext);
if (invoice == null) {
throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceId);
} else {
- final InvoiceJson json = withItems ?
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()),
- invoicesAuditLogs.getInvoiceItemsAuditLogs()) :
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()));
+ final InvoiceJson json = new InvoiceJson(invoice, withItems, accountAuditLogs);
return Response.status(Status.OK).entity(json).build();
}
}
@@ -145,19 +133,12 @@ public class InvoiceResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException {
final TenantContext tenantContext = context.createContext(request);
final Invoice invoice = invoiceApi.getInvoiceByNumber(invoiceNumber, tenantContext);
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(ImmutableList.<Invoice>of(invoice),
- auditMode.getLevel(),
- tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(invoice.getAccountId(), auditMode.getLevel(), tenantContext);
if (invoice == null) {
throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceNumber);
} else {
- final InvoiceJson json = withItems ?
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()),
- invoicesAuditLogs.getInvoiceItemsAuditLogs()) :
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()));
+ final InvoiceJson json = new InvoiceJson(invoice, withItems, accountAuditLogs);
return Response.status(Status.OK).entity(json).build();
}
}
@@ -186,7 +167,7 @@ public class InvoiceResource extends JaxRsResourceBase {
final Invoice generatedInvoice = invoiceApi.triggerInvoiceGeneration(UUID.fromString(accountId), inputDate, dryRun,
callContext);
if (dryRun) {
- return Response.status(Status.OK).entity(new InvoiceJson(generatedInvoice, null)).build();
+ return Response.status(Status.OK).entity(new InvoiceJson(generatedInvoice)).build();
} else {
return uriBuilder.buildResponse(InvoiceResource.class, "getInvoice", generatedInvoice.getId());
}
@@ -250,7 +231,7 @@ public class InvoiceResource extends JaxRsResourceBase {
@POST
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
- @Path("/" +CHARGES)
+ @Path("/" + CHARGES)
public Response createExternalCharge(final InvoiceItemJson externalChargeJson,
@QueryParam(QUERY_REQUESTED_DT) final String requestedDateTimeString,
@QueryParam(QUERY_PAY_INVOICE) @DefaultValue("false") final Boolean payInvoice,
@@ -334,11 +315,18 @@ public class InvoiceResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final TenantContext tenantContext = context.createContext(request);
final List<Payment> payments = paymentApi.getInvoicePayments(UUID.fromString(invoiceId), tenantContext);
- final AuditLogsForPayments auditLogsForPayments = auditUserApi.getAuditLogsForPayments(payments, auditMode.getLevel(), tenantContext);
-
final List<PaymentJson> result = new ArrayList<PaymentJson>(payments.size());
+ if (payments.size() == 0) {
+ return Response.status(Status.OK).entity(result).build();
+ }
+
+ final AccountAuditLogsForObjectType auditLogsForPayments = auditUserApi.getAccountAuditLogs(payments.get(0).getAccountId(),
+ ObjectType.PAYMENT,
+ auditMode.getLevel(),
+ tenantContext);
+
for (final Payment cur : payments) {
- result.add(new PaymentJson(cur, auditLogsForPayments.getPaymentsAuditLogs().get(cur.getId())));
+ result.add(new PaymentJson(cur, auditLogsForPayments.getAuditLogs(cur.getId())));
}
return Response.status(Status.OK).entity(result).build();
@@ -430,16 +418,20 @@ public class InvoiceResource extends JaxRsResourceBase {
}
@GET
- @Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS)
+ @Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String invoiceIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, context.createContext(request));
+ @QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, InvoiceApiException {
+ final UUID invoiceId = UUID.fromString(invoiceIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final Invoice invoice = invoiceApi.getInvoice(invoiceId, tenantContext);
+ return super.getTags(invoice.getAccountId(), invoiceId, auditMode, includedDeleted, tenantContext);
}
@POST
- @Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS)
+ @Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response createTags(@PathParam(ID_PARAM_NAME) final String id,
@@ -454,7 +446,7 @@ public class InvoiceResource extends JaxRsResourceBase {
}
@DELETE
- @Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS)
+ @Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response deleteTags(@PathParam(ID_PARAM_NAME) final String id,
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
index ca1ee21..f7046e9 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
@@ -82,6 +82,7 @@ public interface JaxrsResource {
public static final String QUERY_PAYMENT_WITH_REFUNDS_AND_CHARGEBACKS = "withRefundsAndChargebacks";
public static final String QUERY_TAGS = "tagList";
+ public static final String QUERY_TAGS_INCLUDED_DELETED = "includedDeleted";
public static final String QUERY_CUSTOM_FIELDS = "customFieldList";
public static final String QUERY_PAYMENT_METHOD_PLUGIN_NAME = "pluginName";
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
index 150b97e..e583cd4 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -17,8 +17,10 @@
package com.ning.billing.jaxrs.resources;
import java.util.Collection;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import javax.ws.rs.core.Response;
@@ -48,6 +50,7 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
@@ -98,14 +101,19 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
return null;
}
- protected Response getTags(final UUID taggedObjectId, final AuditMode auditMode, final TenantContext context) throws TagDefinitionApiException {
- final List<Tag> tags = tagUserApi.getTagsForObject(taggedObjectId, getObjectType(), context);
+ protected Response getTags(final UUID accountId, final UUID taggedObjectId, final AuditMode auditMode, final boolean includeDeleted, final TenantContext context) throws TagDefinitionApiException {
+ final List<Tag> tags = tagUserApi.getTagsForObject(taggedObjectId, getObjectType(), includeDeleted, context);
+ final AccountAuditLogsForObjectType tagsAuditLogs = auditUserApi.getAccountAuditLogs(accountId, ObjectType.TAG, auditMode.getLevel(), context);
+ final Map<UUID, TagDefinition> tagDefinitionsCache = new HashMap<UUID, TagDefinition>();
final Collection<TagJson> result = new LinkedList<TagJson>();
for (final Tag tag : tags) {
- final TagDefinition tagDefinition = tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context);
- // TODO PIERRE - Bulk API
- final List<AuditLog> auditLogs = auditUserApi.getAuditLogs(tag.getId(), ObjectType.TAG, auditMode.getLevel(), context);
+ if (tagDefinitionsCache.get(tag.getTagDefinitionId()) == null) {
+ tagDefinitionsCache.put(tag.getTagDefinitionId(), tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context));
+ }
+ final TagDefinition tagDefinition = tagDefinitionsCache.get(tag.getTagDefinitionId());
+
+ final List<AuditLog> auditLogs = tagsAuditLogs.getAuditLogs(tag.getId());
result.add(new TagJson(tagDefinition, auditLogs));
}
@@ -189,7 +197,6 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
return toLocalDate(account, inputDateTime, context);
}
-
protected LocalDate toLocalDate(final Account account, final String inputDate, final TenantContext context) {
final LocalDate maybeResult = extractLocalDate(inputDate);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
index 0a65996..8f99a77 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
@@ -121,8 +121,8 @@ public class PaymentResource extends JaxRsResourceBase {
paymentJson = new PaymentJson(payment,
null, // TODO - the keys are really only used for the timeline
- refunds,
- chargebacks);
+ refunds,
+ chargebacks);
} else {
paymentJson = new PaymentJson(payment, null);
}
@@ -135,10 +135,10 @@ public class PaymentResource extends JaxRsResourceBase {
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response retryFailedPayment(@PathParam(ID_PARAM_NAME) final String paymentIdString,
- @HeaderParam(HDR_CREATED_BY) final String createdBy,
- @HeaderParam(HDR_REASON) final String reason,
- @HeaderParam(HDR_COMMENT) final String comment,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException, PaymentApiException {
+ @HeaderParam(HDR_CREATED_BY) final String createdBy,
+ @HeaderParam(HDR_REASON) final String reason,
+ @HeaderParam(HDR_COMMENT) final String comment,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException, PaymentApiException {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
@@ -150,13 +150,11 @@ public class PaymentResource extends JaxRsResourceBase {
return Response.status(Status.OK).entity(new PaymentJson(newPayment, null)).build();
}
-
-
@GET
@Path("/{paymentId:" + UUID_PATTERN + "}/" + CHARGEBACKS)
@Produces(APPLICATION_JSON)
public Response getChargebacksForPayment(@PathParam("paymentId") final String paymentId,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException {
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException {
final TenantContext tenantContext = context.createContext(request);
final List<InvoicePayment> chargebacks = invoicePaymentApi.getChargebacksByPaymentId(UUID.fromString(paymentId), tenantContext);
@@ -173,7 +171,6 @@ public class PaymentResource extends JaxRsResourceBase {
return Response.status(Response.Status.OK).entity(chargebacksJson).build();
}
-
@GET
@Path("/{paymentId:" + UUID_PATTERN + "}/" + REFUNDS)
@Produces(APPLICATION_JSON)
@@ -229,7 +226,7 @@ public class PaymentResource extends JaxRsResourceBase {
}
@GET
- @Path("/{paymentId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
+ @Path("/{paymentId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
@Produces(APPLICATION_JSON)
public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@@ -238,7 +235,7 @@ public class PaymentResource extends JaxRsResourceBase {
}
@POST
- @Path("/{paymentId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
+ @Path("/{paymentId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
@@ -252,7 +249,7 @@ public class PaymentResource extends JaxRsResourceBase {
}
@DELETE
- @Path("/{paymentId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
+ @Path("/{paymentId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
@@ -268,10 +265,14 @@ public class PaymentResource extends JaxRsResourceBase {
@GET
@Path("/{paymentId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String paymentIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, context.createContext(request));
+ @QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, PaymentApiException {
+ final UUID paymentId = UUID.fromString(paymentIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final Payment payment = paymentApi.getPayment(paymentId, false, tenantContext);
+ return super.getTags(payment.getAccountId(), paymentId, auditMode, includedDeleted, tenantContext);
}
@POST
@@ -290,7 +291,7 @@ public class PaymentResource extends JaxRsResourceBase {
}
@DELETE
- @Path("/{paymentId:" + UUID_PATTERN + "}/"+ TAGS)
+ @Path("/{paymentId:" + UUID_PATTERN + "}/" + TAGS)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response deleteTags(@PathParam(ID_PARAM_NAME) final String id,
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
index f464200..eeb33e6 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
@@ -74,6 +74,7 @@ import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.userrequest.CompletionUserRequestBase;
import com.google.inject.Inject;
@@ -114,7 +115,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
final UUID uuid = UUID.fromString(subscriptionId);
final Subscription subscription = subscriptionApi.getSubscriptionForEntitlementId(uuid, context.createContext(request));
- final SubscriptionJson json = new SubscriptionJson(subscription, null, null, null);
+ final SubscriptionJson json = new SubscriptionJson(subscription, null, null);
return Response.status(Status.OK).entity(json).build();
}
@@ -429,10 +430,14 @@ public class SubscriptionResource extends JaxRsResourceBase {
@GET
@Path("/{subscriptionId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String subscriptionIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, context.createContext(request));
+ @QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, SubscriptionApiException {
+ final UUID subscriptionId = UUID.fromString(subscriptionIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final Subscription subscription = subscriptionApi.getSubscriptionForEntitlementId(subscriptionId, tenantContext);
+ return super.getTags(subscription.getAccountId(), subscriptionId, auditMode, includedDeleted, tenantContext);
}
@POST
diff --git a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
index 30a7eea..d123f56 100644
--- a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
+++ b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
@@ -22,10 +22,12 @@ import org.joda.time.DateTime;
import org.testng.Assert;
import org.testng.annotations.Test;
+import com.ning.billing.ObjectType;
import com.ning.billing.jaxrs.JaxrsTestSuiteNoDB;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.audit.DefaultAuditLog;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
import com.ning.billing.util.dao.EntityAudit;
import com.ning.billing.util.dao.TableName;
@@ -67,7 +69,7 @@ public class TestAuditLogJson extends JaxrsTestSuiteNoDB {
final ChangeType changeType = ChangeType.DELETE;
final EntityAudit entityAudit = new EntityAudit(tableName, recordId, changeType, null);
- final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLog auditLog = new DefaultAuditLog(new AuditLogModelDao(entityAudit, callContext), ObjectType.ACCOUNT_EMAIL, UUID.randomUUID());
final AuditLogJson auditLogJson = new AuditLogJson(auditLog);
Assert.assertEquals(auditLogJson.getChangeType(), changeType.toString());
NEWS 2(+2 -0)
diff --git a/NEWS b/NEWS
index 06a5585..31f07c8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,7 @@
0.8.7
DDL: remove unused paid_through_date column
+ Add API to retrieve deleted tags
+ Update killbill-oss-parent to 0.5.9
0.8.6
Partial fix for https://github.com/killbill/killbill/issues/141
diff --git a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
index 68195ff..6377b2d 100644
--- a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
+++ b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
@@ -40,7 +40,7 @@ import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.entity.Pagination;
-public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi {
+public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi {
private volatile ServiceRegistration<PaymentPluginApi> paymentInfoPluginRegistration;
@@ -90,6 +90,16 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi
}
@Override
+ public Pagination<PaymentInfoPlugin> searchPayments(final String searchKey, final Long offset, final Long limit, final TenantContext tenantContext) throws PaymentPluginApiException {
+ return callWithRuntimeAndChecking(new PluginCallback(VALIDATION_PLUGIN_TYPE.PAYMENT) {
+ @Override
+ public Pagination<PaymentInfoPlugin> doCall(final Ruby runtime) throws PaymentPluginApiException {
+ return ((PaymentPluginApi) pluginInstance).searchPayments(searchKey, offset, limit, tenantContext);
+ }
+ });
+ }
+
+ @Override
public RefundInfoPlugin processRefund(final UUID kbAccountId, final UUID kbPaymentId, final BigDecimal refundAmount, final Currency currency, final CallContext context) throws PaymentPluginApiException {
return callWithRuntimeAndChecking(new PluginCallback(VALIDATION_PLUGIN_TYPE.PAYMENT) {
diff --git a/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java b/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
index 718ca6b..3396d2c 100644
--- a/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
+++ b/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
@@ -52,6 +52,11 @@ public class TestPaymentPluginApi implements PaymentPluginApi {
testDao.insertProcessedPayment(kbPaymentId, kbPaymentMethodId, amount);
return new PaymentInfoPlugin() {
@Override
+ public UUID getKbPaymentId() {
+ return kbPaymentId;
+ }
+
+ @Override
public BigDecimal getAmount() {
return amount;
}
@@ -104,6 +109,36 @@ public class TestPaymentPluginApi implements PaymentPluginApi {
}
@Override
+ public Pagination<PaymentInfoPlugin> searchPayments(final String searchKey, final Long offset, final Long limit, final TenantContext tenantContext) throws PaymentPluginApiException {
+ return new Pagination<PaymentInfoPlugin>() {
+ @Override
+ public Long getCurrentOffset() {
+ return 0L;
+ }
+
+ @Override
+ public Long getNextOffset() {
+ return null;
+ }
+
+ @Override
+ public Long getMaxNbRecords() {
+ return 0L;
+ }
+
+ @Override
+ public Long getTotalNbRecords() {
+ return 0L;
+ }
+
+ @Override
+ public Iterator<PaymentInfoPlugin> iterator() {
+ return null;
+ }
+ };
+ }
+
+ @Override
public RefundInfoPlugin processRefund(final UUID kbAccountId, final UUID kbPaymentId, final BigDecimal refundAmount, final Currency currency, final CallContext context) throws PaymentPluginApiException {
return null;
}
@@ -165,7 +200,6 @@ public class TestPaymentPluginApi implements PaymentPluginApi {
};
}
-
@Override
public void resetPaymentMethods(final UUID kbAccountId, final List<PaymentMethodInfoPlugin> paymentMethods) throws PaymentPluginApiException {
}
diff --git a/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java b/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
index f5c0871..854aa07 100644
--- a/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
+++ b/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
@@ -53,6 +53,11 @@ public class TestPaymentPluginApi implements PaymentPluginApiWithTestControl {
public PaymentInfoPlugin processPayment(final UUID accountId, final UUID kbPaymentId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final CallContext context) throws PaymentPluginApiException {
return withRuntimeCheckForExceptions(new PaymentInfoPlugin() {
@Override
+ public UUID getKbPaymentId() {
+ return kbPaymentId;
+ }
+
+ @Override
public BigDecimal getAmount() {
return amount;
}
@@ -105,6 +110,11 @@ public class TestPaymentPluginApi implements PaymentPluginApiWithTestControl {
final BigDecimal someAmount = new BigDecimal("12.45");
return withRuntimeCheckForExceptions(new PaymentInfoPlugin() {
@Override
+ public UUID getKbPaymentId() {
+ return kbPaymentId;
+ }
+
+ @Override
public BigDecimal getAmount() {
return someAmount;
}
@@ -152,6 +162,36 @@ public class TestPaymentPluginApi implements PaymentPluginApiWithTestControl {
}
@Override
+ public Pagination<PaymentInfoPlugin> searchPayments(final String searchKey, final Long offset, final Long limit, final TenantContext tenantContext) throws PaymentPluginApiException {
+ return new Pagination<PaymentInfoPlugin>() {
+ @Override
+ public Long getCurrentOffset() {
+ return 0L;
+ }
+
+ @Override
+ public Long getNextOffset() {
+ return null;
+ }
+
+ @Override
+ public Long getMaxNbRecords() {
+ return 0L;
+ }
+
+ @Override
+ public Long getTotalNbRecords() {
+ return 0L;
+ }
+
+ @Override
+ public Iterator<PaymentInfoPlugin> iterator() {
+ return null;
+ }
+ };
+ }
+
+ @Override
public RefundInfoPlugin processRefund(final UUID accountId, final UUID kbPaymentId, final BigDecimal refundAmount, final Currency currency, final CallContext context) throws PaymentPluginApiException {
final BigDecimal someAmount = new BigDecimal("12.45");
@@ -259,7 +299,6 @@ public class TestPaymentPluginApi implements PaymentPluginApiWithTestControl {
public void resetPaymentMethods(final UUID accountId, final List<PaymentMethodInfoPlugin> paymentMethods) throws PaymentPluginApiException {
}
-
private <T> T withRuntimeCheckForExceptions(final T result) throws PaymentPluginApiException {
if (paymentPluginApiExceptionOnNextCalls != null) {
throw paymentPluginApiExceptionOnNextCalls;
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
index 8352981..0ee1c3b 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
@@ -90,6 +90,16 @@ public class DefaultPaymentApi implements PaymentApi {
}
@Override
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final TenantContext context) {
+ return paymentProcessor.searchPayments(searchKey, offset, limit, internalCallContextFactory.createInternalTenantContext(context));
+ }
+
+ @Override
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final TenantContext context) throws PaymentApiException {
+ return paymentProcessor.searchPayments(searchKey, offset, limit, pluginName, internalCallContextFactory.createInternalTenantContext(context));
+ }
+
+ @Override
public List<Payment> getInvoicePayments(final UUID invoiceId, final TenantContext context) {
return paymentProcessor.getInvoicePayments(invoiceId, internalCallContextFactory.createInternalTenantContext(context));
}
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
index f6bf2ae..19f8e02 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
@@ -86,10 +86,6 @@ public class PaymentMethodProcessor extends ProcessorBase {
super(pluginRegistry, accountInternalApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi);
}
- public Set<String> getAvailablePlugins() {
- return pluginRegistry.getAllServices();
- }
-
public UUID addPaymentMethod(final String paymentPluginServiceName, final Account account,
final boolean setDefault, final PaymentMethodPlugin paymentMethodProps, final InternalCallContext context)
throws PaymentApiException {
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
index 6ee14fa..addd642 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
@@ -16,8 +16,12 @@
package com.ning.billing.payment.core;
+import com.google.common.base.Function;
import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
import com.google.inject.name.Named;
import com.ning.billing.ErrorCode;
import com.ning.billing.ObjectType;
@@ -32,12 +36,16 @@ import com.ning.billing.osgi.api.OSGIServiceRegistration;
import com.ning.billing.payment.api.DefaultPayment;
import com.ning.billing.payment.api.DefaultPaymentErrorEvent;
import com.ning.billing.payment.api.DefaultPaymentInfoEvent;
+import com.ning.billing.payment.api.DefaultPaymentMethod;
import com.ning.billing.payment.api.DefaultPaymentPluginErrorEvent;
import com.ning.billing.payment.api.Payment;
import com.ning.billing.payment.api.PaymentApiException;
+import com.ning.billing.payment.api.PaymentMethod;
+import com.ning.billing.payment.api.PaymentMethodPlugin;
import com.ning.billing.payment.api.PaymentStatus;
import com.ning.billing.payment.dao.PaymentAttemptModelDao;
import com.ning.billing.payment.dao.PaymentDao;
+import com.ning.billing.payment.dao.PaymentMethodModelDao;
import com.ning.billing.payment.dao.PaymentModelDao;
import com.ning.billing.payment.dao.RefundModelDao;
import com.ning.billing.payment.dispatcher.PluginDispatcher;
@@ -56,6 +64,9 @@ import com.ning.billing.events.PaymentErrorInternalEvent;
import com.ning.billing.account.api.AccountInternalApi;
import com.ning.billing.invoice.api.InvoiceInternalApi;
import com.ning.billing.tag.TagInternalApi;
+import com.ning.billing.util.entity.DefaultPagination;
+import com.ning.billing.util.entity.Pagination;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -138,6 +149,73 @@ public class PaymentProcessor extends ProcessorBase {
return fromPaymentModelDao(model, pluginInfo, context);
}
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final InternalTenantContext internalTenantContext) {
+ // Note that we cannot easily do streaming here, since we would have to rely on the statistics
+ // returned by the Pagination objects from the plugins and we probably don't want to do that (if
+ // one plugin gets it wrong, it may starve the others).
+ final List<Payment> allResults = new LinkedList<Payment>();
+ Long totalNbRecords = 0L;
+ Long maxNbRecords = 0L;
+
+ // Search in all plugins (we treat the full set of results as a union with respect to offset/limit)
+ boolean firstSearch = true;
+ for (final String pluginName : getAvailablePlugins()) {
+ try {
+ final Pagination<Payment> payments;
+ if (allResults.size() >= limit) {
+ // We have enough results, we just keep going (limit 1) to get the stats
+ payments = searchPayments(searchKey, firstSearch ? offset : 0L, 1L, pluginName, internalTenantContext);
+ // Required to close database connections
+ ImmutableList.<Payment>copyOf(payments);
+ } else {
+ payments = searchPayments(searchKey, firstSearch ? offset : 0L, limit - allResults.size(), pluginName, internalTenantContext);
+ allResults.addAll(ImmutableList.<Payment>copyOf(payments));
+ }
+ firstSearch = false;
+ totalNbRecords += payments.getTotalNbRecords();
+ maxNbRecords += payments.getMaxNbRecords();
+ } catch (final PaymentApiException e) {
+ log.warn("Error while searching plugin " + pluginName, e);
+ // Non-fatal, continue to search other plugins
+ }
+ }
+
+ return new DefaultPagination<Payment>(offset, limit, totalNbRecords, maxNbRecords, allResults.iterator());
+ }
+
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
+ final Pagination<PaymentInfoPlugin> payments;
+ try {
+ payments = pluginApi.searchPayments(searchKey, offset, limit, buildTenantContext(internalTenantContext));
+ } catch (final PaymentPluginApiException e) {
+ throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENTS, pluginName, searchKey);
+ }
+
+ return new DefaultPagination<Payment>(payments,
+ limit,
+ Iterators.<Payment>filter(Iterators.<PaymentInfoPlugin, Payment>transform(payments.iterator(),
+ new Function<PaymentInfoPlugin, Payment>() {
+ @Override
+ public Payment apply(final PaymentInfoPlugin paymentInfoPlugin) {
+ if (paymentInfoPlugin.getKbPaymentId() == null) {
+ // Garbage from the plugin?
+ log.debug("Plugin {} returned a payment without a kbPaymentId for searchKey {}", pluginName, searchKey);
+ return null;
+ }
+
+ final PaymentModelDao model = paymentDao.getPayment(paymentInfoPlugin.getKbPaymentId(), internalTenantContext);
+ if (model == null) {
+ log.warn("Unable to find payment id " + paymentInfoPlugin.getKbPaymentId() + " present in plugin " + pluginName);
+ return null;
+ }
+
+ return fromPaymentModelDao(model, paymentInfoPlugin, internalTenantContext);
+ }
+ }),
+ Predicates.<Payment>notNull()));
+ }
+
public List<Payment> getInvoicePayments(final UUID invoiceId, final InternalTenantContext context) {
return getPayments(paymentDao.getPaymentsForInvoice(invoiceId, context), context);
}
diff --git a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
index b582bc8..a68b447 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
@@ -17,6 +17,7 @@
package com.ning.billing.payment.core;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -113,6 +114,10 @@ public abstract class ProcessorBase {
}
}
+ public Set<String> getAvailablePlugins() {
+ return pluginRegistry.getAllServices();
+ }
+
protected PaymentPluginApi getPaymentPluginApi(final String pluginName) throws PaymentApiException {
final PaymentPluginApi pluginApi = pluginRegistry.getServiceForName(pluginName);
if (pluginApi == null) {
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
index e7590c8..d23374f 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
@@ -17,6 +17,7 @@
package com.ning.billing.payment.provider;
import java.math.BigDecimal;
+import java.util.UUID;
import org.joda.time.DateTime;
@@ -26,6 +27,7 @@ import com.ning.billing.payment.plugin.api.PaymentPluginStatus;
public class DefaultNoOpPaymentInfoPlugin implements PaymentInfoPlugin {
+ private final UUID kbPaymentId;
private final BigDecimal amount;
private final DateTime effectiveDate;
private final DateTime createdDate;
@@ -33,8 +35,9 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentInfoPlugin {
private final String error;
private final Currency currency;
- public DefaultNoOpPaymentInfoPlugin(final BigDecimal amount, final Currency currency, final DateTime effectiveDate,
+ public DefaultNoOpPaymentInfoPlugin(final UUID kbPaymentId, final BigDecimal amount, final Currency currency, final DateTime effectiveDate,
final DateTime createdDate, final PaymentPluginStatus status, final String error) {
+ this.kbPaymentId = kbPaymentId;
this.amount = amount;
this.effectiveDate = effectiveDate;
this.createdDate = createdDate;
@@ -44,6 +47,11 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentInfoPlugin {
}
@Override
+ public UUID getKbPaymentId() {
+ return kbPaymentId;
+ }
+
+ @Override
public BigDecimal getAmount() {
return amount;
}
@@ -90,13 +98,14 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentInfoPlugin {
@Override
public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("DefaultNoOpPaymentInfoPlugin");
- sb.append("{amount=").append(amount);
+ final StringBuilder sb = new StringBuilder("DefaultNoOpPaymentInfoPlugin{");
+ sb.append("kbPaymentId=").append(kbPaymentId);
+ sb.append(", amount=").append(amount);
sb.append(", effectiveDate=").append(effectiveDate);
sb.append(", createdDate=").append(createdDate);
sb.append(", status=").append(status);
sb.append(", error='").append(error).append('\'');
+ sb.append(", currency=").append(currency);
sb.append('}');
return sb.toString();
}
@@ -112,18 +121,24 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentInfoPlugin {
final DefaultNoOpPaymentInfoPlugin that = (DefaultNoOpPaymentInfoPlugin) o;
- if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+ if (amount != null ? amount.compareTo(that.amount) != 0 : that.amount != null) {
return false;
}
- if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
+ if (createdDate != null ? createdDate.compareTo(that.createdDate) != 0 : that.createdDate != null) {
return false;
}
- if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
+ if (currency != that.currency) {
+ return false;
+ }
+ if (effectiveDate != null ? effectiveDate.compareTo(that.effectiveDate) != 0 : that.effectiveDate != null) {
return false;
}
if (error != null ? !error.equals(that.error) : that.error != null) {
return false;
}
+ if (kbPaymentId != null ? !kbPaymentId.equals(that.kbPaymentId) : that.kbPaymentId != null) {
+ return false;
+ }
if (status != that.status) {
return false;
}
@@ -133,11 +148,13 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentInfoPlugin {
@Override
public int hashCode() {
- int result = amount != null ? amount.hashCode() : 0;
+ int result = kbPaymentId != null ? kbPaymentId.hashCode() : 0;
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
result = 31 * result + (status != null ? status.hashCode() : 0);
result = 31 * result + (error != null ? error.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
return result;
}
}
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
index 9de86b6..066000e 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
@@ -96,7 +96,7 @@ public class DefaultNoOpPaymentProviderPlugin implements NoOpPaymentPluginApi {
}
final PaymentPluginStatus status = (makeAllInvoicesFailWithError.get() || makeNextInvoiceFailWithError.getAndSet(false)) ? PaymentPluginStatus.ERROR : PaymentPluginStatus.PROCESSED;
- final PaymentInfoPlugin result = new DefaultNoOpPaymentInfoPlugin(amount, currency, clock.getUTCNow(), clock.getUTCNow(), status, null);
+ final PaymentInfoPlugin result = new DefaultNoOpPaymentInfoPlugin(kbPaymentId, amount, currency, clock.getUTCNow(), clock.getUTCNow(), status, null);
payments.put(kbPaymentId.toString(), result);
return result;
}
@@ -111,6 +111,29 @@ public class DefaultNoOpPaymentProviderPlugin implements NoOpPaymentPluginApi {
}
@Override
+ public Pagination<PaymentInfoPlugin> searchPayments(final String searchKey, final Long offset, final Long limit, final TenantContext tenantContext) throws PaymentPluginApiException {
+ final ImmutableList<PaymentInfoPlugin> allResults = ImmutableList.<PaymentInfoPlugin>copyOf(Iterables.<PaymentInfoPlugin>filter(Iterables.<PaymentInfoPlugin>concat(payments.values()), new Predicate<PaymentInfoPlugin>() {
+ @Override
+ public boolean apply(final PaymentInfoPlugin input) {
+ return (input.getKbPaymentId() != null && input.getKbPaymentId().toString().equals(searchKey)) ||
+ (input.getFirstPaymentReferenceId() != null && input.getFirstPaymentReferenceId().contains(searchKey)) ||
+ (input.getSecondPaymentReferenceId() != null && input.getSecondPaymentReferenceId().contains(searchKey));
+ }
+ }));
+
+ final List<PaymentInfoPlugin> results;
+ if (offset >= allResults.size()) {
+ results = ImmutableList.<PaymentInfoPlugin>of();
+ } else if (offset + limit > allResults.size()) {
+ results = allResults.subList(offset.intValue(), allResults.size());
+ } else {
+ results = allResults.subList(offset.intValue(), offset.intValue() + limit.intValue());
+ }
+
+ return new DefaultPagination<PaymentInfoPlugin>(offset, limit, (long) results.size(), (long) payments.values().size(), results.iterator());
+ }
+
+ @Override
public void addPaymentMethod(final UUID kbAccountId, final UUID kbPaymentMethodId, final PaymentMethodPlugin paymentMethodProps, final boolean setDefault, final CallContext context) throws PaymentPluginApiException {
final PaymentMethodPlugin realWithID = new DefaultNoOpPaymentMethodPlugin(kbPaymentMethodId, paymentMethodProps);
List<PaymentMethodPlugin> pms = paymentMethods.get(kbPaymentMethodId.toString());
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java
index 8658da9..ba12401 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java
@@ -60,12 +60,17 @@ public class ExternalPaymentProviderPlugin implements PaymentPluginApi {
@Override
public PaymentInfoPlugin processPayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final CallContext context) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(amount, currency, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, amount, currency, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null);
}
@Override
public PaymentInfoPlugin getPaymentInfo(final UUID kbAccountId, final UUID kbPaymentId, final TenantContext context) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(BigDecimal.ZERO, null, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, BigDecimal.ZERO, null, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null);
+ }
+
+ @Override
+ public Pagination<PaymentInfoPlugin> searchPayments(final String searchKey, final Long offset, final Long limit, final TenantContext tenantContext) throws PaymentPluginApiException {
+ return new DefaultPagination<PaymentInfoPlugin>(offset, limit, 0L, 0L, Iterators.<PaymentInfoPlugin>emptyIterator());
}
@Override
diff --git a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
index f4e4ec9..39d330b 100644
--- a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -102,7 +102,7 @@ public class MockPaymentProviderPlugin implements NoOpPaymentPluginApi {
}
final PaymentPluginStatus status = (makeAllInvoicesFailWithError.get() || makeNextInvoiceFailWithError.getAndSet(false)) ? PaymentPluginStatus.ERROR : PaymentPluginStatus.PROCESSED;
- final PaymentInfoPlugin result = new DefaultNoOpPaymentInfoPlugin(amount, currency, clock.getUTCNow(), clock.getUTCNow(), status, null);
+ final PaymentInfoPlugin result = new DefaultNoOpPaymentInfoPlugin(kbPaymentId, amount, currency, clock.getUTCNow(), clock.getUTCNow(), status, null);
payments.put(kbPaymentId.toString(), result);
return result;
}
@@ -116,6 +116,18 @@ public class MockPaymentProviderPlugin implements NoOpPaymentPluginApi {
return payment;
}
+ @Override
+ public Pagination<PaymentInfoPlugin> searchPayments(final String searchKey, final Long offset, final Long limit, final TenantContext tenantContext) throws PaymentPluginApiException {
+ final ImmutableList<PaymentInfoPlugin> results = ImmutableList.<PaymentInfoPlugin>copyOf(Iterables.<PaymentInfoPlugin>filter(payments.values(), new Predicate<PaymentInfoPlugin>() {
+ @Override
+ public boolean apply(final PaymentInfoPlugin input) {
+ return (input.getKbPaymentId() != null && input.getKbPaymentId().equals(searchKey)) ||
+ (input.getFirstPaymentReferenceId() != null && input.getFirstPaymentReferenceId().contains(searchKey)) ||
+ (input.getSecondPaymentReferenceId() != null && input.getSecondPaymentReferenceId().contains(searchKey));
+ }
+ }));
+ return DefaultPagination.<PaymentInfoPlugin>build(offset, limit, results);
+ }
@Override
public void addPaymentMethod(final UUID kbAccountId, final UUID kbPaymentMethodId, final PaymentMethodPlugin paymentMethodProps, final boolean setDefault, final CallContext context) throws PaymentPluginApiException {
diff --git a/payment/src/test/java/com/ning/billing/payment/provider/TestDefaultNoOpPaymentInfoPlugin.java b/payment/src/test/java/com/ning/billing/payment/provider/TestDefaultNoOpPaymentInfoPlugin.java
index f74c0e0..c056958 100644
--- a/payment/src/test/java/com/ning/billing/payment/provider/TestDefaultNoOpPaymentInfoPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/provider/TestDefaultNoOpPaymentInfoPlugin.java
@@ -31,21 +31,22 @@ public class TestDefaultNoOpPaymentInfoPlugin extends PaymentTestSuiteNoDB {
@Test(groups = "fast")
public void testEquals() throws Exception {
+ final UUID kbPaymentId = UUID.randomUUID();
final BigDecimal amount = new BigDecimal("1.394810E-3");
final DateTime effectiveDate = clock.getUTCNow().plusDays(1);
final DateTime createdDate = clock.getUTCNow();
final PaymentPluginStatus status = PaymentPluginStatus.UNDEFINED;
final String error = UUID.randomUUID().toString();
- final DefaultNoOpPaymentInfoPlugin info = new DefaultNoOpPaymentInfoPlugin(amount, Currency.USD, effectiveDate, createdDate,
+ final DefaultNoOpPaymentInfoPlugin info = new DefaultNoOpPaymentInfoPlugin(kbPaymentId, amount, Currency.USD, effectiveDate, createdDate,
status, error);
Assert.assertEquals(info, info);
- final DefaultNoOpPaymentInfoPlugin sameInfo = new DefaultNoOpPaymentInfoPlugin(amount, Currency.USD, effectiveDate, createdDate,
+ final DefaultNoOpPaymentInfoPlugin sameInfo = new DefaultNoOpPaymentInfoPlugin(kbPaymentId, amount, Currency.USD, effectiveDate, createdDate,
status, error);
Assert.assertEquals(sameInfo, info);
- final DefaultNoOpPaymentInfoPlugin otherInfo = new DefaultNoOpPaymentInfoPlugin(amount, Currency.USD, effectiveDate, createdDate,
+ final DefaultNoOpPaymentInfoPlugin otherInfo = new DefaultNoOpPaymentInfoPlugin(kbPaymentId, amount, Currency.USD, effectiveDate, createdDate,
status, UUID.randomUUID().toString());
Assert.assertNotEquals(otherInfo, info);
}
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index d4cb24f..d61cf7e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
<parent>
<artifactId>killbill-oss-parent</artifactId>
<groupId>com.ning.billing</groupId>
- <version>0.5.8</version>
+ <version>0.5.9</version>
</parent>
<artifactId>killbill</artifactId>
<version>0.8.7-SNAPSHOT</version>
diff --git a/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java b/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
index 81d747f..cb39d3d 100644
--- a/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
+++ b/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
@@ -27,10 +27,12 @@ import org.skife.jdbi.v2.tweak.TransactionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.ning.billing.util.dao.AuditLogModelDaoMapper;
import com.ning.billing.util.dao.DateTimeArgumentFactory;
import com.ning.billing.util.dao.DateTimeZoneArgumentFactory;
import com.ning.billing.util.dao.EnumArgumentFactory;
import com.ning.billing.util.dao.LocalDateArgumentFactory;
+import com.ning.billing.util.dao.RecordIdIdMappingsMapper;
import com.ning.billing.util.dao.UUIDArgumentFactory;
import com.ning.billing.util.dao.UuidMapper;
import com.ning.jetty.jdbi.config.DaoConfig;
@@ -71,6 +73,8 @@ public class DBIProvider implements Provider<DBI> {
dbi.registerArgumentFactory(new LocalDateArgumentFactory());
dbi.registerArgumentFactory(new EnumArgumentFactory());
dbi.registerMapper(new UuidMapper());
+ dbi.registerMapper(new AuditLogModelDaoMapper());
+ dbi.registerMapper(new RecordIdIdMappingsMapper());
if (sqlLog != null) {
dbi.setSQLLog(sqlLog);
diff --git a/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java b/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
index 5126a79..5782bd8 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
@@ -432,14 +432,22 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
return getInvoiceWithAudits(invoiceId, AuditLevel.NONE);
}
+ protected InvoiceJson getInvoice(final String invoiceId, final Boolean withItems) throws IOException {
+ return doGetInvoice(invoiceId, withItems, InvoiceJson.class, AuditLevel.NONE);
+ }
+
protected InvoiceJson getInvoiceWithAudits(final String invoiceId, final AuditLevel auditLevel) throws IOException {
- return doGetInvoice(invoiceId, Boolean.FALSE, InvoiceJson.class, auditLevel);
+ return doGetInvoice(invoiceId, Boolean.TRUE, InvoiceJson.class, auditLevel);
}
protected InvoiceJson getInvoice(final Integer invoiceNumber) throws IOException {
return getInvoice(invoiceNumber.toString());
}
+ protected InvoiceJson getInvoice(final Integer invoiceNumber, final Boolean withItems) throws IOException {
+ return doGetInvoice(invoiceNumber.toString(), withItems, InvoiceJson.class, AuditLevel.NONE);
+ }
+
protected InvoiceJson getInvoiceWithItems(final String invoiceId) throws IOException {
return getInvoiceWithItemsWithAudits(invoiceId, AuditLevel.NONE);
}
@@ -470,7 +478,7 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
}
protected List<InvoiceJson> getInvoicesForAccountWithAudits(final String accountId, final AuditLevel auditLevel) throws IOException {
- return doGetInvoicesForAccount(accountId, Boolean.FALSE, new TypeReference<List<InvoiceJson>>() {}, auditLevel);
+ return doGetInvoicesForAccount(accountId, Boolean.TRUE, new TypeReference<List<InvoiceJson>>() {}, auditLevel);
}
protected List<InvoiceJson> getInvoicesWithItemsForAccount(final String accountId) throws IOException {
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
index 34a661e..c58fc6f 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
@@ -37,6 +37,7 @@ import com.ning.billing.util.api.AuditLevel;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
public class TestInvoice extends TestJaxrsBase {
@@ -60,8 +61,15 @@ public class TestInvoice extends TestJaxrsBase {
Assert.assertNull(auditLogJson.getComments());
}
- // Check we can retrieve an individual invoice
final InvoiceJson invoiceJson = invoices.get(0);
+
+ // Check get with & without items
+ assertTrue(getInvoice(invoiceJson.getInvoiceId(), Boolean.FALSE).getItems().isEmpty());
+ assertTrue(getInvoice(invoiceJson.getInvoiceNumber(), Boolean.FALSE).getItems().isEmpty());
+ assertEquals(getInvoice(invoiceJson.getInvoiceId(), Boolean.TRUE).getItems().size(), invoiceJson.getItems().size());
+ assertEquals(getInvoice(invoiceJson.getInvoiceNumber(), Boolean.TRUE).getItems().size(), invoiceJson.getItems().size());
+
+ // Check we can retrieve an individual invoice
final InvoiceJson firstInvoiceJson = getInvoice(invoiceJson.getInvoiceId());
assertEquals(firstInvoiceJson, invoiceJson);
@@ -173,7 +181,7 @@ public class TestInvoice extends TestJaxrsBase {
assertEquals(paymentsFromJson.size(), 2);
PaymentJson secondPayment = null;
for (PaymentJson cur : paymentsFromJson) {
- if (! cur.getPaymentId().equals(initialPaymentId)) {
+ if (!cur.getPaymentId().equals(initialPaymentId)) {
secondPayment = cur;
break;
}
@@ -291,7 +299,6 @@ public class TestInvoice extends TestJaxrsBase {
assertEquals(getInvoicesForAccount(accountJson.getAccountId()).size(), 3);
}
-
@Test(groups = "slow")
public void testExternalChargeOnNewInvoiceWithAutomaticPayment() throws Exception {
final AccountJson accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
@@ -345,7 +352,7 @@ public class TestInvoice extends TestJaxrsBase {
// Post an external charge
final BigDecimal chargeAmount = BigDecimal.TEN;
final InvoiceJson invoiceWithItems = createExternalChargeForInvoice(accountJson.getAccountId(), invoiceId,
- null, chargeAmount, null, null, false);
+ null, chargeAmount, null, null, false);
assertEquals(invoiceWithItems.getItems().size(), originalNumberOfItemsForInvoice + 1);
assertNull(invoiceWithItems.getItems().get(originalNumberOfItemsForInvoice).getBundleId());
@@ -379,7 +386,6 @@ public class TestInvoice extends TestJaxrsBase {
assertEquals(adjustedInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
}
-
@Test(groups = "slow")
public void testExternalChargeForBundleOnExistingInvoice() throws Exception {
final AccountJson accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
@@ -396,7 +402,7 @@ public class TestInvoice extends TestJaxrsBase {
final BigDecimal chargeAmount = BigDecimal.TEN;
final String bundleId = UUID.randomUUID().toString();
final InvoiceJson invoiceWithItems = createExternalChargeForInvoice(accountJson.getAccountId(), invoiceId,
- bundleId, chargeAmount, null, null, false);
+ bundleId, chargeAmount, null, null, false);
assertEquals(invoiceWithItems.getItems().size(), originalNumberOfItemsForInvoice + 1);
assertEquals(invoiceWithItems.getItems().get(originalNumberOfItemsForInvoice).getBundleId(), bundleId);
diff --git a/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java b/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
index 6f629b8..fd57844 100644
--- a/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
+++ b/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
@@ -16,44 +16,24 @@
package com.ning.billing.util.audit.api;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
-import javax.annotation.Nullable;
import javax.inject.Inject;
import com.ning.billing.ObjectType;
-import com.ning.billing.entitlement.api.Subscription;
-import com.ning.billing.entitlement.api.SubscriptionBundle;
-import com.ning.billing.entitlement.api.SubscriptionEvent;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.payment.api.Payment;
-import com.ning.billing.payment.api.Refund;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.audit.AccountAuditLogs;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForAccount;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
-import com.ning.billing.util.audit.DefaultAuditLogsForBundles;
-import com.ning.billing.util.audit.DefaultAuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.DefaultAuditLogsForInvoices;
-import com.ning.billing.util.audit.DefaultAuditLogsForPayments;
-import com.ning.billing.util.audit.DefaultAuditLogsForRefunds;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
import com.ning.billing.util.audit.dao.AuditDao;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.dao.TableName;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
public class DefaultAuditUserApi implements AuditUserApi {
@@ -68,77 +48,28 @@ public class DefaultAuditUserApi implements AuditUserApi {
}
@Override
- public AuditLogsForAccount getAuditLogsForAccount(final UUID accountId, final AuditLevel auditLevel, final TenantContext context) {
- return new DefaultAuditLogsForAccount(getAuditLogs(accountId, ObjectType.ACCOUNT, auditLevel, context));
- }
-
- @Override
- public AuditLogsForBundles getAuditLogsForBundles(final List<SubscriptionBundle> bundles, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> bundlesAuditLogs = new HashMap<UUID, List<AuditLog>>();
- final Map<UUID, List<AuditLog>> subscriptionsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final SubscriptionBundle bundle : bundles) {
- bundlesAuditLogs.put(bundle.getId(), getAuditLogs(bundle.getId(), ObjectType.BUNDLE, auditLevel, context));
- for (final Subscription cur : bundle.getSubscriptions()) {
-
- final ImmutableList<SubscriptionEvent> events = ImmutableList.<SubscriptionEvent>copyOf(Collections2.filter(bundle.getTimeline().getSubscriptionEvents(), new Predicate<SubscriptionEvent>() {
- @Override
- public boolean apply(@Nullable final SubscriptionEvent input) {
- return input.getEntitlementId().equals(cur.getId());
- }
- }));
- subscriptionsAuditLogs.put(cur.getId(), getAuditLogs(cur.getId(), ObjectType.SUBSCRIPTION, auditLevel, context));
- for (final SubscriptionEvent event : events) {
- subscriptionEventsAuditLogs.put(event.getId(), getAuditLogs(event.getId(), event.getSubscriptionEventType().getObjectType(), auditLevel, context));
- }
- }
- }
-
- return new DefaultAuditLogsForBundles(bundlesAuditLogs, subscriptionsAuditLogs, subscriptionEventsAuditLogs);
- }
-
- @Override
- public AuditLogsForInvoicePayments getAuditLogsForInvoicePayments(final List<InvoicePayment> invoicePayments, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> invoicePaymentsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final InvoicePayment invoicePayment : invoicePayments) {
- invoicePaymentsAuditLogs.put(invoicePayment.getId(), getAuditLogs(invoicePayment.getId(), ObjectType.INVOICE_PAYMENT, auditLevel, context));
- }
-
- return new DefaultAuditLogsForInvoicePayments(invoicePaymentsAuditLogs);
- }
-
- @Override
- public AuditLogsForRefunds getAuditLogsForRefunds(final List<Refund> refunds, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> refundsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final Refund refund : refunds) {
- refundsAuditLogs.put(refund.getId(), getAuditLogs(refund.getId(), ObjectType.REFUND, auditLevel, context));
+ public AccountAuditLogs getAccountAuditLogs(final UUID accountId, final AuditLevel auditLevel, final TenantContext tenantContext) {
+ // Optimization - bail early
+ if (AuditLevel.NONE.equals(auditLevel)) {
+ return new DefaultAccountAuditLogs(accountId);
}
- return new DefaultAuditLogsForRefunds(refundsAuditLogs);
+ return auditDao.getAuditLogsForAccountRecordId(auditLevel, internalCallContextFactory.createInternalTenantContext(accountId, tenantContext));
}
@Override
- public AuditLogsForPayments getAuditLogsForPayments(final List<Payment> payments, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> paymentsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final Payment payment : payments) {
- paymentsAuditLogs.put(payment.getId(), getAuditLogs(payment.getId(), ObjectType.PAYMENT, auditLevel, context));
+ public AccountAuditLogsForObjectType getAccountAuditLogs(final UUID accountId, final ObjectType objectType, final AuditLevel auditLevel, final TenantContext tenantContext) {
+ // Optimization - bail early
+ if (AuditLevel.NONE.equals(auditLevel)) {
+ return new DefaultAccountAuditLogsForObjectType(auditLevel);
}
- return new DefaultAuditLogsForPayments(paymentsAuditLogs);
- }
-
- @Override
- public AuditLogsForInvoices getAuditLogsForInvoices(final List<Invoice> invoices, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> invoiceAuditLogs = new HashMap<UUID, List<AuditLog>>();
- final Map<UUID, List<AuditLog>> invoiceItemsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final Invoice invoice : invoices) {
- invoiceAuditLogs.put(invoice.getId(), getAuditLogs(invoice.getId(), ObjectType.INVOICE, auditLevel, context));
- for (final InvoiceItem invoiceItem : invoice.getInvoiceItems()) {
- invoiceItemsAuditLogs.put(invoiceItem.getId(), getAuditLogs(invoiceItem.getId(), ObjectType.INVOICE_ITEM, auditLevel, context));
- }
+ final TableName tableName = getTableNameFromObjectType(objectType);
+ if (tableName == null) {
+ return new DefaultAccountAuditLogsForObjectType(auditLevel);
}
- return new DefaultAuditLogsForInvoices(invoiceAuditLogs, invoiceItemsAuditLogs);
+ return auditDao.getAuditLogsForAccountRecordId(tableName, auditLevel, internalCallContextFactory.createInternalTenantContext(accountId, tenantContext));
}
@Override
diff --git a/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java b/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
index ab88cbd..e11446f 100644
--- a/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
+++ b/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
@@ -19,12 +19,20 @@ package com.ning.billing.util.audit.dao;
import java.util.List;
import java.util.UUID;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
import com.ning.billing.util.dao.TableName;
public interface AuditDao {
+ // Make sure to consume all or call close() when done to release the connection
+ public DefaultAccountAuditLogs getAuditLogsForAccountRecordId(AuditLevel auditLevel, InternalTenantContext context);
+
+ // Make sure to consume all or call close() when done to release the connection
+ public DefaultAccountAuditLogsForObjectType getAuditLogsForAccountRecordId(TableName tableName, AuditLevel auditLevel, InternalTenantContext context);
+
public List<AuditLog> getAuditLogsForId(TableName tableName, UUID objectId, AuditLevel auditLevel, InternalTenantContext context);
}
diff --git a/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java b/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
index 1aa55e6..f9f032b 100644
--- a/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
+++ b/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
@@ -16,28 +16,39 @@
package com.ning.billing.util.audit.dao;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import javax.inject.Inject;
import org.skife.jdbi.v2.IDBI;
+import com.ning.billing.ObjectType;
+import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.clock.Clock;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.audit.ChangeType;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
+import com.ning.billing.util.audit.DefaultAuditLog;
import com.ning.billing.util.cache.CacheControllerDispatcher;
-import com.ning.billing.callcontext.InternalTenantContext;
-import com.ning.billing.clock.Clock;
import com.ning.billing.util.dao.NonEntityDao;
import com.ning.billing.util.dao.NonEntitySqlDao;
+import com.ning.billing.util.dao.RecordIdIdMappings;
import com.ning.billing.util.dao.TableName;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
public class DefaultAuditDao implements AuditDao {
@@ -51,6 +62,104 @@ public class DefaultAuditDao implements AuditDao {
}
@Override
+ public DefaultAccountAuditLogs getAuditLogsForAccountRecordId(final AuditLevel auditLevel, final InternalTenantContext context) {
+ final UUID accountId = nonEntitySqlDao.getIdFromObject(context.getAccountRecordId(), TableName.ACCOUNT.getTableName());
+
+ // Lazy evaluate records to minimize the memory footprint (these can yield a lot of results)
+ // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here.
+ // Since we want to stream the results out, we don't want to auto-commit when this method returns.
+ final EntitySqlDao auditSqlDao = transactionalSqlDao.onDemand(EntitySqlDao.class);
+ final Iterator<AuditLogModelDao> auditLogsForAccountRecordId = auditSqlDao.getAuditLogsForAccountRecordId(context);
+ final Iterator<AuditLog> allAuditLogs = buildAuditLogsFromModelDao(auditLogsForAccountRecordId, context);
+
+ return new DefaultAccountAuditLogs(accountId, auditLevel, allAuditLogs);
+ }
+
+ @Override
+ public DefaultAccountAuditLogsForObjectType getAuditLogsForAccountRecordId(final TableName tableName, final AuditLevel auditLevel, final InternalTenantContext context) {
+ final String actualTableName;
+ if (tableName.hasHistoryTable()) {
+ actualTableName = tableName.getHistoryTableName().name(); // upper cased
+ } else {
+ actualTableName = tableName.getTableName();
+ }
+
+ // Lazy evaluate records to minimize the memory footprint (these can yield a lot of results)
+ // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here.
+ // Since we want to stream the results out, we don't want to auto-commit when this method returns.
+ final EntitySqlDao auditSqlDao = transactionalSqlDao.onDemand(EntitySqlDao.class);
+ final Iterator<AuditLogModelDao> auditLogsForTableNameAndAccountRecordId = auditSqlDao.getAuditLogsForTableNameAndAccountRecordId(actualTableName, context);
+ final Iterator<AuditLog> allAuditLogs = buildAuditLogsFromModelDao(auditLogsForTableNameAndAccountRecordId, context);
+
+ return new DefaultAccountAuditLogsForObjectType(auditLevel, allAuditLogs);
+ }
+
+ private Iterator<AuditLog> buildAuditLogsFromModelDao(final Iterator<AuditLogModelDao> auditLogsForAccountRecordId, final InternalTenantContext tenantContext) {
+ final Map<TableName, Map<Long, UUID>> recordIdIdsCache = new HashMap<TableName, Map<Long, UUID>>();
+ final Map<TableName, Map<Long, UUID>> historyRecordIdIdsCache = new HashMap<TableName, Map<Long, UUID>>();
+ return Iterators.<AuditLogModelDao, AuditLog>transform(auditLogsForAccountRecordId,
+ new Function<AuditLogModelDao, AuditLog>() {
+ @Override
+ public AuditLog apply(final AuditLogModelDao input) {
+ // If input is for e.g. TAG_DEFINITION_HISTORY, retrieve TAG_DEFINITIONS
+ // For tables without history, e.g. TENANT, originalTableNameForHistoryTableName will be null
+ final TableName originalTableNameForHistoryTableName = findTableNameForHistoryTableName(input.getTableName());
+
+ final ObjectType objectType;
+ final UUID auditedEntityId;
+ if (originalTableNameForHistoryTableName != null) {
+ // input point to a history entry
+ objectType = originalTableNameForHistoryTableName.getObjectType();
+
+ if (historyRecordIdIdsCache.get(originalTableNameForHistoryTableName) == null) {
+ if (TableName.ACCOUNT.equals(originalTableNameForHistoryTableName)) {
+ final Iterable<RecordIdIdMappings> mappings = nonEntitySqlDao.getHistoryRecordIdIdMappingsForAccountsTable(originalTableNameForHistoryTableName.getTableName(),
+ input.getTableName().getTableName(),
+ tenantContext);
+ historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+ } else if (TableName.TAG_DEFINITIONS.equals(originalTableNameForHistoryTableName)) {
+ final Iterable<RecordIdIdMappings> mappings = nonEntitySqlDao.getHistoryRecordIdIdMappingsForTablesWithoutAccountRecordId(originalTableNameForHistoryTableName.getTableName(),
+ input.getTableName().getTableName(),
+ tenantContext);
+ historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+ } else {
+ final Iterable<RecordIdIdMappings> mappings = nonEntitySqlDao.getHistoryRecordIdIdMappings(originalTableNameForHistoryTableName.getTableName(),
+ input.getTableName().getTableName(),
+ tenantContext);
+ historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+
+ }
+ }
+
+ auditedEntityId = historyRecordIdIdsCache.get(originalTableNameForHistoryTableName).get(input.getTargetRecordId());
+ } else {
+ objectType = input.getTableName().getObjectType();
+
+ if (recordIdIdsCache.get(input.getTableName()) == null) {
+ final Iterable<RecordIdIdMappings> mappings = nonEntitySqlDao.getRecordIdIdMappings(input.getTableName().getTableName(),
+ tenantContext);
+ recordIdIdsCache.put(input.getTableName(), RecordIdIdMappings.toMap(mappings));
+ }
+
+ auditedEntityId = recordIdIdsCache.get(input.getTableName()).get(input.getTargetRecordId());
+ }
+
+ return new DefaultAuditLog(input, objectType, auditedEntityId);
+ }
+
+ private TableName findTableNameForHistoryTableName(final TableName historyTableName) {
+ for (final TableName tableName : TableName.values()) {
+ if (historyTableName.equals(tableName.getHistoryTableName())) {
+ return tableName;
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+
+ @Override
public List<AuditLog> getAuditLogsForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
if (tableName.hasHistoryTable()) {
return doGetAuditLogsViaHistoryForId(tableName, objectId, auditLevel, context);
@@ -64,7 +173,7 @@ public class DefaultAuditDao implements AuditDao {
if (recordId == null) {
return ImmutableList.<AuditLog>of();
} else {
- return getAuditLogsForRecordId(tableName, recordId, auditLevel, context);
+ return getAuditLogsForRecordId(tableName, objectId, recordId, auditLevel, context);
}
}
@@ -78,32 +187,44 @@ public class DefaultAuditDao implements AuditDao {
final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
@Override
public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
- historyTableName.getTableName().toLowerCase(),
- targetRecordId,
- context);
+ final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
+ historyTableName.getTableName().toLowerCase(),
+ targetRecordId,
+ context);
+ return buildAuditLogsFromModelDao(auditLogsViaHistoryForTargetRecordId, tableName.getObjectType(), objectId);
}
});
- return buildAuditLogs(auditLevel, allAuditLogs);
+ return filterAuditLogs(auditLevel, allAuditLogs);
}
- private List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final Long targetRecordId, final AuditLevel auditLevel, final InternalTenantContext context) {
+ private List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final UUID auditedEntityId, final Long targetRecordId, final AuditLevel auditLevel, final InternalTenantContext context) {
final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
@Override
public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
- targetRecordId,
- context);
+ final List<AuditLogModelDao> auditLogsForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
+ targetRecordId,
+ context);
+ return buildAuditLogsFromModelDao(auditLogsForTargetRecordId, tableName.getObjectType(), auditedEntityId);
}
});
- return buildAuditLogs(auditLevel, allAuditLogs);
+ return filterAuditLogs(auditLevel, allAuditLogs);
+ }
+
+ private List<AuditLog> buildAuditLogsFromModelDao(final List<AuditLogModelDao> auditLogsForAccountRecordId, final ObjectType objectType, final UUID auditedEntityId) {
+ return Lists.<AuditLogModelDao, AuditLog>transform(auditLogsForAccountRecordId,
+ new Function<AuditLogModelDao, AuditLog>() {
+ @Override
+ public AuditLog apply(final AuditLogModelDao input) {
+ return new DefaultAuditLog(input, objectType, auditedEntityId);
+ }
+ });
}
- private List<AuditLog> buildAuditLogs(final AuditLevel auditLevel, final List<AuditLog> auditLogs) {
+ private List<AuditLog> filterAuditLogs(final AuditLevel auditLevel, final List<AuditLog> auditLogs) {
// TODO Do the filtering in the query
if (AuditLevel.FULL.equals(auditLevel)) {
return auditLogs;
- } else if (AuditLevel.MINIMAL.equals(auditLevel) && auditLogs.size() > 0) {
+ } else if (AuditLevel.MINIMAL.equals(auditLevel) && !auditLogs.isEmpty()) {
if (ChangeType.INSERT.equals(auditLogs.get(0).getChangeType())) {
return ImmutableList.<AuditLog>of(auditLogs.get(0));
} else {
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java
new file mode 100644
index 0000000..963eb20
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.util.audit;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.util.api.AuditLevel;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.AbstractIterator;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+
+public class DefaultAccountAuditLogs implements AccountAuditLogs {
+
+ private final UUID accountId;
+ private final AuditLevel auditLevel;
+ private final Collection<AuditLog> accountAuditLogs;
+
+ private final Map<ObjectType, DefaultAccountAuditLogsForObjectType> auditLogsCache = new HashMap<ObjectType, DefaultAccountAuditLogsForObjectType>();
+
+ public DefaultAccountAuditLogs(final UUID accountId) {
+ this(accountId, AuditLevel.NONE, Iterators.<AuditLog>emptyIterator());
+ }
+
+ public DefaultAccountAuditLogs(final UUID accountId, final AuditLevel auditLevel, final Iterator<AuditLog> accountAuditLogsOrderedByTableName) {
+ this.accountId = accountId;
+ this.auditLevel = auditLevel;
+ // TODO pierre - lame, we should be smarter to avoid loading all entries in memory. It's a bit tricky though...
+ this.accountAuditLogs = ImmutableList.<AuditLog>copyOf(accountAuditLogsOrderedByTableName);
+ }
+
+ public void close() {
+ // Make sure to go through the results to close the connection
+ // no-op for now, see TODO above
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForAccount() {
+ return getAuditLogs(ObjectType.ACCOUNT).getAuditLogs(accountId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForBundle(final UUID bundleId) {
+ return getAuditLogs(ObjectType.BUNDLE).getAuditLogs(bundleId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForSubscription(final UUID subscriptionId) {
+ return getAuditLogs(ObjectType.SUBSCRIPTION).getAuditLogs(subscriptionId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForSubscriptionEvent(final UUID subscriptionEventId) {
+ return getAuditLogs(ObjectType.SUBSCRIPTION_EVENT).getAuditLogs(subscriptionEventId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForInvoice(final UUID invoiceId) {
+ return getAuditLogs(ObjectType.INVOICE).getAuditLogs(invoiceId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForInvoiceItem(final UUID invoiceItemId) {
+ return getAuditLogs(ObjectType.INVOICE_ITEM).getAuditLogs(invoiceItemId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForPayment(final UUID paymentId) {
+ return getAuditLogs(ObjectType.PAYMENT).getAuditLogs(paymentId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForRefund(final UUID refundId) {
+ return getAuditLogs(ObjectType.REFUND).getAuditLogs(refundId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForChargeback(final UUID chargebackId) {
+ return getAuditLogs(ObjectType.INVOICE_PAYMENT).getAuditLogs(chargebackId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForBlockingState(final UUID blockingStateId) {
+ return getAuditLogs(ObjectType.BLOCKING_STATES).getAuditLogs(blockingStateId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForInvoicePayment(final UUID invoicePaymentId) {
+ return getAuditLogs(ObjectType.INVOICE_PAYMENT).getAuditLogs(invoicePaymentId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForTag(final UUID tagId) {
+ return getAuditLogs(ObjectType.TAG).getAuditLogs(tagId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForCustomField(final UUID customFieldId) {
+ return getAuditLogs(ObjectType.CUSTOM_FIELD).getAuditLogs(customFieldId);
+ }
+
+ @Override
+ public AccountAuditLogsForObjectType getAuditLogs(final ObjectType objectType) {
+ if (auditLogsCache.get(objectType) == null) {
+ auditLogsCache.put(objectType, new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator())));
+ }
+
+ // Should never be null
+ return auditLogsCache.get(objectType);
+ }
+
+ private final class ObjectTypeFilter extends AbstractIterator<AuditLog> {
+
+ private boolean hasSeenObjectType = false;
+
+ private final ObjectType objectType;
+ private final Iterator<AuditLog> accountAuditLogs;
+
+ private ObjectTypeFilter(final ObjectType objectType, final Iterator<AuditLog> accountAuditLogs) {
+ this.objectType = objectType;
+ this.accountAuditLogs = accountAuditLogs;
+ }
+
+ @Override
+ protected AuditLog computeNext() {
+ while (accountAuditLogs.hasNext()) {
+ final AuditLog element = accountAuditLogs.next();
+ if (predicate.apply(element)) {
+ hasSeenObjectType = true;
+ return element;
+ } else if (hasSeenObjectType) {
+ // Optimization trick: audit log records are ordered first by table name
+ // (hence object type) - when we are done and we switch to another ObjectType,
+ // we are guaranteed there is nothing left to do
+ return endOfData();
+ }
+ }
+
+ return endOfData();
+ }
+
+ private final Predicate<AuditLog> predicate = new Predicate<AuditLog>() {
+ @Override
+ public boolean apply(final AuditLog auditLog) {
+ return objectType.equals(auditLog.getAuditedObjectType());
+ }
+ };
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java
new file mode 100644
index 0000000..108b170
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.util.audit;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.ning.billing.util.api.AuditLevel;
+import com.ning.billing.util.customfield.ShouldntHappenException;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+
+public class DefaultAccountAuditLogsForObjectType implements AccountAuditLogsForObjectType {
+
+ private final Map<UUID, List<AuditLog>> auditLogsCache;
+
+ private final AuditLevel auditLevel;
+ private final Iterator<AuditLog> allAuditLogsForObjectType;
+
+ public DefaultAccountAuditLogsForObjectType(final AuditLevel auditLevel) {
+ this(auditLevel, Iterators.<AuditLog>emptyIterator());
+ }
+
+ public DefaultAccountAuditLogsForObjectType(final AuditLevel auditLevel, final Iterator<AuditLog> allAuditLogsForObjectType) {
+ this.auditLevel = auditLevel;
+ this.auditLogsCache = new HashMap<UUID, List<AuditLog>>();
+ this.allAuditLogsForObjectType = allAuditLogsForObjectType;
+ }
+
+ // Used by DefaultAccountAuditLogs
+ void initializeIfNeeded(final UUID objectId) {
+ if (auditLogsCache.get(objectId) == null) {
+ auditLogsCache.put(objectId, new LinkedList<AuditLog>());
+ }
+ }
+
+ public void close() {
+ // Make sure to go through the results to close the connection
+ while (allAuditLogsForObjectType.hasNext()) {
+ allAuditLogsForObjectType.next();
+ }
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogs(final UUID objectId) {
+ switch (auditLevel) {
+ case FULL:
+ // We need to go through the whole list
+ cacheAllAuditLogs();
+
+ // We went through the whole list, mark we don't have any entry for it if needed
+ initializeIfNeeded(objectId);
+
+ // Should never be null
+ return auditLogsCache.get(objectId);
+ case MINIMAL:
+ if (auditLogsCache.get(objectId) == null) {
+ // We just want the first INSERT audit log
+ final AuditLog candidate = Iterators.<AuditLog>tryFind(allAuditLogsForObjectType,
+ new Predicate<AuditLog>() {
+ @Override
+ public boolean apply(final AuditLog auditLog) {
+ // As we consume the data source, cache the entries
+ cacheAuditLog(auditLog);
+
+ return objectId.equals(auditLog.getAuditedEntityId()) &&
+ // Given our ordering, this should always be true for the first entry
+ ChangeType.INSERT.equals(auditLog.getChangeType());
+ }
+ }).orNull();
+
+ if (candidate == null) {
+ // We went through the whole list, mark we don't have any entry for it
+ initializeIfNeeded(objectId);
+ }
+ }
+
+ // Should never be null
+ return auditLogsCache.get(objectId);
+ case NONE:
+ // Close the connection ASAP since we won't need it
+ close();
+ return ImmutableList.<AuditLog>of();
+ default:
+ throw new ShouldntHappenException("AuditLevel " + auditLevel + " unsupported");
+ }
+ }
+
+ private void cacheAllAuditLogs() {
+ while (allAuditLogsForObjectType.hasNext()) {
+ final AuditLog auditLog = allAuditLogsForObjectType.next();
+ cacheAuditLog(auditLog);
+ }
+ }
+
+ private void cacheAuditLog(final AuditLog auditLog) {
+ initializeIfNeeded(auditLog.getAuditedEntityId());
+ auditLogsCache.get(auditLog.getAuditedEntityId()).add(auditLog);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("DefaultAccountAuditLogsForObjectType{");
+ sb.append("auditLogsCache=").append(auditLogsCache);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultAccountAuditLogsForObjectType that = (DefaultAccountAuditLogsForObjectType) o;
+
+ if (!auditLogsCache.equals(that.auditLogsCache)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return auditLogsCache.hashCode();
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
index 0c3e07e..b2deef3 100644
--- a/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2012 Ning, Inc.
+ * Copyright 2010-2013 Ning, Inc.
*
* Ning 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
@@ -16,56 +16,76 @@
package com.ning.billing.util.audit;
+import java.util.UUID;
+
import org.joda.time.DateTime;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.dao.EntityAudit;
+import com.ning.billing.ObjectType;
+import com.ning.billing.entity.EntityBase;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
+
+public class DefaultAuditLog extends EntityBase implements AuditLog {
-public class DefaultAuditLog extends EntityAudit implements AuditLog {
+ private final AuditLogModelDao auditLogModelDao;
+ private final ObjectType objectType;
+ private final UUID auditedEntityId;
- private final CallContext callContext;
+ public DefaultAuditLog(final AuditLogModelDao auditLogModelDao, final ObjectType objectType, final UUID auditedEntityId) {
+ super(auditLogModelDao);
+ this.auditLogModelDao = auditLogModelDao;
+ this.objectType = objectType;
+ this.auditedEntityId = auditedEntityId;
+ }
- public DefaultAuditLog(final EntityAudit entityAudit, final CallContext callContext) {
- super(entityAudit.getId(), entityAudit.getTableName(), entityAudit.getTargetRecordId(), entityAudit.getChangeType(), entityAudit.getCreatedDate());
- this.callContext = callContext;
+ @Override
+ public UUID getAuditedEntityId() {
+ return auditedEntityId;
}
+ @Override
+ public ObjectType getAuditedObjectType() {
+ return objectType;
+ }
+
+ @Override
+ public ChangeType getChangeType() {
+ return auditLogModelDao.getChangeType();
+ }
@Override
public String getUserName() {
- return callContext.getUserName();
+ return auditLogModelDao.getCallContext().getUserName();
}
@Override
public DateTime getCreatedDate() {
- return callContext.getCreatedDate();
+ return auditLogModelDao.getCallContext().getCreatedDate();
}
@Override
public String getReasonCode() {
- return callContext.getReasonCode();
+ return auditLogModelDao.getCallContext().getReasonCode();
}
@Override
public String getUserToken() {
- if (callContext.getUserToken() == null) {
+ if (auditLogModelDao.getCallContext().getUserToken() == null) {
return null;
} else {
- return callContext.getUserToken().toString();
+ return auditLogModelDao.getCallContext().getUserToken().toString();
}
}
@Override
public String getComment() {
- return callContext.getComments();
+ return auditLogModelDao.getCallContext().getComments();
}
@Override
public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("DefaultAuditLog {");
- sb.append(super.toString());
- sb.append(", callcontext=").append(callContext);
+ final StringBuilder sb = new StringBuilder("DefaultAuditLog{");
+ sb.append("auditLogModelDao=").append(auditLogModelDao);
+ sb.append(", auditedEntityId=").append(auditedEntityId);
sb.append('}');
return sb.toString();
}
@@ -84,7 +104,10 @@ public class DefaultAuditLog extends EntityAudit implements AuditLog {
final DefaultAuditLog that = (DefaultAuditLog) o;
- if (callContext != null ? !callContext.equals(that.callContext) : that.callContext != null) {
+ if (auditLogModelDao != null ? !auditLogModelDao.equals(that.auditLogModelDao) : that.auditLogModelDao != null) {
+ return false;
+ }
+ if (auditedEntityId != null ? !auditedEntityId.equals(that.auditedEntityId) : that.auditedEntityId != null) {
return false;
}
@@ -94,7 +117,8 @@ public class DefaultAuditLog extends EntityAudit implements AuditLog {
@Override
public int hashCode() {
int result = super.hashCode();
- result = 31 * result + (callContext != null ? callContext.hashCode() : 0);
+ result = 31 * result + (auditLogModelDao != null ? auditLogModelDao.hashCode() : 0);
+ result = 31 * result + (auditedEntityId != null ? auditedEntityId.hashCode() : 0);
return result;
}
}
diff --git a/util/src/main/java/com/ning/billing/util/callcontext/InternalCallContextFactory.java b/util/src/main/java/com/ning/billing/util/callcontext/InternalCallContextFactory.java
index 17c9ed0..c5560b1 100644
--- a/util/src/main/java/com/ning/billing/util/callcontext/InternalCallContextFactory.java
+++ b/util/src/main/java/com/ning/billing/util/callcontext/InternalCallContextFactory.java
@@ -82,6 +82,11 @@ public class InternalCallContextFactory {
return new InternalTenantContext(tenantRecordId, accountRecordId);
}
+ public InternalTenantContext createInternalTenantContext(final UUID accountId, final InternalTenantContext context) {
+ final Long tenantRecordId = context.getTenantRecordId();
+ final Long accountRecordId = getAccountRecordId(accountId, ObjectType.ACCOUNT);
+ return new InternalTenantContext(tenantRecordId, accountRecordId);
+ }
/**
* Crate an internal tenant callcontext from a tenant callcontext, and retrieving the account_record_id from another table
diff --git a/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java b/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
index d9f9b83..7f91aac 100644
--- a/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
@@ -16,6 +16,7 @@
package com.ning.billing.util.dao;
+import java.util.Iterator;
import java.util.List;
import org.skife.jdbi.v2.sqlobject.Bind;
@@ -23,11 +24,11 @@ import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.Define;
-import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
-import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
import com.ning.billing.util.cache.Cachable;
import com.ning.billing.util.cache.Cachable.CacheType;
import com.ning.billing.util.cache.CachableKey;
@@ -39,11 +40,11 @@ import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
* which is good enough: the cache will always get at least the initial CREATION audit log entry, which is the one
* we really care about (both for Analytics and for Kaui's endpoints). Besides, we do cache invalidation properly
* on our own node (see EntitySqlDaoWrapperInvocationHandler).
- *
+ * <p/>
* Note 2: in the queries below, tableName always refers to the TableName enum, not the actual table name (TableName.getTableName()).
*/
@EntitySqlDaoStringTemplate("/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg")
-@RegisterMapper(AuditLogMapper.class)
+// Note: @RegisterMapper annotation won't work here as we build the SqlObject via EntitySqlDao (annotations won't be inherited for JDBI)
public interface AuditSqlDao {
@SqlUpdate
@@ -51,15 +52,28 @@ public interface AuditSqlDao {
@BindBean final InternalCallContext context);
@SqlQuery
+ // Magic value to force MySQL to stream from the database
+ // See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
+ @FetchSize(Integer.MIN_VALUE)
+ public Iterator<AuditLogModelDao> getAuditLogsForAccountRecordId(@BindBean final InternalTenantContext context);
+
+ @SqlQuery
+ // Magic value to force MySQL to stream from the database
+ // See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
+ @FetchSize(Integer.MIN_VALUE)
+ public Iterator<AuditLogModelDao> getAuditLogsForTableNameAndAccountRecordId(@Bind("tableName") final String tableName,
+ @BindBean final InternalTenantContext context);
+
+ @SqlQuery
@Cachable(CacheType.AUDIT_LOG)
- public List<AuditLog> getAuditLogsForTargetRecordId(@CachableKey(1) @Bind("tableName") final String tableName,
- @CachableKey(2) @Bind("targetRecordId") final long targetRecordId,
- @BindBean final InternalTenantContext context);
+ public List<AuditLogModelDao> getAuditLogsForTargetRecordId(@CachableKey(1) @Bind("tableName") final String tableName,
+ @CachableKey(2) @Bind("targetRecordId") final long targetRecordId,
+ @BindBean final InternalTenantContext context);
@SqlQuery
@Cachable(CacheType.AUDIT_LOG_VIA_HISTORY)
- public List<AuditLog> getAuditLogsViaHistoryForTargetRecordId(@CachableKey(1) @Bind("tableName") final String historyTableName, /* Uppercased - used to find entries in audit_log table */
- @CachableKey(2) @Define("historyTableName") final String actualHistoryTableName, /* Actual table name, used in the inner join query */
- @CachableKey(3) @Bind("targetRecordId") final long targetRecordId,
- @BindBean final InternalTenantContext context);
+ public List<AuditLogModelDao> getAuditLogsViaHistoryForTargetRecordId(@CachableKey(1) @Bind("tableName") final String historyTableName, /* Uppercased - used to find entries in audit_log table */
+ @CachableKey(2) @Define("historyTableName") final String actualHistoryTableName, /* Actual table name, used in the inner join query */
+ @CachableKey(3) @Bind("targetRecordId") final long targetRecordId,
+ @BindBean final InternalTenantContext context);
}
diff --git a/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java b/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
index 36d7811..82c3a7f 100644
--- a/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
@@ -19,12 +19,15 @@ package com.ning.billing.util.dao;
import java.util.UUID;
import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.customizers.Define;
import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
import org.skife.jdbi.v2.sqlobject.stringtemplate.UseStringTemplate3StatementLocator;
+import com.ning.billing.callcontext.InternalTenantContext;
+
@UseStringTemplate3StatementLocator
public interface NonEntitySqlDao extends Transactional<NonEntitySqlDao>, CloseMe {
@@ -54,4 +57,23 @@ public interface NonEntitySqlDao extends Transactional<NonEntitySqlDao>, CloseMe
@SqlQuery
public Long getHistoryTargetRecordId(@Bind("recordId") Long recordId, @Define("tableName") final String tableName);
+
+ @SqlQuery
+ public Iterable<RecordIdIdMappings> getHistoryRecordIdIdMappings(@Define("tableName") String tableName,
+ @Define("historyTableName") String historyTableName,
+ @BindBean final InternalTenantContext context);
+
+ @SqlQuery
+ public Iterable<RecordIdIdMappings> getHistoryRecordIdIdMappingsForAccountsTable(@Define("tableName") String tableName,
+ @Define("historyTableName") String historyTableName,
+ @BindBean final InternalTenantContext context);
+
+ @SqlQuery
+ public Iterable<RecordIdIdMappings> getHistoryRecordIdIdMappingsForTablesWithoutAccountRecordId(@Define("tableName") String tableName,
+ @Define("historyTableName") String historyTableName,
+ @BindBean final InternalTenantContext context);
+
+ @SqlQuery
+ public Iterable<RecordIdIdMappings> getRecordIdIdMappings(@Define("tableName") String tableName,
+ @BindBean final InternalTenantContext context);
}
diff --git a/util/src/main/java/com/ning/billing/util/dao/RecordIdIdMappings.java b/util/src/main/java/com/ning/billing/util/dao/RecordIdIdMappings.java
new file mode 100644
index 0000000..5f9fdc5
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/dao/RecordIdIdMappings.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning 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 com.ning.billing.util.dao;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class RecordIdIdMappings {
+
+ private final Long recordId;
+ private final UUID id;
+
+ public RecordIdIdMappings(final long recordId, final UUID id) {
+ this.recordId = recordId;
+ this.id = id;
+ }
+
+ public Long getRecordId() {
+ return recordId;
+ }
+
+ public UUID getId() {
+ return id;
+ }
+
+ public static Map<Long, UUID> toMap(final Iterable<RecordIdIdMappings> mappings) {
+ final Map<Long, UUID> result = new LinkedHashMap<Long, UUID>();
+ for (final RecordIdIdMappings mapping : mappings) {
+ result.put(mapping.getRecordId(), mapping.getId());
+ }
+ return result;
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java
index f4c9148..44506de 100644
--- a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDao.java
@@ -61,6 +61,8 @@ public interface EntitySqlDao<M extends EntityModelDao<E>, E extends Entity> ext
@SqlQuery
public List<M> getByAccountRecordId(@BindBean final InternalTenantContext context);
+ @SqlQuery
+ public List<M> getByAccountRecordIdIncludedDeleted(@BindBean final InternalTenantContext context);
@SqlQuery
@Cachable(CacheType.RECORD_ID)
diff --git a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java
index 143f3bc..e70cfcd 100644
--- a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java
+++ b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java
@@ -77,9 +77,11 @@ public @interface EntitySqlDaoStringTemplate {
final ParameterizedType type = (ParameterizedType) sqlObjectType.getGenericInterfaces()[i];
for (int j = 0; j < type.getActualTypeArguments().length; j++) {
final Type modelType = type.getActualTypeArguments()[j];
- final Class modelClazz = (Class) modelType;
- if (Entity.class.isAssignableFrom(modelClazz)) {
- query.registerMapper(new LowerToCamelBeanMapperFactory(modelClazz));
+ if (modelType instanceof Class) {
+ final Class modelClazz = (Class) modelType;
+ if (Entity.class.isAssignableFrom(modelClazz)) {
+ query.registerMapper(new LowerToCamelBeanMapperFactory(modelClazz));
+ }
}
}
}
diff --git a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
index 02d56bb..4fe070e 100644
--- a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
+++ b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
@@ -384,9 +384,17 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>,
return nonEntityDao.retrieveLastHistoryRecordIdFromTransaction(entityRecordId, entityModelDao.getHistoryTableName(), transactional);
}
- private void insertAudits(final TableName tableName, final Long entityRecordId, final Long historyRecordId, final ChangeType changeType, final InternalCallContext context) {
+ private void insertAudits(final TableName tableName, final Long entityRecordId, final Long historyRecordId, final ChangeType changeType, final InternalCallContext contextMaybeWithoutAccountRecordId) {
final TableName destinationTableName = Objects.firstNonNull(tableName.getHistoryTableName(), tableName);
final EntityAudit audit = new EntityAudit(destinationTableName, historyRecordId, changeType, clock.getUTCNow());
+
+ final InternalCallContext context;
+ // Populate the account record id when creating the account record
+ if (TableName.ACCOUNT.equals(tableName) && ChangeType.INSERT.equals(changeType)) {
+ context = new InternalCallContext(contextMaybeWithoutAccountRecordId, entityRecordId);
+ } else {
+ context = contextMaybeWithoutAccountRecordId;
+ }
sqlDao.insertAuditFromTransaction(audit, context);
// We need to invalidate the caches. There is a small window of doom here where caches will be stale.
diff --git a/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java b/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
index b3a93b4..daf484e 100644
--- a/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
+++ b/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
@@ -22,11 +22,11 @@ import java.util.UUID;
import com.ning.billing.ErrorCode;
import com.ning.billing.ObjectType;
+import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.tag.ControlTagType;
@@ -142,18 +142,18 @@ public class DefaultTagUserApi implements TagUserApi {
}
@Override
- public List<Tag> getTagsForObject(final UUID objectId, final ObjectType objectType, final TenantContext context) {
- return withModelTransform(tagDao.getTagsForObject(objectId, objectType, internalCallContextFactory.createInternalTenantContext(context)));
+ public List<Tag> getTagsForObject(final UUID objectId, final ObjectType objectType, final boolean includedDeleted, final TenantContext context) {
+ return withModelTransform(tagDao.getTagsForObject(objectId, objectType, includedDeleted, internalCallContextFactory.createInternalTenantContext(context)));
}
@Override
- public List<Tag> getTagsForAccountType(final UUID accountId, final ObjectType objectType, final TenantContext context) {
- return withModelTransform(tagDao.getTagsForAccountType(accountId, objectType, internalCallContextFactory.createInternalTenantContext(accountId, context)));
+ public List<Tag> getTagsForAccountType(final UUID accountId, final ObjectType objectType, final boolean includedDeleted, final TenantContext context) {
+ return withModelTransform(tagDao.getTagsForAccountType(accountId, objectType, includedDeleted, internalCallContextFactory.createInternalTenantContext(accountId, context)));
}
@Override
- public List<Tag> getTagsForAccount(final UUID accountId, final TenantContext context) {
- return withModelTransform(tagDao.getTagsForAccount(internalCallContextFactory.createInternalTenantContext(accountId, context)));
+ public List<Tag> getTagsForAccount(final UUID accountId, final boolean includedDeleted, final TenantContext context) {
+ return withModelTransform(tagDao.getTagsForAccount(includedDeleted, internalCallContextFactory.createInternalTenantContext(accountId, context)));
}
private List<Tag> withModelTransform(final List<TagModelDao> input) {
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java
index 888638b..d1307ec 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDao.java
@@ -19,8 +19,6 @@ package com.ning.billing.util.tag.dao;
import java.util.List;
import java.util.UUID;
-import javax.annotation.Nullable;
-
import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,19 +27,19 @@ import com.ning.billing.BillingExceptionBase;
import com.ning.billing.ErrorCode;
import com.ning.billing.ObjectType;
import com.ning.billing.bus.api.PersistentBus;
-import com.ning.billing.util.api.TagApiException;
-import com.ning.billing.util.audit.ChangeType;
-import com.ning.billing.util.cache.CacheControllerDispatcher;
import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.clock.Clock;
+import com.ning.billing.events.TagInternalEvent;
+import com.ning.billing.util.api.TagApiException;
+import com.ning.billing.util.audit.ChangeType;
+import com.ning.billing.util.cache.CacheControllerDispatcher;
import com.ning.billing.util.dao.NonEntityDao;
import com.ning.billing.util.entity.dao.EntityDaoBase;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
-import com.ning.billing.events.TagInternalEvent;
import com.ning.billing.util.tag.ControlTagType;
import com.ning.billing.util.tag.Tag;
import com.ning.billing.util.tag.api.user.TagEventBuilder;
@@ -68,33 +66,42 @@ public class DefaultTagDao extends EntityDaoBase<TagModelDao, Tag, TagApiExcepti
}
@Override
- public List<TagModelDao> getTagsForObject(final UUID objectId, final ObjectType objectType, final InternalTenantContext internalTenantContext) {
+ public List<TagModelDao> getTagsForObject(final UUID objectId, final ObjectType objectType, final boolean includedDeleted, final InternalTenantContext internalTenantContext) {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<TagModelDao>>() {
@Override
public List<TagModelDao> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- return entitySqlDaoWrapperFactory.become(TagSqlDao.class).getTagsForObject(objectId, objectType, internalTenantContext);
+ final TagSqlDao tagSqlDao = entitySqlDaoWrapperFactory.become(TagSqlDao.class);
+ if (includedDeleted) {
+ return tagSqlDao.getTagsForObjectIncludedDeleted(objectId, objectType, internalTenantContext);
+ } else {
+ return tagSqlDao.getTagsForObject(objectId, objectType, internalTenantContext);
+ }
}
});
}
@Override
- public List<TagModelDao> getTagsForAccountType(final UUID accountId, final ObjectType objectType, final InternalTenantContext internalTenantContext) {
-
- final List<TagModelDao> allTags = getTagsForAccount(internalTenantContext);
+ public List<TagModelDao> getTagsForAccountType(final UUID accountId, final ObjectType objectType, final boolean includedDeleted, final InternalTenantContext internalTenantContext) {
+ final List<TagModelDao> allTags = getTagsForAccount(includedDeleted, internalTenantContext);
return ImmutableList.<TagModelDao>copyOf(Collections2.filter(allTags, new Predicate<TagModelDao>() {
@Override
- public boolean apply(@Nullable final TagModelDao input) {
+ public boolean apply(final TagModelDao input) {
return input.getObjectType() == objectType;
}
}));
}
@Override
- public List<TagModelDao> getTagsForAccount(final InternalTenantContext internalTenantContext) {
+ public List<TagModelDao> getTagsForAccount(final boolean includedDeleted, final InternalTenantContext internalTenantContext) {
return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<TagModelDao>>() {
@Override
public List<TagModelDao> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- return entitySqlDaoWrapperFactory.become(TagSqlDao.class).getByAccountRecordId(internalTenantContext);
+ final TagSqlDao tagSqlDao = entitySqlDaoWrapperFactory.become(TagSqlDao.class);
+ if (includedDeleted) {
+ return tagSqlDao.getByAccountRecordIdIncludedDeleted(internalTenantContext);
+ } else {
+ return tagSqlDao.getByAccountRecordId(internalTenantContext);
+ }
}
});
}
@@ -110,7 +117,7 @@ public class DefaultTagDao extends EntityDaoBase<TagModelDao, Tag, TagApiExcepti
switch (changeType) {
case INSERT:
tagEvent = (isControlTag) ?
- tagEventBuilder.newControlTagCreationEvent(tag.getId(), tag.getObjectId(), tag.getObjectType(),tagDefinition,
+ tagEventBuilder.newControlTagCreationEvent(tag.getId(), tag.getObjectId(), tag.getObjectType(), tagDefinition,
context.getAccountRecordId(), context.getTenantRecordId(), context.getUserToken()) :
tagEventBuilder.newUserTagCreationEvent(tag.getId(), tag.getObjectId(), tag.getObjectType(), tagDefinition,
context.getAccountRecordId(), context.getTenantRecordId(), context.getUserToken());
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java
index 152115a..0077072 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java
@@ -20,9 +20,9 @@ import java.util.List;
import java.util.UUID;
import com.ning.billing.ObjectType;
-import com.ning.billing.util.api.TagApiException;
import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.api.TagApiException;
public interface TagDao {
@@ -32,9 +32,9 @@ public interface TagDao {
TagModelDao getById(UUID tagId, InternalTenantContext context);
- List<TagModelDao> getTagsForObject(UUID objectId, ObjectType objectType, InternalTenantContext internalTenantContext);
+ List<TagModelDao> getTagsForObject(UUID objectId, ObjectType objectType, boolean includedDeleted, InternalTenantContext internalTenantContext);
- List<TagModelDao> getTagsForAccountType(UUID accountId, ObjectType objectType, InternalTenantContext internalTenantContext);
+ List<TagModelDao> getTagsForAccountType(UUID accountId, ObjectType objectType, boolean includedDeleted, InternalTenantContext internalTenantContext);
- List<TagModelDao> getTagsForAccount(InternalTenantContext internalTenantContext);
+ List<TagModelDao> getTagsForAccount(boolean includedDeleted, InternalTenantContext internalTenantContext);
}
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
index 720f474..26caab0 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
@@ -25,9 +25,9 @@ import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import com.ning.billing.ObjectType;
-import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.entity.dao.Audited;
import com.ning.billing.util.entity.dao.EntitySqlDao;
import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
@@ -45,4 +45,9 @@ public interface TagSqlDao extends EntitySqlDao<TagModelDao, Tag> {
List<TagModelDao> getTagsForObject(@Bind("objectId") UUID objectId,
@Bind("objectType") ObjectType objectType,
@BindBean InternalTenantContext internalTenantContext);
+
+ @SqlQuery
+ List<TagModelDao> getTagsForObjectIncludedDeleted(@Bind("objectId") UUID objectId,
+ @Bind("objectType") ObjectType objectType,
+ @BindBean InternalTenantContext internalTenantContext);
}
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultTagInternalApi.java b/util/src/main/java/com/ning/billing/util/tag/DefaultTagInternalApi.java
index c766478..880fb82 100644
--- a/util/src/main/java/com/ning/billing/util/tag/DefaultTagInternalApi.java
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultTagInternalApi.java
@@ -61,7 +61,7 @@ public class DefaultTagInternalApi implements TagInternalApi {
@Override
public List<Tag> getTags(final UUID objectId, final ObjectType objectType, final InternalTenantContext context) {
- return ImmutableList.<Tag>copyOf(Collections2.transform(tagDao.getTagsForObject(objectId, objectType, context),
+ return ImmutableList.<Tag>copyOf(Collections2.transform(tagDao.getTagsForObject(objectId, objectType, false, context),
new Function<TagModelDao, Tag>() {
@Override
public Tag apply(final TagModelDao input) {
diff --git a/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
index 1969615..b7e4d4b 100644
--- a/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
@@ -73,3 +73,45 @@ where record_id = :recordId
;
>>
+getHistoryRecordIdIdMappings(tableName, historyTableName) ::= <<
+select
+ ht.record_id
+, t.id
+from <tableName> t
+join <historyTableName> ht on ht.target_record_id = t.record_id
+where t.account_record_id = :accountRecordId
+and t.tenant_record_id = :tenantRecordId
+;
+>>
+
+getHistoryRecordIdIdMappingsForAccountsTable(tableName, historyTableName) ::= <<
+select
+ ht.record_id
+, t.id
+from <tableName> t
+join <historyTableName> ht on ht.target_record_id = t.record_id
+where t.record_id = :accountRecordId
+and t.tenant_record_id = :tenantRecordId
+;
+>>
+
+getHistoryRecordIdIdMappingsForTablesWithoutAccountRecordId(tableName, historyTableName) ::= <<
+select
+ ht.record_id
+, t.id
+from <tableName> t
+join <historyTableName> ht on ht.target_record_id = t.record_id
+where 1 = 1
+and t.tenant_record_id = :tenantRecordId
+;
+>>
+
+getRecordIdIdMappings(tableName) ::= <<
+select
+ t.record_id
+, t.id
+from <tableName> t
+where t.account_record_id = :accountRecordId
+and t.tenant_record_id = :tenantRecordId
+;
+>>
\ No newline at end of file
diff --git a/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
index 64a66fd..6214825 100644
--- a/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
@@ -203,6 +203,15 @@ where <accountRecordIdField("t.")> \<=\> :accountRecordId
;
>>
+getByAccountRecordIdIncludedDeleted(accountRecordId) ::= <<
+select
+<allTableFields("t.")>
+from <tableName()> t
+where <accountRecordIdField("t.")> \<=\> :accountRecordId
+<AND_CHECK_TENANT("t.")>
+<defaultOrderBy("t.")>
+;
+>>
getHistoryTargetRecordId(recordId) ::= <<
select
@@ -332,6 +341,29 @@ values (
;
>>
+getAuditLogsForAccountRecordId() ::= <<
+select
+ <auditTableFields("t.")>
+from <auditTableName()> t
+where <accountRecordIdField("t.")> = :accountRecordId
+<andCheckSoftDeletionWithComma("t.")>
+<AND_CHECK_TENANT("t.")>
+order by t.table_name, <recordIdField("t.")> ASC
+;
+>>
+
+getAuditLogsForTableNameAndAccountRecordId() ::= <<
+select
+ <auditTableFields("t.")>
+from <auditTableName()> t
+where <accountRecordIdField("t.")> = :accountRecordId
+and t.table_name = :tableName
+<andCheckSoftDeletionWithComma("t.")>
+<AND_CHECK_TENANT("t.")>
+<defaultOrderBy("t.")>
+;
+>>
+
getAuditLogsForTargetRecordId() ::= <<
select
<auditTableFields("t.")>
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
index 4d709a9..ae38127 100644
--- a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
@@ -46,3 +46,14 @@ and t.object_type = :objectType
<AND_CHECK_TENANT("t.")>
;
>>
+
+getTagsForObjectIncludedDeleted() ::= <<
+select
+ <allTableFields("t.")>
+from <tableName()> t
+where 1 = 1
+and t.object_id = :objectId
+and t.object_type = :objectType
+<AND_CHECK_TENANT("t.")>
+;
+>>
diff --git a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
index 824e50e..46033f4 100644
--- a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
+++ b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
@@ -22,18 +22,17 @@ import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.tweak.transactions.SerializableTransactionRunner;
+import com.ning.billing.util.dao.AuditLogModelDaoMapper;
import com.ning.billing.util.dao.DateTimeArgumentFactory;
import com.ning.billing.util.dao.DateTimeZoneArgumentFactory;
import com.ning.billing.util.dao.EnumArgumentFactory;
import com.ning.billing.util.dao.LocalDateArgumentFactory;
+import com.ning.billing.util.dao.RecordIdIdMappingsMapper;
import com.ning.billing.util.dao.UUIDArgumentFactory;
import com.ning.billing.util.dao.UuidMapper;
import com.google.inject.Inject;
import com.google.inject.Provider;
-import com.jolbox.bonecp.BoneCPConfig;
-import com.jolbox.bonecp.BoneCPDataSource;
-import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DBIProvider implements Provider<IDBI> {
@@ -53,6 +52,8 @@ public class DBIProvider implements Provider<IDBI> {
dbi.registerArgumentFactory(new LocalDateArgumentFactory());
dbi.registerArgumentFactory(new EnumArgumentFactory());
dbi.registerMapper(new UuidMapper());
+ dbi.registerMapper(new AuditLogModelDaoMapper());
+ dbi.registerMapper(new RecordIdIdMappingsMapper());
// Restart transactions in case of deadlocks
dbi.setTransactionHandler(new SerializableTransactionRunner());
diff --git a/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java b/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java
index 0861ac9..a50d378 100644
--- a/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java
+++ b/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java
@@ -16,35 +16,19 @@
package com.ning.billing.util.audit.api;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
-import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.ning.billing.ObjectType;
-import com.ning.billing.entitlement.api.SubscriptionBundle;
-import com.ning.billing.subscription.api.timeline.BundleBaseTimeline;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.payment.api.Payment;
-import com.ning.billing.payment.api.Refund;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
import com.ning.billing.util.audit.AuditLogsTestBase;
import com.ning.billing.util.audit.dao.MockAuditDao;
import com.ning.billing.util.dao.TableName;
-import com.ning.billing.util.entity.Entity;
import com.google.common.collect.ImmutableList;
@@ -53,7 +37,6 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
private List<AuditLog> auditLogs;
private List<UUID> objectIds;
-
@Override
@BeforeClass(groups = "fast")
public void beforeClass() throws Exception {
@@ -61,7 +44,6 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
auditLogs = ImmutableList.<AuditLog>of(createAuditLog(), createAuditLog(), createAuditLog(), createAuditLog());
objectIds = ImmutableList.<UUID>of(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID());
-
for (final TableName tableName : TableName.values()) {
for (final UUID objectId : objectIds) {
for (final AuditLog auditLog : auditLogs) {
@@ -72,66 +54,6 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
}
@Test(groups = "fast")
- public void testForBundles() throws Exception {
- final List<SubscriptionBundle> bundles = new ArrayList<SubscriptionBundle>();
- for (final UUID objectId : objectIds) {
- final SubscriptionBundle entity = Mockito.mock(SubscriptionBundle.class);
- Mockito.when(entity.getId()).thenReturn(objectId);
- bundles.add(entity);
- }
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForBundles auditLogsForBundles = auditUserApi.getAuditLogsForBundles(bundles, level, callContext);
- verifyAuditLogs(auditLogsForBundles.getBundlesAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForInvoicePayments() throws Exception {
- final List<InvoicePayment> invoicePayments = createMocks(InvoicePayment.class);
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForInvoicePayments auditLogsForInvoicePayments = auditUserApi.getAuditLogsForInvoicePayments(invoicePayments, level, callContext);
- verifyAuditLogs(auditLogsForInvoicePayments.getInvoicePaymentsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForRefunds() throws Exception {
- final List<Refund> refunds = createMocks(Refund.class);
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForRefunds auditLogsForRefunds = auditUserApi.getAuditLogsForRefunds(refunds, level, callContext);
- verifyAuditLogs(auditLogsForRefunds.getRefundsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForPayments() throws Exception {
- final List<Payment> payments = createMocks(Payment.class);
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForPayments auditLogsForPayments = auditUserApi.getAuditLogsForPayments(payments, level, callContext);
- verifyAuditLogs(auditLogsForPayments.getPaymentsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForInvoices() throws Exception {
- final List<Invoice> invoices = createMocks(Invoice.class);
- final List<InvoiceItem> invoiceItems = createMocks(InvoiceItem.class);
- for (final Invoice invoice : invoices) {
- Mockito.when(invoice.getInvoiceItems()).thenReturn(invoiceItems);
- }
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForInvoices auditLogsForInvoices = auditUserApi.getAuditLogsForInvoices(invoices, level, callContext);
- verifyAuditLogs(auditLogsForInvoices.getInvoiceAuditLogs(), level);
- verifyAuditLogs(auditLogsForInvoices.getInvoiceItemsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
public void testForObject() throws Exception {
for (final ObjectType objectType : ObjectType.values()) {
for (final UUID objectId : objectIds) {
@@ -147,34 +69,4 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
}
}
}
-
- private void verifyAuditLogs(final Map<UUID, List<AuditLog>> objectsAuditLogs, final AuditLevel level) {
- Assert.assertEquals(objectsAuditLogs.size(), objectIds.size());
-
- if (AuditLevel.NONE.equals(level)) {
- for (final UUID objectId : objectIds) {
- Assert.assertEquals(objectsAuditLogs.get(objectId).size(), 0);
- }
- } else if (AuditLevel.MINIMAL.equals(level)) {
- for (final UUID objectId : objectIds) {
- Assert.assertEquals(objectsAuditLogs.get(objectId).size(), 1);
- Assert.assertEquals(objectsAuditLogs.get(objectId).get(0), auditLogs.get(0));
- }
- } else {
- for (final UUID objectId : objectIds) {
- Assert.assertEquals(objectsAuditLogs.get(objectId), auditLogs);
- }
- }
- }
-
- private <T extends Entity> List<T> createMocks(final Class<T> clazz) {
- final List<T> entities = new ArrayList<T>();
- for (final UUID objectId : objectIds) {
- final T entity = Mockito.mock(clazz);
- Mockito.when(entity.getId()).thenReturn(objectId);
- entities.add(entity);
- }
-
- return entities;
- }
}
diff --git a/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java b/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java
index 56d2349..b6982ee 100644
--- a/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java
+++ b/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java
@@ -22,9 +22,11 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
import com.ning.billing.util.dao.TableName;
import com.google.common.base.Objects;
@@ -51,6 +53,16 @@ public class MockAuditDao implements AuditDao {
}
@Override
+ public DefaultAccountAuditLogs getAuditLogsForAccountRecordId(final AuditLevel auditLevel, final InternalTenantContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DefaultAccountAuditLogsForObjectType getAuditLogsForAccountRecordId(final TableName tableName, final AuditLevel auditLevel, final InternalTenantContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public List<AuditLog> getAuditLogsForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
final Map<UUID, List<AuditLog>> auditLogsForTableName = auditLogsForTables.get(tableName);
if (auditLogsForTableName == null) {
diff --git a/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
index b249338..d8f837a 100644
--- a/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
+++ b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
@@ -29,6 +29,8 @@ import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
+import com.ning.billing.util.audit.AccountAuditLogs;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.dao.TableName;
@@ -63,6 +65,12 @@ public class TestDefaultAuditDao extends UtilTestSuiteWithEmbeddedDB {
for (final AuditLevel level : AuditLevel.values()) {
final List<AuditLog> auditLogs = auditDao.getAuditLogsForId(TableName.TAG, tag.getId(), level, internalCallContext);
verifyAuditLogsForTag(auditLogs, level);
+
+ final AccountAuditLogs accountAuditLogs = auditDao.getAuditLogsForAccountRecordId(level, internalCallContext);
+ verifyAuditLogsForTag(accountAuditLogs.getAuditLogs(ObjectType.TAG).getAuditLogs(tag.getId()), level);
+
+ final AccountAuditLogsForObjectType accountAuditLogsForObjectType = auditDao.getAuditLogsForAccountRecordId(TableName.TAG, level, internalCallContext);
+ verifyAuditLogsForTag(accountAuditLogsForObjectType.getAuditLogs(tag.getId()), level);
}
}
@@ -102,7 +110,7 @@ public class TestDefaultAuditDao extends UtilTestSuiteWithEmbeddedDB {
tagDao.create(new TagModelDao(theTag), internalCallContext);
assertListenerStatus();
- final List<TagModelDao> tags = tagDao.getTagsForObject(objectId, ObjectType.ACCOUNT, internalCallContext);
+ final List<TagModelDao> tags = tagDao.getTagsForObject(objectId, ObjectType.ACCOUNT, false, internalCallContext);
Assert.assertEquals(tags.size(), 1);
tag = tags.get(0);
Assert.assertEquals(tag.getTagDefinitionId(), tagDefinition.getId());
diff --git a/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java b/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
index b519df5..785b062 100644
--- a/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
+++ b/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
@@ -21,12 +21,14 @@ import java.util.UUID;
import org.testng.Assert;
import org.testng.annotations.Test;
+import com.ning.billing.ObjectType;
+import com.ning.billing.callcontext.DefaultCallContext;
+import com.ning.billing.clock.ClockMock;
import com.ning.billing.util.UtilTestSuiteNoDB;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.callcontext.DefaultCallContext;
import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.clock.ClockMock;
import com.ning.billing.util.dao.EntityAudit;
import com.ning.billing.util.dao.TableName;
@@ -47,7 +49,7 @@ public class TestDefaultAuditLog extends UtilTestSuiteNoDB {
final ClockMock clock = new ClockMock();
final CallContext callContext = new DefaultCallContext(tenantId, userName, callOrigin, userType, userToken, clock);
- final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLog auditLog = new DefaultAuditLog(new AuditLogModelDao(entityAudit, callContext), ObjectType.ACCOUNT_EMAIL, UUID.randomUUID());
Assert.assertEquals(auditLog.getChangeType(), changeType);
Assert.assertNull(auditLog.getComment());
Assert.assertNotNull(auditLog.getCreatedDate());
@@ -71,15 +73,15 @@ public class TestDefaultAuditLog extends UtilTestSuiteNoDB {
final ClockMock clock = new ClockMock();
final CallContext callContext = new DefaultCallContext(tenantId, userName, callOrigin, userType, userToken, clock);
- final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLogModelDao auditLog = new AuditLogModelDao(entityAudit, callContext);
Assert.assertEquals(auditLog, auditLog);
- final AuditLog sameAuditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLogModelDao sameAuditLog = new AuditLogModelDao(entityAudit, callContext);
Assert.assertEquals(sameAuditLog, auditLog);
clock.addMonths(1);
final CallContext otherCallContext = new DefaultCallContext(tenantId, userName, callOrigin, userType, userToken, clock);
- final AuditLog otherAuditLog = new DefaultAuditLog(entityAudit, otherCallContext);
+ final AuditLogModelDao otherAuditLog = new AuditLogModelDao(entityAudit, otherCallContext);
Assert.assertNotEquals(otherAuditLog, auditLog);
}
}
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java
index 5653a7f..890febb 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java
@@ -24,9 +24,9 @@ import java.util.Map;
import java.util.UUID;
import com.ning.billing.ObjectType;
-import com.ning.billing.util.api.TagApiException;
import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.api.TagApiException;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
@@ -65,7 +65,7 @@ public class MockTagDao implements TagDao {
}
@Override
- public List<TagModelDao> getTagsForObject(final UUID objectId, final ObjectType objectType, final InternalTenantContext internalTenantContext) {
+ public List<TagModelDao> getTagsForObject(final UUID objectId, final ObjectType objectType, final boolean includedDeleted, final InternalTenantContext internalTenantContext) {
if (tagStore.get(objectId) == null) {
return ImmutableList.<TagModelDao>of();
}
@@ -79,12 +79,12 @@ public class MockTagDao implements TagDao {
}
@Override
- public List<TagModelDao> getTagsForAccountType(final UUID accountId, final ObjectType objectType, final InternalTenantContext internalTenantContext) {
+ public List<TagModelDao> getTagsForAccountType(final UUID accountId, final ObjectType objectType, final boolean includedDeleted, final InternalTenantContext internalTenantContext) {
throw new UnsupportedOperationException();
}
@Override
- public List<TagModelDao> getTagsForAccount(final InternalTenantContext internalTenantContext) {
+ public List<TagModelDao> getTagsForAccount(final boolean includedDeleted, final InternalTenantContext internalTenantContext) {
throw new UnsupportedOperationException();
}
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java
index ab76d25..34211b4 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDao.java
@@ -135,10 +135,10 @@ public class TestDefaultTagDao extends UtilTestSuiteWithEmbeddedDB {
assertListenerStatus();
// Make sure we can retrieve it via the DAO
- final List<TagModelDao> foundTags = tagDao.getTagsForObject(objectId, objectType, internalCallContext);
+ final List<TagModelDao> foundTags = tagDao.getTagsForObject(objectId, objectType, false, internalCallContext);
Assert.assertEquals(foundTags.size(), 1);
Assert.assertEquals(foundTags.get(0).getTagDefinitionId(), createdTagDefinition.getId());
- final List<TagModelDao> foundTagsForAccount = tagDao.getTagsForAccount(internalCallContext);
+ final List<TagModelDao> foundTagsForAccount = tagDao.getTagsForAccount(false, internalCallContext);
Assert.assertEquals(foundTagsForAccount.size(), 1);
Assert.assertEquals(foundTagsForAccount.get(0).getTagDefinitionId(), createdTagDefinition.getId());
@@ -148,7 +148,9 @@ public class TestDefaultTagDao extends UtilTestSuiteWithEmbeddedDB {
assertListenerStatus();
// Make sure the tag is deleted
- Assert.assertEquals(tagDao.getTagsForObject(objectId, objectType, internalCallContext).size(), 0);
- Assert.assertEquals(tagDao.getTagsForAccount(internalCallContext).size(), 0);
+ Assert.assertEquals(tagDao.getTagsForObject(objectId, objectType, false, internalCallContext).size(), 0);
+ Assert.assertEquals(tagDao.getTagsForAccount(false, internalCallContext).size(), 0);
+ Assert.assertEquals(tagDao.getTagsForObject(objectId, objectType, true, internalCallContext).size(), 1);
+ Assert.assertEquals(tagDao.getTagsForAccount(true, internalCallContext).size(), 1);
}
}