Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 27 Next »

Front-end

Say we have the following order:

With this improvements, we want to split the amount of the delivery fee into two fields:

  • delivery fee and management fee.

Similar to what we have in the current app (airtouch):

  • gastos de envio → delivery fee

  • otros gastos → management fee

FE tech discovery can be found here

Mapping of how delivery fee is set (BE):

  • PriceOrder

    • Calls partner to get price related info including fees.

    • Persists fees into the database

  • GetOrder

    • Retrieves order related info from the database, including fees

Backend discovery

  • priceOrder

    • intl-whitelabel-app → priceOrder

    • intl-whitelabel-graphql → priceOrder

    • intl-fullfilment-service → priceOrder

      • updateDeliveryEntry

        • intl-delivery-service

        • getFeeAndDiscountByBrand ( using intl-packages delivery lib or intl-delivery-service?)

  • Delivery fees are managed by the fee service ( intl-delivery-service):

    • getFeeAndDiscountByBrand

      • getFeeChargeByTier

        • It get the values from launchdarkly based on the service mode.

          • If catering , it uses tiered-catering-delivery-fees

          • Otherwise, it uses tiered-delivery-fees

        • Searches the tier list from highest to lowest key, stopping when requestedAmountCents exceeds that tier.

        • Said that, we can to analyze the following "return” to propose the management fee. Apart from that, looks like Launchdarkly existing configuration (variations) were thought to enable "free delivery” and we can leverage this approach.

              return {
                baseDeliveryFee: fee, --> LD fee
                deliverySurchargeFee, -->  LD expandedFees (based on delivery quotation value)
                discount, --> LD discount
                fee: fee + geographicalFee + serviceFee + smallCartFee + deliverySurchargeFee,
                geographicalFee, --> LD geographicalFee
                serviceFee, --> Calculated with LD serviceFeePercent of the requested amount
                smallCartFee, --> LD smallCartFee
              };

 launchdark config example (dev)

