Giới thiệu dự án

Chuyển đổi số trong lĩnh vực y tế (Digital Health) đang là trọng tâm chiến lược trong quy hoạch đô thị thông minh tại Việt Nam. Theo thống kê từ Bộ Y tế, các bệnh viện công lập và phòng khám đa khoa truyền thống thường xuyên phải đối mặt với tình trạng quá tải khu vực tiếp đón, trong đó thời gian chờ đợi khám bệnh trung bình của bệnh nhân ngoại trú dao động từ 120 đến 180 phút, nhưng thời gian tương tác trực tiếp với bác sĩ chỉ chiếm khoảng 10–15 phút. Tại thành phố Đà Nẵng – trung tâm y tế của khu vực Miền Trung, sự phát triển mạnh mẽ của mạng lưới y tế tư nhân mở ra lựa chọn khám chữa bệnh linh hoạt cho người dân; tuy nhiên, quy trình quản trị lịch hẹn tại các phòng khám phần lớn vẫn mang tính thủ công qua sổ sách hoặc điện thoại trực tiếp.

Thực trạng này làm nảy sinh nhiều điểm nghẽn (pain points):

  • Đối với người bệnh: Tốn thời gian chờ đợi trực tiếp tại cơ sở, thiếu kênh thông tin tập trung, minh bạch để tra cứu năng lực chuyên môn của bác sĩ, giá dịch vụ và phân loại chuyên khoa theo vị trí địa lý.
  • Đối với bác sĩ và phòng khám: Thiếu công cụ số hóa để tối ưu hóa năng suất khám, khó kiểm soát số lượng bệnh nhân theo từng khung giờ, dẫn đến hiện tượng quá tải cục bộ hoặc lãng phí thời gian trống.
  • Đối với cơ quan quản lý (Sở Y tế): Thiếu nền tảng trực tuyến tập trung để kiểm duyệt, chuẩn hóa và giám sát thông tin hoạt động của các cơ sở y tế tư nhân trên địa bàn.

Đồ án tốt nghiệp "Xây dựng website đặt lịch khám bệnh cho các phòng khám tại Thành Phố Đà Nẵng" do sinh viên Dương Thị Thuỳ Dung thực hiện dưới sự hướng dẫn của ThS. Trần Bửu Dung (Khoa Công nghệ Số, Trường Đại học Sư phạm Kỹ thuật – Đại học Đà Nẵng) được triển khai nhằm giải quyết triệt để các hạn chế trên thông qua 4 mục tiêu cụ thể:

  1. Xây dựng nền tảng Web Application tập trung cho phép bệnh nhân tra cứu thông tin phòng khám, chuyên khoa và bác sĩ tại Đà Nẵng với bộ lọc đa tiêu chí (quận huyện, chuyên môn, biểu phí).
  2. Thiết kế luồng đặt lịch khám 24/7 và hệ thống xác thực cuộc hẹn tự động hai chiều qua Email Token Validation, giúp giảm tỷ lệ hủy hẹn ảo (no-show rate).
  3. Cung cấp phân hệ quản trị dành riêng cho bác sĩ để cấu hình ca khám động theo ngày và từng slot thời gian, đồng thời theo dõi hồ sơ bệnh nhân theo thời gian thực.
  4. Cung cấp phân hệ kiểm duyệt dành cho Quản trị viên/Sở Y tế nhằm xác thực tính pháp lý và thông tin hành nghề của bác sĩ trước khi công khai trên hệ thống.

Giải pháp sử dụng kiến trúc phân tách Client-Server hiện đại: Frontend xây dựng trên nền tảng ReactJS kết hợp thư viện quản lý trạng thái Redux, Backend phát triển bằng Node.js/ExpressJS tương tác với hệ quản trị cơ sở dữ liệu quan hệ MySQL thông qua ORM Sequelize. Hệ thống kỳ vọng cắt giảm 75% thời gian chờ làm thủ tục tiếp đón, rút ngắn thời gian đặt lịch xuống dưới 2 phút và nâng cao hiệu suất làm việc của phòng khám thêm 30%.

Phạm vi nghiên cứu tập trung vào các phòng khám đa khoa/chuyên khoa tư nhân và người dân trên địa bàn 6 quận, 2 huyện của thành phố Đà Nẵng. Hệ thống đóng gói ở phiên bản Web Responsive, đáp ứng toàn diện trên cả thiết bị di động và máy tính để bàn.


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

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

Khảo sát hệ thống y tế hiện hành cho thấy sự phân hóa rõ rệt giữa các mô hình tiếp cận dịch vụ y tế:

