Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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_pricings table, surfaced to the API as package.dynamic_pricings and managed in code by the DynamicPricingsForPackage concern. This system has been superseded for new work by Dynamic Pricings 2.0 — the rule-based, per-restaurant pricing service backed by the hungryhub-team/pricing-engine microservice. Both pages share the same umbrella term “Dynamic Pricing” in PRDs and release notes; use this page when the work touches per-package hh_package_pricings records, 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 :
    1. Weekday (Mon - Fri)
    2. Weekend (Sat - Sun)
    3. Everyday
    4. Custom
    5. Holidays / Special Day
  • Admin can add pricing option on each package
  • Admin can add multiple pricing option
  • Admin can see 3 pricing type:
    1. Normal price (only have 1 price)
    2. price by party size (have multiple price based on party size)
    3. price by day (custom price for each day)
  • Admin can see 4 default custom day option:
    1. Weekday (Mon - Fri)
    2. Weekend (Sat - Sun)
    3. Everyday
    4. Custom (Admin can pick which day)
  • There are 2 section of Price by day:
    1. Custom Day (required)
    2. 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:
    1. for dynamic pricing promotion
      1. Open Edit Package
      2. Go to price section
      3. Pick price type Price by Day
      4. Go to Public Holidays /Special Days section
      5. Checked the Display Promotion Badge
      6. Insert the percentage number
    2. for come more pay less promotion
      1. Open Edit Package
      2. Go to promotion section
      3. Checked the Come more pay less
    3. for top up badge
      1. Open Edit Package
      2. Go to promotion section
      3. Checked the Display Top Up Badge
  • The system will show the highest promotion percentage
  • The Top Up Badge can be used for :
    1. Normal Price
    2. Price by Party Size
    3. Price by Day
    4. Price by Day → Public holidays / Special days
    5. 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:
    1. Normal Price
    2. Price by Party Size
    3. Price by Day → Public holidays / Special days
    4. 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

From Package Page

For Vendor

  • 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.compact to package.dynamic_pricings
  • Replace .pricing_type to .dynamic_price_pricing_model
  • replace .pricing_model to .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 promotionBadgeDisplay and promotionBadgePercentage fields 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_text in the list of keys for dynamic pricing JSON representation.
  • Added promotion_badge_text to 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_seat and max_seat from package level if the pricing setting was by_day
  • If type normal no 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 Infinity will be “{min_seat} and more”
	"min_seat": "1",
    "max_seat": "Infinity",
  • Added a new field promotionBadge to the GraphQL queries, which includes promotionType and promotionText.
  •  New icon files added.
  • Introduced a new Vue component PromotionBadge for displaying promotional badges.
  • Integrated the new PromotionBadge component into various restaurant and favorite card components.
  • Adjusted layout and styles to accommodate the new PromotionBadge.
  • Added support for promotionBadge in package-related components.
  • Enhanced dynamic pricing and package card components to display promotional information.
  • Updated restaurant models and mappers to include promotionBadge data.
  • Updated relevant store and type definitions to include promotionBadge.
  • Integrated PromotionBadge into 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

MethodPathURLDescriptionResponsePayload
allall package apiAdd 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”: {}
}
}
allall package apiAdd 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”: {}
}
}
allall package apiAdd 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”: {}
}
}
allall package apiadd 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”: {}
}
}
allall package apiAdd 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”: {}
}
}
allall package apiadd 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_listhttps://{hh-server-host}/api/partner/v1/restaurant_packages/dynamic_pricing_listGet 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_model on hh_package_package_attrs table default to per_person
  • Change column dynamic_pricing_type on hh_package_package_attrs table to normal
  • Ignore column kids_price_rate on all package table

DB Schema / Database Migration

  • Add column dynamic_pricing_type and pricing_model to hh_package_package_attrs table
  • Add column title , by_day_category , start_date , end_date , selected_days , dynamic_pricing_type , pricing_model to hh_package_pricings table
  • Add column start_date , end_date to hh_package_pricing_groups
  • Add translation for kids_policy on HhPackage::PackageAttr add_monetize
  • Add monetize to kids_price on hh_package_pricings and when column currency is not exist on hh_package_pricings table using currency: { present: false }
  • add promotion_badge_percentage to hh_package_package_attrs table, column type decimal
  • add promotion_badge_percentage to hh_package_pricings table, column type decimal

Improvement:

Feature NameDateWhat ChangedDescription
Show exact price for dynamic pricing and come more pay lessNov 2024Change price on create and edit bookingChange price on admin and partner portal
Public holiday adjustmentDec 2024Add adjustment on holiday setting at edit package
promotion badgemarch 2025Add promotion badge