{
"0": {
"app": {
"discount": 0,
"expandedFees": {
"460": 0,
"560": 0,
"825": 265,
"999": 265,
"default": 0
},
"fee": 399,
"serviceFeePercent": 0,
"smallCartFee": 250
},
"googleFoodOrdering": {
"discount": 0,
"fee": 0,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"kiosk": {
"discount": 0,
"fee": 0,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"web": {
"discount": 0,
"expandedFees": {
"460": 0,
"560": 0,
"825": 265,
"999": 265,
"default": 0
},
"fee": 399,
"serviceFeePercent": 0,
"smallCartFee": 250
}
},
"1000": {
"app": {
"discount": 0,
"expandedFees": {
"460": 0,
"560": 0,
"825": 265,
"999": 265,
"default": 0
},
"fee": 399,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"googleFoodOrdering": {
"discount": 0,
"fee": 0,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"kiosk": {
"discount": 0,
"fee": 0,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"web": {
"discount": 0,
"expandedFees": {
"460": 0,
"560": 0,
"825": 265,
"999": 265,
"default": 0
},
"fee": 399,
"serviceFeePercent": 0,
"smallCartFee": 0
}
},
"2000": {
"app": {
"discount": 0,
"expandedFees": {
"460": 0,
"560": 0,
"825": 265,
"999": 265,
"default": 0
},
"fee": 399,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"googleFoodOrdering": {
"discount": 0,
"fee": 0,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"kiosk": {
"discount": 0,
"fee": 0,
"serviceFeePercent": 0,
"smallCartFee": 0
},
"web": {
"discount": 0,
"expandedFees": {
"460": 0,
"560": 0,
"825": 265,
"999": 265,
"default": 0
},
"fee": 399,
"serviceFeePercent": 0,
"smallCartFee": 0
}
}
}

  • Going further in priceOrder (fulfillment), it reaches the applyQuote service

    • await this.quotesApi.applyQuote(applyQuoteParameters);

      • /api/v1/quotes/apply

    • intl-delivery-service

      • return this.service.enqueueApplyQuoteNotification(request);SQS_APPLY_QUOTE_QUEUE_URL / SNS_QUOTE_TOPIC_ARN

  • Here, the services are decoupled. Therefore, there is a lambda function that listens to the apply quote queue and handles it.

    • intl-delivery-service

      • on-apply-quote Lambda

      • return quoteService.applyQuote(message);

      • async applyQuote(request: ApplyQuoteRequestDto): Promise<ApplyQuoteResponseDto> {

      • getFees

As result, zeroed fees are being set. See cloud watch logs from lambda function.

*The quotedFee comes from partners. In Iberia, it comes from DMP, aka: intl-partners-delivery. But it depends on the market. DMP also uses launchdarkly to calculate the fee. It doesn’t get the other fees.

Once we get these fees (including the zeroed one), intl-delivery-service sends the result to

  • SNS: dev-plk-delivery-quote-outcome

    • SQS: aws-rbi-dev-plk-apply-delivery-service-quote

      • Lambda: sls-rbi-dev-plk-orders-delivery-service-apply-quote ( intl-orders-service)

        • Which get the message and updates the current order in the database (dynamodb)


BE Proposal

  • Enhance this lambda function (dev-plk-delivery-on-apply-quote) to not overwrite discount and service fees with zeroes. It should keep the value from launchdarkly.

  • Configure launchdarkly to fit business needs enabling FE to show fees and discounts properly.

    • discount <> 0

    • serviceFee <> 0

    • fee <> 0


Proposal validation with transactions team:

https://rbidigital.slack.com/archives/C04D0V74P0D/p1702672116251489

Note: The calls to the BE in priceOrder is executed through gateway. A double-check is desirable to ensure that graphql flow is not impacted.

FE impacts

When discount, fee and service fee come to FE, intl-whitelabel-app can be changed to display FREE fees as according to UX (figma). The design screens should be adapted to consider them accordingly. In such case, depending on the launchdarkly config ( fee tier), we may have a different value for fee, service and discount. In principle, to minimize BE impacts, we may continue using a single field for discount. It’s up to the FE display "FREE” for the related use-cases. E.g:

  • discount == fee + servicefee

    • FREE fee

    • FREE service fee

  • discount == fee, but discount < fee+servicefee

    • FREE fee

    • X.XX service fee

  • discount < fee

    • X.XX fee

    • X.XX service fee

  • Other configurations may not be supported


Feature control

As usual the activation of this feature should be done using LD feature flag in both FE and BE. Later it can leverage a new sanity config (toogle) under guest checkout.

Enhancements

  • Since, in the future, we may have partners who calculates delivery fees not only based on LD, we can have an additional config for FREE delivery fee / FREE delivery service fee, where BE (intl-delivery-service) would override LD values - meaning that discount can be set with the same amount of the fee or fee + service fee.


Architecture

In partners service, create quote flow calls both in delivery : quote_create and quote_apply

Configured webhooks*:

 Integration for store 1111 (zaragoza) - exists dev DELIVERY_QUOTE_CREATE and fallback(DELIVERY_QUOTE)
{
  "integrationId": "a6e48415-ff02-44e9-bba3-ae9918e0cac1",
  "partnerId": "2acdd610-fad8-4acc-a030-eee340041a8c",
  "secret": "$3cr3t",
  "stores": [
    {
      "country": "ES",
      "storeId": "005484"
    },
    {
      "country": "ES",
      "storeId": "1111"
    },
    {
      "country": "ES",
      "storeId": "13769"
    },
    {
      "country": "ES",
      "storeId": "2222"
    },
    {
      "country": "ES",
      "storeId": "60000"
    }
  ],
  "webhooks": [
    {
      "type": "DELIVERY_CREATE",
      "url": "https://euw3-dev-plk-partners-delivery.rbictg.com/api/v1/ES/PLK/orders"
    },
    {
      "type": "DELIVERY_QUOTE_APPLY",
      "url": "https://euw3-dev-plk-partners-delivery.rbictg.com/api/v1/ES/PLK/quotes/apply"
    },
    {
      "type": "DELIVERY_QUOTE_CREATE",
      "url": "https://euw3-dev-plk-partners-delivery.rbictg.com/api/v1/ES/PLK/quotes"
    },
    {
      "type": "MENU_PRICES_AVAILABILITY_UPDATE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/menu/menu/version?mock_secret=$3cr3t"
    },
    {
      "type": "ORDER_COMMIT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/orders/commit?mock_secret=$3cr3t"
    },
    {
      "type": "ORDER_FIRE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/orders/fire?mock_secret=$3cr3t"
    },
    {
      "type": "ORDER_PRICE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/orders/price?mock_secret=$3cr3t"
    },
    {
      "type": "STORE_SUPPORT_TICKET_EVENT",
      "url": "https://euw3-dev-plk-partners-delivery.rbictg.com/api/v1/ES/PLK/complaints"
    }
  ]
}
 Integration for store 3385 (fuenlenbrada) - exists mocked DELIVERY_QUOTE - returning hard coded fee value
{
  "integrationId": "e5ef1f71-caa0-4ba8-888f-4d937b64f50f",
  "partnerId": "7425a4c0-f5bb-4f10-9bf0-6918b319525a",
  "secret": "4b26e43f0d7c7a51fbc6581d33549921",
  "stores": [
    {
      "country": "ES",
      "storeId": "3385"
    }
  ],
  "webhooks": [
    {
      "type": "DELIVERY_CREATE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/delivery/create?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "DELIVERY_EVENT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/delivery/events?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "DELIVERY_QUOTE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/delivery/quote?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "GENERAL_SUPPORT_TICKET_EVENT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/tickets/events?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "MENU_EVENT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/menu/events?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "MENU_PRICES_AVAILABILITY_UPDATE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/menu/updated?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "MENU_UPDATED",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/menu/updated?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "ORDER_COMMIT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/orders/commit?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "ORDER_EVENT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/orders/events?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "ORDER_FIRE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/orders/fire?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "ORDER_PRICE",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/orders/price?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "STORE_HEARTBEAT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/stores/status?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "STORE_SUPPORT_TICKET_EVENT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/tickets/events?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    },
    {
      "type": "TICKET_EVENT",
      "url": "https://euw3-dev-plk-mock-partners-integrations.rbictg.com/tickets/events?mock_secret=4b26e43f0d7c7a51fbc6581d33549921"
    }
  ]
}


Possible existing bugs

During this discovery, strange behaviors were detected. They are detailed here

Hints:

How to run local lambdas:

  • Example:

    • yarn start:function on-apply-quote

  • No labels