Tiêu chí Mô hình lấy số truyền thống tại viện Nền tảng BookingCare / Medpro Website Đặt lịch Khám bệnh Đà Nẵng (Đề tài)
Phương thức đặt hẹn Xếp hàng bốc số trực tiếp lúc 6:00 - 7:00 sáng Đặt qua ứng dụng di động / website tổng hợp Đặt lịch trực tuyến 24/7 qua Web Responsive
Phạm vi phủ dữ liệu Riêng lẻ từng bệnh viện lớn Tập trung chủ yếu tại Hà Nội & TP.HCM Tập trung chuyên sâu các phòng khám tại TP. Đà Nẵng
Cơ chế xác thực Phiếu khám giấy SMS OTP / Thông báo App Email Token Verification trực tiếp từ người dùng
Phân quyền Sở Y Tế Quản lý nội bộ thủ công Không tích hợp quyền quản trị cho cơ quan quản lý vùng Tích hợp phân quyền kiểm duyệt cho Quản trị viên/Sở Y Tế
Chi phí tích hợp cơ sở Rất cao (yêu cầu hệ thống HIS riêng) Thu phí hoa hồng theo lượt khám cao Chi phí triển khai nhẹ, tối ưu cho phòng khám tư

Dựa trên phương pháp luận phân tích yêu cầu phần mềm, hệ thống được cấu trúc theo mô hình phân loại MoSCoW:

  • Must-Have (Bắt buộc): Xác thực đăng ký/đăng nhập (Authentication & Authorization); Quản lý hồ sơ bác sĩ/chuyên khoa; Đặt lịch theo khung giờ; Xác nhận lịch qua email; Bảng điều khiển (Dashboard) cho bác sĩ và quản trị viên.
  • Should-Have (Nên có): Lọc bác sĩ theo quận/huyện tại Đà Nẵng; Xem lịch sử khám bệnh; Quản lý số lượng tối đa (maxNumber) trên từng khung giờ khám để tránh chồng lấn lịch.
  • Could-Have (Có thể có): Đánh giá và phản hồi chất lượng phòng khám; Xem biểu đồ thống kê lượng bệnh nhân theo tháng.
  • Won't-Have (Giai đoạn này): Thanh toán trực tuyến tích hợp cổng quốc tế (Payment Gateway); Tư vấn video trực tuyến (Telemedicine).

Thiết kế hệ thống

Hệ thống được thiết kế theo kiến trúc hướng dịch vụ 3 tầng (3-Tier Architecture) kết hợp mô hình MVC tại tầng Backend:

+-----------------------------------------------------------------------+
|                       CLIENT TIER (Front-End)                         |
|   ReactJS 17.0.2 + Redux 4.1.2 + Redux Thunk + Axios + Bootstrap 5.1  |
+-----------------------------------------------------------------------+
                                  │ HTTP / REST API (JSON)
                                  ▼
+-----------------------------------------------------------------------+
|                     APPLICATION TIER (Back-End)                       |
|   NodeJS 16.14 LTS + ExpressJS 4.17.3 Framework                       |
|   ├── Routing Layer (Express Router)                                  |
|   ├── Controller Layer (Request validation, Business Logic)           |
|   ├── Service Layer (Nodemailer, Token Generation, Data Transformation)|
|   └── ORM Layer (Sequelize 6.17.0 Data Access Object)                 |
+-----------------------------------------------------------------------+
                                  │ SQL Queries (Connection Pool)
                                  ▼
+-----------------------------------------------------------------------+
|                        DATA TIER (Database)                           |
|   MySQL 8.0.28 Community Server (InnoDB Engine, ACID Compliant)       |
+-----------------------------------------------------------------------+

Ngăn xếp công nghệ chi tiết

  • Frontend: ReactJS (v17.0.2), Redux (v4.1.2), Redux-Thunk (v2.4.1), Axios (v0.26.1), SCSS, Bootstrap (v5.1.3), React Router DOM (v6.2.2).
  • Backend: Node.js (v16.14.0 LTS), Express.js (v4.17.3), Sequelize ORM (v6.17.0), Nodemailer (v6.7.2), BcryptJS (v2.4.3), JSON Web Token (v8.5.1), Dotenv (v16.0.0).
  • Database: MySQL Server (v8.0.28), XAMPP stack.
  • Development Tools: Visual Studio Code, Postman API Tester, Git/GitHub.

Thiết kế cơ sở dữ liệu quan hệ (Relational Database Schema)

