Skip to content

Data Model

This document explains the core database model. The backend uses JPA entities and PostgreSQL. Branch coordinates use PostGIS-compatible geography points. Backend data model ERD

Users and Roles

User

Table:

text
users

Important fields:

FieldMeaning
idPrimary key.
name, email, passwordCore identity fields. Email is unique. Password is hashed.
phoneNumber, profileUrl, addressProfile information.
isActiveAccount activation flag. Inactive users are blocked by AuthFilter.
rolesMany-to-many relation through users_roles.
deliveryLocationCurrent active delivery location.
restaurantOne-to-one restaurant owned by a manager.
managedBranchBranch assigned to a branch manager.
lastSelectedPaymentMethodLast used payment method for checkout defaults.
requirePasswordChangeForces created users to change password before using app.
createdByCompanyTracks who created a company-owned/managed account.
tokenVersionUsed to invalidate old JWTs.

Role

Roles are enum-backed through RoleName:

text
ADMIN
DELIVERY
MANAGER
CUSTOMER
BRANCH_MANAGER

Restaurant Structure

Restaurant

Table:

text
restaurant

Represents a brand/company, not a physical store.

Important fields:

  • name
  • description
  • coverImageUrl
  • profileImageUrl
  • phoneNumber
  • isPromoted
  • isDeleted
  • owner
  • categories
  • createdAt

RestaurantBranch

Table:

text
restaurant_locations

Represents a physical branch.

Important fields:

FieldMeaning
addressHuman-readable branch address.
locationPostGIS geography(Point,4326).
phoneNumberBranch contact.
isActiveWhether branch is active in system.
restaurantParent restaurant.
openingHoursWeekly opening hours.
availableItemsBranch-specific menu items.
deliveryRadiusInKmMaximum delivery radius. Current annotation max is 8.
isClosedManual/current closed flag.
minOrderAmountMinimum subtotal for checkout.
avgPrepTimeInMinutesPreparation time used in delivery estimate.
averageRating, reviewCountDenormalized review stats.
paymentMethodsAccepted branch payment methods.
managerAssigned branch manager user.
deletedSoft-delete flag.
dailyOrderCountUsed for trending logic and reset job.

The RestaurantBranchListener updates Redis GEO key restaurant:locations after branch saves and removes branch IDs after branch deletes.

OpeningHour

Table:

text
opening_hours

Fields:

  • dayOfWeek
  • openTime
  • closeTime
  • branch

The menu model is deliberately two-level so the app can scale to restaurants with many branches.

Table:

text
menus

This is a master menu item created by a restaurant manager.

Fields:

  • name
  • description
  • imageUrl
  • category
  • optionGroups

The master item does not hold branch-specific price or availability.

BranchMenuItem

Table:

text
branch_menu_items

This joins a master menu item to a branch.

Fields:

FieldMeaning
branchPhysical branch.
menuMaster menu item.
priceBranch-specific price.
isHighlightedBranch-specific promotion/highlight toggle.
isAvailableBranch-specific sold-out toggle.

Customers add BranchMenuItem.id to the cart, not Menu.id, because price and availability belong to the branch.

OptionGroup

Represents a group of choices for a menu item.

Example:

text
Choose sauce

Fields:

  • name
  • minSelection
  • maxSelection
  • variants
  • isDeleted
  • restaurant

OptionVariant

Represents one selectable option inside a group.

Example:

text
Garlic sauce

Fields:

  • name
  • recommendedPrice
  • group
  • isDeleted

BranchOptionConfig

Represents branch-level override for an option variant.

Fields:

  • branch
  • variant
  • priceOverride
  • isAvailable

Database business rule:

text
(branch_id, variant_id) must be unique

That prevents duplicate override rows such as "Blloku branch + Garlic sauce" twice.

Cart Model

Cart

Table:

text
carts

Fields:

  • user
  • cartItems
  • restaurantBranch
  • tipAmount
  • deliveryNote
  • selectedPaymentMethod
  • promoCode TODO

A cart is branch-specific. The current repository lookup is by user and branch.

CartItem

Table:

text
cart_items

Fields:

  • cart
  • branchMenuItem
  • quantity
  • pricePerUnit
  • subTotal
  • cartItemVariants

pricePerUnit includes the branch item price plus selected variant effective prices at the time the item was added.

CartItemVariant

Stores selected option variants for a cart item.

Order Model

Order

Table:

text
orders

Important fields:

FieldMeaning
userCustomer.
deliveryPersonAssigned delivery user.
orderStatusCurrent order state.
paymentStatusCurrent payment state.
paymentPayment attempts/records.
orderItemsSnapshot of purchased items.
totalAmount, serviceFee, tipAmount, subtotal, deliveryPriceMonetary values.
distanceInMetersRoute distance at checkout/order time.
estAvgDeliveryTimeInMinutesEstimated average delivery time.
actualDeliveryTimeDelivery duration after completion.
actualDeliveryDateSet when delivery starts.
pickedUpAtTimestamp field exists; current code sets it when marking delivered.
orderDateCreated at persist time.
paymentMethodCASH_ON_DELIVERY, CARD, or POK.
deliveryNoteCustomer note copied from cart.
latitude, longitude, addressDelivery destination snapshot.
branchBranch fulfilling the order.
lastUpdatedHibernate update timestamp.
driverEarningsDelivery driver earnings.
reasonOfFailureFailure reason, when relevant.
cartHashDetects duplicate unchanged PokPay checkout attempts.

OrderStatus

Current enum values:

text
INITIALIZED
CONFIRMED
DELIVERED
ON_THE_WAY
CANCELLED
FAILED
PREPARING
READY_FOR_PICKUP

OrderItem

Snapshot of menu item at order time. It stores quantity, item name, unit price, subtotal, and selected variants.

OrderItemVariant

Snapshot of selected variant data. This is important because variant names/prices may change later, but historical orders should remain stable.

Payment Model

PaymentMethodEntity

Table:

text
payment_method

Fields:

  • id
  • name
  • paymentMethod

paymentMethod enum:

text
CASH_ON_DELIVERY
CARD
POK

Payment

Table:

text
payments

Fields:

  • paymentGateway
  • order
  • amount
  • paymentStatus
  • transactionId
  • paymentDate
  • createdDate
  • paymentUrl
  • expiresAt
  • refundStatus

PaymentStatus

Current enum values:

text
PENDING
REJECTED
COMPLETED
FAILED
REFUNDED
PENDING_PAYMENT
CANCELED
TO_REFUND
EXPIRED
ABANDONED

Delivery Location Model

DeliveryLocation

Table:

text
delivery-location

Fields:

  • latitude
  • longitude
  • locationName
  • nickname
  • user

These are saved customer addresses/locations.

Live Driver Location

Live delivery-driver coordinates are not saved in the DeliveryLocation table.

They are written to Redis:

text
driver_loc:{driverId}

Stored JSON:

json
{
  "latitude": 41.3275,
  "longitude": 19.8189
}

TTL:

text
1 hour

This is correct for live tracking: it avoids permanently storing every driver movement. The missing piece is a read/display path for frontend/admin/customer tracking.

Reviews

Reviews belong to:

  • customer user,
  • branch,
  • optionally menu item depending on service flow.

Branch average rating and review count are denormalized onto RestaurantBranch.