Promotion Badge
Description / Background
In the current system, there is no setting available for users to configure or display ongoing promotion or discount campaigns. This limitation reduces visibility and flexibility in managing promotional strategies. To address this, the system should include a dedicated setting that allows administrators or users to enable and display promotion or discount campaigns as needed.
Objectives
- User can see the promotion badge on the restaurant card on Homepage
- User can see the promotion badge on the restaurant card on Search page
- User can see the promotion badge on the restaurant card on Group Landing page
- User can see the promotion badge on the restaurant card on Store page
- User can see the promotion badge on the price card on Detail package page

- Admin can set the promotion on the edit package promotion section
- If admin set the date is blank, should use the package expiry date (old default setting)

- Admin can set the promotion on dynamic pricing setting on edit package
- The system will pick the highest percentage of the promotion to show
- Restaurant has more than a package that have a badge, should use one of the highest percentage of the badge
- Branch A
- Outlet A → have 20% promotion
- Outlet B → have 40% promotion
- Outlet C → have 60% promotion So, branch A will display the Outlet C that have the highest percentage
- Branch B
- Outlet A → have 20% promotion
- Outlet B → have 40% promotion
- Outlet C → have come 2 pay 1 promotion→ 50% So, branch B will display the Outlet C that have the highest percentage
- Branch A
Scope
restaurant card on homepage, search page, group landing page, store page. price card on package detail page
Sequence Diagram / Flow

ERD

Backend Implementation
- Added the ability to display promotion badges for different pricing types (normal, by party size, by day, holidays).
- Introduced new form elements to handle the promotion badge percentage and display conditions.
- Updated the
validatePricingandsanitizemethods to include promotion badge data. - Added new methods
updatePromotionBadgeDisplay,sanitizePricing,sanitizePackageAttrAttributes,toggleDisplayTopupBadge, andtoggleDisplayTopupBadgeHolidayto handle the promotion badge logic. - Updated to include promotion badge data in the event payload.
- Added
promotion_badgeto the restaurant payload. - Added a new worker
ExpiredPromotionBadgeDynamicPriceWorkerto handle expired promotion badges. - Added a new worker file to handle the expiration of promotion badge dynamic prices.
- Added methods to handle the logic for determining the highest promotion badge.
- The
after_save :delete_duplicatescallback was moved to be after theafter_update :send_update_total_locations_eventcallback. - The
highest_promotion_badgemethod was updated to not requirerestaurant_idsas a parameter. Instead, it calculatesrestaurant_idsinternally based on the presence ofbranch_idorrestaurant_id. - Added a check for
empty_date_pricing_group, which verifies if any pricing groups have a nullend_date. - Updated the return logic to use
pricing_groups.firstonly ifdynamic_price_comemore_payless?andempty_date_pricing_groupare true. - Simplified the
linkattribute by removing the redundant quotes aroundbranch_id. - Modified the
promotion_badgeattribute to callobject.highest_promotion_badgewithout passingrestaurant_idsas a parameter. - Reformatted the
promotion_badgemethod to use dot notation for method chaining. - Changed the logic in
get_comemore_payless_percentageto check forempty_date_pricing_groupsand ensure the correct order of pricing groups. - Added a check to return
nilfor promotion type and text ifhighest_promohas a zero percentage discount. - This prevents returning a promotion badge with a zero discount.
- Updated
promotion_typemethod to usefetch_comemore_payless. - Added
fetch_comemore_paylessmethod to determine active pricing groups. - Adjusted
promotion_textmethod to format text based on the newfetch_comemore_paylessmethod. - Implemented a new
promotion_badgemethod with an option to include percentage. - Introduced helper methods
get_best_promotion,get_promotion_badge_percentage,get_comemore_payless_percentage,get_promotion_type, andpromotion_text. - These methods compute the best discount from badge and
comemore_paylesspromotions and format the text accordingly. - Removed redundant promotion badge methods and cleaned up legacy promotion logic.
- Updated the
get_comemore_payless_percentagemethod to first check for active pricing groups. - Added a fallback to use default pricing groups if no active ones are found but
restaurant_packageshave an activeend_date. - Ensured the query for
comemore paylessis consistent and includes a fallback mechanism. - A new comment was added to ignore
promotion_badge_displayparams. - The
promotion_badge_displayparameter is deleted frompermitted_params[:package_attr_attributes]. - The
generate_gyg_package(package)function is now only called ifparams[:package][:gyg_packages_attributes]is present. - Added a check to include
gyg_packages_paramsinparams[:package][:gyg_packages_attributes]if present.
[
github.com
https://github.com/hungryhub-team/hh-server/pull/6420/files
](https://github.com/hungryhub-team/hh-server/pull/6420/files)
[
github.com
https://github.com/hungryhub-team/hh-server/pull/6448
](https://github.com/hungryhub-team/hh-server/pull/6448)
https://github.com/hungryhub-team/hh-server/pull/6445
[
github.com
https://github.com/hungryhub-team/hh-server/pull/6429/files
](https://github.com/hungryhub-team/hh-server/pull/6429/files)
[
github.com
https://github.com/hungryhub-team/hh-server/pull/6424/files
](https://github.com/hungryhub-team/hh-server/pull/6424/files)
Hybrid Implementation
- Added a new
promotionBadgefield to the GraphQL queries. This field includespromotionTypeandpromotionText. src/assets/icons/icon-come-more-pay-less.png(new image file)src/assets/icons/icon-discount.png(new image file)src/components/common/PromotionBadge.vue(new Vue component for displaying promotion badges)- Integrated the new
PromotionBadgecomponent to display promotion badges in various parts of the UI. - Updated layout and styling to accommodate the new badges.
- Added
promotionBadgeto theFeaturedRestaurantandRestaurantmodels. - Adjusted layout and grid classes to better handle the new promotion badges.
- Updated mappers to include the new
promotionBadgefield. - Added support for
promotionBadgein the restaurant packages. - Added new schemas and types to support
promotionBadge.
[
github.com
https://github.com/hungryhub-team/hh-pegasus/pull/1530
](https://github.com/hungryhub-team/hh-pegasus/pull/1530)
PRD & Task
Private (https://app.clickup.com/9003122396/docs/8ca1fpw-7922/8ca1fpw-43856)
Private (https://app.clickup.com/t/86cx3baf1)
Design
[
www.figma.com
https://www.figma.com/design/5q2WPEzciWeE8pZa9SieFS/Dynamic-Pricing?node-id=1719-338&t=adhw9xvfL1dcrVba-1
](https://www.figma.com/design/5q2WPEzciWeE8pZa9SieFS/Dynamic-Pricing?node-id=1719-338&t=adhw9xvfL1dcrVba-1)
API Blueprint
| Method | Path | URL | Description | Payload |
|---|---|---|---|---|
| all | all API that have restaurant data, restaurant package data | Add new attribute :promotion_badge |
New Query
-
DB Schema / Database Migration
- Added two new migration files to add
promotion_badge_percentageattributes tohh_package_pricingsandpackage_attr.
Improvement:
| Feature Name | Date | What Changed | Description |
|---|---|---|---|
| promotion badge | April 7 2025 | Initial doc | Add new promotion badge to show the package promotion |