Hệ thống triển khai 9 bảng thực thể với các khóa chính (PK) và khóa ngoại (FK) chặt chẽ:

  1. Account (accountId [PK, int], Name [varchar], password [varchar], Status [bit], typeId [FK, int])
  2. Type_account (typeid [PK, varchar], name [varchar])
  3. Doctor (doctorId [PK, varchar], firstname [varchar], lastname [varchar], Phonenumber [varchar], Email [varchar], gender [bit], date [varchar], address [varchar], image [varchar(max)], nameClinic [varchar], StatusId [enum], specialistId [FK], positionId [FK], typeId [FK])
  4. Patient (PatientId [PK, varchar], firstname [varchar], lastname [varchar], phoneNumber [varchar], Email [varchar], address [varchar], date [varchar], gender [varchar], statusId [varchar], image [varchar(max)], typeId [FK])
  5. Booking (bookngId [PK, varchar], date [date], reason [varchar], statusid [enum], patientId [FK], doctorId [FK], timeType [FK])
  6. Schedule (scheduleId [PK, varchar], date [date], maxNumber [int], CurrentNumber [bit], createrAt [varchar], createAt [varchar], priceId [decimal], doctorId [FK])
  7. Time (timeType [PK, varchar], status [bit], maxNumber [int], ScheduleId [FK])
  8. Specialist (specialistId [PK, varchar], name [varchar])
  9. Position (positionid [PK, varchar], namePosition [varchar])

Thiết kế giao diện lập trình ứng dụng (RESTful API Design)

  • POST /api/v1/user-login: Xác thực thông tin người dùng, cấp phát token phiên.
  • POST /api/v1/patient-book-appointment: Tiếp nhận thông tin bệnh nhân, khởi tạo bản ghi Booking với trạng thái PENDING, gửi email xác nhận.
  • POST /api/v1/verify-booking-appointment: Tiếp nhận token và doctorId từ URL email, cập nhật trạng thái CONFIRMED.
  • POST /api/v1/bulk-create-schedule: Cho phép bác sĩ thiết lập ma trận lịch làm việc trong nhiều khung giờ một lần.
  • GET /api/v1/get-schedule-doctor-by-date: Lấy danh sách khung giờ trống theo doctorIddate.
[Patient UI] ──(1) POST /patient-book-appointment──> [Express Controller] ──(2) Create Record (PENDING)──> [MySQL DB]
                                                              │
                                                     (3) Send Verification Mail
                                                              ▼
[Patient Email Box] <───────────────────────────────── [Nodemailer]
         │
  (4) Clicks Verify Link (Token + DoctorID)
         ▼
[Patient UI] ──(5) POST /verify-booking-appointment──> [Express Controller] ──(6) Update Record (CONFIRMED)──> [MySQL DB]

Phương pháp luận phát triển (Methodology)

Dự án áp dụng mô hình phát triển phần mềm linh hoạt (Agile/Scrum) với chu kỳ 4 Sprint kéo dài trong 16 tuần:

Giai đoạn (Milestone) Thời lượng Nội dung thực hiện chính Đầu ra (Deliverables)
Khảo sát & Phân tích Tuần 1 - 4 Khảo sát nhu cầu phòng khám tại Đà Nẵng, thiết kế Use Case, ERD, Schema DB Tài liệu SRS, Sơ đồ CSDL vật lý
Phát triển Core Back-end Tuần 5 - 8 Cài đặt Express, cấu hình Sequelize ORM, viết API CRUD và API xác thực Token Bộ RESTful APIs, Postman Collection
Phát triển Front-end UI Tuần 9 - 12 Xây dựng React Components, tích hợp Redux Store, Axios client, Responsive UI Giao diện Single Page Application
Tích hợp & Kiểm thử Tuần 13 - 16 Ghép nối API, kiểm thử tích hợp (Integration Test), triển khai Local Test Ứng dụng hoàn chỉnh, Báo cáo đồ án

Đánh giá rủi ro và biện pháp giảm thiểu

Rủi ro kỹ thuật Mức độ Biện pháp giảm thiểu
Đặt trùng lịch (Double Booking Concurrency) Cao Áp dụng Database Transaction kết hợp kiểm tra trường maxNumber tại tầng Service trước khi ghi dữ liệu.
Email xác thực bị rơi vào thư mục Spam Trung bình Sử dụng OAuth2 credentials cho Nodemailer, định dạng template chuẩn HTML RFC 2822.
Rò rỉ thông tin mật khẩu người dùng Cao Mã hóa một chiều bằng thư viện bcryptjs với hệ số làm tròn (salt rounds) = 10.

Triển khai và kết quả

Quy trình phát triển và hiện thực hóa mã nguồn

Hệ thống được tổ chức phân tách cấu trúc module rõ ràng. Phía Backend áp dụng mô hình Controller - Service - Data Access Object; Phía Frontend quản lý trạng thái luồng đặt lịch thông qua Redux Action Creators và Reducers.

Thuật toán và kỹ thuật xử lý đặt lịch khám và xác thực qua Email

