killbill-uncached

junction: run account BCD refresh even in dry-run mode Signed-off-by:

12/5/2018 1:21:45 PM

Details

diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 1eb38a9..1d459ec 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -28,7 +28,7 @@
       <option name="useParameterizedTypeForCollectionMethods" value="true" />
       <option name="doNotWeakenToJavaLangObject" value="true" />
       <option name="onlyWeakentoInterface" value="true" />
-      <stopClasses>org.killbill.billing.catalog.api.Plan</stopClasses>
+      <stopClasses>org.killbill.billing.catalog.api.Plan,org.killbill.billing.junction.BillingEventSet</stopClasses>
     </inspection_tool>
     <inspection_tool class="UnnecessaryConstantArrayCreationExpression" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UseOfJDBCDriverClass" enabled="true" level="WARNING" enabled_by_default="true" />
diff --git a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
index 50c2af3..a096e5e 100644
--- a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
+++ b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
@@ -139,12 +139,35 @@ public class DefaultInternalBillingApi implements BillingInternalApi {
         }
     }
 
-    private void addBillingEventsForBundles(final List<SubscriptionBaseBundle> bundles, final ImmutableAccountData account, final DryRunArguments dryRunArguments, final InternalCallContext context,
-                                            final DefaultBillingEventSet result, final Set<UUID> skipSubscriptionsSet, final Catalog catalog, final List<Tag> tagsForAccount) throws AccountApiException, CatalogApiException, SubscriptionBaseApiException {
-        final boolean dryRunMode = dryRunArguments != null;
-
+    private void addBillingEventsForBundles(final List<SubscriptionBaseBundle> bundles,
+                                            final ImmutableAccountData account,
+                                            final DryRunArguments dryRunArguments,
+                                            final InternalCallContext context,
+                                            final DefaultBillingEventSet result,
+                                            final Set<UUID> skipSubscriptionsSet,
+                                            final Catalog catalog,
+                                            final List<Tag> tagsForAccount) throws AccountApiException, CatalogApiException, SubscriptionBaseApiException {
         final int currentAccountBCD = accountApi.getBCD(context);
+        addBillingEventsForBundles(bundles,
+                                   account,
+                                   dryRunArguments,
+                                   context,
+                                   result,
+                                   skipSubscriptionsSet,
+                                   catalog,
+                                   tagsForAccount,
+                                   currentAccountBCD);
+    }
 
+    private void addBillingEventsForBundles(final List<SubscriptionBaseBundle> bundles,
+                                            final ImmutableAccountData account,
+                                            final DryRunArguments dryRunArguments,
+                                            final InternalCallContext context,
+                                            final DefaultBillingEventSet result,
+                                            final Set<UUID> skipSubscriptionsSet,
+                                            final Catalog catalog,
+                                            final List<Tag> tagsForAccount,
+                                            final int currentAccountBCD) throws AccountApiException, CatalogApiException, SubscriptionBaseApiException {
         // In dryRun mode, when we care about invoice generated for new BASE subscription, no such bundle exists yet; we still
         // want to tap into subscriptionBase logic, so we make up a bundleId
         if (dryRunArguments != null &&
@@ -185,46 +208,58 @@ public class DefaultInternalBillingApi implements BillingInternalApi {
         }
 
         // If dryRun is specified, we don't want to to update the account BCD value, so we initialize the flag updatedAccountBCD to true
-        if (currentAccountBCD == 0 && !dryRunMode) {
-            BillingEvent oldestAccountAlignedBillingEvent = null;
-
-            for (final BillingEvent event : result) {
-                if (event.getBillingAlignment() != BillingAlignment.ACCOUNT) {
-                    continue;
-                }
+        if (currentAccountBCD == 0) {
+            final Integer accountBCDCandidate = computeAccountBCD(result);
+            if (accountBCDCandidate == null) {
+                return;
+            }
 
-                final BigDecimal recurringPrice = event.getRecurringPrice(event.getEffectiveDate());
-                final boolean hasRecurringPrice = recurringPrice != null; // Note: could be zero (BCD would still be set, by convention)
-                final boolean hasUsage = event.getUsages() != null && !event.getUsages().isEmpty();
-                if (!hasRecurringPrice &&
-                    !hasUsage) {
-                    // Nothing to bill, ignored for the purpose of BCD calculation
-                    continue;
-                }
+            // Because we now have computed the real BCD, we need to re-compute the BillingEvents BCD for ACCOUNT alignments (see BillCycleDayCalculator#calculateBcdForAlignment).
+            // The code could maybe be optimized (no need to re-run the full function?), but since it's run once per account, it's probably not worth it.
+            result.clear();
+            addBillingEventsForBundles(bundles, account, dryRunArguments, context, result, skipSubscriptionsSet, catalog, tagsForAccount, accountBCDCandidate);
 
-                if (oldestAccountAlignedBillingEvent == null ||
-                    event.getEffectiveDate().compareTo(oldestAccountAlignedBillingEvent.getEffectiveDate()) < 0 ||
-                    (event.getEffectiveDate().compareTo(oldestAccountAlignedBillingEvent.getEffectiveDate()) == 0 && event.getTotalOrdering().compareTo(oldestAccountAlignedBillingEvent.getTotalOrdering()) < 0)) {
-                    oldestAccountAlignedBillingEvent = event;
-                }
+            final boolean dryRunMode = dryRunArguments != null;
+            if (!dryRunMode) {
+                log.info("Setting account BCD='{}', accountId='{}'", accountBCDCandidate, account.getId());
+                accountApi.updateBCD(account.getExternalKey(), accountBCDCandidate, context);
             }
+        }
+    }
 
-            if (oldestAccountAlignedBillingEvent == null) {
-                return;
+    private Integer computeAccountBCD(final BillingEventSet result) throws CatalogApiException {
+        BillingEvent oldestAccountAlignedBillingEvent = null;
+
+        for (final BillingEvent event : result) {
+            if (event.getBillingAlignment() != BillingAlignment.ACCOUNT) {
+                continue;
             }
 
-            // BCD in the account timezone
-            final int accountBCDCandidate = oldestAccountAlignedBillingEvent.getBillCycleDayLocal();
-            Preconditions.checkState(accountBCDCandidate > 0, "Wrong Account BCD calculation for event: " + oldestAccountAlignedBillingEvent);
+            final BigDecimal recurringPrice = event.getRecurringPrice(event.getEffectiveDate());
+            final boolean hasRecurringPrice = recurringPrice != null; // Note: could be zero (BCD would still be set, by convention)
+            final boolean hasUsage = event.getUsages() != null && !event.getUsages().isEmpty();
+            if (!hasRecurringPrice &&
+                !hasUsage) {
+                // Nothing to bill, ignored for the purpose of BCD calculation
+                continue;
+            }
 
-            log.info("Setting account BCD='{}', accountId='{}'", accountBCDCandidate, account.getId());
-            accountApi.updateBCD(account.getExternalKey(), accountBCDCandidate, context);
+            if (oldestAccountAlignedBillingEvent == null ||
+                event.getEffectiveDate().compareTo(oldestAccountAlignedBillingEvent.getEffectiveDate()) < 0 ||
+                (event.getEffectiveDate().compareTo(oldestAccountAlignedBillingEvent.getEffectiveDate()) == 0 && event.getTotalOrdering().compareTo(oldestAccountAlignedBillingEvent.getTotalOrdering()) < 0)) {
+                oldestAccountAlignedBillingEvent = event;
+            }
+        }
 
-            // Because we now have computed the real BCD, we need to re-compute the BillingEvents BCD for ACCOUNT alignments (see BillCycleDayCalculator#calculateBcdForAlignment).
-            // The code could maybe be optimized (no need to re-run the full function?), but since it's run once per account, it's probably not worth it.
-            result.clear();
-            addBillingEventsForBundles(bundles, account, dryRunArguments, context, result, skipSubscriptionsSet, catalog, tagsForAccount);
+        if (oldestAccountAlignedBillingEvent == null) {
+            return null;
         }
+
+        // BCD in the account timezone
+        final int accountBCDCandidate = oldestAccountAlignedBillingEvent.getBillCycleDayLocal();
+        Preconditions.checkState(accountBCDCandidate > 0, "Wrong Account BCD calculation for event: " + oldestAccountAlignedBillingEvent);
+
+        return accountBCDCandidate;
     }
 
     private void addBillingEventsForSubscription(final ImmutableAccountData account,