Restaurant Ordering System Backend

Overview

front-end repo https://github.com/JensLiu/restaurant-ordering-system-frontend

back-end repo https://github.com/JensLiu/restaurant-ordering-system-backend

Project demo https://ordering.jensdevelops.de

⚠️ Do NOT enter your payment information, instead use the test card provided in the documentation
TL;DR: Card No. 4242 4242 4242 4242 Document: Test payment methods

👤 Accounts

  • customer@jensdevelops.de
  • chef@jensdevelops.de
  • manager@jensdevelops.de

Password: password

Use case

use case

Deployment: Railway Architecture

railway

Backend Tech Stack

Tech Used in
Spring MVC Controllers
Spring Security + JWT Authentication
Spring Data JPA + Hibernate Database access and analysis queries
Stripe Payment
Jakarta Web Socket Notification

Features

Authentication

Authenticate user on each API request

Upon each request, a JWT access token must be attached either as an HTTP-only cookie or an Authentication header. Only users with the correct identity can access the endpoints within its role.

When signed in, the user will be given an access token and a refresh token. When the access token expires, the user can use the refresh token to refresh it since the refresh token lasts longer. (It is implemented in the front end to automatically refresh when receiving responses with the unauthorised status code).

Profile management

Each user can modify their name, avatar, and password.

Menu item management

Managers can

  • Add/Edit/Remove categories
  • Add/Edit/Remove menu items

Each menu item has the following attributes:

  • id
  • name
  • description
  • image source
  • sold out flag
  • delete flag
  • flavour list
  • category list
  • <size, price> pair list

Menu items can only be deleted if no orders have been made using them, or they will be flagged as deleted but remain in the database (archived)

Its flavour or <size, price> pair can only be deleted when no related order has been made. Once saved, it cannot be altered. (You can delete and add a new pair to achieve this)

Stripe payment integration

  • Upon checkout, the backend will calculate the total price, then call the stripe API to make a payment intent and send the redirect URL as a response. The front end will be able to redirect to the stripe payment page.
  • Upon successful payment (webhook callback from Stripe), it will automatically update the payment status and call the notification service to notify chefs of an incoming order.

Order Analysis

Peak hour analysis

Helps managers to decide when more staff are needed Peak Hour

Trending category analysis

Helps managers to know the sales of each category Trending Categories

Trending item analysis

Helps managers to decide which items and their ingredients to prepare more Trending Items

Valuable customer analysis

Helps managers to find out loyal and valuable customers, and give them discounts etc. Valuable Customers

Realtime notification

It uses Web Socket to notify users connected to the server. Chefs are notified when an order is placed. Customers are notified when an order is being prepared or finished.

In the current implementation, each user can only log in once at a time. Multiple logins will result in previous websocket connections being killed.

Global Error Handling and Response Enveloping

Errors

Errors are divided into three categories: AuthExceptions, BusinessExceptions and InfrastructureExceptions.

  • AuthExceptions are thrown when the accessing user does not have the correct role
  • BusinessExceptions are thrown when business logic is violated
  • InfrastructureExceptions are thrown when there’s an internal error

Response Envelope

All responses are packed into the following format

{
  "data": {
    "field": "value"
  },
  "message": "success/failed"
}

Database design

database ⚠️ Note: conversation/chat feature is not implemented

Deployment

Configure the following environment variables or rewrite the application-prod.yaml

spring:
  datasource:
    username: ${PROD_DB_USER}
    password: ${PROD_DB_PASSWORD}
    url: jdbc:${PROD_DB_URL}
    driver-class-name: ${PROD_DB_DRIVER_NAME}
  jpa:
    properties:
      hibernate:
        use_sql_comments: true
        format_sql: true
        jdbc:
          lob:
            non_contextual_creation: true
    hibernate:
      ddl-auto: update
    database-platform: ${PROD_DB_DIALECT_CLASS}

app:
  jwt:
    secret: ${PROD_JWT_SECRET}
    access-token:
      cookie-name: ${PROD_JWT_ACCESS_TOKEN_COOKIE_NAME}
      expiration-ms: ${PROD_JWT_ACCESS_TOKEN_EXPIRATION_MS}
    refresh-token:
      cookie-name: ${PROD_JWT_REFRESH_TOKEN_COOKIE_NAME}
      expiration-ms: ${PROD_JWT_REFRESH_TOKEN_EXPIRATION_MS}
  stripe:
    api: ${PROD_STRIPE_API}
    webhook:
      secret: ${PROD_STRIPE_WEBHOOK_SECRET}

References