/* * Copyright 2014-2015 Groupon, Inc * Copyright 2014-2015 The Billing Project, LLC * * The Billing Project licenses this file to you under the Apache License, version 2.0 * (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.killbill.billing.catalog; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import org.joda.time.DateTime; import org.killbill.billing.catalog.api.CatalogApiException; import org.killbill.billing.catalog.api.Currency; import org.killbill.billing.catalog.api.InternationalPrice; import org.killbill.billing.catalog.api.Plan; import org.killbill.billing.catalog.api.PlanPhasePriceOverride; import org.killbill.billing.catalog.api.Price; import org.killbill.billing.catalog.override.DefaultPriceOverride; import org.killbill.xmlloader.XMLLoader; import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.io.Resources; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertTrue; public class TestDefaultPriceOverride extends CatalogTestSuiteWithEmbeddedDB { @Test(groups = "slow") public void testBasic() throws Exception { final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class); catalog.initialize(catalog, null); 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, BigDecimal.ONE, null); overrides.add(phase1); final PlanPhasePriceOverride phase3 = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[2].getName(), Currency.USD, null, new BigDecimal("142.41")); overrides.add(phase3); final DefaultPlan overriddenPlan = priceOverride.getOrCreateOverriddenPlan(catalog, plan, new DateTime(catalog.getEffectiveDate()), overrides, internalCallContext); final Matcher m = DefaultPriceOverride.CUSTOM_PLAN_NAME_PATTERN.matcher(overriddenPlan.getName()); assertTrue(m.matches()); assertEquals(m.group(1), plan.getName()); assertEquals(overriddenPlan.getProduct().getName(), plan.getProduct().getName()); assertEquals(overriddenPlan.getRecurringBillingPeriod(), plan.getRecurringBillingPeriod()); if (plan.getEffectiveDateForExistingSubscriptions() != null) { assertEquals(overriddenPlan.getEffectiveDateForExistingSubscriptions().compareTo(plan.getEffectiveDateForExistingSubscriptions()), 0); } assertNotEquals(overriddenPlan.getFinalPhase().getName(), plan.getFinalPhase().getName()); assertEquals(overriddenPlan.getPlansAllowedInBundle(), plan.getPlansAllowedInBundle()); assertEquals(overriddenPlan.getAllPhases().length, overriddenPlan.getAllPhases().length); for (int i = 0; i < overriddenPlan.getAllPhases().length; i++) { final DefaultPlanPhase initialPhase = (DefaultPlanPhase) plan.getAllPhases()[i]; final DefaultPlanPhase newPhase = (DefaultPlanPhase) overriddenPlan.getAllPhases()[i]; final PlanPhasePriceOverride override = Iterables.tryFind(overrides, new Predicate<PlanPhasePriceOverride>() { @Override public boolean apply(final PlanPhasePriceOverride input) { return input.getPhaseName().equals(initialPhase.getName()); } }).orNull(); assertNotEquals(newPhase.getName(), initialPhase.getName()); assertEquals(newPhase.getDuration(), initialPhase.getDuration()); assertEquals(newPhase.getPhaseType(), initialPhase.getPhaseType()); assertEquals(newPhase.getUsages().length, initialPhase.getUsages().length); if (initialPhase.getFixed() != null) { assertEquals(newPhase.getFixed().getType(), initialPhase.getFixed().getType()); assertInternationalPrice(newPhase.getFixed().getPrice(), initialPhase.getFixed().getPrice(), override, true); } if (initialPhase.getRecurring() != null) { assertInternationalPrice(newPhase.getRecurring().getRecurringPrice(), initialPhase.getRecurring().getRecurringPrice(), override, false); } } } @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, null); 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); overrides.add(phase1); priceOverride.getOrCreateOverriddenPlan(catalog, plan, new DateTime(catalog.getEffectiveDate()), overrides, internalCallContext); } @Test(groups = "slow") public void testGetOverriddenPlan() throws Exception { final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class); catalog.initialize(catalog, null); 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, BigDecimal.ONE, null); overrides.add(phase1); final PlanPhasePriceOverride phase3 = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[2].getName(), Currency.USD, null, new BigDecimal("142.41")); overrides.add(phase3); final DefaultPlan overriddenPlanCreated = priceOverride.getOrCreateOverriddenPlan(catalog, plan, new DateTime(catalog.getEffectiveDate()), overrides, internalCallContext); System.out.println("overriddenPlanCreated = " + overriddenPlanCreated.getName()); final DefaultPlan overriddenPlan = priceOverride.getOverriddenPlan(overriddenPlanCreated.getName(), catalog, internalCallContext); assertEquals(overriddenPlan.getProduct().getName(), plan.getProduct().getName()); assertEquals(overriddenPlan.getRecurringBillingPeriod(), plan.getRecurringBillingPeriod()); if (plan.getEffectiveDateForExistingSubscriptions() != null) { assertEquals(overriddenPlan.getEffectiveDateForExistingSubscriptions().compareTo(plan.getEffectiveDateForExistingSubscriptions()), 0); } assertNotEquals(overriddenPlan.getFinalPhase().getName(), plan.getFinalPhase().getName()); assertEquals(overriddenPlan.getPlansAllowedInBundle(), plan.getPlansAllowedInBundle()); assertEquals(overriddenPlan.getAllPhases().length, overriddenPlan.getAllPhases().length); for (int i = 0; i < overriddenPlan.getAllPhases().length; i++) { final DefaultPlanPhase initialPhase = (DefaultPlanPhase) plan.getAllPhases()[i]; final DefaultPlanPhase newPhase = (DefaultPlanPhase) overriddenPlan.getAllPhases()[i]; final PlanPhasePriceOverride override = Iterables.tryFind(overrides, new Predicate<PlanPhasePriceOverride>() { @Override public boolean apply(final PlanPhasePriceOverride input) { return input.getPhaseName().equals(initialPhase.getName()); } }).orNull(); assertNotEquals(newPhase.getName(), initialPhase.getName()); assertEquals(newPhase.getName(), overriddenPlan.getName() + "-" + initialPhase.getName().split("-")[initialPhase.getName().split("-").length -1]); assertEquals(newPhase.getDuration(), initialPhase.getDuration()); assertEquals(newPhase.getPhaseType(), initialPhase.getPhaseType()); assertEquals(newPhase.getUsages().length, initialPhase.getUsages().length); if (initialPhase.getFixed() != null) { assertEquals(newPhase.getFixed().getType(), initialPhase.getFixed().getType()); assertInternationalPrice(newPhase.getFixed().getPrice(), initialPhase.getFixed().getPrice(), override, true); } if (initialPhase.getRecurring() != null) { assertInternationalPrice(newPhase.getRecurring().getRecurringPrice(), initialPhase.getRecurring().getRecurringPrice(), override, false); } } } private void assertInternationalPrice(final InternationalPrice newInternationalPrice, final InternationalPrice initInternationalPrice, final PlanPhasePriceOverride override, final boolean isFixed) throws CatalogApiException { if (initInternationalPrice.getPrices().length == 0) { if (override != null) { assertEquals(newInternationalPrice.getPrices().length, 1); assertEquals(newInternationalPrice.getPrice(override.getCurrency()).compareTo(isFixed ? override.getFixedPrice() : override.getRecurringPrice()), 0); } } else { assertEquals(newInternationalPrice.getPrices().length, initInternationalPrice.getPrices().length); for (int i = 0; i < newInternationalPrice.getPrices().length; i++) { final Price initPrice = initInternationalPrice.getPrices()[i]; final Price newPrice = newInternationalPrice.getPrices()[i]; if (override != null && override.getCurrency() == initPrice.getCurrency() && ((isFixed && override.getFixedPrice() != null) || (!isFixed && override.getRecurringPrice() != null))) { assertEquals(newPrice.getValue().compareTo(isFixed ? override.getFixedPrice() : override.getRecurringPrice()), 0); } else { if (initPrice != null && initPrice.getValue() != null) { assertEquals(newPrice.getValue().compareTo(initPrice.getValue()), 0); } } } } } }