Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Questions:

  •  N/D

Technical Refinement

Goal

The main objective is to allow the customers to use promo codes at checkout to receive benefits coming from offers.

Front-end refinement

...

From what we understand the current feature at checkout allow promo code just to type CBA offers and this feature is deprecated. More infos: https://rbidigital.slack.com/archives/C04FZ5HTH35/p1693855082030399.

As CBA feature is deprecated we need to change the promo code field to accept loyalty promo codes. (here more details on how to configure the promo code on sanity and voucherify: /wiki/spaces/CG/pages/984973325- OBS.: The documentation explain how configure promo codes to CBA offers and Loyalty Offers, So follow just the loyalty steps.)

After the config, we will have the config offer like this:

...

OBS.: On In-App Benefits there is just one item. If there are more itens, the discount will be the first item.

Acceptance criteria

...

Apply promotional codes at checkout;

  • Same as when the promo code is applied on the offers page;

...

Use the current design of the promotional code field at checkout;

...

Hide the link “View saved promotional“

intl-whitelabel-app

Tasks:

...

title1 - TASK: Create a new promo code flow for loyalty
  • Create a feature flag;

  • The first step to use the loyalty promo code at checkout will be to change the validation promo code flow.

    • On the promo code component field, we will need to add a feature flag:

      • When this flag is enabled: The promo code flow will be LOYALTY OFFER

      • When this flag is disabled: The promo code flow will be CBA OFFER (current flow)

  • We will create a new hook to contain all the rules of this flow

    • We can use the same hook used to offer page flow.

      • intl-whitelabel-app/workspaces/frontend/src/state/loyalty/hooks/use-redeem-promo-codes.ts

...

languagetypescript

...

Questions:

  •  N/D

Technical Refinement

Goal

The main objective is to allow the customers to use promo codes at checkout to receive benefits coming from offers.

Front-end refinement

...

From what we understand the current feature at checkout allow promo code just to type CBA offers and this feature is deprecated. More infos: https://rbidigital.slack.com/archives/C04FZ5HTH35/p1693855082030399.

As CBA feature is deprecated we need to change the promo code field to accept loyalty promo codes. (here more details on how to configure the promo code on sanity and voucherify: /wiki/spaces/CG/pages/984973325- OBS.: The documentation explain how configure promo codes to CBA offers and Loyalty Offers, So follow just the loyalty steps.)

After the config, we will have the config offer like this:

...

OBS.: On In-App Benefits there is just one item. If there are more itens, the discount will be the first item.

How to create a config offer and vinculate to a Voucherify voucher

...

intl-whitelabel-app

Acceptance criteria

  • We can’t impact the other markets

  • Apply promotional codes at checkout

    • Same as when the promo code is applied on the offers page

    • Validate the promotional code on voucherify

  • Use the current design of the promotional code field at checkout

  • If the customer has a promo code saved on the offers page, we don’t validate the promo code on voucherify

  • When the checkout page is refreshed, the promo code should continue applied

  • The “apply promotional codes” would follow the sanity rules

  • When the customer uses the promo code, would hides from the offers page

  • This feature just works if the feature flag is enabled

  • Would be possible to apply the promo code on the offers page

  • If the promotional code is removed, must refresh page to request price order again.

Tasks:

