Giới thiệu dự án

Sự phát triển mạnh mẽ của ngành du lịch cùng xu hướng du lịch tự túc (solo travel/backpacking) tại Việt Nam tạo ra nhu cầu rất lớn về các công cụ hỗ trợ cá nhân hóa hành trình. Theo các báo cáo từ Google Destination Insights và Tổng cục Du lịch Việt Nam, nhu cầu tìm kiếm điểm đến và chia sẻ trải nghiệm du lịch trực tuyến tăng trưởng vượt bậc với hơn 35% mỗi năm. Tuy nhiên, người dùng hiện nay thường gặp khó khăn khi phải sử dụng phân mảnh nhiều ứng dụng rời rạc: một nơi để tìm kiếm thông tin, một nơi lưu lại hình ảnh, và một nền tảng khác để ghi chép hành trình.

Các nền tảng blog truyền thống bộc lộ nhiều điểm nghẽn (pain points) lớn: nội dung mang tính một chiều từ quản trị viên, thiếu sự tương tác hai chiều, không hỗ trợ lưu trữ tọa độ bản đồ chi tiết, và không có công cụ cho phép từng cá nhân tự quản lý kho lưu trữ hành trình (travel timeline & photo albums) của chính mình. Đồ án "Ứng dụng quản lý du lịch cá nhân" do nhóm sinh viên Trần Minh Tùng và Nguyễn Trường Yên thực hiện dưới sự hướng dẫn của ThS. Mai Tuấn Khôi tại Khoa Công nghệ Thông tin - Trường Đại học Sư phạm Kỹ thuật TP.HCM được nghiên cứu nhằm giải quyết trọn vẹn bài toán này.

+-----------------------------------------------------------------------------------+
|                        MỤC TIÊU DỰ ÁN HỆ THỐNG DU LỊCH CÁ NHÂN                    |
+-----------------------------------------------------------------------------------+
|  1. Xây dựng nền tảng Web SPA hiện đại, thân thiện, tương thích đa thiết bị.      |
|  2. Cung cấp bộ tính năng quản lý hành trình cá nhân: Album, Địa điểm, Bài viết.  |
|  3. Thiết lập mạng xã hội tương tác: Like, Comment, Follow, Map Tracking.        |
|  4. Xây dựng Portal quản trị đa tầng (RBAC) phân quyền Admin và Moderator.        |
|  5. Tối ưu hóa hiệu năng dữ liệu bằng GraphQL và hệ quản trị phi quan hệ MongoDB.  |
+-----------------------------------------------------------------------------------+

Phương pháp tiếp cận của đề tài là xây dựng ứng dụng web theo kiến trúc phân tầng hiện đại (Single Page Application - SPA kết hợp Micro-services Ready Backend). Hệ thống ứng dụng công nghệ React.js cho giao diện người dùng, NestJS kết hợp GraphQL (Apollo Server) cho tầng xử lý nghiệp vụ, và MongoDB làm cơ sở dữ liệu lưu trữ phi cấu trúc. Giải pháp này giúp loại bỏ tình trạng over-fetching dữ liệu, tối ưu hóa tốc độ tải trang dưới 1.5 giây, nâng cao khả năng mở rộng (scalability) và cho phép người dùng kiểm soát toàn bộ dữ liệu du lịch cá nhân trên một không gian tập trung.

Phạm vi nghiên cứu tập trung vào hệ thống quản lý du lịch đa đối tượng (Guest, User, Moderator, Admin) tại thị trường Việt Nam, tích hợp xác thực qua Facebook OAuth 2.0 và bản đồ số hướng dẫn hành trình.


Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Khảo sát thực tế các hệ thống chia sẻ du lịch hiện hành cho thấy một số ưu và nhược điểm rõ nét:

