@Test
  public void testSingleItemDiscountPromotion() throws Exception {

    final PromotionService promotionService =
        ctx().getBean("promotionService", PromotionService.class);

    MutableShoppingCart shoppingCart = new ShoppingCartImpl();
    shoppingCart.initialise(
        ctx().getBean("amountCalculationStrategy", AmountCalculationStrategy.class));
    final ShoppingCartCommandFactory commands =
        ctx().getBean("shoppingCartCommandFactory", ShoppingCartCommandFactory.class);

    // basic init
    commands.execute(shoppingCart, (Map) singletonMap(ShoppingCartCommand.CMD_SETSHOP, 10));
    commands.execute(
        shoppingCart, (Map) singletonMap(ShoppingCartCommand.CMD_CHANGECURRENCY, "EUR"));

    // create discount promotion
    final Promotion amount50 =
        promotionService.getGenericDao().getEntityFactory().getByIface(Promotion.class);
    amount50.setCode("ORDER_50");
    amount50.setShopCode(shoppingCart.getShoppingContext().getShopCode());
    amount50.setCurrency("EUR");
    amount50.setName("50 off on orders over 200");
    amount50.setPromoType(Promotion.TYPE_ORDER);
    amount50.setPromoAction(Promotion.ACTION_FIXED_AMOUNT_OFF);
    amount50.setEligibilityCondition("shoppingCartItemTotal.priceSubTotal > 200.00");
    amount50.setPromoActionContext("50");
    amount50.setEnabled(true);

    promotionService.create(amount50);

    try {
      // add qualifying items
      Map<String, String> param = new HashMap<String, String>();
      param.put(ShoppingCartCommand.CMD_SETQTYSKU, "CC_TEST4");
      param.put(ShoppingCartCommand.CMD_SETQTYSKU_P_QTY, "2.00");
      commands.execute(shoppingCart, (Map) param);

      assertEquals(1, shoppingCart.getCartItemList().size());

      final CartItem cc_test4 = shoppingCart.getCartItemList().get(0);

      assertEquals("CC_TEST4", cc_test4.getProductSkuCode());
      assertFalse(cc_test4.isPromoApplied());
      assertNull(cc_test4.getAppliedPromo());
      assertEquals("2", cc_test4.getQty().toString());
      assertEquals("123.00", cc_test4.getListPrice().toString());
      assertEquals("123.00", cc_test4.getSalePrice().toString());
      assertEquals("123.00", cc_test4.getPrice().toString());

      assertEquals("246.00", shoppingCart.getTotal().getListSubTotal().toString());
      assertEquals("196.00", shoppingCart.getTotal().getSubTotal().toString());
      assertTrue(shoppingCart.getTotal().isOrderPromoApplied());
      assertEquals("ORDER_50", shoppingCart.getTotal().getAppliedOrderPromo());
    } finally {
      // clean test
      promotionService.delete(amount50);
    }
  }
  /** {@inheritDoc} */
  public void perform(final Map<String, Object> context) {
    final BigDecimal amountOff = getAmountValue(getRawPromotionActionContext(context));
    if (MoneyUtils.isFirstBiggerThanSecond(amountOff, BigDecimal.ZERO)) {
      final MutableShoppingCart cart = getShoppingCart(context);
      final CartItem cartItem = getShoppingCartItem(context);

      // we may have compound discounts so need to use final price
      final BigDecimal promoPrice;
      if (MoneyUtils.isFirstBiggerThanSecond(amountOff, cartItem.getPrice())) {
        promoPrice = MoneyUtils.ZERO;
      } else {
        promoPrice = cartItem.getPrice().subtract(amountOff);
      }

      cart.setProductSkuPromotion(
          cartItem.getProductSkuCode(), promoPrice, getPromotionCode(context));
    }
  }
 /** {@inheritDoc} */
 public BigDecimal testDiscountValue(final Map<String, Object> context) {
   final CartItem cartItem = getShoppingCartItem(context);
   return getDiscountValue(getRawPromotionActionContext(context), cartItem.getSalePrice());
 }