meta data for this page
  •  

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
sap_hybris_commerce:orders:vouchers_concepts_features [2019/08/27 12:54] – created Antonio Robirosasap_hybris_commerce:orders:vouchers_concepts_features [2019/12/18 20:17] (current) – external edit 127.0.0.1
Line 4: Line 4:
  
 <WRAP center round important 100%> <WRAP center round important 100%>
-This extension is deprecated since SAP Hybris 6.1. You must use the the Promotion Engine for new projects. [[https://help.sap.com/viewer/9d346683b0084da2938be8a285c0c27a/1905/en-US/c844a77cd9674d678ffb5e4534ff136a.html|Promotions (Legacy) vs. Promotion Engine]]+This extension is deprecated since SAP Hybris 6.3. You must use the coupons of the Promotion Engine for new projects. [[https://help.sap.com/viewer/9d346683b0084da2938be8a285c0c27a/1905/en-US/c844a77cd9674d678ffb5e4534ff136a.html|Promotions (Legacy) vs. Promotion Engine]]
 </WRAP> </WRAP>
  
Line 54: Line 54:
 ===== Pitfalls ====== ===== Pitfalls ======
  
-  *  **The voucher uses extensively the jalo layer.** The voucher service delegates the calls to the voucherManager.+  *  **The voucher uses extensively the jalo layer.** Please read the long explanation below. The voucher service delegates the calls to the voucherManager
     * After the redemption or the release the cart is recalculated using the jalo layer (price factory). If you have any custom code in the **calculationService** (like the calculation of special prices or delivery costs), you would have to recalculate the cart or order with the calculation service after calling the voucher service.     * After the redemption or the release the cart is recalculated using the jalo layer (price factory). If you have any custom code in the **calculationService** (like the calculation of special prices or delivery costs), you would have to recalculate the cart or order with the calculation service after calling the voucher service.
     * Your custom voucher restrictions must implement the jalo methods Restriction.isFulfilledInternal(AbstractOrder paramAbstractOrder) and Restriction.isFulfilledInternal(Product paramProduct). This code will stop working if the extension is migrated to the model layer.     * Your custom voucher restrictions must implement the jalo methods Restriction.isFulfilledInternal(AbstractOrder paramAbstractOrder) and Restriction.isFulfilledInternal(Product paramProduct). This code will stop working if the extension is migrated to the model layer.
Line 60: Line 60:
   * **The voucher code is saved separately from the voucher model in the cart.** You would have to call the voucher service to get each one of them. The discount saved in the cart doesn't store the voucher code.   * **The voucher code is saved separately from the voucher model in the cart.** You would have to call the voucher service to get each one of them. The discount saved in the cart doesn't store the voucher code.
   * The serial vouchers only work in the database which generated them. **You cannot import a list of serial vouchers codes into another system**. If you want to use serial vouchers in your integration or unit test you have to generate a voucher code on the fly at the beginning of the test.   * The serial vouchers only work in the database which generated them. **You cannot import a list of serial vouchers codes into another system**. If you want to use serial vouchers in your integration or unit test you have to generate a voucher code on the fly at the beginning of the test.
 +
 +==== Use of the Jalo Layer in the voucher extension ====
 +The Voucher extension hasn't migrated yet to the model layer and the creation, redeem and removal of vouchers depends heavily on Jalo attributes which aren't accessible in the model layer. This means that any custom code you implement for the vouchers will have an akward mix of jalo and model layers calls. There are also some pitfalls you must be aware of.
 +
 +=== Calculation of the cart ======
 +
 +  * After a voucher is redeemed or removed, the voucher extension recalculates the cart using the jalo layer. If you have written your own calculation service, you would have to recalculate the cart again because the voucher extension doesn't call your custom logic but the old price factory class.
 +  * If you have cart with a valid voucher and a product is removed or added or its quantity is changed, the restrictions of the voucher aren't checked. If the restrictions aren't fullfilled, the discount of the voucher isn't applied and you don't get any exception. If you want to remove the voucher from the cart, you would have to recheck if the voucher is applicable to cart and remove the voucher if is not.
 +
 +=== Place Order ======
 +
 +When you clone a cart to create the order, the list of applied voucher codes won't be copied. The field AbstractOrder.appliedVoucherCodes is private. Due to this no accessors are created for the model. Another issue is that vouchers aren't consumed when you copy them to the order.
 +
 +To avoid this issue you have to clone the order from the cart, remove the vouchers and reapply them:
 +<code java>
 +public void transferVouchers(final CartModel cart, final OrderModel order)
 +  {
 +    final Collection appliedVouchers = getAppliedVoucherCodes(cart);
 +    //We remove any voucher discount which may be copied.
 +    removeAllVouchers(order);
 +    for (final String voucherCode : appliedVouchers)
 +    {
 +      redeemVoucher(voucherCode, order);
 +    }
 +  }
 +
 +/**
 +   * Removes all the voucher information from the abstract order. It is used after an order was created from a cart.
 +   *
 +   * @param pAbstractOrderModel
 +   */
 +  private void removeAllVouchers(final AbstractOrderModel pAbstractOrderModel) {
 +    for (DiscountModel aDiscount : pAbstractOrderModel.getDiscounts()) {
 +      if (aDiscount instanceof VoucherModel) {
 +        try
 +        {
 +          removeDiscount(null, pAbstractOrderModel, (VoucherModel)aDiscount);
 +        }
 +        catch (AcmeVoucherNotFoundException e)
 +        {
 +          if (LOG.isDebugEnabled())
 +          {
 +            LOG.debug("Unable to remove the voucher " + aDiscount + " from the list of discount. Ignoring the error.");
 +          }
 +
 +        }
 +      }
 +    }
 +    removeAllAppliedVoucherCodes(pAbstractOrderModel);
 +  }
 +
 +private void removeDiscount(final String pVoucherCode, final AbstractOrderModel pCartModel, final VoucherModel pVoucherModel)
 +      throws AcmeVoucherNotFoundException
 +  {
 +    final List newDiscounts = new ArrayList(pCartModel.getDiscounts());
 +    if (newDiscounts.remove(pVoucherModel))
 +    {
 +      pCartModel.setDiscounts(newDiscounts);
 +    }
 +    else
 +    {
 +      throw new AcmeVoucherNotFoundException("Unable to find the voucher "
 +          + (pVoucherCode == null ? pVoucherModel : "with the code " + pVoucherCode)
 +          + " in the cart.");
 +    }
 +    // We send the changes to the jalo class.
 +    this.modelService.save(pCartModel);
 +  }
 +
 +private void removeAllAppliedVoucherCodes(final AbstractOrderModel pAbstractOrderModel)
 +  {
 +    final AbstractOrder jaloOrder = this.modelService.getSource(pAbstractOrderModel);
 +    jaloOrder.setProperty(
 +          GeneratedVoucherConstants.Attributes.AbstractOrder.APPLIEDVOUCHERCODES, new ArrayList());
 +  }
 +</code>
 +
 +I would prefer to avoid using Jalo, but I can't. This problem is a known issue: [[https://wiki.hybris.com/pages/viewpage.action?pageId=186258194|https://wiki.hybris.com/pages/viewpage.action?pageId=186258194]]
 +
 +=== Serial Vouchers ======
 +
 +The code of the voucher is generated using a cipher and random values stored in the database. Due to this, you cannot reuse the code in another database. If you try to export and import the serial vouchers using Impex, the codes won't work because you cannot export the fields key, alphabet and the secret key. If you would like to use serial vouchers during your integration tests, you would have to create the code on the fly:
 +
 +<code java>
 +String voucherCode = this.getCurrentCase().getVoucherCode();
 +if (voucherCode.length() == 3)
 +{
 +      voucherCode = this.getNewSerialVoucherCode(voucherCode);
 +}
 +</code>
  
 --Based on SAP Hybris 5.3 --Based on SAP Hybris 5.3