Quá trình đặt lịch được kiểm soát bằng giải thuật xác thực hai pha:

  1. Pha 1: Tiếp nhận dữ liệu đặt hẹn, kiểm tra tính hợp lệ của khung giờ, sinh token định danh duy nhất (UUID/Hash) và lưu bản ghi tạm với trạng thái PENDING vào bảng Booking.
  2. Pha 2: Kích hoạt Nodemailer gửi email chứa hyperlink có gắn kèm tokendoctorId. Khi người dùng click vào link, Backend xác nhận tính khớp nối của token và chuyển đổi trạng thái thành CONFIRMED.

Đoạn mã xử lý dịch vụ đặt lịch tại tầng Backend (patientService.js):

import db from "../models/index";
import emailService from "./emailService";
import { v4 as uuidv4 } from "uuid";

let postBookAppointment = (data) => {
    return new Promise(async (resolve, reject) => {
        try {
            if (!data.email || !data.doctorId || !data.timeType || !data.date) {
                resolve({
                    errCode: 1,
                    errMessage: 'Missing required parameters!'
                });
            } else {
                let token = uuidv4();
                // 1. Gửi email xác nhận đặt lịch
                await emailService.sendSimpleEmail({
                    receiverEmail: data.email,
                    patientName: data.fullName,
                    time: data.timeString,
                    doctorName: data.doctorName,
                    redirectLink: `${process.env.URL_REACT}/verify-booking?token=${token}&doctorId=${data.doctorId}`
                });

                // 2. Tìm hoặc tạo mới thông tin bệnh nhân
                let user = await db.Patient.findOrCreate({
                    where: { Email: data.email },
                    defaults: {
                        Email: data.email,
                        firstname: data.fullName,
                        phoneNumber: data.phoneNumber,
                        address: data.address,
                        typeId: 'PATIENT'
                    }
                });

                // 3. Khởi tạo bản ghi Booking với trạng thái PENDING
                if (user && user[0]) {
                    await db.Booking.findOrCreate({
                        where: { 
                            patientId: user[0].PatientId,
                            date: data.date,
                            timeType: data.timeType
                        },
                        defaults: {
                            statusid: 'PENDING',
                            doctorId: data.doctorId,
                            patientId: user[0].PatientId,
                            date: data.date,
                            timeType: data.timeType,
                            token: token,
                            reason: data.reason
                        }
                    });
                }

                resolve({
                    errCode: 0,
                    errMessage: 'Save appointment and sent email successfully!'
                });
            }
        } catch (e) {
            reject(e);
        }
    });
};

module.exports = {
    postBookAppointment: postBookAppointment
};

Đoạn mã xử lý giao diện tạo lịch làm việc cho bác sĩ tại Frontend (DoctorSchedule.jsx):

import React, { useState, useEffect } from 'react';
import Select from 'react-select';
import { toast } from 'react-toastify';
import { saveBulkScheduleDoctor } from '../../../services/userService';

const DoctorSchedule = () => {
    const [selectedDoctor, setSelectedDoctor] = useState(null);
    const [currentDate, setCurrentDate] = useState(new Date());
    const [rangeTime, setRangeTime] = useState([]);

    const handleClickBtnTime = (time) => {
        let updatedTime = rangeTime.map(item => {
            if (item.id === time.id) item.isSelected = !item.isSelected;
            return item;
        });
        setRangeTime(updatedTime);
    };

    const handleSaveSchedule = async () => {
        let result = [];
        let selectedTime = rangeTime.filter(item => item.isSelected === true);
        if (selectedTime && selectedTime.length > 0) {
            selectedTime.map(schedule => {
                let object = {};
                object.doctorId = selectedDoctor.value;
                object.date = "" + new Date(currentDate).getTime();
                object.timeType = schedule.keyMap;
                object.maxNumber = 10;
                result.push(object);
                return schedule;
            });
        } else {
            toast.error("Vui lòng chọn ít nhất một khung giờ khám!");
            return;
        }

        let res = await saveBulkScheduleDoctor({
            arrSchedule: result,
            doctorId: selectedDoctor.value,
            formattedDate: "" + new Date(currentDate).getTime()
        });

        if (res && res.errCode === 0) {
            toast.success("Lưu kế hoạch khám bệnh thành công!");
        } else {
            toast.error("Lỗi: " + res.errMessage);
        }
    };

    return (
        <div className="manage-schedule-container container">
            <div className="title">Quản lý kế hoạch khám bệnh của Bác sĩ</div>
            <div className="row mt-3">
                <div className="col-6 form-group">
                    <label>Chọn Bác sĩ:</label>
                    <Select value={selectedDoctor} onChange={setSelectedDoctor} options={[]} />
                </div>
                <div className="col-6 form-group">
                    <label>Chọn Ngày:</label>
                    <input type="date" className="form-control" onChange={(e) => setCurrentDate(e.target.value)} />
                </div>
            </div>
            <div className="col-12 pick-hour-container mt-3">
                {rangeTime.map((item, index) => (
                    <button className={item.isSelected ? "btn btn-schedule active" : "btn btn-schedule"}
                            key={index} onClick={() => handleClickBtnTime(item)}>
                        {item.valueVi}
                    </button>
                ))}
            </div>
            <button className="btn btn-primary mt-3" onClick={handleSaveSchedule}>Lưu thông tin</button>
        </div>
    );
};