const onRemove = () => { ...
Expand
title1 - TASK: Apply a promo code flow for loyalty
  • Create a feature flag

    • ENABLE_LOYALTY_OFFER_PROMO_CODE_AT_CHECKOUT

  • The first step to use the loyalty promo code at checkout will be to change the validation promo code flow.

    • On the promo code component field, we will need to add a feature flag:

      • When this flag is enabled: The promo code flow will be LOYALTY OFFER

      • When this flag is disabled: The promo code flow will be CBA OFFER (current flow)

  • Where the new logic can be (two options):

    • A new hook to contain all the rules of this flow

      • The should be in app/workspaces/frontend/src/state/loyalty/hooks/use-redeem-promo-code-checkout

    • We can use the same hook used to offer page flow.

      • intl-whitelabel-app/workspaces/frontend/src/state/loyalty/hooks/use-redeem-promo-codes.ts

Code Block
languagetypescript
const onSubmitLoyaltyPromoCode = useCallback(async () => {
    setPromoCodeValidationLoading(true)

    // const loyaltyId = 'ec5cec01-b41b-509b-9111-310ab5a18154'

    let event = createRbiApplyPromoCodeEvent(promoCodeInput, 'Successful')
    const personalizedOffer = await redeemMutation(user?.loyaltyId || '', promoCodeInput)
      .catch((e: PromoCodeError) => {
    if (appliedOfferPromoCode?.loyaltyEngineId) {    const reason = buildErrorMessageFromPromoCodeError(e)
        constsetPromoCodeErrorMessageId(
standardOffersLimit =         earningCalculationData?.EarningCalculation?.offerRedemptionLimits?.standardOffersLimit(reason as TPromoCodeErrorMessageIds) || PromoCodeErrorMessageIds.default
1;        dispatch(actions.loyalty.setSelectedOffer(appliedOfferPromoCode));

     dispatch(actions.loyalty.setAppliedOffers([appliedOfferPromoCode]));   logger.error(`Error validating promo   if (isDiscountLoyaltyOffer(appliedOfferPromoCode)code ${e}`)
{        event // If limit of offers reached remove the first one
= createRbiApplyPromoCodeEvent(promoCodeInput, 'Failed', e.message)
      })
       if (appliedOffers?.length >= standardOffersLimit) {.finally(() => {
        setPromoCodeValidationLoading(false)
   removeFromCart({ cartId: appliedOffers[0].cartId });

    trackEvent(event)

  }  if (personalizedOffer) {
     //Discount offers should not show menu item detailsawait handleRedemption(personalizedOffer)

      // clear promo code input & dispatch(error message
      setPromoCodeErrorMessageId(null)
  actions.loyalty.applyOffer({    setPromoCodeInput('')

      toast.success(formatMessage({ id: appliedOfferPromoCode.loyaltyEngineId,'offerAddedToCart' }))
    }
  }, [
   type: OfferType.GLOBALformatMessage,
    handleRedemption,
    promoCodeInput,
  isStackable: appliedOfferPromoCode.isStackable  redeemMutation,
    trackEvent,
    user?.loyaltyId,
  ])
  isSurprise:
isSurpriseOffer(appliedOfferPromoCode),  
   useEffect(() => {
    cmsId:if (appliedOfferPromoCode?._id,loyaltyEngineId) {
      const standardOffersLimit =
  cartId: 'discount-offer',     earningCalculationData?.EarningCalculation?.offerRedemptionLimits?.standardOffersLimit || 1

  })    dispatch(actions.loyalty.setSelectedOffer(appliedOfferPromoCode))
    );  dispatch(actions.loyalty.setAppliedOffers([appliedOfferPromoCode]))

   }   if     dispatch(actions.loyalty.setCmsOffers([appliedOfferPromoCode](isDiscountLoyaltyOffer(appliedOfferPromoCode)); {
     return;   // If }limit of offers reached remove  dispatch(actions.loyalty.setSelectedOffer(null));
the first one
   dispatch(actions.loyalty.setAppliedOffers([]));     if dispatch(actions.loyalty.setCmsOffers([]));appliedOffers?.length >= standardOffersLimit) {
      // eslint-disable-next-line react-hooks/exhaustive-deps   }, [appliedOfferPromoCode]);

Attention points:

  1. We need to apply (dispatch) the personalised offer on some contexts:

    1. actions.loyalty.setSelectedOffer(personalizedOffer)

    2. actions.loyalty.setAppliedOffers

    3. actions.loyalty.applyOffer

    4. actions.loyalty.setCmsOffers

OBS.: It’s possible we need to apply the offer in another context too.

  1. When we click on remove in offer info (after applying the offer), we need to remove the offer in all contexts.

    Image Removed
  2. When the customers reload the page, the offer must continue applied.

  3. Verify the need for other validations

With this update, the frontend is prepared to apply the promo code to loyalty.

Image Removed
Expand
title2 - TASK: Updated action Remove button

We will need to update the button action to remove the applied offer on loyalty.offers.cmsOffers

  • path: intl-whitelabel-app/workspaces/frontend/src/state/global-state/models/loyalty/offers/offers.slice.ts

    Code Block
    languagetypescript
    removeCmsOffers: (state, { payload }: PayloadAction<LoyaltyOffer>) => {
      state.cmsOffers = state.cmsOffers.filter(offer => offer._id !== payload._id);
    },
  • path: intl-whitelabel-app/workspaces/frontend/src/pages/cart/your-cart/cart-offer.tsx

    Code Block
    languagetypescript
    removeFromCart({ cartId: appliedOffers[0].cartId })
            }
    
            //Discount offers should not show menu item details
            dispatch(
              actions.loyalty.applyOffer({
                id: appliedOfferPromoCode.loyaltyEngineId,
                type: OfferType.GLOBAL,
                isStackable: appliedOfferPromoCode.isStackable,
                isSurprise: isSurpriseOffer(appliedOfferPromoCode),
                cmsId: appliedOfferPromoCode._id,
                cartId: 'discount-offer',
              })
            )
          }
    
          dispatch(actions.loyalty.setCmsOffers([appliedOfferPromoCode]))
          return
        }
    
        dispatch(actions.loyalty.
    removeCmsOffers
    setSelectedOffer(
    selectedLoyaltyOffer
    null))
    ; };
    • OBS.: Change also:

      • path: intl-whitelabel-app/workspaces/frontend/src/state/global-state/models/loyalty/loyalty.actions.ts

    Expand
    title3 - TASK: Hide CBA Options
    • We will need to hide the CBA option to ensure that anything CBA option shows.

      Image Removed
      • Then, we will create a new attribute to hide this option;

        • This attribute value can be the opposite of the value of feature flag (flag created on task 1)

          Image Removed
    Expand
    title4 - TASK: Apply discount again if not used
    • Currently, we don’t have the validated voucher flow on whitelabel-app and voucherify, Just the burn voucher flow when we applied the promo code.

    • When we applied the promo code, the offer get saved on the offers page.

      • So, We need to validate the offers saved and compare the promo code added on the field to offers saved before validating the promo code on voucherify.

        • If we have a promo code saved, we will apply the offer without validating voucherify.

        • If we don’t have one, we will validate the promo code with voucherify;

    Expand
    title5 - TASK: Clean the applied offer when finished the order
    When finish the order, we need to clean the offers on cookies, sessions, etc.
    
        dispatch(actions.loyalty.setAppliedOffers([]))
        dispatch(actions.loyalty.setCmsOffers([]))
    
        // eslint-disable-next-line react-hooks/exhaustive-deps
      }, [appliedOfferPromoCode])

    The code above was developed in the PoC and is a new code.

    Attention points:

    1. We need to apply (dispatch) the personalised offer on some contexts:

      1. actions.loyalty.setSelectedOffer(personalizedOffer)

      2. actions.loyalty.setAppliedOffers

      3. actions.loyalty.applyOffer

      4. actions.loyalty.setCmsOffers

    OBS.: It’s possible we need to apply the offer in another context too.

    1. When we click on remove in offer info (after applying the offer), we need to remove the offer in all contexts.

      Image Added
    2. When the customers reload the page, the offer must continue applied.

    3. Verify the need for other validations

    4. If the user is not authenticated we need to ask for the login

      1. The behavior will be the same as we have on offers page

    With this update, the frontend is prepared to apply the promo code to loyalty.

    Image Added
    Expand
    title2 - TASK: Updated action Remove button
    • We will need to update the button action to remove the applied offer on loyalty.offers.cmsOffers

      • path: intl-whitelabel-app/workspaces/frontend/src/pagesstate/order-confirmation/order-confirmation.tsxglobal-state/models/loyalty/offers/offers.slice.ts

        Code Block
        languagetypescript
    useEffect(() =>
      • removeCmsOffers: (state, { payload }: 
    if (!loading && !orderErrors)
      • PayloadAction<LoyaltyOffer>) => {
          state.cmsOffers = 
    dispatch(actions
      • state.
    loyalty
      • cmsOffers.
    setSelectedOffer(null)); dispatch(actions.loyalty.setAppliedOffers([]));
      • filter(offer => offer._id !== payload._id)
        },
      • path: intl-whitelabel-app/workspaces/frontend/src/pages/cart/your-cart/cart-offer.tsx

        Code Block
        languagetypescript
        const onRemove = () => {
          ...
          dispatch(actions.loyalty.
    setCmsOffers
      • removeCmsOffers(
    []
      • selectedLoyaltyOffer))
    ;
      • 
        
    } }, [dispatch, loading, orderErrors]);

    intl-partners-service (backend)

    After applying the Whitelabel will do a call to the backend to calculate the discount value:

    ...

    How is the calculation done?

    So basically, we need to send (via slack) to Winrest the offers sanityId.

    They register these sanityId on their system and after that, always we use some offers with these sanityId registered, Winrest will return the calculation offers correctly.

    Example:

    To use the offer Test: Test Discount Offer (Sanity DEV)

    Solution proposal

    • Currently, we already sent the sanityId offer to the backend (intl-partners-service);

      Image Removed
    • Then, we need to send the discount information to Winrest;

      • With the sanityId that we have, we will find the discount values by getOffers(sanityId: string)

        • path: intl-partners-service/src/modules/orders/cart-total.service.ts

    • We will add a new attribute orderDiscounts on the webhook payload;

    Note

    We will send it to Winrest always in percentage (requested to Winrest, 'cause will be easier for them);

    ...

    The orderDiscounts object would be in each cart object;

    If the discount is amount type, we will transform it to percentage type;

    E.g: If the total cart is 10 euros and amount discount is 5 euros;

    We will calculate the discount:

    Code Block
    discount = (100 * 5) / 100;
    discount = 50%;

    Tasks:

    Expand
    title1 - TASK: Create a method to calculate the percentage offer;
  • Create a feature flag;

  • Create a method to calculate the percentage offer.

  • path: intl-partners-service/src/modules/orders/orders.service.ts

  • We will send the discount values per cart item to Winrest, but the calculation of the discount percentage will be based on the cart total, which will be easier to calculate and in the end will have the same result if we calculate the discount per item.

  • The method will receive two params:

    • appliedOffers: IAppliedOffer[] | null | undefined

      • Offer applied on the cart;

        Image Removed
    • total: number | undefined

      • total cart value;

  • The method return will be:

    • Promise<IOrderDiscounts[] | undefined>

      • Where the IOrderDiscounts.type will be always a percentage;

  • To discover the discount values we will need to use the method getOffers

    • path: intl-partners-service/src/modules/orders/cart-total.service.ts

    • This method is private, so we will update it to public;

  • If the discount offer is a type amount we will calculate the percentage over the total cart value;

  • E.g: If the total cart is 10 euros and amount discount is 5 euros;

    • We will calculate the discount:

      Code Block
      discount = Math.round((5 * 100) / 10)
      discount = 50%; 
  • So the payload will be:

    Code Block
    languagejson
    "orderDiscounts": [
      {
        "type": "percentage",
        "value": 50
      }
    ]
  • payload

  • Code Block
    languagejson
    {
      "callbackUrl": "https://euw3-dev-plk-partners-api.rbictg.com/api/v1/orders/84b5f1df-28df-4e6f-a871-a2783602436f/price/callback",
      "cart": {
        "menuSelections": [
          {
            "externalReferenceId": "800853",
            "id": "f9f5b02e-bee8-4dd1-a5fa-222b79516a98",
            "menuSelections": [
              {
                "externalReferenceId": "800852",
                "id": "item_67167",
                "menuSelections": [],
                "price": {
                  "amount": 679,
                  "currency": "EUR"
                },
                "quantity": 1,
                "orderDiscounts": [
                  {
                    "type": "percentage",
                    "value": 50
                  }
                ]
              },
              {
                "externalReferenceId": "940151",
                "id": "item_50929",
                "menuSelections": [],
                "price": {
                  "amount": 0,
                  "currency": "EUR"
                },
                "quantity": 1,
                "orderDiscounts": [
                  {
                    "type": "percentage",
                    "value": 50
                  }
                ]
              },
              {
                "externalReferenceId": "940180",
                "id": "item_66018",
                "menuSelections": [],
                "price": {
                  "amount": 1500,
                  "currency": "EUR"
                },
                "quantity": 1,
                "orderDiscounts": [
                  {
                    "type": "percentage",
                    "value": 50
                  }
                ]
              },
              {
                "externalReferenceId": "940325",
                "id": "45adf5bb-2f3d-4c40-a735-cf59d5a661ef",
                "menuSelections": [],
                "price": {
                  "amount": 0,
                  "currency": "EUR"
                },
                "quantity": 1,
                "orderDiscounts": [
                  {
                    "type": "percentage",
                    "value": 50
                  }
                ]
              }
            ],
            "price": {
              "amount": 1100,
              "currency": "EUR"
            },
            "quantity": 1,
            "orderDiscounts": [
              {
                "type": "percentage",
                "value": 50
              }
            ]
          }
        ]
      },
      "channel": "WHITELABEL_IN_STORE",
      "fees": [],
      "id": "84b5f1df-28df-4e6f-a871-a2783602436f",
      "instructions": [],
      "serviceMode": "TAKEOUT",
      "storeId": "1111"
    }
    Expand
    title3 - TASK: Show only promo code input
    • We need to render only the input for the promotional code instead of the collapse structure if our flag is ON

      • Before

        image-20240104-152340.pngImage Added

      • After our change (with our flag ON)

        image-20240104-151214.pngImage Added

    • Raphael Ferreira Gomes said that when the component is expanded some events are dispatched to mParticle. We need to validate what will happen now that the component will be loaded in the screen without the collapse. He recommended that we need to talk with Manuel (Manuel Rodrigues da Silva) to understand if this will be a problem and what’s expect for the events part ← To be validate during development

      • Do we need to fire events if the component is already rendered in the screen?

    Expand
    title4 - TASK: Apply discount again if not used - NOT FOR NOW

    This task is not for now. We’ll develop a PoC and validate the ideas first

    • Currently, we don’t have the validated voucher flow on whitelabel-app and voucherify, Just the burn voucher flow when we applied the promo code.

    • When we applied the promo code, the offer get saved on the offers page.

      • So, We need to validate the offers saved and compare the promo code added on the field to offers saved before validating the promo code on voucherify.

        • If we have a promo code saved, we will apply the offer without validating voucherify.

        • If we don’t have one, we will validate the promo code with voucherify

    • When have the promo code information on file:

      • path: intl-whitelabel-app/workspaces/frontend/src/pages/loyalty/loyalty-offers/loyalty-offers.tsx

        Code Block
        languagetypescript
        const { sortedTilesAndOffers, marketingTileTop, marketingTileBottom } =
          useOffersPageMarketingTiles({
            offers,
            offersPageMarketingTiles: marketingTiles,
            selectedOffer: selectedIncentive || null,
          })
      • On object sortedTilesAndOffers

        Image Added

    Important: We don’t have the POC to this task

    Expand
    title5 - TASK: Clean the applied offer when finished the order - MOVED TO ANOTHER TASK

    This task was moved to another task

    This task was moved to another task as this objective conflicts with we’ll do in the

    Jira Legacy
    serverSystem JIRA
    serverId255417eb-03fa-3e2f-a6ba-05d325fec50d
    keyIBFEC-1419


    Important (BLOCKED): apparently this flow changed in the current app and the result was not what Rodrigo showed in the screenshots below (redeem in restaurant modal). We don’t have enough time during the A&D to go deep on this. We can talk with de Sousa Santos, Rodrigo to understand better what code we should base in.

    There is a feature flag that limits what kind of modal should be shown: ENABLE_IMPROVED_SIMPLIFIED_REDEEM_IN_RESTAURANT_STATIC_OFFERS

    With this flag on, we won’t have a close modal button like the one below:

    Image Added

    And when it’s turned on it will be shown as below:

    Image Added

    • When finish the order, we need to clean the offers on cookies, sessions, etc.

      • path: intl-whitelabel-app/workspaces/frontend/src/pages/order-confirmation/order-confirmation.tsx

      • Suggestion of PoC code: Instead of clear each state using a set function (showed in the PoC code below) we can improve this creating new slices to handle with the data clear:

        • selectedOffer state → We can create a new slice to clear/reset this state

        • appliedOffers state → We can reuse the resetAppliedOffers() slice that already exists to clear/reset this state instead of set an empty array

        • cmsOffers state → We can create a new slice to clear/reset this state

        • As last resource we can create a new slice to clear all the data related to the applied offer

    Code Block
    languagetypescript
    useEffect(() => {
      if (!loading && !orderErrors) {
        dispatch(actions.loyalty.setSelectedOffer(null))
        dispatch(actions.loyalty.setAppliedOffers([]))
        dispatch(actions.loyalty.setCmsOffers([]))
      }
    }, [dispatch, loading, orderErrors])

    • After the order is finished, we need to apply the sanity rules too, for example:

      • If the number used voucher is 1, after the order, the offer should be removed from the offer page

        Image Added
      • we can use the same logic on the component OfferRedemptionModal

        • path: intl-whitelabel-app/workspaces/frontend/src/components/offer-redemption-modal/index.tsx

        • When we click on Redeem in Restaurant

          Image Added
        • Will show the modal and if we click on the close button, the offers will removed on the offer page. So we can use the same logic:

          Image Added
      • OBS: This relation between offer x customer, probably is saved on dynamoBD

        • We can find the answer on intl-promotion-service repository, from redeemCoupon method flow

    intl-partners-service (backend)

    After applying the Whitelabel will do a call to the backend to calculate the discount value:

    ...

    How is the calculation done?

    So basically, we need to send (via slack) to Winrest the offers sanityId.

    They register these sanityId on their system and after that, always we use some offers with these sanityId registered, Winrest will return the calculation offers correctly.

    Example:

    To use the offer Test: Test Discount Offer (Sanity DEV)

    Solution proposal

    • Currently, we already sent the sanityId offer to the backend (intl-partners-service)

      Image Added
    • Then, we need to send the discount information to Winrest

      • With the sanityId that we have, we will find the discount values by getOffers(sanityId: string)

        • path: intl-partners-service/src/modules/orders/cart-total.service.ts

    • We will add a new attribute orderDiscounts on the webhook IWebhookPriceOrder payload

    Acceptance criteria

    • We can’t impact the other markets

    • If there is an offer applied on the “input cart“, we need to send the discount to Winrest

    Tasks:

    Expand
    title6 - TASK: Send to orderDiscount to Winrest
    • Create a feature flag in Tech Platform

      • ENABLE_LOYALTY_OFFER_PROMOCODE_AT_CHECKOUT

      • Set settings env, brand, marketing

    image-20240103-190008.pngImage Added
    • Should enable SDK settings

      image-20240103-190117.pngImage Added

    • Update mapOrderDiscounts method to return the offer discount also.

      • path: intl-partners-service/src/modules/orders/orders.service.ts

      • method name: mapOffersDiscounts

    Expand
    title2 - TASK: Update the calculated total card;
    • Currently, the total cart is calculated the all item values including the offers configs, so we need to remove the discount offers config this calc;

      • path: intl-partners-service/src/modules/orders/cart-total.service.ts

      • method: calculate(cart: ICart)

    • We will refactor this method abstracting the logic into two parts because we will need just the part of the method code to this flow. But we can’t change the calculate(cart: ICart) because it is used in other flows. Then, we will create a new method.

    • As the POC method public calculateTotalCart(cart: ICart)

    Expand
    title3 - TASK: Add the discount on the order;
    • We will use all methods created above (mapOffersDiscounts and calculateTotalCart):

      • path: intl-partners-service/src/modules/orders/orders.service.ts

    • On method public async price(input: IPriceOrderRequest):

      • We will import the attribute appliedOffers on object input.cart;

      • We will protect the code with feature flag here;

      • We will calculate the total cart without possible discounts (calculateTotalCart) and use the method mapOffersDiscounts to create the object with percentage discount:

        Code Block
        languagetypescript
        let discountsOffer;
        if (FEATURE_FLAG && appliedOffers?.length) {
          const totalCart = this.cartTotalService.calculateTotalCart(input.cart);
          discountsOffer = await this.mapOffersDiscounts(appliedOffers, totalCart);
        }
        
      • We will add the variable orderDiscounts on attribute orderDiscounts from newOrder object;

        Image Removed
    const verifyDiscountTypes = (cartEntry: ICartEntry): boolean => { return ( cartEntry.type !== CartEntryType.offerDiscount && cartEntry.type !== CartEntryType.offerCombo && cartEntry.type !== CartEntryType.offerItem ); };

  • Create function to get LaunchDarkly.

    • image-20240103-190754.pngImage Added

  • In the line 328 we should validate flag ENABLE_AT_LOYALTY_OFFER_CHECKOUT

    Image AddedImage Added
  • To discover the discount values we will need to use the method getOffers

    • path: intl-partners-service/src/modules/orders/cart-total.service.ts

    • This method is private, so we will update it to public

  • After that, we will send the discount to Winrest via IWebhookPriceOrder adding the orderDiscounts

    Image Added
  • Payload will be:

  • Expand
    title4 - TASK: Send the new discount object to Winrest
    • We will need to send the new discount attribute to Winrest by webhook:

      Image Removed
    • Then, we will add the new attribute on mapper mapRbiCart;

    • So we will add the variable discountsOffer to mapRbiCart: mapRbiCart(pricingCart, discountsOffer);

      • In this method, we will add a new condition to send the discount values:

        Image Removed
        Code Block
        languagetypescript
        if (FEATURE_FLAG && orderDiscounts?.length && verifyDiscountTypes(cartEntry)) {
          result.orderDiscounts = orderDiscounts;
        }
      • Where, the verifyDiscountTypes method verify item type of the cart that there will be a discount because the types (CartEntryType.offerDiscount, CartEntryType.offerCombo, CartEntryType.offerItem) are already the offer of an item;

    Code Block
    languagejson
    Code Block
    languagejson
    {
      "callbackUrl": "https://euw3-dev-plk-partners-api.rbictg.com/api/v1/orders/84b5f1df-28df-4e6f-a871-a2783602436f/price/callback",
      "cart": {
        "menuSelections": [
          {
            "externalReferenceId": "800853",
            "id": "f9f5b02e-bee8-4dd1-a5fa-222b79516a98",
            "menuSelections": [
              {
                "externalReferenceId": "800852",
                "id": "item_67167",
                "menuSelections": [],
                "price": {
                  "amount": 679,
                  "currency": "EUR"
                },
                "quantity": 1
              }
            ],
            "price": {
              "amount": 1100,
              "currency": "EUR"
            },
            "quantity": 1
          }
        ]
      },
      "channel": "WHITELABEL_IN_STORE",
      "fees": [],
      "id": "84b5f1df-28df-4e6f-a871-a2783602436f",
      "instructions": [],
      "serviceMode": "TAKEOUT",
      "storeId": "1111",
      "orderDiscounts": [
        {
          "type": "percentage", // or amount
          "value": 50
        }
      ]
    }

    Screenshots

    • N/A

    POC

    Impact Analysis

    • N/A

    Dependencies

    ...