Questions:
...
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
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 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.
...
Expand |
---|
title | 1 - TASK: Apply a promo code flow for loyalty |
---|
|
Code Block |
---|
| 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) => {
const reason = buildErrorMessageFromPromoCodeError(e)
setPromoCodeErrorMessageId(
(reason as TPromoCodeErrorMessageIds) || PromoCodeErrorMessageIds.default
)
logger.error(`Error validating promo code ${e}`)
event = createRbiApplyPromoCodeEvent(promoCodeInput, 'Failed', e.message)
})
.finally(() => {
setPromoCodeValidationLoading(false)
})
trackEvent(event)
if (personalizedOffer) {
await handleRedemption(personalizedOffer)
// clear promo code input & error message
setPromoCodeErrorMessageId(null)
setPromoCodeInput('')
toast.success(formatMessage({ id: 'offerAddedToCart' }))
}
}, [
formatMessage,
handleRedemption,
promoCodeInput,
redeemMutation,
trackEvent,
user?.loyaltyId,
])
useEffect(() => {
if (appliedOfferPromoCode?.loyaltyEngineId) {
const standardOffersLimit =
earningCalculationData?.EarningCalculation?.offerRedemptionLimits?.standardOffersLimit || 1
dispatch(actions.loyalty.setSelectedOffer(appliedOfferPromoCode))
dispatch(actions.loyalty.setAppliedOffers([appliedOfferPromoCode]))
if (isDiscountLoyaltyOffer(appliedOfferPromoCode)) {
// If limit of offers reached remove the first one
if (appliedOffers?.length >= standardOffersLimit) {
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.setSelectedOffer(null))
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:We need to apply (dispatch) the personalised offer on some contexts: actions.loyalty.setSelectedOffer(personalizedOffer)
actions.loyalty.setAppliedOffers
actions.loyalty.applyOffer
actions.loyalty.setCmsOffers
OBS.: It’s possible we need to apply the offer in another context too. When we click on remove in offer info (after applying the offer), we need to remove the offer in all contexts. When the customers reload the page, the offer must continue applied. Verify the need for other validations If the user is not authenticated we need to ask for the login 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. |
...
Expand |
---|
title | 3 - 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 Raphael Ferreira Gomes said that when the component is expanded some events are dispatched to mParticle. We need to validate what will happen if the component loads already expanded. now that the component will be loaded in the screen without the collapse. He recommended that we need to talk with Manuel (Ramon Manuel LuceroRodrigues da Silva) to understand if this will be a problem and what’s expect for the events part ← To be validate during development
|
Expand |
---|
title | 4 - 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. When have the promo code information on file:
Important: We don’t have the POC to this task |
Expand |
---|
title | 5 - TASK: Clean the applied offer when finished the order - BLOCKED |
---|
| Important (BLOCKED): apparently this flow changed in the current app and the |
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 |
---|
server | System JIRA |
---|
serverId | 255417eb-03fa-3e2f-a6ba-05d325fec50d |
---|
key | IBFEC-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. Image Removedenough 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 AddedAnd when it’s turned on it will be shown as below: Image Added Code Block |
---|
| useEffect(() => {
if (!loading && !orderErrors) {
dispatch(actions.loyalty.setSelectedOffer(null))
dispatch(actions.loyalty.setAppliedOffers([]))
dispatch(actions.loyalty.setCmsOffers([]))
}
}, [dispatch, loading, orderErrors]) |
|
...
Expand |
---|
title | 6 - TASK: Send to orderDiscount to Winrest |
---|
|
Code Block |
---|
| {
"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
}
]
} |
|
...