Nền tảng Ưu điểm Hạn chế Khả năng tương tác người dùng
Blog Du Lịch Bụi Giao diện đơn giản, bài viết chi tiết về lịch trình và chi phí. Chỉ có 1 tác giả đăng bài, giao diện thiếu cân đối, màu sắc nhạt. Thấp (Chỉ đọc và bình luận cơ bản)
Dulichbui24 Tập trung du lịch nội địa, tích hợp liên kết vận tải hành khách. Bài viết mang tính cá nhân của chủ blog, thiếu tính năng mạng xã hội. Thấp (Nội dung thụ động)
Traveloka Blog Thông tin phong phú, thương hiệu uy tín, liên kết tour và vé. Nặng tính thương mại hóa/bán vé, cấu trúc bài viết phức tạp, lỗi login. Trung bình (Tập trung chuyển đổi booking)
Gody.vn Cho phép người dùng viết bài review, có bản đồ lộ trình chi tiết. Khó kiểm soát trùng lặp nội dung, giao diện nhiều quảng cáo gây nhiễu. Khá (Có kiểm duyệt nhưng dễ spam)
Hệ thống đề xuất Quản lý album ảnh theo tọa độ, tương tác đa chiều, kiểm duyệt RBAC chặt chẽ. Cần kết nối Internet liên tục để tải bản đồ thời gian thực. Rất cao (Mạng xã hội du lịch cá nhân hóa)

Phân loại yêu cầu người dùng theo mô hình MoSCoW:

  • Must-have: Đăng nhập bằng Facebook OAuth 2.0, đăng bài viết kèm hình ảnh và tọa độ, tạo/quản lý album ảnh cá nhân, lưu địa điểm đã đi, hệ thống duyệt/khóa bài viết cho Moderator/Admin.
  • Should-have: Tính năng Follow/Unfollow, Like, Comment đa cấp, Báo cáo vi phạm (Report User/Post), Bản đồ số dẫn đường (Map navigation), Thống kê tổng quan cho quản trị viên.
  • Could-have: Chia sẻ trực tiếp lên mạng xã hội Facebook, lọc bài viết theo vùng miền và thời gian mở cửa.
  • Won't-have (giai đoạn này): Tích hợp cổng thanh toán trực tuyến và đặt phòng khách sạn trực tiếp (OTA booking).

Thách thức kỹ thuật lớn nhất là xử lý các tập dữ liệu đa phương tiện (ảnh độ phân giải cao) gắn liền với tọa độ địa lý và quan hệ tương tác phức tạp mà vẫn phải đảm bảo tốc độ phản hồi API cực nhanh.

Thiết kế hệ thống

Kiến trúc hệ thống được thiết kế theo mô hình 3 tầng (3-Tier Decoupled Architecture):

+-------------------------------------------------------------------+
|                        CLIENT TIER (SPA)                          |
|         React.js (v16.14) + Apollo Client + Styled Components     |
+---------------------------------+---------------------------------+
                                  |
                           GraphQL Queries / Mutations (HTTP/HTTPS)
                                  |
+---------------------------------v---------------------------------+
|                       SERVER TIER (NestJS)                        |
|  +-------------------------------------------------------------+  |
|  | Guards (JWT & RBAC) -> GraphQL Resolvers -> Nest Services   |  |
|  +-------------------------------------------------------------+  |
|  | Interceptors, DTO Validation Pipes, Mongoose Data Adapters  |  |
|  +-------------------------------------------------------------+  |
+---------------------------------+---------------------------------+
                                  |
                          Mongoose ODM Protocol
                                  |
+---------------------------------v---------------------------------+
|                        DATA & STORAGE TIER                        |
|        MongoDB Database (v4.4)  |  Cloud Media Storage / CDN      |
+-------------------------------------------------------------------+

Công nghệ sử dụng với phiên bản cụ thể:

  • Frontend: React.js v16.14.0, Apollo Client v3.3, React Router DOM v5.2, Ant Design / Material-UI components.
  • Backend: NestJS v7.0.0, GraphQL v15.0, Apollo Server Express v2.19, Passport-Facebook v3.0, JSON Web Token (JWT).
  • Database: MongoDB v4.4 Server kết hợp thư viện ODM Mongoose v5.10.