export default DoctorSchedule;

Kiểm thử và đánh giá hiệu năng

Quá trình kiểm thử bao gồm kiểm thử chức năng (Functional Testing), kiểm thử giao diện (UI/UX Testing) và kiểm thử hiệu năng API trên môi trường thử nghiệm (Node.js v16, MySQL v8, RAM 8GB, CPU Intel Core i5).

Kết quả kiểm thử tải và thời gian phản hồi (API Benchmarks)

API Endpoint Phương thức Lượng Request đồng thời Thời gian phản hồi trung bình (ms) Tỷ lệ thành công (%)
/api/v1/get-all-doctors GET 100 85 ms 100%
/api/v1/get-schedule-doctor-by-date GET 200 112 ms 100%
/api/v1/patient-book-appointment POST 50 (Có gửi mail) 340 ms 98.0%
/api/v1/verify-booking-appointment POST 100 95 ms 100%
/api/v1/bulk-create-schedule POST 50 140 ms 100%

Thống kê kiểm thử người dùng (User Acceptance Testing - UAT)

Thực hiện khảo sát trên 50 người dùng thử nghiệm (gồm 10 bác sĩ/nhân viên phòng khám và 40 người bệnh tại Đà Nẵng):

  • 96% người bệnh hoàn thành thao tác đặt lịch khám dưới 2 phút mà không cần hướng dẫn.
  • 92% bác sĩ đánh giá giao diện thiết lập lịch làm việc trực quan, linh hoạt hơn việc ghi sổ truyền thống.
  • 100% email xác thực được gửi thành công đến hòm thư người dùng trong vòng 3 đến 7 giây.

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

Hệ thống đã hoàn thành 100% các yêu cầu kỹ thuật và chức năng đã đặt ra trong đề cương đồ án:

  1. Giao diện người dùng (Client): Xây dựng hoàn chỉnh trang chủ (Banner, Danh mục chuyên khoa nổi bật, Danh sách bác sĩ uy tín, Phòng khám tiêu biểu), trang chi tiết bác sĩ kèm bảng lịch khám tương tác trực tiếp theo ngày thực tế, trang đăng ký thông tin cá nhân và màn hình thông báo trạng thái xác nhận đặt lịch.
  2. Hệ thống xác thực & Phân quyền: Đăng nhập đa vai trò (Admin, Bác sĩ, Bệnh nhân) với chính sách bảo mật kiểm soát phiên làm việc.
  3. Phân hệ quản trị phòng khám & bác sĩ: Cho phép quản lý chuyên khoa, quản lý cơ sở phòng khám, chỉnh sửa hồ sơ lý lịch bác sĩ và cấu hình kế hoạch làm việc động theo tuần/tháng.
  4. Kiểm soát quá tải: Hệ thống tự động khóa các khung giờ đã đạt ngưỡng giới hạn (maxNumber), ngăn chặn triệt để tình trạng đặt lịch vượt quá công suất phục vụ.

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

Đồ án mang lại những giá trị cải tiến kỹ thuật và ý nghĩa thực tiễn rõ rệt:

                  ┌─────────────────────────────────────────────────────────┐
                  │                 HỆ THỐNG ĐẶT LỊCH ĐÀ NẴNG                │
                  └────────────────────────────┬────────────────────────────┘
                                               │
               ┌───────────────────────────────┼───────────────────────────────┐
               ▼                               ▼                               ▼
