low-level design (LLD) for a food delivery app

Samrat XSamrat X
4 min read

Here is a low-level design for a food delivery app with the given requirements:

Database Design:

  • Restaurants:

    • Restaurant ID

    • Name

    • Address

    • City

    • Contact Information

    • Description

    • Operating Hours

    • Cuisine Types (e.g., Italian, Mexican)

    • Meal Types (e.g., Lunch, Dinner)

    • Menu Items (relationship to a separate table)

    • Ratings and Reviews

  • Users:

    • User ID

    • Name

    • Email

    • Phone Number

    • Address

    • Payment Information

    • Order History

    • Cart Items

    • Favorite Restaurants

    • Applied Coupons

  • Menu Items:

    • Item ID

    • Restaurant ID (foreign key)

    • Item Name

    • Description

    • Price

    • Cuisine Type

    • Meal Type

    • Availability

  • Orders:

    • Order ID

    • User ID (foreign key)

    • Restaurant ID (foreign key)

    • Delivery Boy ID (foreign key)

    • Status (e.g., Pending, Out for Delivery, Delivered)

    • Items (relationship to a separate table)

    • Total Amount

    • Tax Details

    • Payment Status

    • Delivery Address

  • Cart Items:

    • Cart Item ID

    • User ID (foreign key)

    • Item ID (foreign key)

    • Quantity

    • Subtotal

  • Delivery Boys:

    • Delivery Boy ID

    • Name

    • Phone Number

    • Vehicle Type

    • Availability Status

    • Completed Deliveries

  • Coupons:

    • Coupon ID

    • Code

    • Discount Percentage

    • Expiry Date

    • Minimum Order Amount

    • Applicable Restaurants (optional)

JavaScript Implementation:

Restaurant Registration and Profile Management:

// Restaurant registration
function registerRestaurant(restaurantName, address, city, contactInfo, description) {
    const restaurantId = generateUniqueId();
    const newRestaurant = {
        id: restaurantId,
        name: restaurantName,
        address: address,
        city: city,
        contactInfo: contactInfo,
        description: description,
        operatingHours: [],
        cuisineTypes: [],
        mealTypes: [],
        menuItems: [],
        ratings: []
    };
    database.restaurants.push(newRestaurant);
    return restaurantId;
}

// Restaurant profile update
function updateRestaurantProfile(restaurantId, updates) {
    const restaurant = database.restaurants.find(r => r.id === restaurantId);
    if (restaurant) {
        Object.assign(restaurant, updates);
    }
}

let uniqueIdCounter = 0;

function generateUniqueId() {
    return uniqueIdCounter++;
}

User Registration and Profile Management:

// User registration
function registerUser(name, email, password) {
    const userId = generateUniqueId();
    const encryptedPassword = encryptPassword(password);
    const newUser = {
        id: userId,
        name: name,
        email: email,
        password: encryptedPassword,
        address: null,
        paymentInfo: [],
        orderHistory: [],
        cartItems: [],
        favoriteRestaurants: []
    };
    database.users.push(newUser);
    return userId;
}

// User profile update
function updateUserProfile(userId, updates) {
    const user = database.users.find(u => u.id === userId);
    if (user) {
        Object.assign(user, updates);
    }
}

Search Restaurants:

function searchRestaurants(query, city) {
    const regex = new RegExp(query, 'i');
    return database.restaurants.filter(restaurant =>
        restaurant.name.match(regex) || restaurant.city.toLowerCase() === city
    );
}

Manage Menu Items:

// Add/update menu item
function updateMenuItem(restaurantId, itemId, updates) {
    const restaurant = database.restaurants.find(r => r.id === restaurantId);
    if (restaurant) {
        const itemIndex = restaurant.menuItems.findIndex(item => item.id === itemId);
        if (itemIndex !== -1) {
            Object.assign(restaurant.menuItems[itemIndex], updates);
        }
    }
}

// Get menu items by cuisine or meal type
function getMenuItemsByCategory(cuisineType, mealType) {
    const menuItems = [];
    database.restaurants.forEach(restaurant => {
        restaurant.menuItems.forEach(item => {
            if ((cuisineType && item.cuisineType === cuisineType) ||
                (mealType && item.mealType === mealType)) {
                menuItems.push(item);
            }
        });
    });
    return menuItems;
}

Cart and Order Management:

// Add/remove item from cart
function updateCartItem(userId, itemId, quantity) {
    const user = database.users.find(u => u.id === userId);
    if (user) {
        const cartItemIndex = user.cartItems.findIndex(item => item.id === itemId);
        if (cartItemIndex !== -1) {
            user.cartItems[cartItemIndex].quantity = quantity;
        } else if (quantity > 0) {
            const newCartItem = { id: itemId, quantity: quantity };
            user.cartItems.push(newCartItem);
        }
    }
}

// Place order
function placeOrder(userId, restaurantId, deliveryAddress, items, totalAmount, couponCode) {
    const user = database.users.find(u => u.id === userId);
    if (user) {
        const newOrder = {
            id: generateUniqueId(),
            userId: userId,
            restaurantId: restaurantId,
            deliveryBoyId: null,
            status: 'Pending',
            items: items,
            totalAmount: totalAmount,
            taxDetails: calculateTax(totalAmount),
            paymentStatus: 'Pending',
            deliveryAddress: deliveryAddress,
            couponCode: couponCode
        };
        user.orderHistory.push(newOrder);
        database.orders.push(newOrder);
    }
}

// Get order status
function getOrderStatus(orderId) {
    const order = database.orders.find(o => o.id === orderId);
    return order ? order.status : null;
}

Payment and Coupon Management:

// Apply coupon
function applyCoupon(userId, couponCode) {
    const user = database.users.find(u => u.id === userId);
    if (user) {
        const coupon = database.coupons.find(c => c.code === couponCode);
        if (coupon && user.orderHistory.length > 0) {
            user.orderHistory[user.orderHistory.length - 1].couponCode = couponCode;
        }
    }
}

// Make payment
function makePayment(orderId, paymentMode) {
    const order = database.orders.find(o => o.id === orderId);
    if (order) {
        order.paymentStatus = 'Paid';
        order.paymentMode = paymentMode;
    }
}

Delivery Boy Management:

// Assign delivery boy to an order
function assignDeliveryBoy(orderId, deliveryBoyId) {
    const order = database.orders.find(o => o.id === orderId);
    if (order) {
        order.deliveryBoyId = deliveryBoyId;
        order.status = 'Out for Delivery';
    }
}

// Get deliveries made by a delivery boy
function getDeliveriesByDeliveryBoy(deliveryBoyId) {
    return database.orders.filter(order => order.deliveryBoyId === deliveryBoyId);
}

This is a simplified implementation, and there are many more features and functionalities that can be added based on the requirements. The code provided here serves as a starting point for the low-level design of the food delivery app.

0
Subscribe to my newsletter

Read articles from Samrat X directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Samrat X
Samrat X