Thiết kế mô hình dữ liệu chính trong MongoDB:

# GraphQL Schema đại diện cho cấu trúc bài viết và người dùng
type User {
  id: ID!
  facebookId: String!
  name: String!
  avatar: String
  role: RoleEnum! # ADMIN | MODERATOR | USER
  albums: [Album!]
  savedLocations: [Location!]
  createdAt: String!
}

type Post {
  id: ID!
  title: String!
  content: String!
  images: [String!]!
  location: LocationInput!
  author: User!
  status: PostStatusEnum! # PENDING | APPROVED | LOCKED
  likes: [User!]!
  comments: [Comment!]!
  openingHours: String
  createdAt: String!
}

Bảo mật và hiệu năng được thiết kế qua cơ chế xác thực kép (OAuth 2.0 kết hợp Stateless JWT Authentication), phân quyền dựa trên vai trò (Role-Based Access Control - RBAC) bằng NestJS Guards, chống tấn công XSS/CORS, cùng cơ chế phân trang dựa trên con trỏ (Cursor-based Pagination) trên các Resolver GraphQL.

Methodology

Dự án áp dụng phương pháp phát triển phần mềm Agile/Scrum rút gọn, chia làm các sprint linh hoạt trong tổng thời gian 15 tuần (30/03/2020 đến 19/07/2020):

Tuần 01 - 03: Khảo sát hiện trạng, đặc tả Use Case, thiết kế cơ sở dữ liệu MongoDB.
Tuần 04 - 06: Thiết kế UI/UX (Guest/User/Admin), R&D công nghệ NestJS + GraphQL.
Tuần 07 - 10: Xây dựng Backend NestJS API, Module User, Module Admin, tích hợp DB.
Tuần 11 - 13: Hoàn thiện chức năng Thống kê, Module Báo cáo, Refactor GraphQL Resolvers.
Tuần 14 - 15: Kiểm thử tự động & thủ công, sửa lỗi bảo mật, hoàn thiện báo cáo tốt nghiệp.

Kế hoạch quản trị rủi ro tập trung vào việc ngăn chặn rò rỉ dữ liệu phiên làm việc, giới hạn dung lượng tải ảnh, và đảm bảo cơ chế kiểm duyệt bài viết tự động chuyển trạng thái PENDING trước khi hiển thị công khai.


Implementation và kết quả

Development process

Quá trình lập trình tuân thủ nghiêm ngặt mô hình module hóa của NestJS và nguyên tắc Component-Driven Development của React.js.

Mã nguồn triển khai NestJS Resolver kiểm soát nghiệp vụ tạo và kiểm duyệt bài viết:

@Resolver('Post')
export class PostResolver {
  constructor(private readonly postService: PostService) {}

  @Mutation(() => PostType)
  @UseGuards(GqlAuthGuard, RolesGuard)
  @Roles('USER', 'ADMIN')
  async createPost(
    @Args('createPostInput') createPostInput: CreatePostInput,
    @CurrentUser() user: UserEntity,
  ): Promise<PostType> {
    // Tự động gán trạng thái PENDING để chờ Moderator phê duyệt
    return this.postService.create({
      ...createPostInput,
      authorId: user.id,
      status: PostStatus.PENDING,
    });
  }

  @Mutation(() => PostType)
  @UseGuards(GqlAuthGuard, RolesGuard)
  @Roles('MODERATOR', 'ADMIN')
  async approvePost(@Args('postId') postId: string): Promise<PostType> {
    return this.postService.updateStatus(postId, PostStatus.APPROVED);
  }
}

Phía Client sử dụng React Hook cùng Apollo Client để thực hiện gọi API tối ưu:

import React from 'react';
import { useMutation, gql } from '@apollo/client';

const LIKE_POST_MUTATION = gql`
  mutation LikePost($postId: ID!) {
    likePost(postId: $postId) {
      id
      likesCount
      isLiked
    }
  }
`;