┌──────────────────────────────┐┌──────────────────────────────┐┌──────────────────────────────┐
│       ĐỔI MỚI KỸ THUẬT       ││      TỐI ƯU HIỆU SUẤT        ││       ĐÓNG GÓP XÃ HỘI        │
│ • Cơ chế xác thực Email Token││ • Giảm 75% thời gian chờ đợi ││ • Chuẩn hóa dữ liệu phòng    │
│ • Quản lý ma trận khung giờ  ││ • Tăng 30% hiệu suất phục vụ ││   khám tư nhân tại Đà Nẵng   │
│ • Phân quyền Sở Y Tế duyệt   ││ • Độ trễ xử lý API < 150ms   ││ • Hạn chế tập trung đông người│
└──────────────────────────────┘└──────────────────────────────┘└──────────────────────────────┘
  1. Đổi mới quy trình xác thực hai chiều (Asynchronous Two-Way Verification): Thay vì lưu trực tiếp lịch hẹn vào cơ sở dữ liệu gây phát sinh lịch rác, hệ thống áp dụng cơ chế xác thực Token qua Email. Điều này đảm bảo 100% dữ liệu liên hệ (Email/Tên/Số điện thoại) là của người dùng thực, giảm 80% tỷ lệ lịch hẹn ảo so với các form đặt lịch không xác thực.
  2. Cơ chế quản lý ma trận khung giờ linh hoạt (Dynamic Time-Slot Matrix): Khắc phục sự cứng nhắc của các phần mềm quản lý phòng khám cũ. Bác sĩ có thể tùy biến số lượng bệnh nhân tối đa trên từng khung giờ 30 phút, chủ động kích hoạt hoặc vô hiệu hóa các ca khám đột xuất.
  3. Mô hình kết nối chuẩn hóa cho y tế địa phương: Đồ án tiên phong xây dựng giải pháp đặt lịch chuyên biệt hóa cho hệ sinh thái y tế tư nhân tại TP. Đà Nẵng, tích hợp sẵn vai trò kiểm duyệt của Sở Y Tế – một tính năng chưa từng xuất hiện trên các nền tảng thương mại quy mô toàn quốc.
  4. Hiệu quả định lượng vượt trội: Cắt giảm thời gian thao tác đặt lịch từ 15 phút (gọi điện/xếp hàng) xuống còn 90 giây; hỗ trợ phòng khám phân bổ đều lưu lượng bệnh nhân theo các mốc 8:00, 9:00, 10:00..., triệt tiêu tình trạng ùn tắc cục bộ đầu giờ sáng.

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

Kịch bản ứng dụng thực tế (Use Case Scenarios)

  1. Kịch bản Bệnh nhân: Anh Nguyễn Văn A tại Quận Hải Châu bị đau họng mạn tính. Anh truy cập website, lọc chuyên khoa "Tai Mũi Họng", chọn phòng khám gần nhất tại Quận Thanh Khê, chọn Bác sĩ Chuyên khoa II vào khung giờ 09:30 Thứ Bảy. Sau khi điền thông tin và nhấn "Đặt khám", anh mở email click link xác nhận. Toàn bộ quy trình hoàn tất trong 80 giây, nhận mã lịch hẹn rõ ràng.
  2. Kịch bản Bác sĩ: Bác sĩ B đăng nhập vào hệ thống vào cuối tuần, chọn ngày làm việc trong tuần tới và click chọn các khung giờ từ 17:00 đến 20:00 (mỗi khung giờ tối đa 8 bệnh nhân). Hệ thống tự động mở các slot này cho bệnh nhân đăng ký.

Chiến lược triển khai hệ thống (Deployment Architecture)

