Details
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
index 245440f..7a82864 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
+import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.xml.bind.JAXBException;
import javax.xml.transform.TransformerException;
@@ -167,14 +168,14 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
@Override
- public void createDefaultEmptyCatalog(final DateTime effectiveDate, final CallContext callContext) throws CatalogApiException {
+ public void createDefaultEmptyCatalog(@Nullable final DateTime effectiveDate, final CallContext callContext) throws CatalogApiException {
try {
final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(callContext);
final StandaloneCatalog currentCatalog = getCurrentStandaloneCatalogForTenant(internalTenantContext);
final CatalogUpdater catalogUpdater = (currentCatalog != null) ?
- new CatalogUpdater(currentCatalog) :
- new CatalogUpdater(BillingMode.IN_ADVANCE, effectiveDate, null);
+ new CatalogUpdater(currentCatalog) :
+ new CatalogUpdater(BillingMode.IN_ADVANCE, getSafeFirstCatalogEffectiveDate(effectiveDate), null);
catalogCache.clearCatalog(internalTenantContext);
tenantApi.updateTenantKeyValue(TenantKey.CATALOG.toString(), catalogUpdater.getCatalogXML(), callContext);
@@ -184,15 +185,14 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
}
@Override
- public void addSimplePlan(final SimplePlanDescriptor descriptor, final DateTime effectiveDate, final CallContext callContext) throws CatalogApiException {
+ public void addSimplePlan(final SimplePlanDescriptor descriptor, @Nullable final DateTime effectiveDate, final CallContext callContext) throws CatalogApiException {
try {
final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(callContext);
final StandaloneCatalog currentCatalog = getCurrentStandaloneCatalogForTenant(internalTenantContext);
final CatalogUpdater catalogUpdater = (currentCatalog != null) ?
- new CatalogUpdater(currentCatalog) :
- new CatalogUpdater(BillingMode.IN_ADVANCE, effectiveDate, descriptor.getCurrency());
-
+ new CatalogUpdater(currentCatalog) :
+ new CatalogUpdater(BillingMode.IN_ADVANCE, getSafeFirstCatalogEffectiveDate(effectiveDate), descriptor.getCurrency());
catalogUpdater.addSimplePlanDescriptor(descriptor);
catalogCache.clearCatalog(internalTenantContext);
@@ -214,6 +214,12 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
throw new CatalogApiException(e);
}
}
+ private DateTime getSafeFirstCatalogEffectiveDate(@Nullable final DateTime input) {
+ // The effectiveDate for the initial version does not matter too much
+ // Because of #760, we want to make that client passing a approximate date (e.g today.toDateTimeAtStartOfDay()) will find the version
+ final DateTime catalogEffectiveDate = clock.getUTCNow().minusDays(1);
+ return (input == null || input.isAfter(catalogEffectiveDate)) ? catalogEffectiveDate : input;
+ }
private StandaloneCatalog getCurrentStandaloneCatalogForTenant(final InternalTenantContext internalTenantContext) throws CatalogApiException {
final VersionedCatalog versionedCatalog = (VersionedCatalog) catalogService.getCurrentCatalog(false, false, internalTenantContext);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
index c193b16..4586e4a 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
@@ -181,8 +181,11 @@ public class VersionedCatalog extends ValidatingConfig<VersionedCatalog> impleme
}
}
+
+ final boolean initialVersion = (i == 0);
final DateTime catalogEffectiveDate = CatalogDateHelper.toUTCDateTime(c.getEffectiveDate());
- if (!subscriptionStartDate.isBefore(catalogEffectiveDate)) { // Its a new subscription this plan always applies
+ if (initialVersion || // Prevent issue with time granularity -- see #760
+ !subscriptionStartDate.isBefore(catalogEffectiveDate)) { // It's a new subscription this plan always applies
return new CatalogPlanEntry(c, plan);
} else { //Its an existing subscription
if (plan.getEffectiveDateForExistingSubscriptions() != null) { //if it is null any change to this does not apply to existing subscriptions
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
index 3dcb60f..b70e54f 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
@@ -48,15 +48,9 @@ public class TestVersionedCatalog extends CatalogTestSuiteNoDB {
final DateTime dt214 = new DateTime("2011-02-14T00:01:00+00:00");
final DateTime dt3 = new DateTime("2011-03-03T00:01:00+00:00");
- // New subscription
- try {
- vc.findPlan("pistol-monthly", dt0, dt0);
- Assert.fail("Exception should have been thrown there are no plans for this date");
- } catch (CatalogApiException e) {
- // Expected behaviour
- log.error("Expected exception", e);
+ // We find it although the date provided is too early because we default to first catalog version
+ final Plan newSubPlan0 = vc.findPlan("pistol-monthly", dt0, dt0);
- }
final Plan newSubPlan1 = vc.findPlan("pistol-monthly", dt1, dt1);
final Plan newSubPlan2 = vc.findPlan("pistol-monthly", dt2, dt2);
final Plan newSubPlan214 = vc.findPlan("pistol-monthly", dt214, dt214);
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/CatalogResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/CatalogResource.java
index fea4aa9..4eea0e9 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/CatalogResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/CatalogResource.java
@@ -221,7 +221,7 @@ public class CatalogResource extends JaxRsResourceBase {
simplePlan.getTrialLength(),
simplePlan.getTrialTimeUnit(),
simplePlan.getAvailableBaseProducts());
- catalogUserApi.addSimplePlan(desc, clock.getUTCNow(), callContext);
+ catalogUserApi.addSimplePlan(desc, null, callContext);
return uriBuilder.buildResponse(uriInfo, CatalogResource.class, null, null, request);
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java
index b0cc317..664fcea 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java
@@ -37,6 +37,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
+import org.joda.time.DateTime;
import org.killbill.billing.ObjectType;
import org.killbill.billing.account.api.AccountUserApi;
import org.killbill.billing.callcontext.DefaultCallContext;
@@ -140,11 +141,13 @@ public class TenantResource extends JaxRsResourceBase {
if (!useGlobalDefault) {
final CallContext callContext = new DefaultCallContext(null, tenant.getId(), createdBy, CallOrigin.EXTERNAL,
UserType.CUSTOMER, Context.getOrCreateUserToken(), clock);
- catalogUserApi.createDefaultEmptyCatalog(clock.getUTCNow(),callContext);
+
+ catalogUserApi.createDefaultEmptyCatalog(null, callContext);
}
return uriBuilder.buildResponse(uriInfo, TenantResource.class, "getTenant", tenant.getId(), request);
}
+
@TimedResource
@POST
@Path("/" + REGISTER_NOTIFICATION_CALLBACK)
@@ -420,4 +423,5 @@ public class TenantResource extends JaxRsResourceBase {
protected ObjectType getObjectType() {
return ObjectType.TENANT;
}
+
}