export const LikeButton = ({ postId, initialLikes }) => {
  const [likePost, { loading }] = useMutation(LIKE_POST_MUTATION, {
    optimisticResponse: {
      likePost: {
        id: postId,
        likesCount: initialLikes + 1,
        isLiked: true,
        __typename: 'Post',
      },
    },
  });

  return (
    <button disabled={loading} onClick={() => likePost({ variables: { postId } })}>
      Yêu thích ({initialLikes})
    </button>
  );
};

Testing và validation

Quy trình kiểm thử được triển khai toàn diện qua 3 bộ test case chính:

  • Kiểm thử Guest: 12 kịch bản (Đăng nhập OAuth, xem bài viết, xem bản đồ không cần xác thực). Tỷ lệ đạt: 100%.
  • Kiểm thử User: 45 kịch bản (Đăng bài, chỉnh sửa album, xóa ảnh, comment, like, follow, report). Tỷ lệ đạt: 98.2% (đã fix 2 lỗi liên quan đến upload nhiều ảnh định dạng HEIC).
  • Kiểm thử Admin/Moderator: 28 kịch bản (Phân quyền, khóa user, duyệt bài, đổi mật khẩu, xuất báo cáo thống kê). Tỷ lệ đạt: 100%.

Kết quả đo kiểm hiệu năng hệ thống:

  • Thời gian phản hồi API trung bình: 85ms đối với GraphQL Queries, 120ms đối với Mutations có xử lý hình ảnh.
  • Lighthouse Performance Score: Đạt 92/100 điểm về hiệu năng hiển thị trên trình duyệt web.
  • Kiểm thử tải (Stress Test): Xử lý ổn định 500 yêu cầu đồng thời (Concurrency Request) với tỷ lệ lỗi < 0.1%.
+-------------------------------------------------------------------------+
|                    KẾT QUẢ KIỂM THỬ VÀ BENCHMARK HỆ THỐNG               |
+-------------------------------------------------------------------------+
|  Chỉ số kiểm định                  |  Kết quả thực nghiệm               |
+------------------------------------+------------------------------------+
|  Tổng số Test Cases thực thi       |  85 Cases                          |
|  Test Case Pass Rate               |  99.1%                             |
|  API Latency (GraphQL Query)       |  85ms                              |
|  API Latency (Data Mutation)       |  120ms                             |
|  Payload Reduction vs REST         |  -45%                              |
|  Điểm đánh giá trải nghiệm (CSAT)  |  4.6 / 5.0 (35 người thử nghiệm)   |
+-------------------------------------------------------------------------+

Kết quả đạt được

Hệ thống đã hoàn thiện đầy đủ 100% các chức năng đề ra trong đề cương khóa luận:

  • Triển khai thành công 21 nghiệp vụ người dùng (User Actor).
  • Triển khai hoàn chỉnh 3 nghiệp vụ kiểm duyệt viên (Moderator Actor) và 5 nghiệp vụ quản trị viên (Admin Actor).
  • Hệ thống quản trị thời gian thực với bảng điều khiển trực quan giúp kiểm soát toàn bộ bài đăng và người dùng vi phạm.

Đổi mới và đóng góp

  1. Ứng dụng GraphQL vào bài toán mạng xã hội du lịch: Khác với phần lớn các đồ án sử dụng kiến trúc RESTful thông thường, hệ thống sử dụng GraphQL Schema-First approach giúp giảm 45% lượng dữ liệu thừa truyền qua mạng internet, cho phép client chủ động lấy đúng trường thông tin cần hiển thị (tọa độ, ảnh preview, tên địa điểm).
  2. Cơ chế lưu vết và quản lý không gian du lịch cá nhân hóa: Không chỉ dừng lại ở bài viết văn bản thông thường, hệ thống cấu trúc hóa từng chuyến đi thành các Album ảnh gắn liền với tọa độ định vị (Geolocation), hỗ trợ hiển thị hành trình trực quan trên bản đồ số.
  3. Mô hình phân quyền kiểm soát nội dung 3 lớp (Guest - User - Moderator - Admin): Thiết lập quy trình tiền kiểm (Pre-moderation) và hậu kiểm (Post-moderation) thông qua hệ thống báo cáo vi phạm giúp giải quyết triệt để vấn đề thông tin rác hoặc quảng cáo sai lệch.

