killbill-memoizeit

jaxrs, entitlement: Original implementation for new per subscription

6/1/2016 8:00:05 PM

Details

diff --git a/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBase.java b/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBase.java
index 07bec90..6536626 100644
--- a/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBase.java
+++ b/api/src/main/java/org/killbill/billing/subscription/api/SubscriptionBase.java
@@ -100,6 +100,8 @@ public interface SubscriptionBase extends Entity, Blockable {
 
     public ProductCategory getCategory();
 
+    public Integer getBillCycleDayLocal();
+
     public SubscriptionBaseTransition getPendingTransition();
 
     public SubscriptionBaseTransition getPreviousTransition();
diff --git a/api/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransition.java b/api/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransition.java
index 035a349..508b495 100644
--- a/api/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransition.java
+++ b/api/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransition.java
@@ -62,5 +62,9 @@ public interface SubscriptionBaseTransition {
 
     public SubscriptionBaseTransitionType getTransitionType();
 
+    public Integer getPreviousBillingCycleDayLocal();
+
+    public Integer getNextBillingCycleDayLocal();
+
     public DateTime getCreatedDate();
 }
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
index 6a370f4..2c83c68 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
@@ -281,7 +281,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
 
     @Override
     public Integer getBillCycleDayLocal() {
-        return null;
+        return getSubscriptionBase().getBillCycleDayLocal();
     }
 
     @Override
@@ -699,8 +699,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     }
 
     @Override
