killbill-memoizeit

jaxrs: Allow late usage data to be recorded before subscription

4/27/2018 1:08:04 AM

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/UsageResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/UsageResource.java
index 1e51050..000d28d 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/UsageResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/UsageResource.java
@@ -59,9 +59,12 @@ import org.killbill.billing.util.callcontext.TenantContext;
 import org.killbill.clock.Clock;
 import org.killbill.commons.metrics.TimedResource;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Ordering;
 import com.google.inject.Singleton;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -124,8 +127,11 @@ public class UsageResource extends JaxRsResourceBase {
         final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request);
         // Verify subscription exists..
         final Entitlement entitlement = entitlementApi.getEntitlementForId(json.getSubscriptionId(), callContext);
-        if (entitlement.getState() != EntitlementState.ACTIVE) {
-            return Response.status(Status.BAD_REQUEST).build();
+        if (entitlement.getEffectiveEndDate() != null) {
+            final LocalDate highestRecordDate = getHighestRecordDate(json.getUnitUsageRecords());
+            if (entitlement.getEffectiveEndDate().compareTo(highestRecordDate) < 0) {
+                return Response.status(Status.BAD_REQUEST).build();
+            }
         }
 
         final SubscriptionUsageRecord record = json.toSubscriptionUsageRecord();
@@ -133,6 +139,28 @@ public class UsageResource extends JaxRsResourceBase {
         return Response.status(Status.CREATED).build();
     }
 
+    @VisibleForTesting
+    LocalDate getHighestRecordDate(final List<UnitUsageRecordJson> records) {
+        final Iterable<Iterable<LocalDate>> recordedDates = Iterables.transform(records, new Function<UnitUsageRecordJson, Iterable<LocalDate>>() {
+
+            @Override
+            public Iterable<LocalDate> apply(final UnitUsageRecordJson input) {
+                final Iterable<LocalDate> result = Iterables.transform(input.getUsageRecords(), new Function<UsageRecordJson, LocalDate>() {
+                    @Override
+                    public LocalDate apply(final UsageRecordJson input) {
+                        return input.getRecordDate();
+                    }
+                });
+                return result;
+            }
+        });
+        final Iterable<LocalDate> sortedRecordedDates = Ordering.<LocalDate>natural()
+                .reverse()
+                .sortedCopy(Iterables.concat(recordedDates));
+
+        return Iterables.getFirst(sortedRecordedDates, null);
+    }
+
     @TimedResource
     @GET
     @Path("/{subscriptionId:" + UUID_PATTERN + "}/{unitType}")
diff --git a/jaxrs/src/test/java/org/killbill/billing/jaxrs/resources/TestJaxRsResourceBase.java b/jaxrs/src/test/java/org/killbill/billing/jaxrs/resources/TestJaxRsResourceBase.java
index 85195c0..979f012 100644
--- a/jaxrs/src/test/java/org/killbill/billing/jaxrs/resources/TestJaxRsResourceBase.java
+++ b/jaxrs/src/test/java/org/killbill/billing/jaxrs/resources/TestJaxRsResourceBase.java
@@ -19,7 +19,10 @@ package org.killbill.billing.jaxrs.resources;
 
 import java.util.List;
 
+import org.joda.time.LocalDate;
 import org.killbill.billing.jaxrs.JaxrsTestSuiteNoDB;
+import org.killbill.billing.jaxrs.json.SubscriptionUsageRecordJson.UnitUsageRecordJson;
+import org.killbill.billing.jaxrs.json.SubscriptionUsageRecordJson.UsageRecordJson;
 import org.killbill.billing.payment.api.PluginProperty;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -67,4 +70,50 @@ public class TestJaxRsResourceBase extends JaxrsTestSuiteNoDB {
             super(null, null, null, null, null, null, null, null, null);
         }
     }
+
+
+    @Test(groups = "fast")
+    public void testGetHighestRecordDate() throws Exception {
+        final UsageResourceTest usageResource = new UsageResourceTest();
+
+        final List<UsageRecordJson> fooRecords = ImmutableList.<UsageRecordJson>builder()
+                .add(new UsageRecordJson(new LocalDate(2018, 03, 04), 28L))
+                .add(new UsageRecordJson(new LocalDate(2018, 03, 05), 2L))
+                .add(new UsageRecordJson(new LocalDate(2018, 03, 01), 1L))
+                .add(new UsageRecordJson(new LocalDate(2018, 04, 06), 24L))
+                .build();
+        final UnitUsageRecordJson unitRecordFoo = new UnitUsageRecordJson("foo", fooRecords);
+
+        final List<UsageRecordJson> barRecords = ImmutableList.<UsageRecordJson>builder()
+                .add(new UsageRecordJson(new LocalDate(2018, 02, 04), 28L))
+                .add(new UsageRecordJson(new LocalDate(2018, 03, 06), 2L))
+                .add(new UsageRecordJson(new LocalDate(2018, 04, 18), 1L)) // Highest date point
+                .add(new UsageRecordJson(new LocalDate(2018, 04, 13), 24L))
+                .build();
+        final UnitUsageRecordJson unitRecordBar = new UnitUsageRecordJson("bar", barRecords);
+
+        final List<UsageRecordJson> zooRecords = ImmutableList.<UsageRecordJson>builder()
+                .add(new UsageRecordJson(new LocalDate(2018, 02, 04), 28L))
+                .add(new UsageRecordJson(new LocalDate(2018, 03, 06), 2L))
+                .add(new UsageRecordJson(new LocalDate(2018, 04, 17), 1L))
+                .add(new UsageRecordJson(new LocalDate(2018, 04, 12), 24L))
+                .build();
+        final UnitUsageRecordJson unitRecordZoo = new UnitUsageRecordJson("zoo", zooRecords);
+
+        final List<UnitUsageRecordJson> input = ImmutableList.<UnitUsageRecordJson>builder()
+                .add(unitRecordFoo)
+                .add(unitRecordBar)
+                .add(unitRecordZoo)
+                .build();
+        final LocalDate result = usageResource.getHighestRecordDate(input);
+
+        Assert.assertTrue(result.compareTo(new LocalDate(2018, 04, 18)) == 0);
+    }
+
+
+    private static class UsageResourceTest extends UsageResource {
+        public UsageResourceTest() {
+            super(null, null, null, null, null, null, null, null, null, null);
+        }
+    }
 }