So sánh hệ thống với các giải pháp trên thị trường:

Tiêu chí Dulichbui24 Gody.vn Hệ thống đề tài
Kiến trúc dữ liệu WordPress REST API Monolithic REST NestJS + GraphQL + MongoDB
Quản lý Album cá nhân Không hỗ trợ Có hỗ trợ Quản lý đa cấp gắn liền tọa độ
Quy trình kiểm duyệt bài Không có (Admin viết) Hậu kiểm (Post-mod) Tiền kiểm + Hậu kiểm + Phân quyền RBAC
Tối ưu hóa Payload dữ liệu Thấp (Over-fetching) Trung bình Tối ưu cao (Chính xác theo GraphQL Query)

Ứng dụng thực tế và triển khai

Hệ thống sẵn sàng đưa vào ứng dụng thực tế với các kịch bản:

  • Cộng đồng phượt thủ và du lịch tự túc: Ghi chép nhật ký hành trình theo thời gian thực và chia sẻ kinh nghiệm địa điểm ăn uống, nghỉ ngơi thực tế.
  • Kênh quảng bá du lịch địa phương: Tạo không gian mở cho người dân bản địa chia sẻ những điểm đến mới lạ mà các công ty lữ hành lớn chưa khai thác.

Hướng dẫn triển khai (Deployment Guide)

Yêu cầu môi trường máy chủ:

  • Hệ điều hành: Ubuntu 20.04 LTS trở lên.
  • Node.js Runtime: v14.17.0+ hoặc v16.x LTS.
  • Cơ sở dữ liệu: MongoDB v4.4+ Replica Set.
  • Web Server: Nginx (Reverse Proxy & SSL Termination).

Các bước thiết lập bằng dòng lệnh:

# 1. Clone source code và cài đặt dependencies
git clone https://github.com/travel-management/travel-app.git
cd travel-app
npm install

# 2. Cấu hình biến môi trường (.env)
cat <<EOF > .env
PORT=4000
MONGODB_URI=mongodb://localhost:27017/travel_management
JWT_SECRET=YourSuperSecretKey2020
FACEBOOK_APP_ID=your_fb_app_id
FACEBOOK_APP_SECRET=your_fb_app_secret
EOF

# 3. Build ứng dụng NestJS Backend và React Frontend
npm run build

# 4. Khởi chạy với PM2 Process Manager
pm2 start dist/main.js --name "travel-backend"

Dự toán chi phí hạ tầng ban đầu cực kỳ tiết kiệm, chỉ từ $10 - $20/tháng trên các nền tảng VPS (DigitalOcean/Linode), có thể phục vụ tốt quy mô 10.000 người dùng hoạt động hàng tháng (MAU).


Hạn chế và hướng phát triển

Dù đạt được kết quả khả quan, đề tài vẫn còn một số điểm cần tiếp tục hoàn thiện:

  • Hạn chế: Cơ chế tìm kiếm hiện tại chủ yếu dựa trên Pattern Matching của MongoDB, chưa tích hợp Full-text Search chuyên sâu; chưa hỗ trợ chế độ ngoại tuyến (Offline Mode) khi người dùng di chuyển vào khu vực không có sóng di động.
  • Hướng phát triển tương lai:
    1. Tích hợp công cụ tìm kiếm phân tán Elasticsearch để tối ưu hóa bộ lọc địa điểm theo bán kính và từ khóa không dấu.
    2. Xây dựng ứng dụng di động đa nền tảng bằng React Native nhằm đồng bộ trải nghiệm với phiên bản Web.
    3. Ứng dụng trí tuệ nhân tạo (AI/Machine Learning) trong việc gợi ý lộ trình du lịch thông minh dựa trên sở thích và ngân sách của từng cá nhân.

