killbill-memoizeit

invoice: refactor set/remove WRITTEN_OFF APIs Move the

10/4/2012 8:57:50 PM

Details

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 ab33eac..eba5843 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
@@ -26,6 +26,8 @@ import javax.annotation.Nullable;
 
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.ning.billing.ErrorCode;
 import com.ning.billing.account.api.Account;
@@ -44,6 +46,8 @@ import com.ning.billing.invoice.model.ExternalChargeInvoiceItem;
 import com.ning.billing.invoice.template.HtmlInvoiceGenerator;
 import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.bus.Bus.EventBusException;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.callcontext.TenantContext;
@@ -55,22 +59,27 @@ import com.google.inject.Inject;
 
 public class DefaultInvoiceUserApi implements InvoiceUserApi {
 
+    private static final Logger log = LoggerFactory.getLogger(DefaultInvoiceUserApi.class);
+
     private final InvoiceDao dao;
     private final InvoiceDispatcher dispatcher;
     private final AccountUserApi accountUserApi;
     private final TagUserApi tagUserApi;
     private final HtmlInvoiceGenerator generator;
     private final InternalCallContextFactory internalCallContextFactory;
+    private final Bus eventBus;
 
     @Inject
     public DefaultInvoiceUserApi(final InvoiceDao dao, final InvoiceDispatcher dispatcher, final AccountUserApi accountUserApi,
-                                 final TagUserApi tagUserApi, final HtmlInvoiceGenerator generator, final InternalCallContextFactory internalCallContextFactory) {
+                                 final TagUserApi tagUserApi, final HtmlInvoiceGenerator generator, final InternalCallContextFactory internalCallContextFactory,
+                                 final Bus eventBus) {
         this.dao = dao;
         this.dispatcher = dispatcher;
         this.accountUserApi = accountUserApi;
         this.tagUserApi = tagUserApi;
         this.generator = generator;
         this.internalCallContextFactory = internalCallContextFactory;
+        this.eventBus = eventBus;
     }
 
     @Override
@@ -138,16 +147,24 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
 
     @Override
     public void tagInvoiceAsWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException, InvoiceApiException {
-        // Retrieve the invoice for the internal call context
+        // Note: the tagUserApi is audited
+        tagUserApi.addTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), context);
+
+        // Retrieve the invoice for the account id
         final Invoice invoice = dao.getById(invoiceId, internalCallContextFactory.createInternalCallContext(context));
-        dao.setWrittenOff(invoiceId, internalCallContextFactory.createInternalCallContext(invoice.getAccountId(), context));
+        // This is for overdue
+        notifyBusOfInvoiceAdjustment(invoiceId, invoice.getAccountId(), context.getUserToken());
     }
 
     @Override
     public void tagInvoiceAsNotWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException, InvoiceApiException {
-        // Retrieve the invoice for the internal call context
+        // Note: the tagUserApi is audited
+        tagUserApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), context);
+
+        // Retrieve the invoice for the account id
         final Invoice invoice = dao.getById(invoiceId, internalCallContextFactory.createInternalCallContext(context));
-        dao.removeWrittenOff(invoiceId, internalCallContextFactory.createInternalCallContext(invoice.getAccountId(), context));
+        // This is for overdue
+        notifyBusOfInvoiceAdjustment(invoiceId, invoice.getAccountId(), context.getUserToken());
     }
 
     @Override
@@ -262,4 +279,11 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
         return generator.generateInvoice(account, invoice, manualPay);
     }
 
+    private void notifyBusOfInvoiceAdjustment(final UUID invoiceId, final UUID accountId, final UUID userToken) {
+        try {
+            eventBus.post(new DefaultInvoiceAdjustmentEvent(invoiceId, accountId, userToken));
+        } catch (EventBusException e) {
+            log.warn("Failed to post adjustment event for invoice " + invoiceId, e);
+        }
+    }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/AuditedInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/AuditedInvoiceDao.java
index 279fecb..3735ffb 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/AuditedInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/AuditedInvoiceDao.java
@@ -55,7 +55,6 @@ import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.invoice.model.RefundAdjInvoiceItem;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
 import com.ning.billing.util.ChangeType;
-import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.Bus.EventBusException;
@@ -63,9 +62,7 @@ import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.dao.EntityAudit;
-import com.ning.billing.util.dao.ObjectType;
 import com.ning.billing.util.dao.TableName;
