@Test
  public void getTemplateProducts_AllProductTypes() throws Exception {
    // given
    final Product template =
        createTemplateProduct(
            tpSup.getOrganizationId(), "product", "techProduct", ServiceStatus.ACTIVE);
    final Product customerTemplate =
        createCustomerSpecificCopiedProduct(tpSup, template, ServiceStatus.ACTIVE);
    final Product partnerTemplate = createPartnerProductCopy(template, tpSup, ServiceStatus.ACTIVE);
    runTX(
        new Callable<Void>() {
          public Void call() throws Exception {
            Subscriptions.createSubscription(ds, tpSup.getOrganizationId(), template);
            Subscriptions.createSubscription(ds, tpSup.getOrganizationId(), customerTemplate);
            Subscriptions.createPartnerSubscription(
                ds, tpSup.getOrganizationId(), partnerTemplate.getProductId(), "partnerSub", tpSup);
            return null;
          }
        });

    // when
    List<Product> products =
        runTX(
            new Callable<List<Product>>() {
              public List<Product> call() {
                return localService.getTemplateProducts();
              }
            });

    // then
    assertEquals(1, products.size());
    assertEquals(template.getKey(), products.get(0).getKey());
  }
  @Test
  public void getProductsForVendor_FilterInStatuses() throws Exception {
    // give
    givenBrokerOrg();
    container.login(brokerUserKey, UserRoleType.BROKER_MANAGER.name());

    Product templateInactive =
        createTemplateProduct(
            broker.getOrganizationId(),
            "productInactive",
            "techProductInactive",
            ServiceStatus.INACTIVE);
    Product templateActive =
        createTemplateProduct(
            broker.getOrganizationId(), "productActive", "techProductActive", ServiceStatus.ACTIVE);
    createTemplateProduct(
        broker.getOrganizationId(), "productDeleted", "techProductDeleted", ServiceStatus.DELETED);
    createTemplateProduct(
        broker.getOrganizationId(),
        "productObsolete",
        "techProductObsolete",
        ServiceStatus.OBSOLETE);
    Product templateSuspended =
        createTemplateProduct(
            broker.getOrganizationId(),
            "productSuspended",
            "techProductSuspended",
            ServiceStatus.SUSPENDED);
    // when
    List<Product> products =
        runTX(
            new Callable<List<Product>>() {
              public List<Product> call() {
                return localService.getProductsForVendor();
              }
            });
    // then
    assertEquals(3, products.size());
    assertEquals(templateInactive.getKey(), products.get(0).getKey());
    assertEquals(ServiceStatus.INACTIVE, products.get(0).getStatus());

    assertEquals(templateActive.getKey(), products.get(1).getKey());
    assertEquals(ServiceStatus.ACTIVE, products.get(1).getStatus());

    assertEquals(ServiceStatus.SUSPENDED, products.get(2).getStatus());
    assertEquals(templateSuspended.getKey(), products.get(2).getKey());
  }
  @Test(expected = OperationNotPermittedException.class)
  public void filterServiceConfiguration_NoTemplate() throws Exception {
    product.setType(ServiceType.CUSTOMER_TEMPLATE);
    VOServicePaymentConfiguration conf =
        createServiceConfiguration(product.getKey(), PaymentType.INVOICE);

    pcf.filterServiceConfiguration(Arrays.asList(conf));
  }
  @Test(expected = OperationNotPermittedException.class)
  public void filterServiceConfiguration_NotPermitted() throws Exception {
    product.setVendor(reseller);
    VOServicePaymentConfiguration conf =
        createServiceConfiguration(product.getKey(), PaymentType.INVOICE);

    pcf.filterServiceConfiguration(Arrays.asList(conf));
  }
  @Test
  public void filterServiceConfiguration_NoChange() throws Exception {
    VOServicePaymentConfiguration conf =
        createServiceConfiguration(product.getKey(), PaymentType.INVOICE);

    List<VOServicePaymentConfiguration> list = pcf.filterServiceConfiguration(Arrays.asList(conf));

    assertEquals(new ArrayList<VOServicePaymentConfiguration>(), list);
  }
  @Test
  public void filterServiceConfiguration_Change() throws Exception {
    VOServicePaymentConfiguration conf =
        createServiceConfiguration(product.getKey(), PaymentType.CREDIT_CARD);
    List<VOServicePaymentConfiguration> input = Arrays.asList(conf);

    List<VOServicePaymentConfiguration> list = pcf.filterServiceConfiguration(input);

    assertEquals(input, list);
  }
  @Test
  public void getPartnerProductsForTemplate() throws Exception {
    // give
    Organization broker1 = createOrgWithRole(OrganizationRoleType.BROKER);
    Organization broker2 = createOrgWithRole(OrganizationRoleType.BROKER);
    Organization broker3 = createOrgWithRole(OrganizationRoleType.BROKER);
    Organization reseller1 = createOrgWithRole(OrganizationRoleType.RESELLER);
    Organization reseller2 = createOrgWithRole(OrganizationRoleType.RESELLER);

    final Product template =
        createTemplateProduct(
            tpSup.getOrganizationId(), "product", "techProduct", ServiceStatus.ACTIVE);
    createCustomerSpecificCopiedProduct(tpSup, template, ServiceStatus.ACTIVE);
    createSubscriptionSpecificProductCopy(tpSup, template);

    Product brokerActiveProduct = createPartnerProductCopy(template, broker1, ServiceStatus.ACTIVE);
    Product resellerInactiveProduct =
        createPartnerProductCopy(template, reseller1, ServiceStatus.INACTIVE);
    createPartnerProductCopy(template, broker2, ServiceStatus.OBSOLETE);
    createPartnerProductCopy(template, broker3, ServiceStatus.DELETED);
    createPartnerProductCopy(template, reseller2, ServiceStatus.SUSPENDED);

    // when
    List<Product> products =
        runTX(
            new Callable<List<Product>>() {
              public List<Product> call() throws Exception {
                return localService.getPartnerProductsForTemplate(template.getKey());
              }
            });

    // then
    assertEquals(5, products.size());
    assertEquals(brokerActiveProduct.getKey(), products.get(0).getKey());
    assertEquals(resellerInactiveProduct.getKey(), products.get(1).getKey());
  }
  @Test(expected = ConcurrentModificationException.class)
  public void saveRevenueShareModelsForProduct_concurrentExecution() throws Exception {
    // given
    Product product = createProductForSave(tpSup, true, "mp", "tp", "productA", "pm");
    final long productKey = product.getKey();

    CatalogEntry catalogEntryOfProduct = getCatalogEntryForProduct(productKey);
    final RevenueShareModel brokerRevenueShare = new RevenueShareModel();
    brokerRevenueShare.setKey(catalogEntryOfProduct.getBrokerPriceModel().getKey());
    brokerRevenueShare.setRevenueShare(new BigDecimal("100.00"));
    final RevenueShareModel resellerRevenueShare = new RevenueShareModel();
    resellerRevenueShare.setKey(catalogEntryOfProduct.getResellerPriceModel().getKey());
    resellerRevenueShare.setRevenueShare(new BigDecimal("100.00"));

    // when
    container.login(poUserKey, ROLE_PLATFORM_OPERATOR);
    runTX(
        new Callable<Void>() {
          public Void call() throws Exception {
            localService.saveRevenueShareModelsForProduct(
                productKey, brokerRevenueShare, resellerRevenueShare, 0, 0);
            return null;
          }
        });
    runTX(
        new Callable<Void>() {
          public Void call() throws Exception {
            localService.saveRevenueShareModelsForProduct(
                productKey, brokerRevenueShare, resellerRevenueShare, 0, 0);
            return null;
          }
        });
    fail();

    // then a ConcurrentModificationException occurs
  }
  @Before
  public void setup() throws Exception {
    ds = mock(DataService.class);

    pt = new PaymentType();
    pt.setPaymentTypeId(PaymentType.INVOICE);
    pt.setKey(12345);

    Organization op = new Organization();
    op.setOrganizationId(OrganizationRoleType.PLATFORM_OPERATOR.name());

    supplier = new Organization();
    supplier.setOrganizationId("supplier");
    Organizations.grantOrganizationRole(supplier, OrganizationRoleType.SUPPLIER);

    reseller = new Organization();
    reseller.setOrganizationId("reseller");
    Organizations.grantOrganizationRole(reseller, OrganizationRoleType.RESELLER);

    OrganizationReference ref =
        OrganizationReferences.addReference(
            op, supplier, OrganizationReferenceType.PLATFORM_OPERATOR_TO_SUPPLIER);
    OrganizationReferences.enablePayment(ref, pt)
        .setOrganizationRole(new OrganizationRole(OrganizationRoleType.SUPPLIER));

    ref =
        OrganizationReferences.addReference(
            op, reseller, OrganizationReferenceType.PLATFORM_OPERATOR_TO_RESELLER);
    OrganizationReferences.enablePayment(ref, pt)
        .setOrganizationRole(new OrganizationRole(OrganizationRoleType.RESELLER));

    customer = new Organization();
    customer.setOrganizationId("customer");

    noCustomer = new Organization();
    noCustomer.setOrganizationId("noCustomer");

    ref =
        OrganizationReferences.addReference(
            supplier, customer, OrganizationReferenceType.SUPPLIER_TO_CUSTOMER);
    OrganizationReferences.enablePayment(ref, pt);

    ref =
        OrganizationReferences.addReference(
            reseller, customer, OrganizationReferenceType.RESELLER_TO_CUSTOMER);
    OrganizationReferences.enablePayment(ref, pt);

    product = new Product();
    product.setKey(9876);
    product.setVendor(supplier);
    product.setType(ServiceType.TEMPLATE);
    product.setPaymentTypes(Arrays.asList(new ProductToPaymentType(product, pt)));

    pcf = new PaymentConfigurationFilter(ds);

    user = new PlatformUser();
    user.setOrganization(supplier);

    when(ds.getCurrentUser()).thenReturn(user);
    when(ds.getReference(eq(Product.class), eq(product.getKey()))).thenReturn(product);
    when(ds.getReference(eq(Product.class), eq(PROD_NOT_FOUND_KEY)))
        .thenThrow(new ObjectNotFoundException(ClassEnum.SERVICE, "product"));

    when(ds.getReferenceByBusinessKey(any(DomainObject.class)))
        .thenAnswer(
            new Answer<DomainObject<?>>() {

              public DomainObject<?> answer(InvocationOnMock invocation) throws Throwable {
                Object object = invocation.getArguments()[0];
                if (object instanceof Organization) {
                  Organization o = (Organization) object;
                  if (customer.getOrganizationId().equals(o.getOrganizationId())) {
                    return customer;
                  }
                  if (noCustomer.getOrganizationId().equals(o.getOrganizationId())) {
                    return noCustomer;
                  }
                  throw new ObjectNotFoundException(ClassEnum.ORGANIZATION, o.getOrganizationId());
                }
                throw new ObjectNotFoundException(
                    ClassEnum.ORGANIZATION, object.getClass().getName());
              }
            });
  }
  @Test
  public void saveRevenueShareModelsForProduct_UpdateRevenueShares() throws Exception {
    // given
    Product product = createProductForSave(tpSup, true, "mp", "tp", "productA", "pm");
    final long productKey = product.getKey();

    CatalogEntry catalogEntryOfProduct = getCatalogEntryForProduct(productKey);
    final RevenueShareModel brokerRevenueShare = new RevenueShareModel();
    brokerRevenueShare.setKey(catalogEntryOfProduct.getBrokerPriceModel().getKey());
    brokerRevenueShare.setRevenueShare(new BigDecimal("100.00"));
    final RevenueShareModel resellerRevenueShare = new RevenueShareModel();
    resellerRevenueShare.setKey(catalogEntryOfProduct.getResellerPriceModel().getKey());
    resellerRevenueShare.setRevenueShare(new BigDecimal("100.00"));

    // when
    container.login(poUserKey, ROLE_PLATFORM_OPERATOR);
    Map<RevenueShareModelType, RevenueShareModel> revenueShares =
        runTX(
            new Callable<Map<RevenueShareModelType, RevenueShareModel>>() {
              public Map<RevenueShareModelType, RevenueShareModel> call() throws Exception {
                return localService.saveRevenueShareModelsForProduct(
                    productKey, brokerRevenueShare, resellerRevenueShare, 0, 0);
              }
            });

    // then
    assertEquals(
        new BigDecimal("100.00"),
        revenueShares.get(RevenueShareModelType.BROKER_REVENUE_SHARE).getRevenueShare());
    assertEquals(
        new BigDecimal("100.00"),
        revenueShares.get(RevenueShareModelType.RESELLER_REVENUE_SHARE).getRevenueShare());

    // validate stored values in the database
    runTX(
        new Callable<Void>() {
          public Void call() throws Exception {
            Product result = ds.getReference(Product.class, productKey);
            List<CatalogEntry> entries = result.getCatalogEntries();
            assertEquals(1, entries.size());
            CatalogEntry ce = entries.get(0);
            RevenueShareModel brokerRevenueShare = ce.getBrokerPriceModel();
            assertNotNull(brokerRevenueShare);
            assertEquals(new BigDecimal("100.00"), brokerRevenueShare.getRevenueShare());
            RevenueShareModel resellerRevenueShare = ce.getBrokerPriceModel();
            assertNotNull(resellerRevenueShare);
            assertEquals(new BigDecimal("100.00"), resellerRevenueShare.getRevenueShare());

            List<DomainHistoryObject<?>> brokerRevenueHistories =
                ds.findHistory(brokerRevenueShare);
            assertEquals(2, brokerRevenueHistories.size());
            assertEquals(ModificationType.MODIFY, brokerRevenueHistories.get(1).getModtype());

            List<DomainHistoryObject<?>> resellerRevenueHistories =
                ds.findHistory(resellerRevenueShare);
            assertEquals(2, resellerRevenueHistories.size());
            assertEquals(ModificationType.MODIFY, resellerRevenueHistories.get(1).getModtype());
            return null;
          }
        });
  }