use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class InvoiceItemFactory method computePrettyName.
//
// Returns an array of string for 'pretty' names [prettyPlanName, prettyPlanPhaseName, prettyUsageName]
//
private static String[] computePrettyName(final InvoiceItemType type, final DateTime transitionDate, @Nullable final String productName, @Nullable final String planName, @Nullable final String phaseName, @Nullable final String usageName, @Nullable final VersionedCatalog catalog) {
final String[] result = new String[4];
final boolean computePrettyName = catalog != null && (type == InvoiceItemType.FIXED || type == InvoiceItemType.RECURRING || type == InvoiceItemType.TAX || type == InvoiceItemType.USAGE);
String prettyProductName = null;
String prettyPlanName = null;
String prettyPlanPhaseName = null;
String prettyUsageName = null;
// Trying to optimize safe default behavior by checking both input and each intermediary null result at each step -- and doing poor on the Cyclomatic complexity
try {
if (computePrettyName) {
if (planName != null) {
// We are simply looking for the most recent version of a catalog version having such plan
// Finding the right entry would require some expensive operations which are probably not worth it for this use case.
Plan plan = null;
final List<StaticCatalog> versions = catalog.getVersions();
for (int i = versions.size() - 1; i >= 0; i--) {
final StaticCatalog curVersion = versions.get(i);
try {
plan = curVersion.findPlan(planName);
} catch (final CatalogApiException e) {
if (e.getCode() != ErrorCode.CAT_NO_SUCH_PLAN.getCode()) {
throw e;
}
}
if (plan != null) {
break;
}
}
if (plan != null) {
prettyPlanName = plan.getPrettyName();
if (productName != null) {
Preconditions.checkState(plan.getProduct().getName().equals(productName));
prettyProductName = plan.getProduct().getPrettyName();
}
if (phaseName != null) {
final PlanPhase planPhase = plan.findPhase(phaseName);
if (planPhase != null) {
prettyPlanPhaseName = planPhase.getPrettyName();
if (usageName != null) {
Usage usage = null;
for (Usage cur : planPhase.getUsages()) {
if (cur.getName().equals(usageName)) {
usage = cur;
break;
}
}
if (usage != null) {
prettyUsageName = usage.getPrettyName();
}
}
}
}
}
}
}
} catch (final CatalogApiException e) {
log.warn("Failed to compute invoice pretty names:", e.getMessage());
} finally {
result[0] = prettyProductName;
result[1] = prettyPlanName;
result[2] = prettyPlanPhaseName;
result[3] = prettyUsageName;
}
return result;
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class BundleResource method searchBundles.
@TimedResource
@GET
@Path("/" + SEARCH + "/{searchKey:" + ANYTHING_PATTERN + "}")
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Search bundles", response = BundleJson.class, responseContainer = "List")
@ApiResponses(value = {})
public Response searchBundles(@PathParam("searchKey") final String searchKey, @QueryParam(QUERY_SEARCH_OFFSET) @DefaultValue("0") final Long offset, @QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit, @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode, @javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
final TenantContext tenantContext = context.createTenantContextNoAccountId(request);
final Pagination<SubscriptionBundle> bundles = subscriptionApi.searchSubscriptionBundles(searchKey, offset, limit, tenantContext);
final URI nextPageUri = uriBuilder.nextPage(BundleResource.class, "searchBundles", bundles.getNextOffset(), limit, ImmutableMap.<String, String>of(QUERY_AUDIT, auditMode.getLevel().toString()), ImmutableMap.<String, String>of("searchKey", searchKey));
final AtomicReference<Map<UUID, AccountAuditLogs>> accountsAuditLogs = new AtomicReference<Map<UUID, AccountAuditLogs>>(new HashMap<UUID, AccountAuditLogs>());
return buildStreamingPaginationResponse(bundles, new Function<SubscriptionBundle, BundleJson>() {
@Override
public BundleJson apply(final SubscriptionBundle bundle) {
// Cache audit logs per account
if (accountsAuditLogs.get().get(bundle.getAccountId()) == null) {
accountsAuditLogs.get().put(bundle.getAccountId(), auditUserApi.getAccountAuditLogs(bundle.getAccountId(), auditMode.getLevel(), tenantContext));
}
try {
return new BundleJson(bundle, null, accountsAuditLogs.get().get(bundle.getAccountId()));
} catch (final CatalogApiException unused) {
// Does not happen because we pass a null Currency
throw new RuntimeException(unused);
}
}
}, nextPageUri);
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class DefaultSubscriptionBaseTransferApi method toEvents.
@VisibleForTesting
List<SubscriptionBaseEvent> toEvents(final List<ExistingEvent> existingEvents, final DefaultSubscriptionBase subscription, final DateTime transferDate, final InternalTenantContext context) throws SubscriptionBaseTransferApiException {
try {
final List<SubscriptionBaseEvent> result = new LinkedList<SubscriptionBaseEvent>();
SubscriptionBaseEvent event = null;
ExistingEvent prevEvent = null;
boolean firstEvent = true;
for (ExistingEvent cur : existingEvents) {
// Skip all events prior to the transferDate
if (cur.getEffectiveDate().isBefore(transferDate)) {
prevEvent = cur;
continue;
}
// Add previous event the first time if needed
if (prevEvent != null) {
event = createEvent(firstEvent, prevEvent, subscription, transferDate, context);
if (event != null) {
result.add(event);
firstEvent = false;
}
prevEvent = null;
}
event = createEvent(firstEvent, cur, subscription, transferDate, context);
if (event != null) {
result.add(event);
firstEvent = false;
}
}
// Previous loop did not get anything because transferDate is greater than effectiveDate of last event
if (prevEvent != null) {
event = createEvent(firstEvent, prevEvent, subscription, transferDate, context);
if (event != null) {
result.add(event);
}
prevEvent = null;
}
return result;
} catch (CatalogApiException e) {
throw new SubscriptionBaseTransferApiException(e);
}
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method doCancelPlan.
private boolean doCancelPlan(final Map<DefaultSubscriptionBase, DateTime> subscriptions, final SubscriptionCatalog catalog, final InternalCallContext internalCallContext) throws SubscriptionBaseApiException {
final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = new LinkedList<DefaultSubscriptionBase>();
final List<SubscriptionBaseEvent> cancelEvents = new LinkedList<SubscriptionBaseEvent>();
try {
for (final DefaultSubscriptionBase subscription : subscriptions.keySet()) {
final EntitlementState currentState = subscription.getState();
if (currentState == EntitlementState.CANCELLED) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CANCEL_BAD_STATE, subscription.getId(), currentState);
}
final DateTime effectiveDate = subscriptions.get(subscription);
// If subscription was future cancelled at an earlier date we disallow the operation -- i.e,
// user should first uncancel prior trying to cancel again.
// However, note that in case a future cancellation already exists with a greater or equal effectiveDate,
// the operation is allowed, but such existing cancellation would become invalidated (is_active=0)
final SubscriptionBaseTransition pendingTransition = subscription.getPendingTransition();
if (pendingTransition != null && pendingTransition.getTransitionType() == SubscriptionBaseTransitionType.CANCEL && pendingTransition.getEffectiveTransitionTime().compareTo(effectiveDate) < 0) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CANCEL_BAD_STATE, subscription.getId(), "PENDING CANCELLED");
}
validateEffectiveDate(subscription, effectiveDate);
subscriptionsToBeCancelled.add(subscription);
cancelEvents.addAll(getEventsOnCancelPlan(subscription, effectiveDate, false, catalog, internalCallContext));
if (subscription.getCategory() == ProductCategory.BASE) {
subscriptionsToBeCancelled.addAll(computeAddOnsToCancel(cancelEvents, null, subscription.getBundleId(), effectiveDate, catalog, internalCallContext));
}
}
dao.cancelSubscriptions(subscriptionsToBeCancelled, cancelEvents, catalog, internalCallContext);
boolean allSubscriptionsCancelled = true;
for (final DefaultSubscriptionBase subscription : subscriptions.keySet()) {
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), catalog);
allSubscriptionsCancelled = allSubscriptionsCancelled && (subscription.getState() == EntitlementState.CANCELLED);
}
return allSubscriptionsCancelled;
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
use of org.killbill.billing.catalog.api.CatalogApiException in project killbill by killbill.
the class DefaultSubscriptionBaseApiService method cancelWithPolicyNoValidationAndCatalog.
@Override
public boolean cancelWithPolicyNoValidationAndCatalog(final Iterable<DefaultSubscriptionBase> subscriptions, final BillingActionPolicy policy, final SubscriptionCatalog catalog, final InternalCallContext context) throws SubscriptionBaseApiException {
final Map<DefaultSubscriptionBase, DateTime> subscriptionsWithEffectiveDate = new HashMap<DefaultSubscriptionBase, DateTime>();
try {
for (final DefaultSubscriptionBase subscription : subscriptions) {
final BillingAlignment billingAlignment = (subscription.getState() == EntitlementState.PENDING ? null : catalog.billingAlignment(new PlanPhaseSpecifier(subscription.getLastActivePlan().getName(), subscription.getLastActivePhase().getPhaseType()), clock.getUTCNow(), subscription.getLastTransitionForCurrentPlan().getEffectiveTransitionTime()));
final Integer accountBillCycleDayLocal = accountInternalApi.getBCD(context);
final DateTime effectiveDate = subscription.getEffectiveDateForPolicy(policy, billingAlignment, accountBillCycleDayLocal, context);
subscriptionsWithEffectiveDate.put(subscription, effectiveDate);
}
return doCancelPlan(subscriptionsWithEffectiveDate, catalog, context);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
} catch (final AccountApiException e) {
throw new SubscriptionBaseApiException(e);
}
}
Aggregations