Dynamic Pricings 1.0
Note: This page documents Dynamic Pricings 1.0, the per-package rule-array system configured via the legacy Admin Dashboard. Each package stores an array of rules on the
hh_package_pricingstable, surfaced to the API aspackage.dynamic_pricingsand managed in code by theDynamicPricingsForPackageconcern. This system has been superseded for new work by Dynamic Pricings 2.0 — the rule-based, per-restaurant pricing service backed by thehungryhub-team/pricing-enginemicroservice. Both pages share the same umbrella term “Dynamic Pricing” in PRDs and release notes; use this page when the work touches per-packagehh_package_pricingsrecords, and link to 2.0 for any rule, modifier, or AI-driven recommendation logic.
Description / Background
Restaurant wants to set multiple pricing for each day, they want to have weekday prices, weekend prices and holiday prices. They want to fully customize the price for each day.
Glossary
Private (https://app.clickup.com/9003122396/docs/8ca1fpw-35796/8ca1fpw-41516)
Objectives
Dynamic Pricings 1.0
- User can find dynamic pricing on store page
- User can see pricing option on package details
- User can see detail pricing for Public Holiday / special day
- User can scroll detail pricing for public holiday / special day if its more than 3 days
- User can see minimum 2 types of pricing options
- User can only see current and future pricing option
- User can see the detail pricing by hovering
- User can see the pricing name (custom from inputing on admin dashboard)
- User can see separate holiday price
If the package have 3 holiday, valentine, new year, and christmas. It will show as 3 different section card on user side.
- User can see the promotion badge on top of Book + button on store page




- 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 pricing on package detail page

- There are 5 category of pricing option :
- Weekday (Mon - Fri)
- Weekend (Sat - Sun)
- Everyday
- Custom
- Holidays / Special Day
- Admin can add pricing option on each package
- Admin can add multiple pricing option
- Admin can see 3 pricing type:
- Normal price (only have 1 price)
- price by party size (have multiple price based on party size)
- price by day (custom price for each day)
- Admin can see 4 default custom day option:
- Weekday (Mon - Fri)
- Weekend (Sat - Sun)
- Everyday
- Custom (Admin can pick which day)
- There are 2 section of Price by day:
- Custom Day (required)
- Holidays / SpecialDay
- Admin can add title on custom day
- Admin can see the public holiday / special day section

- Admin can setting specific start and end dining date on public holidays/special day section
- Admin can add the holiday title (TH, CN and EN) on public holidays/special day section
- Admin can set name for Price by day
- Admin and Owner will be able to see the price per person after selecting the date, time and number of people when creating the booking.
- Admin and Owner will be able to see the price per person after selecting the date, time and number of people when editing the booking.
- Admin can set the promotion badge on edit package:
- for dynamic pricing promotion
- Open Edit Package
- Go to price section
- Pick price type Price by Day

- Go to Public Holidays /Special Days section

- Checked the Display Promotion Badge
- Insert the percentage number

- for come more pay less promotion
- Open Edit Package
- Go to promotion section

- Checked the Come more pay less
- for top up badge
- Open Edit Package
- Go to promotion section
- Checked the Display Top Up Badge
- for dynamic pricing promotion
- The system will show the highest promotion percentage
- The Top Up Badge can be used for :
- Normal Price
- Price by Party Size
- Price by Day
- Price by Day → Public holidays / Special days
- If there are Top up, special day and come more pay less , should use one of the highest percentage between them
- The Come more pay less can be used for:
- Normal Price
- Price by Party Size
- Price by Day → Public holidays / Special days
- If there are discount promotion and come more pay less , should use one of the highest percentage between them
- The System will transform the come more pay less into percentage to choose which bagde will shows:
100% - ((Group size to pay / group size) *100%)
Come 4 pay 3 → 25% off
Come 5 pay 4 → 20% off
See Dynamic Pricings 2.0 for the rule-based successor (Partner Portal, microservice-backed, AI-driven recommendations, per-restaurant).
Scope
Old Store Page, New Store Page, Admin For All platform
Location
Detail Package
How to find Dynamic Pricings 1.0
- Open Store Page
- Pick the package that you want to book
- Click “View Menu” button
- You can find the Dynamic pricing there

How to set Dynamic Pricings 1.0
Private (https://app.clickup.com/9003122396/docs/8ca1fpw-34056/8ca1fpw-39296)
From Restaurant Page
- Open https://hungryhub.com/admin/restaurants?locale=en
- Pick restaurant
- Click Action ➝ Packages
- Pick the package ➝ click edit
- Change the pricing option and set the pricing
- Save
From Package Page
- Open https://hungryhub.com/admin?locale=en
- Open menu Packages
- Pick the package types (AYCE, PP, XP)
- Pick the package ➝ click edit
- Change the pricing option and set the pricing
- Save
For Vendor
- Open https://hungryhub.com/admin?locale=en
- Open menu Channel
- Pick vendor channel ➝ click Edit
- Check Support dynamic pricing to enable dynamic pricing in the channel

- Click Update Channel
- Now you can find the dynamic pricing response on the API
Sequence Diagram / Flow

ERD
N/A — this feature does not require new tables.
PRD
Private (https://app.clickup.com/9003122396/docs/8ca1fpw-7922/8ca1fpw-36596) Private (https://app.clickup.com/9003122396/docs/8ca1fpw-7922/8ca1fpw-36576) Private (https://app.clickup.com/9003122396/docs/8ca1fpw-11562/8ca1fpw-36616)
Private (https://app.clickup.com/t/86cuyeq08) Private (https://app.clickup.com/t/86cvmtnec) Private (https://app.clickup.com/t/86cw7tme2) Private (https://app.clickup.com/t/86cwm3wkw) Private (https://app.clickup.com/t/86cwavp3m) Private (https://app.clickup.com/t/86cx3baf1)
Backend Implementation
Dynamic Pricings 1.0
- Remove
app/concepts/booking_cpt/cell/landing_page.rb - Remove
include PackagePricingValidationConcern - Add pricing validation on
app/controllers/admin/packages/base_controller.rb - Add model concern
DynamicPricingsForPackage - Change code
[package.pricing].flatten.compacttopackage.dynamic_pricings - Replace
.pricing_typeto.dynamic_price_pricing_model - replace
.pricing_modelto.dynamic_price_dynamic_pricing_type - create api to send dynamic pricing to partner portal
- call the api when owner picking the package name on create booking or edit booking, based on the date, time, adult and kids they picked. It will show the price on the package list before the package name

- Added and modified several sections to support displaying and interacting with promotion badges.
- Introduced
promotionBadgeDisplayandpromotionBadgePercentagefields within form components and their related logic. - Added validation and error handling for the new fields.
- Added a method to fetch the highest promotion badge from a list of restaurants.
- Included
promotion_badge_textin the list of keys for dynamic pricing JSON representation. - Added
promotion_badge_textto the pricing JSON representation. - Added methods to handle promotion badge logic, including determining the type and text of the promotion.
- Added private methods for formatting and updating related fields.
- Added a new field,
promotion_badge_percentage. - Added a new field,
promotion_badge_percentage. - Added attributes to serialize promotion badge information.
- Included promotion badge in the restaurant payload.
- Added a new worker to handle expired promotion badge dynamic prices.
- A new worker to process expired promotion badges.
- Added methods to determine the highest promotion badge for a restaurant.
- Added methods to calculate and format promotion badge percentages and texts.
[
github.com
https://github.com/hungryhub-team/hh-server/pull/5548/files
](https://github.com/hungryhub-team/hh-server/pull/5548/files)
[
github.com
https://github.com/hungryhub-team/book-bite/pull/647/files
](https://github.com/hungryhub-team/book-bite/pull/647/files)
[
github.com
https://github.com/hungryhub-team/hh-server/pull/6420
](https://github.com/hungryhub-team/hh-server/pull/6420)
Frontend Implementation
Dynamic Pricings 1.0
- Use
min_seatandmax_seatfrom package level if the pricing setting was by_day - If type
normalno need to show multiple pricing. - package title will generated by min_seat and max_seat. If min_seat and max_seat numbering will be show like this: “{min_seat} - {max_seat} People” but if max_seat value
Infinitywill be “{min_seat} and more”
"min_seat": "1",
"max_seat": "Infinity",
- Added a new field
promotionBadgeto the GraphQL queries, which includespromotionTypeandpromotionText. - New icon files added.
- Introduced a new Vue component
PromotionBadgefor displaying promotional badges. - Integrated the new
PromotionBadgecomponent into various restaurant and favorite card components. - Adjusted layout and styles to accommodate the new
PromotionBadge. - Added support for
promotionBadgein package-related components. - Enhanced dynamic pricing and package card components to display promotional information.
- Updated restaurant models and mappers to include
promotionBadgedata. - Updated relevant store and type definitions to include
promotionBadge. - Integrated
PromotionBadgeinto various partial and section components.
[
github.com
https://github.com/hungryhub-team/hh-pegasus/pull/478/files
](https://github.com/hungryhub-team/hh-pegasus/pull/478/files)
[
github.com
https://github.com/hungryhub-team/hh-pegasus/pull/552
](https://github.com/hungryhub-team/hh-pegasus/pull/552)
[
github.com
https://github.com/hungryhub-team/hh-pegasus/pull/1530
](https://github.com/hungryhub-team/hh-pegasus/pull/1530)
Design
[
Dynamic Pricing
Created with Figma
https://www.figma.com/file/5q2WPEzciWeE8pZa9SieFS/Dynamic-Pricing?type=design&node-id=52-4393&mode=design&t=V93ew1HXHGdCCbON-0
](https://www.figma.com/file/5q2WPEzciWeE8pZa9SieFS/Dynamic-Pricing?type=design&node-id=52-4393&mode=design&t=V93ew1HXHGdCCbON-0)
[
Show exact price on package name
Created with Figma
https://www.figma.com/design/TBZa2ZP4FwlvRwlazgkPCf/Show-exact-price-on-package-name?node-id=0-1&node-type=canvas&t=tQiPf2MY0ExdBaOS-0
](https://www.figma.com/design/TBZa2ZP4FwlvRwlazgkPCf/Show-exact-price-on-package-name?node-id=0-1&node-type=canvas&t=tQiPf2MY0ExdBaOS-0)
API Blueprint
| Method | Path | URL | Description | Response | Payload |
|---|---|---|---|---|---|
| all | all package api | Add dynamic_pricing response normal per_person | { “dynamic_pricing”: { “mode”: “per_person”, “type”: “normal”, “rules”: [ { “title”: “normal”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “Infinity”, “category_name”: “”, “days”: [], “duration”: 120, “kids_price”: “฿590”, “start_date”: “”, “end_date”: “”, “dynamic_pricing_type”: “normal”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 } ], “kids_price_policy”: “”, “come_more_pay_less_rules”: {} } } | ||
| all | all package api | Add dynamic_pricing response per_person and per_party_size | { “dynamic_pricing”: { “mode”: “per_person”, “type”: “by_party_size”, “rules”: [ { “title”: “null”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “5”, “category_name”: “”, “days”: [], “duration”: 120, “kids_price”: “฿590”, “start_date”: “”, “end_date”: “”, “dynamic_pricing_type”: “by_party_size”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 } ], “kids_price_policy”: “”, “come_more_pay_less_rules”: {} } } | ||
| all | all package api | Add dynamic_pricing response per_person and per_day | { “dynamic_pricing”: { “mode”: “per_person”, “type”: “by_day”, “rules”: [ { “title”: “normal”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “13”, “category_name”: “”, “days”: [ “Sunday”, “Saturday” ], “duration”: 120, “kids_price”: “฿590”, “start_date”: “”, “end_date”: “”, “dynamic_pricing_type”: “custom_day”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 } ], “kids_price_policy”: “”, “come_more_pay_less_rules”: {} } } | ||
| all | all package api | add dynamic pricing response per_day with holiday | { “dynamic_pricing”: { “mode”: “per_person”, “type”: “by_day”, “rules”: [ { “title”: “eee”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “23”, “category_name”: “custom_day”, “days”: [ “Sunday”, “Saturday” ], “duration”: 120, “kids_price”: “฿590”, “start_date”: “”, “end_date”: “”, “dynamic_pricing_type”: “by_day”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 }, { “title”: “fefee”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “23”, “category_name”: “holiday”, “days”: [], “duration”: 120, “kids_price”: “฿590”, “start_date”: “2024-10-18”, “end_date”: “2024-10-18”, “dynamic_pricing_type”: “by_day”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 } ], “kids_price_policy”: “”, “come_more_pay_less_rules”: {} } } | ||
| all | all package api | Add dynamic_pricing response normal per_pack | { “dynamic_pricing”: { “mode”: “per_pack”, “type”: “normal”, “rules”: [ { “title”: “normal”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “Infinity”, “category_name”: “”, “days”: [], “duration”: 120, “kids_price”: “฿590”, “start_date”: “”, “end_date”: “”, “dynamic_pricing_type”: “normal”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 } ], “kids_price_policy”: “”, “come_more_pay_less_rules”: {} } } | ||
| all | all package api | add dynamic pricing response per_pack per_day with holiday | { “dynamic_pricing”: { “mode”: “per_pack”, “type”: “by_day”, “rules”: [ { “title”: “eee”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “23”, “category_name”: “custom_day”, “days”: [ “Sunday”, “Saturday” ], “duration”: 120, “kids_price”: “฿590”, “start_date”: “”, “end_date”: “”, “dynamic_pricing_type”: “by_day”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 }, { “title”: “fefee”, “price”: “฿1,190”, “min_seat”: “1”, “max_seat”: “23”, “category_name”: “holiday”, “days”: [], “duration”: 120, “kids_price”: “฿590”, “start_date”: “2024-10-18”, “end_date”: “2024-10-18”, “dynamic_pricing_type”: “by_day”, “price_cents”: 2000000, “kids_price_cents”: 0, “price_currency”: “THB”, “id”: 2447 } ], “kids_price_policy”: “”, “come_more_pay_less_rules”: {} } } | ||
| POST | /restaurant_packages/dynamic_pricing_list | https://{hh-server-host}/api/partner/v1/restaurant_packages/dynamic_pricing_list | Get package with dynamic pricing. Hit this API when admin and owner picking the package name, based on the date, time, adult and kids they picked | { “success”:true, “message”:“”, “data”:[ { “id”:37640, “name”:“International Buffet + Free Flow Alcoholic Drinks (Test)”, “total_price”:100, “total_adult_price”:100, “quantity”:1, “adult”:“1”, “price”:100, “package_type”:“ayce”, “price_type”:“per_person”, “base_price”:100, “allow_mix”:true } ]} | { “adult”: “1”, “kids”: “3”, “quantity”: 1, “reservation_date”: “16-01-2025”, “mix_and_match”: true, “package_type”: “ayce” } |
New Query
- Change column
pricing_modelonhh_package_package_attrstable default toper_person - Change column
dynamic_pricing_typeonhh_package_package_attrstable tonormal - Ignore column
kids_price_rateon all package table
DB Schema / Database Migration
- Add column
dynamic_pricing_typeandpricing_modeltohh_package_package_attrstable - Add column
title,by_day_category,start_date,end_date,selected_days,dynamic_pricing_type,pricing_modeltohh_package_pricingstable - Add column
start_date,end_datetohh_package_pricing_groups - Add translation for
kids_policyonHhPackage::PackageAttradd_monetize - Add
monetizetokids_priceonhh_package_pricingsand when column currency is not exist onhh_package_pricingstable usingcurrency: { present: false } - add
promotion_badge_percentagetohh_package_package_attrstable, column type decimal - add
promotion_badge_percentagetohh_package_pricingstable, column type decimal
Improvement:
| Feature Name | Date | What Changed | Description |
|---|---|---|---|
| Show exact price for dynamic pricing and come more pay less | Nov 2024 | Change price on create and edit booking | Change price on admin and partner portal |
| Public holiday adjustment | Dec 2024 | Add adjustment on holiday setting at edit package | |
| promotion badge | march 2025 | Add promotion badge |