Đối tượng hưởng lợi

  • Sinh viên ngành CNTT/KTPM: Tham khảo đồ án mẫu chuẩn mực từ khâu khảo sát hiện trạng, vẽ sơ đồ Use Case, thiết kế cơ sở dữ liệu MongoDB đến cách viết tài liệu kỹ thuật chuẩn chỉnh.
  • Lập trình viên Full-stack: Nắm bắt phương pháp kết hợp NestJS, GraphQL và React.js trong một dự án thực tế; học hỏi kỹ thuật viết Custom Guards phân quyền và Apollo Client caching.
  • Doanh nghiệp & Startup du lịch: Sở hữu giải pháp kiến trúc mã nguồn mở có khả năng mở rộng tốt để triển khai các nền tảng mạng xã hội du lịch ngách với chi phí tối ưu.
  • Nhà nghiên cứu: Có thêm số liệu thực nghiệm về hiệu năng truyền tải dữ liệu đa phương tiện qua giao thức GraphQL so với RESTful API truyền thống.

Câu hỏi thường gặp

1. Yêu cầu hệ thống phần cứng tối thiểu để triển khai ứng dụng là gì?

Máy chủ cần tối thiểu 1 vCPU, 2GB RAM và 20GB SSD lưu trữ để chạy mượt mà cả NestJS Backend, MongoDB Server và Nginx Reverse Proxy ở quy mô thử nghiệm ban đầu.

2. Ứng dụng xử lý bài toán quá tải khi lượng người dùng tải ảnh tăng đột biến như thế nào?

Hệ thống sử dụng cơ chế xử lý bất đồng bộ, nén ảnh phía client trước khi upload, đồng thời tích hợp dịch vụ lưu trữ đám mây chuyên dụng (Cloud Storage CDN) giúp giảm tải hoàn toàn cho máy chủ ứng dụng chính.

3. Việc đăng nhập bằng Facebook OAuth 2.0 có an toàn cho dữ liệu người dùng không?

Hệ thống chỉ yêu cầu quyền truy cập công khai cơ bản (public_profile, email) thông qua giao thức OAuth 2.0 tiêu chuẩn. Sau khi xác thực thành công, hệ thống tự động cấp phát mã JWT mã hóa riêng biệt để bảo vệ các phiên làm việc tiếp theo.

4. Quy trình bảo trì và cập nhật schema GraphQL có làm gián đoạn hệ thống không?

GraphQL cho phép bổ sung các Type, Query hoặc Mutation mới mà không làm thay đổi hay phá vỡ các trường dữ liệu hiện hữu (Backward Compatible), loại bỏ hoàn toàn việc phải quản lý phiên bản API (API Versioning v1/v2) phức tạp.

5. Dự toán chi phí vận hành và lộ trình hoàn vốn (ROI) cho hệ thống như thế nào?

Với chi phí duy trì hạ tầng khoảng $120 - $240/năm, khi nền tảng đạt mốc 5.000 người dùng thường xuyên, hệ thống có thể tạo doanh thu từ việc liên kết quảng bá điểm đến cho các homestay, nhà hàng địa phương và đạt điểm hòa vốn sau 6 đến 9 tháng vận hành.


Kết luận

Đồ án tốt nghiệp "Ứng dụng quản lý du lịch cá nhân" của nhóm sinh viên Trần Minh Tùng và Nguyễn Trường Yên (Khoa CNTT - Trường ĐH Sư phạm Kỹ thuật TP.HCM) là một sản phẩm phần mềm hoàn chỉnh, đáp ứng xuất sắc cả về mặt phương pháp luận kỹ thuật phần mềm lẫn tính ứng dụng thực tiễn. Việc ứng dụng thành công các công nghệ tiên tiến gồm React.js, NestJS, GraphQL và MongoDB đã giải quyết hiệu quả các bất cập của các blog du lịch truyền thống, mở ra hướng đi mới trong việc quản lý và chia sẻ trải nghiệm du lịch số hóa cho cộng đồng.