use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class DefaultSubscriptionInternalApi method createBundleForAccount.
@Override
public SubscriptionBaseBundle createBundleForAccount(final UUID accountId, final String bundleKey, final InternalCallContext context) throws SubscriptionBaseApiException {
final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(bundleKey, context);
//
// Because the creation of the SubscriptionBundle is not atomic (with creation of Subscription/SubscriptionEvent), we verify if we were left
// with an empty SubscriptionBaseBundle form a past failing operation (See #684). We only allow reuse if such SubscriptionBaseBundle is fully
// empty (and don't allow use case where all Subscription are cancelled, which is the condition for that key to be re-used)
// Such condition should have been checked upstream (to decide whether that key is valid or not)
//
final SubscriptionBaseBundle existingBundleForAccount = Iterables.tryFind(existingBundles, new Predicate<SubscriptionBaseBundle>() {
@Override
public boolean apply(final SubscriptionBaseBundle input) {
return input.getAccountId().equals(accountId);
}
}).orNull();
// If Bundle already exists, and there is 0 Subscription, we reuse
if (existingBundleForAccount != null) {
try {
final Map<UUID, List<SubscriptionBase>> accountSubscriptions = dao.getSubscriptionsForAccount(context);
final List<SubscriptionBase> subscriptions = accountSubscriptions.get(existingBundleForAccount.getId());
if (subscriptions == null || subscriptions.size() == 0) {
return existingBundleForAccount;
}
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
final DateTime now = clock.getUTCNow();
final DateTime originalCreatedDate = !existingBundles.isEmpty() ? existingBundles.get(0).getCreatedDate() : now;
final DefaultSubscriptionBaseBundle bundle = new DefaultSubscriptionBaseBundle(bundleKey, accountId, now, originalCreatedDate, now, now);
if (null != bundleKey && bundleKey.length() > 255) {
throw new SubscriptionBaseApiException(ErrorCode.EXTERNAL_KEY_LIMIT_EXCEEDED);
}
return dao.createSubscriptionBundle(bundle, context);
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class TestBlockingCalculator method createRealEvent.
protected BillingEvent createRealEvent(final DateTime effectiveDate, final SubscriptionBase subscription, final SubscriptionBaseTransitionType type) {
try {
final Integer billCycleDay = 1;
final Plan plan = new MockPlan();
final Currency currency = Currency.USD;
final String description = "";
final BillingPeriod billingPeriod = BillingPeriod.MONTHLY;
final Long totalOrdering = 0L;
final DateTimeZone tz = DateTimeZone.UTC;
final PlanPhase planPhase = Mockito.mock(PlanPhase.class);
final InternationalPrice recurringPrice = Mockito.mock(InternationalPrice.class);
Mockito.when(recurringPrice.getPrice(Mockito.<Currency>any())).thenReturn(BigDecimal.TEN);
final Recurring recurring = Mockito.mock(Recurring.class);
Mockito.when(recurring.getRecurringPrice()).thenReturn(recurringPrice);
Mockito.when(planPhase.getRecurring()).thenReturn(recurring);
Mockito.when(planPhase.getUsages()).thenReturn(new DefaultUsage[0]);
final BigDecimal fixedPrice = BigDecimal.TEN;
return new DefaultBillingEvent(subscription, effectiveDate, true, plan, planPhase, fixedPrice, currency, billingPeriod, billCycleDay, description, totalOrdering, type, tz, null, false);
} catch (final CatalogApiException e) {
Assert.fail("", e);
}
throw new IllegalStateException();
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class OverriddenPlanCacheLoader method load.
@Override
public Object load(final Object key, final Object argument) {
checkCacheLoaderStatus();
if (!(key instanceof String)) {
throw new IllegalArgumentException("Unexpected key type of " + key.getClass().getName());
}
if (!(argument instanceof CacheLoaderArgument)) {
throw new IllegalArgumentException("Unexpected argument type of " + argument.getClass().getName());
}
final CacheLoaderArgument cacheLoaderArgument = (CacheLoaderArgument) argument;
if (cacheLoaderArgument.getArgs() == null || cacheLoaderArgument.getArgs().length != 2) {
throw new IllegalArgumentException("Invalid arguments for overridden plans");
}
if (!(cacheLoaderArgument.getArgs()[0] instanceof LoaderCallback)) {
throw new IllegalArgumentException("Invalid arguments for overridden plans: missing loaderCallback from argument");
}
if (!(cacheLoaderArgument.getArgs()[1] instanceof StaticCatalog)) {
throw new IllegalArgumentException("Invalid arguments for overridden plans: missing catalog from argument");
}
final String planName = (String) key;
final LoaderCallback callback = (LoaderCallback) cacheLoaderArgument.getArgs()[0];
final StaticCatalog catalog = (StaticCatalog) cacheLoaderArgument.getArgs()[1];
final InternalTenantContext internalTenantContext = ((CacheLoaderArgument) argument).getInternalTenantContext();
try {
log.info("Loading overridden plan {} for tenant {}", planName, internalTenantContext.getTenantRecordId());
return callback.loadPlan(planName, catalog, internalTenantContext);
} catch (final CatalogApiException e) {
throw new IllegalStateException(String.format("Failed to load overridden plan for tenant %s : %s", planName, internalTenantContext.getTenantRecordId()), e);
}
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class DefaultEntitlement method changePlanWithDate.
@Override
public Entitlement changePlanWithDate(final PlanSpecifier spec, final List<PlanPhasePriceOverride> overrides, @Nullable final LocalDate effectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logChangePlan(log, this, spec, overrides, effectiveDate, null);
checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getExternalKey(), null, effectiveDate, effectiveDate, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CHANGE_PLAN, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, null, properties, callContext);
final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
if (!eventsStream.isEntitlementActive()) {
throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
}
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
final DateTime effectiveChangeDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers().iterator().next().getBillingEffectiveDate(), context);
final DateTime resultingEffectiveDate;
try {
resultingEffectiveDate = subscriptionInternalApi.getDryRunChangePlanEffectiveDate(getSubscriptionBase(), spec, effectiveChangeDate, null, overrides, context);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
} catch (final CatalogApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
}
try {
checker.checkBlockedChange(getSubscriptionBase(), resultingEffectiveDate, context);
} catch (final BlockingApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
}
try {
getSubscriptionBase().changePlanWithDate(spec, overrides, resultingEffectiveDate, callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
final Collection<NotificationEvent> notificationEvents = new ArrayList<NotificationEvent>();
final Iterable<BlockingState> addOnsBlockingStates = computeAddOnBlockingStates(resultingEffectiveDate, notificationEvents, callContext, context);
// Record the new state first, then insert the notifications to avoid race conditions
setBlockingStates(addOnsBlockingStates, context);
for (final NotificationEvent notificationEvent : notificationEvents) {
recordFutureNotification(resultingEffectiveDate, notificationEvent, context);
}
return entitlementApi.getEntitlementForId(getId(), callContext);
}
};
return pluginExecution.executeWithPlugin(changePlanWithPlugin, pluginContext);
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class DefaultEntitlement method changePlanOverrideBillingPolicy.
@Override
public Entitlement changePlanOverrideBillingPolicy(final PlanSpecifier spec, final List<PlanPhasePriceOverride> overrides, final LocalDate entitlementEffectiveDate, final BillingActionPolicy actionPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logChangePlan(log, this, spec, overrides, entitlementEffectiveDate, actionPolicy);
checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getExternalKey(), null, entitlementEffectiveDate, null, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CHANGE_PLAN, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, actionPolicy, properties, callContext);
final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
if (!eventsStream.isEntitlementActive()) {
throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
}
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
final DateTime effectiveChangeDate;
try {
effectiveChangeDate = subscriptionInternalApi.getDryRunChangePlanEffectiveDate(getSubscriptionBase(), spec, null, actionPolicy, overrides, context);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
} catch (final CatalogApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
}
try {
checker.checkBlockedChange(getSubscriptionBase(), effectiveChangeDate, context);
} catch (final BlockingApiException e) {
throw new EntitlementApiException(e, e.getCode(), e.getMessage());
}
try {
getSubscriptionBase().changePlanWithPolicy(spec, overrides, actionPolicy, callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
final Collection<NotificationEvent> notificationEvents = new ArrayList<NotificationEvent>();
final Iterable<BlockingState> addOnsBlockingStates = computeAddOnBlockingStates(effectiveChangeDate, notificationEvents, callContext, context);
// Record the new state first, then insert the notifications to avoid race conditions
setBlockingStates(addOnsBlockingStates, context);
for (final NotificationEvent notificationEvent : notificationEvents) {
recordFutureNotification(effectiveChangeDate, notificationEvent, context);
}
return entitlementApi.getEntitlementForId(getId(), callContext);
}
};
return pluginExecution.executeWithPlugin(changePlanWithPlugin, pluginContext);
}
Aggregations