@Override public boolean apply(final CatalogOverridePhaseDefinitionModelDao input) { return input.getParentPhaseName().equals(curPhase.getName()); } }).orNull();
@Override public Double getMinTopUpCredit() throws CatalogApiException { if (!CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_DOUBLE_FIELD_VALUE.equals(minTopUpCredit) && type != BlockType.TOP_UP) { throw new CatalogApiException(ErrorCode.CAT_NOT_TOP_UP_BLOCK, phase.getName()); } return minTopUpCredit; }
@Override public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) { // Safety check if (type == null) { throw new IllegalStateException("type should have been automatically been initialized with VANILLA "); } if (type == BlockType.TOP_UP && CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_DOUBLE_FIELD_VALUE.equals(minTopUpCredit)) { errors.add(new ValidationError(String.format("TOP_UP block needs to define minTopUpCredit for phase %s", phase.getName()), DefaultUsage.class, "")); } return errors; }
@Override public PlanPhase findPhase(final String name) throws CatalogApiException { for (final PlanPhase pp : getAllPhases()) { if (pp.getName().equals(name)) { return pp; } } throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PHASE, name); }
@Override public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) { if (billingMode == BillingMode.IN_ARREAR && usageType == UsageType.CAPACITY && limits.length == 0) { errors.add(new ValidationError(String.format("Usage [IN_ARREAR CAPACITY] section of phase %s needs to define some limits", phase.getName()), DefaultUsage.class, "")); } if (billingMode == BillingMode.IN_ARREAR && usageType == UsageType.CONSUMABLE && blocks.length == 0) { errors.add(new ValidationError(String.format("Usage [IN_ARREAR CONSUMABLE] section of phase %s needs to define some blocks", phase.getName()), DefaultUsage.class, "")); } validateCollection(catalog, errors, limits); return errors; }
@Override public boolean apply(final PlanPhasePriceOverride input) { if (input.getPhaseName() != null) { return input.getPhaseName().equals(curPhase.getName()); } // If the phaseName was not passed, we infer by matching the phaseType. This obviously would not work in a case where // a plan is defined with multiple phases of the same type. final PlanPhaseSpecifier curPlanPhaseSpecifier = input.getPlanPhaseSpecifier(); if (curPlanPhaseSpecifier.getPhaseType().equals(curPhase.getPhaseType())) { return true; } return false; } }).orNull();
@Test(groups = "slow", expectedExceptions = CatalogApiException.class) public void testWithInvalidPriceOverride() throws Exception { final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class); catalog.initialize(catalog); final Plan plan = catalog.findCurrentPlan("discount-standard-monthly"); final List<PlanPhasePriceOverride> overrides = new ArrayList<PlanPhasePriceOverride>(); final PlanPhasePriceOverride phase1 = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[0].getName(), Currency.USD, null, BigDecimal.ONE, null); overrides.add(phase1); priceOverride.getOrCreateOverriddenPlan(catalog, plan, new DateTime(catalog.getEffectiveDate()), overrides, internalCallContext); }
@Test(groups = "slow") public void testOverrideLastPhase() throws Exception { final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarBasic.xml").toExternalForm(), StandaloneCatalog.class); final Plan plan = catalog.findCurrentPlan("standard-monthly"); final PlanPhasePriceOverride[] resolvedOverrides = new PlanPhasePriceOverride[plan.getAllPhases().length]; resolvedOverrides[0] = null; resolvedOverrides[1] = new DefaultPlanPhasePriceOverride(plan.getFinalPhase().getName(), Currency.USD, null, new BigDecimal("128.76"), null); final CatalogOverridePlanDefinitionModelDao newPlan = catalogOverrideDao.getOrCreateOverridePlanDefinition(plan, new DateTime(catalog.getEffectiveDate()), resolvedOverrides, internalCallContext); assertEquals(newPlan.getParentPlanName(), "standard-monthly"); assertTrue(newPlan.getIsActive()); }
private PlanPhasePriceOverride[] createOverrides(final Plan defaultPlan, final List<CatalogOverridePhaseDefinitionModelDao> phaseDefs, final InternalTenantContext context) { final PlanPhasePriceOverride[] result = new PlanPhasePriceOverride[defaultPlan.getAllPhases().length]; for (int i = 0; i < defaultPlan.getAllPhases().length; i++) { final PlanPhase curPhase = defaultPlan.getAllPhases()[i]; final CatalogOverridePhaseDefinitionModelDao overriddenPhase = Iterables.tryFind(phaseDefs, new Predicate<CatalogOverridePhaseDefinitionModelDao>() { @Override public boolean apply(final CatalogOverridePhaseDefinitionModelDao input) { return input.getParentPhaseName().equals(curPhase.getName()); } }).orNull(); if (overriddenPhase != null) { List<UsagePriceOverride> usagePriceOverrides = getUsagePriceOverrides(curPhase, overriddenPhase, context); result[i] = new DefaultPlanPhasePriceOverride(curPhase.getName(), Currency.valueOf(overriddenPhase.getCurrency()), overriddenPhase.getFixedPrice(), overriddenPhase.getRecurringPrice(), usagePriceOverrides); } else { result[i] = null; } } return result; }
@Test(groups = "slow") public void testOverrideTwoOutOfThreePhases() throws Exception { final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class); final Plan plan = catalog.findCurrentPlan("discount-standard-monthly"); final PlanPhasePriceOverride[] resolvedOverrides = new PlanPhasePriceOverride[plan.getAllPhases().length]; resolvedOverrides[0] = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[0].getName(), Currency.USD, BigDecimal.TEN, null, null); resolvedOverrides[1] = null; resolvedOverrides[2] = new DefaultPlanPhasePriceOverride(plan.getFinalPhase().getName(), Currency.USD, null, new BigDecimal("348.64"), null); final CatalogOverridePlanDefinitionModelDao newPlan = catalogOverrideDao.getOrCreateOverridePlanDefinition(plan, new DateTime(catalog.getEffectiveDate()), resolvedOverrides, internalCallContext); assertEquals(newPlan.getParentPlanName(), "discount-standard-monthly"); assertTrue(newPlan.getIsActive()); final List<CatalogOverridePhaseDefinitionModelDao> phases = catalogOverrideDao.getOverriddenPlanPhases(newPlan.getRecordId(), internalCallContext); assertEquals(phases.size(), 2); }
private boolean onPhaseEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent readyPhaseEvent, final Catalog fullCatalog, final InternalCallContext context) { try { final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, readyPhaseEvent.getEffectiveDate(), fullCatalog, context); final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ? PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null; if (nextPhaseEvent != null) { dao.createNextPhaseEvent(subscription, readyPhaseEvent, nextPhaseEvent, context); return true; } } catch (final SubscriptionBaseError e) { log.warn("Error inserting next phase for subscriptionId='{}'", subscription.getId(), e); } return false; }
@Test(groups = "slow") public void testGetOverriddenPlanPhases() throws Exception { final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class); final Plan plan = catalog.findCurrentPlan("discount-standard-monthly"); final PlanPhasePriceOverride[] resolvedOverrides = new PlanPhasePriceOverride[plan.getAllPhases().length]; resolvedOverrides[0] = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[0].getName(), Currency.USD, BigDecimal.TEN, BigDecimal.ONE, null); resolvedOverrides[1] = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[1].getName(), Currency.USD, BigDecimal.ONE, BigDecimal.TEN, null); resolvedOverrides[2] = new DefaultPlanPhasePriceOverride(plan.getFinalPhase().getName(), Currency.USD, BigDecimal.ZERO, new BigDecimal("348.64"), null); final CatalogOverridePlanDefinitionModelDao newPlan = catalogOverrideDao.getOrCreateOverridePlanDefinition(plan, new DateTime(catalog.getEffectiveDate()), resolvedOverrides, internalCallContext); final List<CatalogOverridePhaseDefinitionModelDao> phases = catalogOverrideDao.getOverriddenPlanPhases(newPlan.getRecordId(), internalCallContext); assertEquals(phases.size(), 3); for (int i = 0; i < 3; i++) { final CatalogOverridePhaseDefinitionModelDao curPhase = phases.get(i); assertEquals(curPhase.getCurrency(), resolvedOverrides[i].getCurrency().name()); assertEquals(curPhase.getFixedPrice().compareTo(resolvedOverrides[i].getFixedPrice()), 0); assertEquals(curPhase.getRecurringPrice().compareTo(resolvedOverrides[i].getRecurringPrice()), 0); assertEquals(curPhase.getParentPhaseName(), resolvedOverrides[i].getPhaseName()); } }
@Test(groups = "fast", description = "https://github.com/killbill/killbill/issues/842") public void testCreateAmbiguousPlan() throws CatalogApiException { final DateTime now = clock.getUTCNow(); final SimplePlanDescriptor desc = new DefaultSimplePlanDescriptor("foo-monthly-12345", "Foo", ProductCategory.BASE, Currency.EUR, BigDecimal.TEN, BillingPeriod.MONTHLY, 0, TimeUnit.UNLIMITED, ImmutableList.<String>of()); final CatalogUpdater catalogUpdater = new CatalogUpdater(now, desc.getCurrency()); catalogUpdater.addSimplePlanDescriptor(desc); final StandaloneCatalog catalog = catalogUpdater.getCatalog(); assertEquals(catalog.getCurrentPlans().size(), 1); final StaticCatalog standaloneCatalogWithPriceOverride = new StandaloneCatalogWithPriceOverride(catalog, priceOverride, internalCallContext.getTenantRecordId(), internalCallContextFactory); final Plan plan = catalog.findCurrentPlan("foo-monthly-12345"); assertEquals(plan.getName(), "foo-monthly-12345"); // Verify PriceOverride logic final Plan plan2 = standaloneCatalogWithPriceOverride.findCurrentPlan("foo-monthly-12345"); assertEquals(plan2.getName(), "foo-monthly-12345"); final PlanPhase planPhase = catalog.findCurrentPhase("foo-monthly-12345-evergreen"); assertEquals(planPhase.getName(), "foo-monthly-12345-evergreen"); // Verify PriceOverride logic final PlanPhase phase2 = standaloneCatalogWithPriceOverride.findCurrentPhase("foo-monthly-12345-evergreen"); assertEquals(phase2.getName(), "foo-monthly-12345-evergreen"); }
@Test(groups = "fast") public void testAddExistingPlanWithNewCurrency() throws Exception { final StandaloneCatalog originalCatalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarBasic.xml").toExternalForm(), StandaloneCatalog.class); assertEquals(originalCatalog.getPriceLists().getAllPriceLists().size(), 1); assertEquals(originalCatalog.getPriceLists().getAllPriceLists().get(0).getName(), new PriceListDefault().getName()); assertEquals(originalCatalog.getPriceLists().getAllPriceLists().get(0).getPlans().size(), 3); final CatalogUpdater catalogUpdater = new CatalogUpdater(originalCatalog); final SimplePlanDescriptor desc = new DefaultSimplePlanDescriptor("standard-monthly", "Standard", ProductCategory.BASE, Currency.EUR, BigDecimal.TEN, BillingPeriod.MONTHLY, 30, TimeUnit.DAYS, ImmutableList.<String>of()); catalogUpdater.addSimplePlanDescriptor(desc); final StandaloneCatalog catalog = catalogUpdater.getCatalog(); final Plan plan = catalog.findCurrentPlan("standard-monthly"); assertEquals(plan.getName(), "standard-monthly"); assertEquals(plan.getInitialPhases().length, 1); assertEquals(plan.getInitialPhases()[0].getPhaseType(), PhaseType.TRIAL); assertEquals(plan.getInitialPhases()[0].getFixed().getPrice().getPrices().length, 0); assertEquals(plan.getInitialPhases()[0].getFixed().getPrice().getPrice(Currency.EUR), BigDecimal.ZERO); assertEquals(plan.getInitialPhases()[0].getName(), "standard-monthly-trial"); assertEquals(plan.getFinalPhase().getPhaseType(), PhaseType.EVERGREEN); assertNull(plan.getFinalPhase().getFixed()); assertEquals(plan.getFinalPhase().getName(), "standard-monthly-evergreen"); assertEquals(plan.getFinalPhase().getRecurring().getBillingPeriod(), BillingPeriod.MONTHLY); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices().length, 3); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrice(Currency.EUR), BigDecimal.TEN); }
@Test(groups = "fast") public void testAddNoTrialPlanOnFirstCatalog() throws CatalogApiException { final DateTime now = clock.getUTCNow(); final SimplePlanDescriptor desc = new DefaultSimplePlanDescriptor("foo-monthly", "Foo", ProductCategory.BASE, Currency.EUR, BigDecimal.TEN, BillingPeriod.MONTHLY, 0, TimeUnit.UNLIMITED, ImmutableList.<String>of()); final CatalogUpdater catalogUpdater = new CatalogUpdater(now, desc.getCurrency()); catalogUpdater.addSimplePlanDescriptor(desc); final StandaloneCatalog catalog = catalogUpdater.getCatalog(); assertEquals(catalog.getCurrentProducts().size(), 1); final Product product = catalog.getCurrentProducts().iterator().next(); assertEquals(product.getName(), "Foo"); assertEquals(product.getCategory(), ProductCategory.BASE); assertEquals(catalog.getCurrentPlans().size(), 1); final Plan plan = catalog.findCurrentPlan("foo-monthly"); assertEquals(plan.getName(), "foo-monthly"); assertEquals(plan.getInitialPhases().length, 0); assertEquals(plan.getFinalPhase().getPhaseType(), PhaseType.EVERGREEN); assertNull(plan.getFinalPhase().getFixed()); assertEquals(plan.getFinalPhase().getName(), "foo-monthly-evergreen"); assertEquals(plan.getFinalPhase().getRecurring().getBillingPeriod(), BillingPeriod.MONTHLY); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices().length, 1); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices()[0].getValue(), BigDecimal.TEN); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices()[0].getCurrency(), Currency.EUR); assertEquals(catalog.getPriceLists().getAllPriceLists().size(), 1); final PriceList priceList = catalog.getPriceLists().getAllPriceLists().get(0); assertEquals(priceList.getName(), new PriceListDefault().getName()); assertEquals(priceList.getPlans().size(), 1); assertEquals(priceList.getPlans().iterator().next().getName(), "foo-monthly"); }
@Test(groups = "fast") public void testAddPlanOnExistingCatalog() throws Exception { final StandaloneCatalog originalCatalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarBasic.xml").toExternalForm(), StandaloneCatalog.class); assertEquals(originalCatalog.getPriceLists().getAllPriceLists().size(), 1); assertEquals(originalCatalog.getPriceLists().getAllPriceLists().get(0).getName(), new PriceListDefault().getName()); assertEquals(originalCatalog.getPriceLists().getAllPriceLists().get(0).getPlans().size(), 3); final CatalogUpdater catalogUpdater = new CatalogUpdater(originalCatalog); final SimplePlanDescriptor desc = new DefaultSimplePlanDescriptor("standard-annual", "Standard", ProductCategory.BASE, Currency.USD, BigDecimal.TEN, BillingPeriod.MONTHLY, 0, TimeUnit.UNLIMITED, ImmutableList.<String>of()); catalogUpdater.addSimplePlanDescriptor(desc); final StandaloneCatalog catalog = catalogUpdater.getCatalog(); final Plan plan = catalog.findCurrentPlan("standard-annual"); assertEquals(plan.getName(), "standard-annual"); assertEquals(plan.getInitialPhases().length, 0); assertEquals(plan.getFinalPhase().getPhaseType(), PhaseType.EVERGREEN); assertNull(plan.getFinalPhase().getFixed()); assertEquals(plan.getFinalPhase().getName(), "standard-annual-evergreen"); assertEquals(plan.getFinalPhase().getRecurring().getBillingPeriod(), BillingPeriod.MONTHLY); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices().length, 1); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices()[0].getValue(), BigDecimal.TEN); assertEquals(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices()[0].getCurrency(), Currency.USD); assertEquals(catalog.getPriceLists().getAllPriceLists().size(), 1); final PriceList priceList = catalog.getPriceLists().getAllPriceLists().get(0); assertEquals(priceList.getName(), new PriceListDefault().getName()); assertEquals(priceList.getPlans().size(), 4); }
assertEquals(plan.getInitialPhases()[0].getFixed().getPrice().getPrices()[0].getCurrency(), Currency.EUR); assertEquals(plan.getInitialPhases()[0].getFixed().getPrice().getPrices()[0].getValue(), BigDecimal.ZERO); assertEquals(plan.getInitialPhases()[0].getName(), "foo-monthly-trial"); assertEquals(plan.getFinalPhase().getName(), "foo-monthly-evergreen");
PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null; if (nextPhaseEvent != null) {
PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) : null; if (nextPhaseEvent != null) {
public DefaultSubscriptionEvent(final SubscriptionBaseTransitionData in, final DateTime startDate, final Long searchKey1, final Long searchKey2, final UUID userToken) { this(in.getId(), in.getSubscriptionId(), in.getBundleId(), in.getBundleExternalKey(), in.getEffectiveTransitionTime(), in.getEffectiveTransitionTime(), in.getPreviousState(), (in.getPreviousPlan() != null) ? in.getPreviousPlan().getName() : null, (in.getPreviousPhase() != null) ? in.getPreviousPhase().getName() : null, (in.getPreviousPriceList() != null) ? in.getPreviousPriceList().getName() : null, in.getPreviousBillingCycleDayLocal(), in.getNextState(), (in.getNextPlan() != null) ? in.getNextPlan().getName() : null, (in.getNextPhase() != null) ? in.getNextPhase().getName() : null, (in.getNextPriceList() != null) ? in.getNextPriceList().getName() : null, in.getNextBillingCycleDayLocal(), in.getTotalOrdering(), in.getTransitionType(), in.getRemainingEventsForUserOperation(), startDate, searchKey1, searchKey2, userToken); }