killbill-memoizeit

overdue: fix issue with stale parent state (HA) If the billing

5/7/2018 11:49:11 AM

Details

diff --git a/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java
index b880b1d..cc5ecfa 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java
@@ -135,6 +135,8 @@ public class OverdueStateApplicator {
         if (previousOverdueState.getName().equals(nextOverdueState.getName())) {
             log.debug("OverdueStateApplicator is no-op: previousState={}, nextState={}", previousOverdueState, nextOverdueState);
             return;
+        } else {
+            log.debug("OverdueStateApplicator has new state: previousState={}, nextState={}", previousOverdueState, nextOverdueState);
         }
 
         cancelSubscriptionsIfRequired(effectiveDate, account, nextOverdueState, context);
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
index 7ecdb5c..e247a1f 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
@@ -153,27 +153,38 @@ public class OverdueListener {
     private void insertBusEventIntoNotificationQueue(final UUID accountId, final OverdueAsyncBusNotificationAction action, final InternalCallContext callContext) {
         final boolean shouldInsertNotification = shouldInsertNotification(callContext);
 
-        if (shouldInsertNotification) {
-            OverdueAsyncBusNotificationKey notificationKey = new OverdueAsyncBusNotificationKey(accountId, action);
-            asyncPoster.insertOverdueNotification(accountId, callContext.getCreatedDate(), OverdueAsyncBusNotifier.OVERDUE_ASYNC_BUS_NOTIFIER_QUEUE, notificationKey, callContext);
-
-            try {
-                final List<Account> childrenAccounts = accountApi.getChildrenAccounts(accountId, callContext);
-                if (childrenAccounts != null) {
-                    for (Account childAccount : childrenAccounts) {
-
-                        if (childAccount.isPaymentDelegatedToParent()) {
-                            final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(childAccount.getId(), callContext);
-                            final InternalCallContext accountContext = internalCallContextFactory.createInternalCallContext(internalTenantContext.getAccountRecordId(), callContext);
-                            notificationKey = new OverdueAsyncBusNotificationKey(childAccount.getId(), action);
-                            asyncPoster.insertOverdueNotification(childAccount.getId(), callContext.getCreatedDate(), OverdueAsyncBusNotifier.OVERDUE_ASYNC_BUS_NOTIFIER_QUEUE, notificationKey, accountContext);
-                        }
+        if (!shouldInsertNotification) {
+            log.debug("OverdueListener: shouldInsertNotification=false");
+            return;
+        }
+
+        OverdueAsyncBusNotificationKey notificationKey = new OverdueAsyncBusNotificationKey(accountId, action);
+        asyncPoster.insertOverdueNotification(accountId, callContext.getCreatedDate(), OverdueAsyncBusNotifier.OVERDUE_ASYNC_BUS_NOTIFIER_QUEUE, notificationKey, callContext);
+
+        try {
+            // Refresh parent
+            final Account account = accountApi.getAccountById(accountId, callContext);
+            if (account.getParentAccountId() != null && account.isPaymentDelegatedToParent()) {
+                final InternalTenantContext parentAccountInternalTenantContext = internalCallContextFactory.createInternalTenantContext(account.getParentAccountId(), callContext);
+                final InternalCallContext parentAccountContext = internalCallContextFactory.createInternalCallContext(parentAccountInternalTenantContext.getAccountRecordId(), callContext);
+                notificationKey = new OverdueAsyncBusNotificationKey(account.getParentAccountId(), action);
+                asyncPoster.insertOverdueNotification(account.getParentAccountId(), callContext.getCreatedDate(), OverdueAsyncBusNotifier.OVERDUE_ASYNC_BUS_NOTIFIER_QUEUE, notificationKey, parentAccountContext);
+            }
+
+            // Refresh children
+            final List<Account> childrenAccounts = accountApi.getChildrenAccounts(accountId, callContext);
+            if (childrenAccounts != null) {
+                for (final Account childAccount : childrenAccounts) {
+                    if (childAccount.isPaymentDelegatedToParent()) {
+                        final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(childAccount.getId(), callContext);
+                        final InternalCallContext accountContext = internalCallContextFactory.createInternalCallContext(internalTenantContext.getAccountRecordId(), callContext);
+                        notificationKey = new OverdueAsyncBusNotificationKey(childAccount.getId(), action);
+                        asyncPoster.insertOverdueNotification(childAccount.getId(), callContext.getCreatedDate(), OverdueAsyncBusNotifier.OVERDUE_ASYNC_BUS_NOTIFIER_QUEUE, notificationKey, accountContext);
                     }
                 }
-            } catch (Exception e) {
-                log.error("Error loading child accounts from account " + accountId);
             }
-
+        } catch (final Exception e) {
+            log.error("Error loading child accounts from accountId='{}'", accountId);
         }
     }
 
@@ -183,7 +194,7 @@ public class OverdueListener {
         try {
             overdueConfig = overdueConfigCache.getOverdueConfig(internalTenantContext);
         } catch (final OverdueApiException e) {
-            log.warn("Failed to extract overdue config for tenant " + internalTenantContext.getTenantRecordId());
+            log.warn("Failed to extract overdue config for tenantRecordId='{}'", internalTenantContext.getTenantRecordId());
             overdueConfig = null;
         }
         if (overdueConfig == null || overdueConfig.getOverdueStatesAccount() == null || overdueConfig.getOverdueStatesAccount().getStates() == null) {
@@ -197,5 +208,4 @@ public class OverdueListener {
         }
         return false;
     }
-
 }
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoiceVoid.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoiceVoid.java
index 99a887f..6a79b16 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoiceVoid.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoiceVoid.java
@@ -180,6 +180,7 @@ public class TestInvoiceVoid extends TestJaxrsBase {
         //  move the clock 1 month to check if invoices change
         callbackServlet.pushExpectedEvents(ExtBusEventType.SUBSCRIPTION_PHASE,
                                            ExtBusEventType.INVOICE_CREATION,
+                                           // Overdue state is computed from the parent state
                                            ExtBusEventType.OVERDUE_CHANGE,
                                            ExtBusEventType.BLOCKING_STATE,
                                            ExtBusEventType.OVERDUE_CHANGE,
@@ -187,7 +188,7 @@ public class TestInvoiceVoid extends TestJaxrsBase {
         clock.addDays(31);
         callbackServlet.assertListenerStatus();
 
-        // The parent added other invoice, now it has two (duplicate)
+        // The parent added another invoice, now it has two (duplicate)
         parentInvoices = killBillClient.getInvoicesForAccount(parentAccount.getAccountId(), true, false, requestOptions);
         assertEquals(parentInvoices.size(), 2);