-import com.ning.billing.util.tag.ControlTagType;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Objects;
@@ -326,38 +323,6 @@ public class AuditedInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void setWrittenOff(final UUID invoiceId, final InternalCallContext context) throws TagApiException {
-        invoiceSqlDao.inTransaction(new Transaction<Void, InvoiceSqlDao>() {
-            @Override
-            public Void inTransaction(final InvoiceSqlDao transactional, final TransactionStatus status) throws Exception {
-                // Note: the tagUserApi is audited
-                tagUserApi.addTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), context.toCallContext());
-
-                final Invoice invoice = transactional.getById(invoiceId.toString(), context);
-                notifyBusOfInvoiceAdjustment(transactional, invoiceId, invoice.getAccountId(), context.getUserToken());
-
-                return null;
-            }
-        });
-    }
-
-    @Override
-    public void removeWrittenOff(final UUID invoiceId, final InternalCallContext context) throws TagApiException {
-        invoiceSqlDao.inTransaction(new Transaction<Void, InvoiceSqlDao>() {
-            @Override
-            public Void inTransaction(final InvoiceSqlDao transactional, final TransactionStatus status) throws Exception {
-                // Note: the tagUserApi is audited
-                tagUserApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), context.toCallContext());
-
-                final Invoice invoice = transactional.getById(invoiceId.toString(), context);
-                notifyBusOfInvoiceAdjustment(transactional, invoiceId, invoice.getAccountId(), context.getUserToken());
-
-                return null;
-            }
-        });
-    }
-
-    @Override
     public InvoicePayment createRefund(final UUID paymentId, final BigDecimal requestedRefundAmount, final boolean isInvoiceAdjusted,
                                        final Map<UUID, BigDecimal> invoiceItemIdsWithNullAmounts, final UUID paymentCookieId,
                                        final InternalCallContext context)
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index a97492e..f9e9b4d 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -30,7 +30,6 @@ import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 
@@ -66,10 +65,6 @@ public interface InvoiceDao {
 
     List<Invoice> getAllInvoicesByAccount(UUID accountId, InternalTenantContext context);
 
-    void setWrittenOff(UUID invoiceId, InternalCallContext context) throws TagApiException;
-
-    void removeWrittenOff(UUID invoiceId, InternalCallContext context) throws TagApiException;
-
     InvoicePayment postChargeback(UUID invoicePaymentId, BigDecimal amount, InternalCallContext context) throws InvoiceApiException;
 
     /**
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java
index e2c7fe4..d5aa6dd 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/InvoiceApiTestBase.java
@@ -53,6 +53,7 @@ import com.ning.billing.invoice.tests.InvoicingTestBase;
 import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.junction.api.BillingEventSet;
 import com.ning.billing.mock.api.MockBillCycleDay;
+import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.bus.BusService;
 import com.ning.billing.util.bus.DefaultBusService;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
@@ -91,6 +92,9 @@ public abstract class InvoiceApiTestBase extends InvoicingTestBase {
     protected InvoiceDao invoiceDao;
 
     @Inject
+    protected TagUserApi tagUserApi;
+
+    @Inject
     protected GlobalLocker locker;
 
     @Inject
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 7fa510f..cf256f0 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
@@ -17,6 +17,7 @@
 package com.ning.billing.invoice.api.user;
 
 import java.math.BigDecimal;
+import java.util.Map;
 import java.util.UUID;
 
 import javax.annotation.Nullable;
@@ -33,11 +34,17 @@ import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceItemType;
 import com.ning.billing.invoice.api.migration.InvoiceApiTestBase;
 import com.ning.billing.invoice.model.InvoicingConfiguration;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallOrigin;
 import com.ning.billing.util.callcontext.DefaultCallContextFactory;
 import com.ning.billing.util.callcontext.TenantContext;
 import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.dao.ObjectType;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
+
+import static org.testng.Assert.assertEquals;
 
 public class TestDefaultInvoiceUserApi extends InvoiceApiTestBase {
 
@@ -316,4 +323,17 @@ public class TestDefaultInvoiceUserApi extends InvoiceApiTestBase {
                                                                            .setScale(InvoicingConfiguration.getNumberOfDecimals(),
                                                                                      InvoicingConfiguration.getRoundingMode())), 0);
     }
+
+    @Test(groups = "slow")
+    public void testAddRemoveWrittenOffTag() throws InvoiceApiException, TagApiException {
+        invoiceUserApi.tagInvoiceAsWrittenOff(invoiceId, callContext);
+
+        Map<String, Tag> tags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE, tenantContext);
+        assertEquals(tags.size(), 1);
+        assertEquals(tags.values().iterator().next().getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId());
+
+        invoiceUserApi.tagInvoiceAsNotWrittenOff(invoiceId, callContext);
+        tags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE, tenantContext);
+        assertEquals(tags.size(), 0);
+    }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index 4065ab6..58f5990 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -222,16 +222,6 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void setWrittenOff(final UUID objectId, final InternalCallContext context) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void removeWrittenOff(final UUID objectId, final InternalCallContext context) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public InvoicePayment postChargeback(final UUID invoicePaymentId, final BigDecimal amount, final InternalCallContext context) throws InvoiceApiException {
         throw new UnsupportedOperationException();
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
index 36e1168..7c0f398 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
@@ -41,9 +41,6 @@ import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.dao.ObjectType;
-import com.ning.billing.util.tag.ControlTagType;
-import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.api.DefaultTagUserApi;
 import com.ning.billing.util.tag.dao.MockTagDao;
 import com.ning.billing.util.tag.dao.MockTagDefinitionDao;
@@ -134,33 +131,4 @@ public class TestDefaultInvoiceDao extends InvoiceTestSuite {
         } catch (InvoiceApiException e) {
         }
     }
-
-    @Test(groups = "fast")
-    public void testSetWrittenOff() throws Exception {
-        final UUID invoiceId = UUID.randomUUID();
-
-        final Map<String, Tag> beforeTags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE, callContext);
-        Assert.assertEquals(beforeTags.keySet().size(), 0);
-
-        dao.setWrittenOff(invoiceId, internalCallContext);
-
-        final Map<String, Tag> afterTags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE, callContext);
-        Assert.assertEquals(afterTags.keySet().size(), 1);
-        final UUID tagDefinitionId = ControlTagType.WRITTEN_OFF.getId();
-        Assert.assertEquals(afterTags.values().iterator().next().getTagDefinitionId(), tagDefinitionId);
-    }
-
-    @Test(groups = "fast")
-    public void testRemoveWrittenOff() throws Exception {
-        final UUID invoiceId = UUID.randomUUID();
-
-        dao.setWrittenOff(invoiceId, internalCallContext);
-
-        final Map<String, Tag> beforeTags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE, callContext);
-        Assert.assertEquals(beforeTags.keySet().size(), 1);
-        dao.removeWrittenOff(invoiceId, internalCallContext);
-
-        final Map<String, Tag> afterTags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE, callContext);
-        Assert.assertEquals(afterTags.keySet().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 552c8dc..73792ea 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
@@ -62,14 +62,8 @@ import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.invoice.model.RepairAdjInvoiceItem;
 import com.ning.billing.junction.api.BillingEventSet;
-import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.dao.ObjectType;
 import com.ning.billing.util.entity.EntityPersistenceException;
-import com.ning.billing.util.tag.ControlTagType;
-import com.ning.billing.util.tag.Tag;
-import com.ning.billing.util.tag.dao.AuditedTagDao;
-import com.ning.billing.util.tag.dao.TagDao;
 
 import com.google.common.collect.ImmutableMap;
 
@@ -1317,72 +1311,6 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
     }
 
     @Test(groups = "slow")
-    public void testAddingWrittenOffTag() throws InvoiceApiException, TagApiException {
-        final Subscription subscription = getZombieSubscription();
-
-        final Plan plan = Mockito.mock(Plan.class);
-        Mockito.when(plan.getName()).thenReturn("plan");
-
-        final PlanPhase phase1 = Mockito.mock(PlanPhase.class);
-        Mockito.when(phase1.getName()).thenReturn("plan-phase1");
-
-        final DateTime targetDate1 = clock.getUTCNow();
-        final Currency currency = Currency.USD;
-
-        // create pseudo-random invoice
-        final BillingEvent event1 = createMockBillingEvent(null, subscription, targetDate1, plan, phase1, null,
-                                                           TEN, currency,
-                                                           BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
-                                                           "testEvent1", 1L, SubscriptionTransitionType.CHANGE);
-        final BillingEventSet events = new MockBillingEventSet();
-        events.add(event1);
-
-        final Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, new LocalDate(targetDate1), DateTimeZone.UTC, Currency.USD);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceDao.setWrittenOff(invoice.getId(), internalCallContext);
-
-        final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
-        final Map<String, Tag> tags = tagDao.loadEntities(invoice.getId(), ObjectType.INVOICE, internalCallContext);
-        assertEquals(tags.size(), 1);
-        assertEquals(tags.values().iterator().next().getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId());
-    }
-
-    @Test(groups = "slow")
-    public void testRemoveWrittenOffTag() throws InvoiceApiException, TagApiException {
-        final Subscription subscription = getZombieSubscription();
-
-        final Plan plan = Mockito.mock(Plan.class);
-        Mockito.when(plan.getName()).thenReturn("plan");
-
-        final PlanPhase phase1 = Mockito.mock(PlanPhase.class);
-        Mockito.when(phase1.getName()).thenReturn("plan-phase1");
-
-        final DateTime targetDate1 = clock.getUTCNow();
-        final Currency currency = Currency.USD;
-
-        // create pseudo-random invoice
-        final BillingEvent event1 = createMockBillingEvent(null, subscription, targetDate1, plan, phase1, null,
-                                                           TEN, currency,
-                                                           BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
-                                                           "testEvent1", 1L, SubscriptionTransitionType.CHANGE);
-        final BillingEventSet events = new MockBillingEventSet();
-        events.add(event1);
-
-        final Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, new LocalDate(targetDate1), DateTimeZone.UTC, Currency.USD);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, internalCallContext);
-        invoiceDao.setWrittenOff(invoice.getId(), internalCallContext);
-
-        final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
-        Map<String, Tag> tags = tagDao.loadEntities(invoice.getId(), ObjectType.INVOICE, internalCallContext);
-        assertEquals(tags.size(), 1);
-        assertEquals(tags.values().iterator().next().getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId());
-
-        invoiceDao.removeWrittenOff(invoice.getId(), internalCallContext);
-        tags = tagDao.loadEntities(invoice.getId(), ObjectType.INVOICE, internalCallContext);
-        assertEquals(tags.size(), 0);
-    }
-
-    @Test(groups = "slow")
     public void testDeleteCBANotConsumed() throws Exception {
         final UUID accountId = UUID.randomUUID();