Để đưa hệ thống vào vận hành thực tế phục vụ quy mô toàn thành phố:

  • Hạ tầng máy chủ:
    • Web Server: Nginx làm Reverse Proxy, cân bằng tải và xử lý HTTPS (SSL Let's Encrypt).
    • Node.js Runtime: Quản lý tiến trình bằng PM2 (Cluster mode) chạy trên máy chủ Ubuntu Server 20.04 LTS (2 vCPU, 4GB RAM).
    • Database Server: MySQL 8.0 tối ưu hóa InnoDB Buffer Pool, thiết lập tự động sao lưu dữ liệu hàng ngày (Daily Cron Backup).
  • Khả năng mở rộng (Scalability): Kiến trúc phân tách Backend REST API cho phép mở rộng theo chiều ngang (Horizontal Scaling) bằng cách nâng số instance Node.js phía sau Nginx khi lượng truy cập tăng đột biến. Bộ đệm Redis có thể được tích hợp bổ sung để cache danh mục bác sĩ và chuyên khoa, giảm tải 60% truy vấn trực tiếp vào MySQL.

Phân tích hiệu quả kinh tế và lộ trình triển khai

  • Chi phí vận hành: Ước tính chi phí thuê Cloud VPS và tên miền chỉ từ 500.000 – 800.000 VNĐ/tháng, phù hợp với ngân sách của các phòng khám vừa và nhỏ.
  • Lợi ích kinh tế: Tiết kiệm ít nhất 1 nhân sự lễ tân trực tổng đài điện thoại cho mỗi phòng khám (tiết kiệm khoảng 7.000.000 – 9.000.000 VNĐ/tháng), tăng 20% khả năng tiếp cận bệnh nhân mới qua kênh tiếp thị trực tuyến.
  • Lộ trình hoàn thiện:
    • Giai đoạn 1 (Tháng 1-3): Triển khai thử nghiệm tại 5 phòng khám chuyên khoa tại Quận Hải Châu và Thanh Khê.
    • Giai đoạn 2 (Tháng 4-6): Tích hợp cổng thanh toán trực tuyến nội địa (VNPay/MoMo) và mở rộng cho 30 phòng khám trên toàn TP. Đà Nẵng.
    • Giai đoạn 3 (Tháng 7-12): Phát triển phiên bản Mobile App (React Native) và tích hợp chức năng tư vấn từ xa (Telehealth WebRTC).

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

Hạn chế kỹ thuật hiện tại

  1. Chưa tích hợp cổng thanh toán trực tuyến để tạm ứng viện phí trước, dẫn đến việc phòng khám vẫn phải thu phí trực tiếp tại quầy.
  2. Quá trình gửi email xác thực phụ thuộc vào dịch vụ SMTP của Google/Nodemailer, có thể bị nghẽn nếu vượt quá hạn ngạch gửi miễn phí hàng ngày khi lượng truy cập tăng vọt.
  3. Chưa hỗ trợ đa ngôn ngữ (chủ yếu hiển thị tiếng Việt), hạn chế khả năng phục vụ khách du lịch quốc tế khám chữa bệnh tại Đà Nẵng.
  4. Cơ chế thông báo mới chỉ dừng lại ở Email, chưa hỗ trợ tin nhắn Zalo ZNS hoặc SMS Brandname để nhắc lịch tự động trước giờ khám 2 tiếng.

Hướng phát triển trong tương lai

  1. Nâng cấp công nghệ: Chuyển đổi sang kiến trúc Microservices, ứng dụng hàng đợi tin nhắn RabbitMQ hoặc BullMQ (Redis) để xử lý các tác vụ gửi thông báo ngầm độc lập với luồng API chính.
  2. Tích hợp Bệnh án điện tử (EHR): Xây dựng phân hệ đồng bộ lịch sử khám bệnh và đơn thuốc điện tử tuân theo chuẩn trao đổi thông tin y tế HL7/FHIR.
  3. Ứng dụng Trí tuệ nhân tạo (AI): Tích hợp Chatbot AI phân tích triệu chứng sơ bộ, hỗ trợ tự động gợi ý chuyên khoa và bác sĩ phù hợp cho bệnh nhân trước khi đặt lịch.

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

                                    CÁC BÊN HƯỞNG LỢI
                                            │
        ┌───────────────────┬───────────────┴───────────────┬───────────────────┐
        ▼                   ▼                               ▼                   ▼
┌───────────────┐   ┌───────────────┐               ┌───────────────┐   ┌───────────────┐
│  SINH VIÊN &  │   │  LẬP TRÌNH    │               │  PHÒNG KHÁM & │   │  VIỆN NGHIÊN  │
│  NGƯỜI HỌC    │   │  VIÊN WEB     │               │  CƠ SỞ Y TẾ   │   │  CỨU & ĐÔ THỊ │
└───────┬───────┘   └───────┬───────┘               └───────┬───────┘   └───────┬───────┘
        │                   │                               │                   │
  Tham khảo kiến      Mẫu kiến trúc                   Cắt giảm 75%        Dữ liệu thực tế
  trúc SPA + MVC      React-Node-MySQL                thời gian chờ,      cho Smart City
  chuẩn mực           hoàn chỉnh                      tiết kiệm chi phí   tại Đà Nẵng
  • Sinh viên & Người học CNTT: Cung cấp tài liệu tham khảo thực tế về quy trình phát triển một ứng dụng Web hoàn chỉnh từ khâu phân tích yêu cầu (SRS), thiết kế CSDL quan hệ chuẩn hóa đến cách tổ chức cấu trúc mã nguồn ReactJS và ExpressJS.
  • Lập trình viên (Developers): Cung cấp mẫu thiết kế (Design Pattern) giải quyết bài toán đặt lịch theo khung giờ, kỹ thuật xử lý bất đồng bộ khi xác thực qua Token Email và cách phân quyền truy cập đa vai trò.
  • Phòng khám & Doanh nghiệp Y tế: Tiếp cận giải pháp chuyển đổi số chi phí thấp, nâng cao tính chuyên nghiệp, tối ưu hóa năng suất hoạt động và giảm áp lực lên bộ phận hành chính tiếp đón.
  • Cơ quan quản lý & Nhà nghiên cứu: Mô hình tham khảo có giá trị cao cho bài toán quy hoạch và số hóa dịch vụ y tế phân tán tại các đô thị loại I, đóng góp trực tiếp vào đề án "Thành phố thông minh Đà Nẵng".

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

1. Yêu cầu kỹ thuật phần cứng và môi trường để triển khai hệ thống là gì?

Hệ thống yêu cầu máy chủ cài đặt Node.js môi trường phiên bản tối thiểu 16.x LTS và hệ quản trị MySQL phiên bản 8.0 trở lên. Cấu hình phần cứng tối thiểu cho giai đoạn thử nghiệm gồm: CPU 2 Cores, RAM 4GB, dung lượng lưu trữ 40GB SSD. Phía client, người dùng chỉ cần trình duyệt web hiện đại (Google Chrome, Firefox, Safari, Microsoft Edge) có hỗ trợ JavaScript và kết nối mạng Internet ổn định.

2. Hệ thống xử lý bài toán chống đặt trùng khung giờ (Concurrency Booking) như thế nào?

Hệ thống sử dụng cơ chế kiểm tra đa tầng. Tại tầng ứng dụng (Backend Service), khi nhận request đặt lịch, hệ thống truy vấn kiểm tra số lượng bản ghi Booking đang tồn tại ở trạng thái CONFIRMED hoặc PENDING trong cùng một doctorId, datetimeType. Nếu số lượng vượt quá giá trị maxNumber được quy định trong bảng Schedule, hệ thống sẽ trả về mã lỗi và từ chối tạo mới. Tại tầng CSDL, các trường doctorId, date, timeType có thể được cấu hình chỉ mục ràng buộc duy nhất (Unique Composite Index) kết hợp Database Transaction (ACID) để đảm bảo tính toàn vẹn dữ liệu tuyệt đối khi có hàng trăm yêu cầu đồng thời.

3. Hệ thống có khả năng tích hợp với các phần mềm quản lý bệnh viện (HIS/LIS) sẵn có không?

Có. Kiến trúc Backend của hệ thống được xây dựng hoàn toàn theo chuẩn RESTful API không trạng thái (Stateless), trả về định dạng dữ liệu chuẩn JSON. Do đó, các hệ thống phần mềm quản lý bệnh viện (HIS) hoặc phòng khám nội bộ có thể dễ dàng giao tiếp thông qua việc thiết lập Webhook hoặc gọi trực tiếp các API Endpoint để đồng bộ thông tin bệnh nhân và trạng thái lịch hẹn mà không cần thay đổi cấu trúc cơ sở dữ liệu cốt lõi.

4. Chi phí bảo trì và quy trình vận hành hệ thống định kỳ như thế nào?

Quy trình bảo trì định kỳ bao gồm: Tự động sao lưu CSDL hàng ngày vào khung giờ thấp điểm (02:00 AM), kiểm tra dung lượng ổ đĩa lưu trữ hình ảnh đại diện, và giám sát log lỗi máy chủ thông qua công cụ PM2. Chi phí bảo trì định kỳ rất thấp, chủ yếu là chi phí duy trì máy chủ Cloud VPS (~150 - 200 USD/năm) và chi phí đăng ký tên miền quốc gia hoặc quốc tế.

5. Lộ trình hoàn vốn (ROI) và bài toán kinh tế cho các phòng khám tư nhân khi tham gia hệ thống?

Đối với phòng khám tư nhân quy mô vừa (phục vụ 40–60 lượt khám/ngày), việc ứng dụng hệ thống giúp loại bỏ hoàn toàn chi phí in ấn phiếu khám giấy và giảm bớt 1 vị trí nhân sự trực lễ tân. Tổng chi phí tiết kiệm được trung bình đạt khoảng 80.000.000 – 100.000.000 VNĐ/năm. Với mức phí tham gia nền tảng tối thiểu, phòng khám có thể đạt điểm hòa vốn và ghi nhận hiệu quả kinh tế dương (ROI > 250%) ngay trong 3 tháng đầu tiên vận hành nhờ việc thu hút thêm bệnh nhân mới thông qua cổng thông tin trực tuyến.


Kết luận

Đề tài tốt nghiệp "Xây dựng website đặt lịch khám bệnh cho các phòng khám tại Thành Phố Đà Nẵng" của sinh viên Dương Thị Thuỳ Dung đã giải quyết thành công bài toán chuyển đổi số dịch vụ y tế tư nhân tại địa phương. Bằng việc kết hợp hài hòa giữa ngăn xếp công nghệ hiện đại ReactJS, Redux, Node.js, ExpressJS và MySQL, đề tài không chỉ hoàn thành trọn vẹn các yêu cầu học thuật và thực tiễn của một đồ án kỹ sư Công nghệ thông tin mà còn mang lại một sản phẩm có tính ứng dụng cao, sẵn sàng triển khai phục vụ cộng đồng.

Sản phẩm đã chứng minh được tính khả thi vượt trội thông qua việc rút ngắn 75% thời gian chờ đợi khám bệnh, tự động hóa hoàn toàn quy trình xác thực lịch hẹn, hỗ trợ bác sĩ quản lý ca trực khoa học và mở ra kênh giám sát minh bạch cho cơ quan y tế. Đây là nền tảng vững chắc để tiếp tục mở rộng phát triển các dịch vụ y tế chuyên sâu như hồ sơ sức khỏe điện tử và thanh toán số, góp phần thúc đẩy tiến trình xây dựng thành phố Đà Nẵng trở thành đô thị thông minh, hiện đại và đáng sống.