-    public void updateBCD(final int i, final CallContext callContext) throws EntitlementApiException {
-
+    public void updateBCD(final int newBCD, final CallContext callContext) throws EntitlementApiException {
+        final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
+        try {
+            subscriptionInternalApi.updateBCD(getId(), newBCD, context);
+        } catch (final SubscriptionBaseApiException e) {
+            throw new EntitlementApiException(e);
+        }
     }
 
     private void refresh(final TenantContext context) throws EntitlementApiException {
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/SubscriptionJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/SubscriptionJson.java
index c3eba91..a9208ec 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/SubscriptionJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/SubscriptionJson.java
@@ -71,6 +71,7 @@ public class SubscriptionJson extends JsonBase {
     private final LocalDate chargedThroughDate;
     private final LocalDate billingStartDate;
     private final LocalDate billingEndDate;
+    private final Integer billCycleDayLocal;
     private final List<EventSubscriptionJson> events;
     private final List<PhasePriceOverrideJson> priceOverrides;
 
@@ -294,6 +295,7 @@ public class SubscriptionJson extends JsonBase {
                             @JsonProperty("chargedThroughDate") @Nullable final LocalDate chargedThroughDate,
                             @JsonProperty("billingStartDate") @Nullable final LocalDate billingStartDate,
                             @JsonProperty("billingEndDate") @Nullable final LocalDate billingEndDate,
+                            @JsonProperty("billCycleDayLocal") @Nullable final Integer billCycleDayLocal,
                             @JsonProperty("events") @Nullable final List<EventSubscriptionJson> events,
                             @JsonProperty("priceOverrides") final List<PhasePriceOverrideJson> priceOverrides,
                             @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
@@ -310,6 +312,7 @@ public class SubscriptionJson extends JsonBase {
         this.chargedThroughDate = chargedThroughDate;
         this.billingStartDate = billingStartDate;
         this.billingEndDate = billingEndDate;
+        this.billCycleDayLocal = billCycleDayLocal;
         this.accountId = accountId;
         this.bundleId = bundleId;
         this.subscriptionId = subscriptionId;
@@ -356,6 +359,7 @@ public class SubscriptionJson extends JsonBase {
         this.chargedThroughDate = subscription.getChargedThroughDate();
         this.billingStartDate = subscription.getBillingStartDate();
         this.billingEndDate = subscription.getBillingEndDate();
+        this.billCycleDayLocal = subscription.getBillCycleDayLocal();
         this.accountId = subscription.getAccountId().toString();
         this.bundleId = subscription.getBundleId().toString();
         this.subscriptionId = subscription.getId().toString();
@@ -444,6 +448,10 @@ public class SubscriptionJson extends JsonBase {
         return billingEndDate;
     }
 
+    public Integer getBillCycleDayLocal() {
+        return billCycleDayLocal;
+    }
+
     public List<EventSubscriptionJson> getEvents() {
         return events;
     }
@@ -471,6 +479,7 @@ public class SubscriptionJson extends JsonBase {
         sb.append(", chargedThroughDate=").append(chargedThroughDate);
         sb.append(", billingStartDate=").append(billingStartDate);
         sb.append(", billingEndDate=").append(billingEndDate);
+        sb.append(", billCycleDayLocal=").append(billCycleDayLocal);
         sb.append(", events=").append(events);
         sb.append(", priceOverrides=").append(priceOverrides);
         sb.append('}');
@@ -542,6 +551,9 @@ public class SubscriptionJson extends JsonBase {
         if (priceOverrides != null ? !priceOverrides.equals(that.priceOverrides) : that.priceOverrides != null) {
             return false;
         }
+        if (billCycleDayLocal != null ? !billCycleDayLocal.equals(that.billCycleDayLocal) : that.billCycleDayLocal != null) {
+            return false;
+        }
         return true;
     }
 
@@ -563,6 +575,7 @@ public class SubscriptionJson extends JsonBase {
         result = 31 * result + (chargedThroughDate != null ? chargedThroughDate.hashCode() : 0);
         result = 31 * result + (billingStartDate != null ? billingStartDate.hashCode() : 0);
         result = 31 * result + (billingEndDate != null ? billingEndDate.hashCode() : 0);
+        result = 31 * result + (billCycleDayLocal != null ? billCycleDayLocal.hashCode() : 0);
         result = 31 * result + (events != null ? events.hashCode() : 0);
         result = 31 * result + (priceOverrides != null ? priceOverrides.hashCode() : 0);
         return result;
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
index 5d7140a..d420a75 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
@@ -162,6 +162,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
                                       @QueryParam(QUERY_ENTITLEMENT_REQUESTED_DT) final String entitlementDate,
                                       @QueryParam(QUERY_BILLING_REQUESTED_DT) final String billingDate,
                                       @QueryParam(QUERY_MIGRATED) @DefaultValue("false") final Boolean isMigrated,
+                                      @QueryParam(QUERY_BCD) final Integer newBCD,
                                       @QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion,
                                       @QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("3") final long timeoutSec,
                                       @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@@ -187,7 +188,6 @@ public class SubscriptionResource extends JaxRsResourceBase {
         final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
         final CallContext callContext = context.createContext(createdBy, reason, comment, request);
 
-
         final EntitlementCallCompletionCallback<Entitlement> callback = new EntitlementCallCompletionCallback<Entitlement>() {
             @Override
             public Entitlement doOperation(final CallContext ctx) throws InterruptedException, TimeoutException, EntitlementApiException, SubscriptionApiException, AccountApiException {
@@ -205,9 +205,13 @@ public class SubscriptionResource extends JaxRsResourceBase {
                                                                  BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList());
 
                 final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(entitlement.getPriceOverrides(), planSpec, account.getCurrency());
-                return createAddOnEntitlement ?
-                       entitlementApi.addEntitlement(getBundleIdForAddOnCreation(entitlement), spec, overrides, resolvedEntitlementDate, resolvedBillingDate, isMigrated, pluginProperties, callContext) :
-                       entitlementApi.createBaseEntitlement(account.getId(), spec, entitlement.getExternalKey(), overrides, resolvedEntitlementDate, resolvedBillingDate, isMigrated, pluginProperties, callContext);
+                final Entitlement result = createAddOnEntitlement ?
+                                           entitlementApi.addEntitlement(getBundleIdForAddOnCreation(entitlement), spec, overrides, resolvedEntitlementDate, resolvedBillingDate, isMigrated, pluginProperties, callContext) :
+                                           entitlementApi.createBaseEntitlement(account.getId(), spec, entitlement.getExternalKey(), overrides, resolvedEntitlementDate, resolvedBillingDate, isMigrated, pluginProperties, callContext);
+                if (newBCD != null) {
+                    result.updateBCD(newBCD, callContext);
+                }
+                return result;
             }
 
             private UUID getBundleIdForAddOnCreation(final SubscriptionJson entitlement) throws SubscriptionApiException {
@@ -286,11 +290,11 @@ public class SubscriptionResource extends JaxRsResourceBase {
 
         final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
         final SubscriptionJson baseEntitlement = Iterables.tryFind(entitlements, new Predicate<SubscriptionJson>() {
-                    @Override
-                    public boolean apply(final SubscriptionJson subscription) {
-                        return ProductCategory.BASE.toString().equalsIgnoreCase(subscription.getProductCategory());
-                    }
-            }).orNull();
+            @Override
+            public boolean apply(final SubscriptionJson subscription) {
+                return ProductCategory.BASE.toString().equalsIgnoreCase(subscription.getProductCategory());
+            }
+        }).orNull();
 
         verifyNonNull(baseEntitlement.getAccountId(), "SubscriptionJson accountId needs to be set for BASE product.");
 
@@ -311,8 +315,8 @@ public class SubscriptionResource extends JaxRsResourceBase {
                                                                                          BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), null);
 
                     final PlanSpecifier planSpec = new PlanSpecifier(entitlement.getProductName(),
-                                                                    ProductCategory.valueOf(entitlement.getProductCategory()),
-                                                                    BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList());
+                                                                     ProductCategory.valueOf(entitlement.getProductCategory()),
+                                                                     BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList());
                     final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(entitlement.getPriceOverrides(), planSpec, account.getCurrency());
 
                     EntitlementSpecifier specifier = new EntitlementSpecifier() {
@@ -451,7 +455,6 @@ public class SubscriptionResource extends JaxRsResourceBase {
         return callCompletionCreation.withSynchronization(callback, timeoutSec, callCompletion, callContext);
     }
 
-
     @TimedResource
     @PUT
     @Path("/{subscriptionId:" + UUID_PATTERN + "}/" + BLOCK)
@@ -471,8 +474,6 @@ public class SubscriptionResource extends JaxRsResourceBase {
         return addBlockingState(json, id, BlockingStateType.SUBSCRIPTION, requestedDate, pluginPropertiesString, createdBy, reason, comment, request);
     }
 
-
-
     @TimedResource
     @DELETE
     @Path("/{subscriptionId:" + UUID_PATTERN + "}")
@@ -546,6 +547,32 @@ public class SubscriptionResource extends JaxRsResourceBase {
         return callCompletionCreation.withSynchronization(callback, timeoutSec, callCompletion, callContext);
     }
 
+    @TimedResource
+    @PUT
+    @Produces(APPLICATION_JSON)
+    @Consumes(APPLICATION_JSON)
+    @Path("/{subscriptionId:" + UUID_PATTERN + "}/" + BCD)
+    @ApiOperation(value = "Update the BCD associated to a subscription")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid entitlement supplied")})
+    public Response updateSubscriptionBCD(final SubscriptionJson json,
+                                          @PathParam(ID_PARAM_NAME) final String id,
+                                          @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 UriInfo uriInfo,
+                                          @javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException, EntitlementApiException {
+
+        verifyNonNullOrEmpty(json, "SubscriptionJson body should be specified");
+        verifyNonNullOrEmpty(json.getBillCycleDayLocal(), "SubscriptionJson new BCD should be specified");
+
+        final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+        final UUID subscriptionId = UUID.fromString(id);
+
+        final Entitlement entitlement = entitlementApi.getEntitlementForId(subscriptionId, callContext);
+        entitlement.updateBCD(json.getBillCycleDayLocal(), callContext);
+        return Response.status(Status.OK).build();
+    }
+
     private static final class CompletionUserRequestEntitlement extends CompletionUserRequestBase {
 
         public CompletionUserRequestEntitlement(final UUID userToken) {
diff --git a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleJsonWithSubscriptions.java b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleJsonWithSubscriptions.java
index c27054c..b700827 100644
--- a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleJsonWithSubscriptions.java
+++ b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestBundleJsonWithSubscriptions.java
@@ -73,6 +73,7 @@ public class TestBundleJsonWithSubscriptions extends JaxrsTestSuiteNoDB {
                                                                    new LocalDate(),
                                                                    new LocalDate(),
                                                                    new LocalDate(),
+                                                                   null,
                                                                    ImmutableList.<EventSubscriptionJson>of(event),
                                                                    ImmutableList.of(priceOverride),
                                                                    auditLogs);
diff --git a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestEntitlementJsonWithEvents.java b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestEntitlementJsonWithEvents.java
index 41ed2ba..529fc5a 100644
--- a/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestEntitlementJsonWithEvents.java
+++ b/jaxrs/src/test/java/org/killbill/billing/jaxrs/json/TestEntitlementJsonWithEvents.java
@@ -80,6 +80,7 @@ public class TestEntitlementJsonWithEvents extends JaxrsTestSuiteNoDB {
                                                                                 new LocalDate(),
                                                                                 new LocalDate(),
                                                                                 new LocalDate(),
+                                                                                null,
                                                                                 ImmutableList.<EventSubscriptionJson>of(newEvent),
                                                                                 ImmutableList.of(priceOverride),
                                                                                 null);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
index be975a1..5536e6c 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
@@ -41,6 +41,8 @@ import org.killbill.billing.util.api.AuditLevel;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import com.ning.http.client.Response;
+
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
@@ -297,4 +299,29 @@ public class TestEntitlement extends TestJaxrsBase {
         Assert.assertTrue(objFromJson.equals(entitlementJson));
     }
 
+    @Test(groups = "slow", description = "Verify we can move the BCD associated with the subscription")
+    public void testMoveEntitlementBCD() throws Exception {
+        final DateTime initialDate = new DateTime(2012, 4, 25, 0, 3, 42, 0);
+        clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+
+        final Account accountJson = createAccountWithDefaultPaymentMethod();
+
+        final String productName = "Shotgun";
+        final BillingPeriod term = BillingPeriod.MONTHLY;
+
+        final Subscription entitlementJson = createEntitlement(accountJson.getAccountId(), "99999", productName,
+                                                               ProductCategory.BASE, term, true);
+
+        final Subscription updatedSubscription = new Subscription();
+        updatedSubscription.setSubscriptionId(entitlementJson.getSubscriptionId());
+        updatedSubscription.setBillCycleDayLocal(9);
+        killBillClient.updateSubscriptionBCD(updatedSubscription, DEFAULT_WAIT_COMPLETION_TIMEOUT_SEC, createdBy, reason, comment);
+
+
+        final Subscription result = killBillClient.getSubscription(entitlementJson.getSubscriptionId());
+        // TODO depends on semantics for pending BCD change
+        //Assert.assertEquals(result.getBillCycleDayLocal(), new Integer(9));
+    }
+
+
 }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBase.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBase.java
index 48d01e9..f1ed7c2 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBase.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBase.java
@@ -351,6 +351,21 @@ public class DefaultSubscriptionBase extends EntityBase implements SubscriptionB
         return category;
     }
 
+    @Override
+    public Integer getBillCycleDayLocal() {
+
+        final SubscriptionBaseTransitionDataIterator it = new SubscriptionBaseTransitionDataIterator(
+                clock, transitions, Order.DESC_FROM_FUTURE, Kind.SUBSCRIPTION,
+                Visibility.FROM_DISK_ONLY, TimeLimit.PAST_OR_PRESENT_ONLY);
+        while (it.hasNext()) {
+            final SubscriptionBaseTransition cur = it.next();
+            if (cur.getTransitionType() == SubscriptionBaseTransitionType.BCD_CHANGE) {
+                return cur.getNextBillingCycleDayLocal();
+            }
+        }
+        return null;
+    }
+
     public DateTime getBundleStartDate() {
         return bundleStartDate;
     }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransitionData.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransitionData.java
index 34de332..511b142 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransitionData.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/SubscriptionBaseTransitionData.java
@@ -216,10 +216,12 @@ public class SubscriptionBaseTransitionData implements SubscriptionBaseTransitio
         return nextPriceList;
     }
 
+    @Override
     public Integer getPreviousBillingCycleDayLocal() {
         return previousBillingCycleDayLocal;
     }
 
+    @Override
     public Integer getNextBillingCycleDayLocal() {
         return nextBillingCycleDayLocal;
     }
diff --git a/util/src/test/java/org/killbill/billing/mock/MockSubscription.java b/util/src/test/java/org/killbill/billing/mock/MockSubscription.java
index f852a1b..9f62cab 100644
--- a/util/src/test/java/org/killbill/billing/mock/MockSubscription.java
+++ b/util/src/test/java/org/killbill/billing/mock/MockSubscription.java
@@ -177,6 +177,11 @@ public class MockSubscription implements SubscriptionBase {
     }
 
     @Override
+    public Integer getBillCycleDayLocal() {
+        return null;
+    }
+
+    @Override
     public DateTime getFutureEndDate() {
         return sub.getFutureEndDate();
     }