use of org.killbill.billing.events.EffectiveSubscriptionInternalEvent in project killbill by killbill.
the class DefaultInternalBillingApi method addBillingEventsForSubscription.
private void addBillingEventsForSubscription(final ImmutableAccountData account, final List<SubscriptionBase> subscriptions, final SubscriptionBase baseSubscription, final boolean dryRunMode, final InternalCallContext context, final DefaultBillingEventSet result, final Set<UUID> skipSubscriptionsSet) throws AccountApiException, CatalogApiException, SubscriptionBaseApiException {
// If dryRun is specified, we don't want to to update the account BCD value, so we initialize the flag updatedAccountBCD to true
boolean updatedAccountBCD = dryRunMode;
final Map<UUID, Integer> bcdCache = new HashMap<UUID, Integer>();
int currentAccountBCD = accountApi.getBCD(account.getId(), context);
for (final SubscriptionBase subscription : subscriptions) {
// The subscription did not even start, so there is nothing to do yet, we can skip and avoid some NPE down the line when calculating the BCD
if (subscription.getState() == EntitlementState.PENDING) {
log.info("Skipping subscription id='{}', state = EntitlementState.PENDING", subscription.getId());
continue;
}
final List<EffectiveSubscriptionInternalEvent> billingTransitions = subscriptionApi.getBillingTransitions(subscription, context);
if (billingTransitions.isEmpty() || (billingTransitions.get(0).getTransitionType() != SubscriptionBaseTransitionType.CREATE && billingTransitions.get(0).getTransitionType() != SubscriptionBaseTransitionType.TRANSFER)) {
log.warn("Skipping billing events for subscription " + subscription.getId() + ": Does not start with a valid CREATE transition");
skipSubscriptionsSet.add(subscription.getId());
return;
}
final Catalog catalog = catalogService.getFullCatalog(true, true, context);
Integer overridenBCD = null;
for (final EffectiveSubscriptionInternalEvent transition : billingTransitions) {
//
// A BCD_CHANGE transition defines a new billCycleDayLocal for the subscription and this overrides whatever computation
// occurs below (which is based on billing alignment policy). Also multiple of those BCD_CHANGE transitions could occur,
// to define different intervals with different billing cycle days.
//
overridenBCD = transition.getNextBillCycleDayLocal() != null ? transition.getNextBillCycleDayLocal() : overridenBCD;
final int bcdLocal = overridenBCD != null ? overridenBCD : calculateBcdForTransition(catalog, bcdCache, baseSubscription, subscription, account, currentAccountBCD, transition);
if (currentAccountBCD == 0 && !updatedAccountBCD) {
log.info("Setting account BCD='{}', accountId='{}'", bcdLocal, account.getId());
accountApi.updateBCD(account.getExternalKey(), bcdLocal, context);
updatedAccountBCD = true;
}
final BillingEvent event = new DefaultBillingEvent(account, transition, subscription, bcdLocal, account.getCurrency(), catalog);
result.add(event);
}
}
}
use of org.killbill.billing.events.EffectiveSubscriptionInternalEvent in project killbill by killbill.
the class BeatrixListener method computeExtBusEventEntryFromBusInternalEvent.
private BusEvent computeExtBusEventEntryFromBusInternalEvent(final BusInternalEvent event, final InternalCallContext context) throws JsonProcessingException {
ObjectType objectType = null;
UUID objectId = null;
ExtBusEventType eventBusType = null;
String metaData = null;
UUID accountId = null;
switch(event.getBusEventType()) {
case ACCOUNT_CREATE:
final AccountCreationInternalEvent realEventACR = (AccountCreationInternalEvent) event;
objectType = ObjectType.ACCOUNT;
objectId = realEventACR.getId();
eventBusType = ExtBusEventType.ACCOUNT_CREATION;
break;
case ACCOUNT_CHANGE:
final AccountChangeInternalEvent realEventACH = (AccountChangeInternalEvent) event;
objectType = ObjectType.ACCOUNT;
objectId = realEventACH.getAccountId();
eventBusType = ExtBusEventType.ACCOUNT_CHANGE;
break;
case SUBSCRIPTION_TRANSITION:
final SubscriptionInternalEvent realEventST = (SubscriptionInternalEvent) event;
objectType = ObjectType.SUBSCRIPTION;
objectId = realEventST.getSubscriptionId();
if (realEventST.getTransitionType() == SubscriptionBaseTransitionType.CREATE || realEventST.getTransitionType() == SubscriptionBaseTransitionType.TRANSFER) {
eventBusType = ExtBusEventType.SUBSCRIPTION_CREATION;
} else if (realEventST.getTransitionType() == SubscriptionBaseTransitionType.CANCEL) {
eventBusType = ExtBusEventType.SUBSCRIPTION_CANCEL;
} else if (realEventST.getTransitionType() == SubscriptionBaseTransitionType.PHASE) {
eventBusType = ExtBusEventType.SUBSCRIPTION_PHASE;
} else if (realEventST.getTransitionType() == SubscriptionBaseTransitionType.CHANGE) {
eventBusType = ExtBusEventType.SUBSCRIPTION_CHANGE;
} else if (realEventST.getTransitionType() == SubscriptionBaseTransitionType.UNDO_CHANGE) {
// We map UNDO_CHANGE as a SUBSCRIPTION_CHANGE as we don't have such ext event
eventBusType = ExtBusEventType.SUBSCRIPTION_CHANGE;
} else if (realEventST.getTransitionType() == SubscriptionBaseTransitionType.UNCANCEL) {
eventBusType = ExtBusEventType.SUBSCRIPTION_UNCANCEL;
} else if (realEventST.getTransitionType() == SubscriptionBaseTransitionType.BCD_CHANGE) {
eventBusType = ExtBusEventType.SUBSCRIPTION_BCD_CHANGE;
}
SubscriptionMetadata.ActionType actionType = (event instanceof EffectiveSubscriptionInternalEvent) ? ActionType.EFFECTIVE : ActionType.REQUESTED;
final SubscriptionMetadata subscriptionMetadataObj = new SubscriptionMetadata(actionType, realEventST.getBundleExternalKey());
metaData = objectMapper.writeValueAsString(subscriptionMetadataObj);
break;
case BLOCKING_STATE:
final BlockingTransitionInternalEvent realEventBS = (BlockingTransitionInternalEvent) event;
if (realEventBS.getBlockingType() == BlockingStateType.ACCOUNT) {
objectType = ObjectType.ACCOUNT;
} else if (realEventBS.getBlockingType() == BlockingStateType.SUBSCRIPTION_BUNDLE) {
objectType = ObjectType.BUNDLE;
} else if (realEventBS.getBlockingType() == BlockingStateType.SUBSCRIPTION) {
objectType = ObjectType.SUBSCRIPTION;
}
objectId = realEventBS.getBlockableId();
if (KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName().equals(realEventBS.getService())) {
if (DefaultEntitlementApi.ENT_STATE_START.equals(realEventBS.getStateName())) {
eventBusType = ExtBusEventType.ENTITLEMENT_CREATION;
} else if (DefaultEntitlementApi.ENT_STATE_BLOCKED.equals(realEventBS.getStateName())) {
eventBusType = ExtBusEventType.BUNDLE_PAUSE;
} else if (DefaultEntitlementApi.ENT_STATE_CLEAR.equals(realEventBS.getStateName())) {
eventBusType = ExtBusEventType.BUNDLE_RESUME;
} else if (DefaultEntitlementApi.ENT_STATE_CANCELLED.equals(realEventBS.getStateName())) {
eventBusType = ExtBusEventType.ENTITLEMENT_CANCEL;
}
} else {
eventBusType = ExtBusEventType.BLOCKING_STATE;
final BlockingStateMetadata blockingStateMetadata = new BlockingStateMetadata(realEventBS.getBlockableId(), realEventBS.getService(), realEventBS.getStateName(), realEventBS.getBlockingType(), realEventBS.getEffectiveDate(), realEventBS.isTransitionedToBlockedBilling(), realEventBS.isTransitionedToUnblockedBilling(), realEventBS.isTransitionedToBlockedEntitlement(), realEventBS.isTransitionedToUnblockedEntitlement());
metaData = objectMapper.writeValueAsString(blockingStateMetadata);
}
break;
case INVOICE_CREATION:
final InvoiceCreationInternalEvent realEventInv = (InvoiceCreationInternalEvent) event;
objectType = ObjectType.INVOICE;
objectId = realEventInv.getInvoiceId();
eventBusType = ExtBusEventType.INVOICE_CREATION;
break;
case INVOICE_NOTIFICATION:
final InvoiceNotificationInternalEvent realEventInvNotification = (InvoiceNotificationInternalEvent) event;
objectType = ObjectType.INVOICE;
objectId = null;
// has to be set here because objectId is null with a dryRun Invoice
accountId = realEventInvNotification.getAccountId();
eventBusType = ExtBusEventType.INVOICE_NOTIFICATION;
final InvoiceNotificationMetadata invoiceNotificationMetadata = new InvoiceNotificationMetadata(realEventInvNotification.getTargetDate(), realEventInvNotification.getAmountOwed(), realEventInvNotification.getCurrency());
metaData = objectMapper.writeValueAsString(invoiceNotificationMetadata);
break;
case INVOICE_ADJUSTMENT:
final InvoiceAdjustmentInternalEvent realEventInvAdj = (InvoiceAdjustmentInternalEvent) event;
objectType = ObjectType.INVOICE;
objectId = realEventInvAdj.getInvoiceId();
eventBusType = ExtBusEventType.INVOICE_ADJUSTMENT;
break;
case INVOICE_PAYMENT_INFO:
final InvoicePaymentInfoInternalEvent realEventInvPay = (InvoicePaymentInfoInternalEvent) event;
objectType = ObjectType.INVOICE;
objectId = realEventInvPay.getInvoiceId();
eventBusType = ExtBusEventType.INVOICE_PAYMENT_SUCCESS;
final InvoicePaymentMetadata invoicePaymentInfoMetaDataObj = new InvoicePaymentMetadata(realEventInvPay.getPaymentId(), realEventInvPay.getPaymentAttemptId(), realEventInvPay.getType(), realEventInvPay.getPaymentDate(), realEventInvPay.getAmount(), realEventInvPay.getCurrency(), realEventInvPay.getLinkedInvoicePaymentId(), realEventInvPay.getPaymentCookieId(), realEventInvPay.getProcessedCurrency());
metaData = objectMapper.writeValueAsString(invoicePaymentInfoMetaDataObj);
break;
case INVOICE_PAYMENT_ERROR:
final InvoicePaymentErrorInternalEvent realEventInvPayErr = (InvoicePaymentErrorInternalEvent) event;
objectType = ObjectType.INVOICE;
objectId = realEventInvPayErr.getInvoiceId();
eventBusType = ExtBusEventType.INVOICE_PAYMENT_FAILED;
final InvoicePaymentMetadata invoicePaymentErrorMetaDataObj = new InvoicePaymentMetadata(realEventInvPayErr.getPaymentId(), realEventInvPayErr.getPaymentAttemptId(), realEventInvPayErr.getType(), realEventInvPayErr.getPaymentDate(), realEventInvPayErr.getAmount(), realEventInvPayErr.getCurrency(), realEventInvPayErr.getLinkedInvoicePaymentId(), realEventInvPayErr.getPaymentCookieId(), realEventInvPayErr.getProcessedCurrency());
metaData = objectMapper.writeValueAsString(invoicePaymentErrorMetaDataObj);
break;
case PAYMENT_INFO:
final PaymentInfoInternalEvent realEventPay = (PaymentInfoInternalEvent) event;
objectType = ObjectType.PAYMENT;
objectId = realEventPay.getPaymentId();
eventBusType = ExtBusEventType.PAYMENT_SUCCESS;
final PaymentMetadata paymentInfoMetaDataObj = new PaymentMetadata(realEventPay.getPaymentTransactionId(), realEventPay.getAmount(), realEventPay.getCurrency(), realEventPay.getStatus(), realEventPay.getTransactionType(), realEventPay.getEffectiveDate());
metaData = objectMapper.writeValueAsString(paymentInfoMetaDataObj);
break;
case PAYMENT_ERROR:
final PaymentErrorInternalEvent realEventPayErr = (PaymentErrorInternalEvent) event;
objectType = ObjectType.PAYMENT;
objectId = realEventPayErr.getPaymentId();
eventBusType = ExtBusEventType.PAYMENT_FAILED;
accountId = realEventPayErr.getAccountId();
final PaymentMetadata paymentErrorMetaDataObj = new PaymentMetadata(realEventPayErr.getPaymentTransactionId(), realEventPayErr.getAmount(), realEventPayErr.getCurrency(), realEventPayErr.getStatus(), realEventPayErr.getTransactionType(), realEventPayErr.getEffectiveDate());
metaData = objectMapper.writeValueAsString(paymentErrorMetaDataObj);
break;
case PAYMENT_PLUGIN_ERROR:
final PaymentPluginErrorInternalEvent realEventPayPluginErr = (PaymentPluginErrorInternalEvent) event;
objectType = ObjectType.PAYMENT;
objectId = realEventPayPluginErr.getPaymentId();
eventBusType = ExtBusEventType.PAYMENT_FAILED;
final PaymentMetadata pluginErrorMetaDataObj = new PaymentMetadata(realEventPayPluginErr.getPaymentTransactionId(), realEventPayPluginErr.getAmount(), realEventPayPluginErr.getCurrency(), realEventPayPluginErr.getStatus(), realEventPayPluginErr.getTransactionType(), realEventPayPluginErr.getEffectiveDate());
metaData = objectMapper.writeValueAsString(pluginErrorMetaDataObj);
break;
case OVERDUE_CHANGE:
final OverdueChangeInternalEvent realEventOC = (OverdueChangeInternalEvent) event;
objectType = ObjectType.ACCOUNT;
objectId = realEventOC.getOverdueObjectId();
eventBusType = ExtBusEventType.OVERDUE_CHANGE;
break;
case USER_TAG_CREATION:
final UserTagCreationInternalEvent realUserTagEventCr = (UserTagCreationInternalEvent) event;
objectType = ObjectType.TAG;
objectId = realUserTagEventCr.getTagId();
eventBusType = ExtBusEventType.TAG_CREATION;
metaData = realUserTagEventCr.getTagDefinition().getName();
break;
case CONTROL_TAG_CREATION:
final ControlTagCreationInternalEvent realTagEventCr = (ControlTagCreationInternalEvent) event;
objectType = ObjectType.TAG;
objectId = realTagEventCr.getTagId();
eventBusType = ExtBusEventType.TAG_CREATION;
metaData = realTagEventCr.getTagDefinition().getName();
break;
case USER_TAG_DELETION:
final UserTagDeletionInternalEvent realUserTagEventDel = (UserTagDeletionInternalEvent) event;
objectType = ObjectType.TAG;
objectId = realUserTagEventDel.getTagId();
eventBusType = ExtBusEventType.TAG_DELETION;
metaData = realUserTagEventDel.getTagDefinition().getName();
break;
case CONTROL_TAG_DELETION:
final ControlTagDeletionInternalEvent realTagEventDel = (ControlTagDeletionInternalEvent) event;
objectType = ObjectType.TAG;
objectId = realTagEventDel.getTagId();
eventBusType = ExtBusEventType.TAG_DELETION;
metaData = realTagEventDel.getTagDefinition().getName();
break;
case CUSTOM_FIELD_CREATION:
final CustomFieldCreationEvent realCustomFieldEventCr = (CustomFieldCreationEvent) event;
objectType = ObjectType.CUSTOM_FIELD;
objectId = realCustomFieldEventCr.getCustomFieldId();
eventBusType = ExtBusEventType.CUSTOM_FIELD_CREATION;
break;
case CUSTOM_FIELD_DELETION:
final CustomFieldDeletionEvent realCustomFieldEventDel = (CustomFieldDeletionEvent) event;
objectType = ObjectType.CUSTOM_FIELD;
objectId = realCustomFieldEventDel.getCustomFieldId();
eventBusType = ExtBusEventType.CUSTOM_FIELD_DELETION;
break;
case TENANT_CONFIG_CHANGE:
final TenantConfigChangeInternalEvent realTenantConfigEventChg = (TenantConfigChangeInternalEvent) event;
objectType = ObjectType.TENANT_KVS;
objectId = realTenantConfigEventChg.getId();
eventBusType = ExtBusEventType.TENANT_CONFIG_CHANGE;
metaData = realTenantConfigEventChg.getKey();
break;
case TENANT_CONFIG_DELETION:
final TenantConfigDeletionInternalEvent realTenantConfigEventDel = (TenantConfigDeletionInternalEvent) event;
objectType = ObjectType.TENANT_KVS;
objectId = null;
eventBusType = ExtBusEventType.TENANT_CONFIG_DELETION;
metaData = realTenantConfigEventDel.getKey();
break;
case BROADCAST_SERVICE:
final BroadcastInternalEvent realBroadcastEvent = (BroadcastInternalEvent) event;
objectType = ObjectType.SERVICE_BROADCAST;
objectId = null;
eventBusType = ExtBusEventType.BROADCAST_SERVICE;
final BroadcastMetadata broadcastMetadata = new BroadcastMetadata(realBroadcastEvent.getServiceName(), realBroadcastEvent.getType(), realBroadcastEvent.getJsonEvent());
metaData = objectMapper.writeValueAsString(broadcastMetadata);
break;
default:
}
final TenantContext tenantContext = internalCallContextFactory.createTenantContext(context);
// See #275
accountId = (accountId == null) ? getAccountId(event.getBusEventType(), objectId, objectType, tenantContext) : accountId;
return eventBusType != null ? new DefaultBusExternalEvent(objectId, objectType, eventBusType, accountId, tenantContext.getTenantId(), metaData, context.getAccountRecordId(), context.getTenantRecordId(), context.getUserToken()) : null;
}
use of org.killbill.billing.events.EffectiveSubscriptionInternalEvent in project killbill by killbill.
the class TestBillingApi method createSubscriptionCreationEvent.
private DateTime createSubscriptionCreationEvent(final Plan nextPlan, final PlanPhase nextPhase) throws CatalogApiException {
final DateTime now = clock.getUTCNow();
final DateTime then = now.minusDays(1);
final EffectiveSubscriptionInternalEvent t = new MockEffectiveSubscriptionEvent(eventId, subId, bunId, bunKey, then, now, null, null, null, null, null, EntitlementState.ACTIVE, nextPlan.getName(), nextPhase.getName(), nextPlan.getPriceList().getName(), null, 1L, SubscriptionBaseTransitionType.CREATE, 1, null, 1L, 2L, null);
effectiveSubscriptionTransitions.add(t);
billingTransitions.add(new DefaultSubscriptionBillingEvent(SubscriptionBaseTransitionType.CREATE, nextPlan, nextPhase, now, 1L, null, CatalogDateHelper.toUTCDateTime(nextPlan.getCatalog().getEffectiveDate())));
return now;
}
use of org.killbill.billing.events.EffectiveSubscriptionInternalEvent in project killbill by killbill.
the class TestEventJson method testSubscriptionEvent.
@Test(groups = "fast")
public void testSubscriptionEvent() throws Exception {
final EffectiveSubscriptionInternalEvent e = new DefaultEffectiveSubscriptionEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), null, new DateTime(), EntitlementState.ACTIVE, "pro", "TRIAL", "DEFAULT", null, EntitlementState.CANCELLED, null, null, null, null, 3L, SubscriptionBaseTransitionType.CANCEL, 0, new DateTime(), 1L, 2L, null);
final String json = mapper.writeValueAsString(e);
final Class<?> claz = Class.forName(DefaultEffectiveSubscriptionEvent.class.getName());
final Object obj = mapper.readValue(json, claz);
Assert.assertTrue(obj.equals(e));
}
use of org.killbill.billing.events.EffectiveSubscriptionInternalEvent in project killbill by killbill.
the class TestBillingApi method beforeMethod.
@BeforeMethod(groups = "fast")
public void beforeMethod() throws Exception {
if (hasFailed()) {
return;
}
super.beforeMethod();
final SubscriptionBaseBundle bundle = Mockito.mock(SubscriptionBaseBundle.class);
Mockito.when(bundle.getId()).thenReturn(bunId);
final List<SubscriptionBaseBundle> bundles = ImmutableList.<SubscriptionBaseBundle>of(bundle);
billingTransitions = new LinkedList<SubscriptionBillingEvent>();
effectiveSubscriptionTransitions = new LinkedList<EffectiveSubscriptionInternalEvent>();
final DateTime subscriptionStartDate = clock.getUTCNow().minusDays(3);
subscription = new MockSubscription(subId, bunId, null, null, subscriptionStartDate, subscriptionStartDate);
final List<SubscriptionBase> subscriptions = ImmutableList.<SubscriptionBase>of(subscription);
// Mockito.when(subscription.getBillingAlignment(Mockito.<PlanPhaseSpecifier>any(), Mockito.<DateTime>any(), Mockito.<Catalog>any())).thenReturn(BillingAlignment.ACCOUNT);
Mockito.when(subscriptionInternalApi.getBundlesForAccount(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(bundles);
Mockito.when(subscriptionInternalApi.getSubscriptionsForBundle(Mockito.<UUID>any(), Mockito.<DryRunArguments>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscriptions);
Mockito.when(subscriptionInternalApi.getSubscriptionsForAccount(Mockito.<VersionedCatalog>any(), Mockito.<LocalDate>any(), Mockito.<InternalTenantContext>any())).thenReturn(ImmutableMap.<UUID, List<SubscriptionBase>>builder().put(bunId, subscriptions).build());
Mockito.when(subscriptionInternalApi.getSubscriptionFromId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscription);
Mockito.when(subscriptionInternalApi.getBundleFromId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(bundle);
Mockito.when(subscriptionInternalApi.getBaseSubscription(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscription);
Mockito.when(subscriptionInternalApi.getSubscriptionBillingEvents(Mockito.<VersionedCatalog>any(), Mockito.<SubscriptionBase>any(), Mockito.<InternalTenantContext>any())).thenReturn(billingTransitions);
Mockito.when(subscriptionInternalApi.getAllTransitions(Mockito.<SubscriptionBase>any(), Mockito.<InternalTenantContext>any())).thenReturn(effectiveSubscriptionTransitions);
final VersionedCatalog versionedCatalog = catalogService.getFullCatalog(true, true, internalCallContext);
catalog = (MockCatalog) Iterables.getLast(versionedCatalog.getVersions());
Mockito.when(catalogService.getFullCatalog(true, true, internalCallContext)).thenReturn(versionedCatalog);
// Set a default alignment
((MockSubscription) subscription).setBillingAlignment(BillingAlignment.ACCOUNT);
// Cleanup mock daos
((MockBlockingStateDao) blockingStateDao).clear();
((MockTagDao) tagDao).clear();
}
Aggregations