use of org.killbill.billing.junction.BillingEvent 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.junction.BillingEvent in project killbill by killbill.
the class TestBillingApi method testBillingEventsNoBillingPeriod.
@Test(groups = "fast")
public void testBillingEventsNoBillingPeriod() throws CatalogApiException, AccountApiException, SubscriptionBaseApiException {
final Plan nextPlan = catalog.findPlan("3-PickupTrialEvergreen10USD", clock.getUTCNow());
// The trial has no billing period
final PlanPhase nextPhase = nextPlan.getAllPhases()[0];
final DateTime now = createSubscriptionCreationEvent(nextPlan, nextPhase);
final Account account = createAccount(10);
final SortedSet<BillingEvent> events = billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), null, internalCallContext);
checkFirstEvent(events, nextPlan, account.getBillCycleDayLocal(), subId, now, nextPhase, SubscriptionBaseTransitionType.CREATE.toString());
}
use of org.killbill.billing.junction.BillingEvent in project killbill by killbill.
the class TestBillingApi method testBillingEventsBundleAligned.
@Test(groups = "fast")
public void testBillingEventsBundleAligned() throws CatalogApiException, AccountApiException, SubscriptionBaseApiException {
final Plan nextPlan = catalog.findPlan("7-Horn1USD", clock.getUTCNow());
final PlanPhase nextPhase = nextPlan.getAllPhases()[0];
final DateTime now = createSubscriptionCreationEvent(nextPlan, nextPhase);
final Account account = createAccount(1);
catalog.setBillingAlignment(BillingAlignment.BUNDLE);
((MockSubscription) subscription).setPlan(catalog.findPlan("3-PickupTrialEvergreen10USD", now));
final SortedSet<BillingEvent> events = billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), null, internalCallContext);
// The expected BCD is when the subscription started
checkFirstEvent(events, nextPlan, subscription.getStartDate().getDayOfMonth(), subId, now, nextPhase, SubscriptionBaseTransitionType.CREATE.toString());
}
use of org.killbill.billing.junction.BillingEvent in project killbill by killbill.
the class TestBlockingCalculator method testEventsToRemoveOpenPrev.
// Open ended duration with a previous event
// --X--[----------------------------------
@Test(groups = "fast")
public void testEventsToRemoveOpenPrev() {
final DateTime now = clock.getUTCNow();
final List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
final SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
disabledDuration.add(new DisabledDuration(now, null));
billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
final SortedSet<BillingEvent> results = blockingCalculator.eventsToRemove(disabledDuration, billingEvents, subscription1);
assertEquals(results.size(), 0);
}
use of org.killbill.billing.junction.BillingEvent in project killbill by killbill.
the class TestBlockingCalculator method testCreateNewEventsClosedPrevBetwNext.
// Closed duration with a previous event and in-between event and following
// --X--[------Y-----]-------Z-------------
@Test(groups = "fast")
public void testCreateNewEventsClosedPrevBetwNext() throws CatalogApiException {
final DateTime now = clock.getUTCNow();
final List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
final SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
billingEvents.add(createRealEvent(now.plusDays(3), subscription1));
final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, subscription1, internalCallContext);
assertEquals(results.size(), 2);
assertEquals(results.first().getEffectiveDate(), now);
assertNull(results.first().getFixedPrice());
assertNull(results.first().getRecurringPrice(null));
assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
assertEquals(results.last().getRecurringPrice(null), billingEvents.first().getRecurringPrice(null));
assertEquals(results.last().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
}
Aggregations