Giới thiệu dự án

Sự quá tải tại các cơ sở y tế tuyến đầu cùng quy trình tiếp nhận bệnh nhân thủ công đang tạo ra áp lực lớn cho hệ thống y tế hiện đại. Theo thống kê từ Bộ Y tế và các khảo sát y tế cộng đồng, thời gian chờ đợi trung bình của một bệnh nhân tại các bệnh viện công lập và phòng khám đa khoa dao động từ 2,5 đến 4,5 giờ, trong khi thời gian khám và tư vấn trực tiếp với bác sĩ chuyên khoa chỉ chiếm từ 5 đến 15 phút. Quy trình đăng ký truyền thống qua sổ khám bệnh bằng giấy hoặc xếp hàng lấy số thứ tự tại chỗ bộc lộ nhiều hạn chế nghiêm trọng: tắc nghẽn cục bộ vào các khung giờ cao điểm, nguy cơ lây nhiễm chéo bệnh truyền nhiễm tại khu vực chờ, thiếu tính minh bạch về hồ sơ chuyên môn và lịch trình làm việc thực tế của bác sĩ.

Dự án CDIO (Conceive - Design - Implement - Operate) mã học phần SE 397 Z với đề tài "Xây dựng Website đặt lịch khám bệnh" được thực hiện bởi nhóm nghiên cứu Khoa Công nghệ Thông tin – Đại học Duy Tân, dưới sự hướng dẫn chuyên môn của giảng viên Trần Thị Thanh Lan. Đề tài tập trung giải quyết bài toán cốt lõi: số hóa toàn diện quy trình kết nối giữa bệnh nhân, bác sĩ chuyên khoa và cơ sở y tế thông qua nền tảng web ứng dụng hiện đại.

+------------------+       +-------------------+       +--------------------+
|  Patient Portal  | <---> | Central Backend   | <---> | Database (MySQL)   |
| (Search/Booking) |       | (Node.js/Express) |       | (RBAC, AllCodes)   |
+------------------+       +-------------------+       +--------------------+
         ^                           ^                           ^
         |                           |                           |
+------------------+                 v                           v
| Doctor / Admin   | <---> [Email/OTP Service]       [Data Security Engine]
| Management Panel |
+------------------+

Mục tiêu của dự án

  1. Chuẩn hóa quy trình đặt lịch trực tuyến: Xây dựng cơ chế lập lịch khám động theo từng khung giờ cố định (timeType), kiểm soát số lượng bệnh nhân tối đa (maxNumber) trên mỗi ca khám để triệt tiêu tình trạng quá tải.
  2. Minh bạch hóa thông tin y tế: Thiết lập hồ sơ bác sĩ chi tiết theo chuyên khoa (specialties), phòng khám (Clinics), bảng giá (priceId), bảo hiểm và phương thức thanh toán (paymentId) kết hợp mô tả chuyên sâu bằng định dạng Markdown/HTML.
  3. Tối ưu hóa quy trình xác thực hai lớp (Two-Phase Verification): Triển khai luồng xác nhận lịch hẹn qua Email/Token và mã OTP bảo mật, tự động khóa slot khám và cập nhật dữ liệu thời gian thực.
  4. Phân quyền và quản trị hệ thống chặt chẽ (RBAC): Tách biệt rõ ràng 3 phân hệ người dùng: Admin (Quản trị vận hành), Doctor (Bác sĩ chuyên khoa), và Patient (Bệnh nhân) đi kèm cơ chế chặn tài khoản vi phạm qua danh sách đen (black_list).

Phương pháp tiếp cận và kết quả kỳ vọng

Dự án áp dụng mô hình kiến trúc Client-Server 3 lớp (3-tier Architecture) với công nghệ Web RESTful, sử dụng cơ chế từ điển dữ liệu tập trung AllCodes để đồng bộ hóa mã trạng thái, khung giờ, chuyên khoa và hỗ trợ song ngữ Anh - Việt.

  • Chỉ số kỳ vọng đo lường được: Giảm hơn 70% thời gian chờ đợi tại phòng khám; tỷ lệ trùng lặp lịch khám (Double Booking) đạt mức 0%; độ trễ phản hồi API hệ thống $\le 250\text{ ms}$; đáp ứng đồng thời 500 người dùng hoạt động đồng thời (CCU).
  • Phạm vi và giới hạn: Nền tảng tập trung vào khâu tiếp nhận, lập lịch, quản lý bệnh án ban đầu và thống kê doanh thu phòng khám; chưa tích hợp sâu vào hệ thống phần mềm bệnh viện chuyên dụng (HIS/PACS) hoặc cổng giám định Bảo hiểm Xã hội trực tiếp.

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

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

Thị trường y tế số hiện nay chứng kiến sự chuyển dịch mạnh mẽ từ khám bệnh thụ động sang chủ động đặt hẹn. Bảng so sánh dưới đây làm rõ sự khác biệt giữa các giải pháp hiện hành:

Tiêu chí Tiếp nhận truyền thống Ứng dụng Bệnh viện Độc lập Nền tảng trung gian (BookingCare, Medpro) Hệ thống Website đề tài (SE 397 Z)
Thời gian chờ khám 120 – 240 phút 30 – 60 phút 15 – 30 phút 10 – 20 phút
Chọn bác sĩ & ca khám Ngẫu nhiên / Xếp hàng Giới hạn theo viện Đa dạng cơ sở y tế Chi tiết theo từng khung giờ & chuyên khoa
Minh bạch chi phí Thấp, biết khi thanh toán Trung bình Rõ ràng trước khi đặt Minh bạch theo priceIdpaymentId
Xác thực lịch hẹn Phiếu khám giấy SMS / App Notification Email / SMS Token Email Token kết hợp mã định danh OTP
Cơ chế chống spam/hủy Không có Phụ thuộc nhân sự gọi Bị động qua CSKH Tự động hóa qua black_list và kiểm tra trùng lịch

Phân tích yêu cầu theo mô hình MoSCoW

  • Must-Have (Bắt buộc): Đăng nhập/Đăng xuất bảo mật; Tìm kiếm theo Bác sĩ/Chuyên khoa/Phòng khám; Đặt lịch khám và gửi email xác thực; Quản lý lịch khám theo ngày (Schedules); Quản lý hồ sơ bệnh án (histories); Phân quyền RBAC (Admin, Doctor, Patient).
  • Should-Have (Nên có): Đa ngôn ngữ (English/Tiếng Việt); Quản trị danh mục động qua bảng AllCodes; Thống kê doanh thu theo tháng/quý/năm trên Dashboard; Quản lý danh sách cấm (black_list).
  • Could-Have (Có thể có): Hộp thoại tương tác trực tuyến (Chatbox); Tích hợp mạng xã hội (Like, Share, Comment chuyên gia qua Meta SDK).
  • Won't-Have (Chưa hỗ trợ đợt này): Tư vấn khám bệnh qua Video Call WebRTC thời gian thực; Thanh toán bảo hiểm y tế tự động liên thông cổng dịch vụ công.

Thiết kế hệ thống

Hệ thống được thiết kế theo mô hình phân tầng chặt chẽ nhằm đảm bảo tính toàn vẹn dữ liệu, hiệu năng và khả năng mở rộng:

+-----------------------------------------------------------------------+
|                       CLIENT LAYER (Single Page App)                  |
|    React 18.2 | Redux Toolkit | Bootstrap 5 | React-Intl (i18n)       |
+-----------------------------------------------------------------------+
                                  |
                           HTTP/HTTPS (REST API)
                                  v
+-----------------------------------------------------------------------+
|                       APPLICATION / SERVER LAYER                      |
|    Node.js 18 LTS | Express 4.18 | JWT Auth | Nodemailer Engine        |
|    - Routing & Controllers                                            |
|    - Business Services (Booking, Schedule, User Management)           |
|    - Middlewares (RBAC, Rate Limiting, Input Validation)              |
+-----------------------------------------------------------------------+
                                  |
                         Sequelize ORM 6.32
                                  v
+-----------------------------------------------------------------------+
|                       DATABASE LAYER (MySQL 8.0)                      |
|   Users, Schedules, Bookings, Clinics, doctor_info, AllCodes, ...    |
+-----------------------------------------------------------------------+

Technology Stack & Versioning

  • Frontend: ReactJS 18.2.0, Redux Toolkit 1.9.5, React Router DOM 6.14.0, Axios 1.5.0, Bootstrap 5.3.0, FontAwesome 6.4.0, React-Markdown 8.0.7.
  • Backend: Node.js 18.18.0 LTS, Express.js 4.18.2, Sequelize ORM 6.32.1, JSON Web Token (jsonwebtoken 9.0.2), BcryptJS 2.4.3, Nodemailer 6.9.4, Dotenv 16.3.1.
  • Database: MySQL 8.0.34 Community Server với InnoDB Storage Engine hỗ trợ ACID Transactions.

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

Hệ thống quản lý 11 thực thể quan hệ, chuẩn hóa ở dạng chuẩn 3NF:

  1. Users: userId (PK, Int), email (Varchar), password (Varchar - Hash Bcrypt), firstName, lastName, address, phoneNumber, gender, image (Blob), roleId (FK $\rightarrow$ AllCodes), keyMap (FK $\rightarrow$ AllCodes).
  2. AllCodes: key (PK, Varchar 255), type (Varchar 255), valueEn (Varchar 255), valueVi (Varchar 255).
  3. Clinics: clinicId (PK, Int), name (Varchar), address (Varchar), image (Longblob), descriptionHTML (Text), descriptionMarkdown (Text).
  4. specialties: specialtyId (PK, Int), name (Varchar), image (Longblob), clinicId (FK $\rightarrow$ Clinics), descriptionHTML (Text), descriptionMarkdown (Text).
  5. doctor_info: doctor_infor_Id (PK, Int), doctorId (FK $\rightarrow$ Users), specialtyId (FK $\rightarrow$ specialties), clinicId (FK $\rightarrow$ Clinics), priceId (FK $\rightarrow$ AllCodes), provinceId (FK $\rightarrow$ AllCodes), paymentId (FK $\rightarrow$ AllCodes), addressClinic, nameClinic, note, count (Int).
  6. doctor_intro: doctor_intro_Id (PK, Int), doctorId (FK $\rightarrow$ Users), specialtyId (FK $\rightarrow$ specialties), clinicId (FK $\rightarrow$ Clinics), contentHTML (Longtext), contentMarkdown (Longtext), description (Longtext).
  7. Schedules: scheduleId (PK, Int), currentNumber (Varchar), maxNumber (Int), date (Varchar), timeType (Timestamp/Varchar - FK $\rightarrow$ AllCodes), doctorId (FK $\rightarrow$ Users).
  8. Patients: patientId (PK, Int), email (Varchar), fullName (Varchar), address (Varchar), phoneNumber (Varchar), gender (Varchar), roleId (Varchar).
  9. Bookings: bookingId (PK, Int), statusId (Varchar - FK $\rightarrow$ AllCodes), doctorId (FK $\rightarrow$ Users), patientId (FK $\rightarrow$ Patients), date (Varchar), timeType (Timestamp/Varchar - FK $\rightarrow$ AllCodes).
  10. histories: historyId (PK, Int), patientId (FK $\rightarrow$ Patients), doctorId (FK $\rightarrow$ Users), email (Varchar), statusId (Text), timeType (Varchar), diagnose (Varchar).
  11. black_list: blockedId (PK, Int), patientId (FK $\rightarrow$ Patients), doctorId (FK $\rightarrow$ Users), statusId (Varchar), timeType (Timestamp), keyMap (Varchar).

Danh mục API Endpoints cốt lõi

HTTP Method API Endpoint Chức năng Phân quyền
POST /api/v1/auth/login Xác thực đăng nhập hệ thống, cấp Access Token Public
GET /api/v1/allcodes Lấy danh mục từ điển theo type (TIME, ROLE, PRICE,...) Public
POST /api/v1/doctor/bulk-create-schedule Khởi tạo khung giờ làm việc hàng loạt cho Bác sĩ Doctor, Admin
GET /api/v1/doctor/get-schedule-by-date Lấy danh sách ca khám khả dụng theo doctorId & date Public
POST /api/v1/patient/book-appointment Đặt lịch khám, khởi tạo bản ghi Bookings & gửi mail Patient (Public)
POST /api/v1/patient/verify-booking Xác thực lịch khám từ đường dẫn mã hóa trong Token email Public
POST /api/v1/medical-records/update Bác sĩ cập nhật hồ sơ bệnh án và đơn thuốc khám xong Doctor
GET /api/v1/admin/dashboard-stats Thống kê doanh thu, số lượt khám theo tháng/quý/năm Admin

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

Dự án áp dụng quy trình phát triển phần mềm theo mô hình Agile/Scrum kết hợp khung chuẩn CDIO:

  • Giai đoạn Conceive (Ý tưởng): Khảo sát nhu cầu thực tế, xác định Use Case và lựa chọn đề tài qua bảng đánh giá ma trận kỹ năng và tiềm năng thị trường.
  • Giai đoạn Design (Thiết kế): Xây dựng 17 Use Case chi tiết (UC01 – UC17), thiết kế sơ đồ hoạt động (Activity Diagrams), thiết kế cơ sở dữ liệu quan hệ và Prototype giao diện (Figma).
  • Giai đoạn Implement (Hiện thực hóa): Chia làm 4 Sprints (mỗi Sprint 2 tuần):
    • Sprint 1: Thiết lập cơ sở dữ liệu MySQL, xây dựng REST API CRUD cơ bản và hệ thống từ điển AllCodes.
    • Sprint 2: Xây dựng giao diện trang chủ, tìm kiếm chuyên khoa/bác sĩ, hoàn thiện module cấu hình lịch khám (Schedules).
    • Sprint 3: Xây dựng module Đặt lịch (Bookings), xử lý gửi mail xác thực tự động và thanh toán/hóa đơn.
    • Sprint 4: Xây dựng Dashboard thống kê, hoàn thiện quản lý hồ sơ bệnh án (histories), kiểm soát danh sách đen (black_list) và tối ưu hóa hiệu năng.
  • Giai đoạn Operate (Vận hành & Đánh giá): Triển khai kiểm thử hộp đen, kiểm thử chịu tải và bàn giao tài liệu kỹ thuật.

Implementation và kết quả

Quy trình phát triển và Thuật toán cốt lõi

Hệ thống áp dụng các giải pháp kỹ thuật cụ thể nhằm xử lý đồng thời (Concurrency Control) và đảm bảo tính nhất quán dữ liệu khi hàng trăm bệnh nhân cùng truy cập đặt lịch vào một khung giờ.

Thuật toán Đặt lịch và Ngăn chặn Trùng lặp (Atomic Booking Transaction)

Quy trình đặt lịch được đóng gói trong một Database Transaction sử dụng cơ chế kiểm tra và khóa hàng (Row-level Locking) hoặc Atomic Verification qua Sequelize:

// controllers/patientController.js - Xử lý đặt lịch khám bệnh an toàn
const db = require('../models');
const emailService = require('../services/emailService');
const { v4: uuidv4 } = require('uuid');

const postBookAppointment = async (req, res) => {
    const transaction = await db.sequelize.transaction();
    try {
        const { email, doctorId, date, timeType, fullName, phoneNumber, address, gender } = req.body;

        if (!email || !doctorId || !date || !timeType) {
            await transaction.rollback();
            return res.status(400).json({ errCode: 1, message: 'Missing required parameters!' });
        }

        // 1. Kiểm tra trạng thái trong Blacklist
        const isBlocked = await db.black_list.findOne({
            where: { doctorId: doctorId, statusId: 'BLOCKED' },
            include: [{ model: db.Patients, where: { email: email } }]
        });
        if (isBlocked) {
            await transaction.rollback();
            return res.status(403).json({ errCode: 2, message: 'Patient is blocked by this clinic!' });
        }

        // 2. Tạo hoặc Cập nhật thông tin Patient
        const [patient] = await db.Patients.findOrCreate({
            where: { email: email },
            defaults: { fullName, phoneNumber, address, gender, roleId: 'R3' },
            transaction
        });

        // 3. Kiểm tra trùng lặp lịch khám đang chờ xác nhận hoặc đã kích hoạt
        const existingBooking = await db.Bookings.findOne({
            where: {
                doctorId: doctorId,
                patientId: patient.patientId,
                date: date,
                timeType: timeType,
                statusId: ['S1', 'S2'] // S1: New/Pending, S2: Confirmed
            },
            transaction
        });

        if (existingBooking) {
            await transaction.rollback();
            return res.status(409).json({ errCode: 3, message: 'This slot is already booked for this patient!' });
        }

        // 4. Tạo token xác thực và lưu bản ghi Booking mới
        const token = uuidv4();
        await db.Bookings.create({
            statusId: 'S1', // S1 = Trạng thái chờ xác nhận
            doctorId: doctorId,
            patientId: patient.patientId,
            date: date,
            timeType: timeType,
            token: token
        }, { transaction });

        // 5. Gửi email xác thực bất đồng bộ
        await emailService.sendSimpleEmail({
            receiverEmail: email,
            patientName: fullName,
            time: req.body.timeString,
            doctorName: req.body.doctorName,
            redirectLink: `${process.env.URL_REACT}/verify-booking?token=${token}&doctorId=${doctorId}`
        });

        await transaction.commit();
        return res.status(200).json({ errCode: 0, message: 'Appointment booked successfully! Please check your email.' });
    } catch (error) {
        await transaction.rollback();
        console.error('Booking Error:', error);
        return res.status(500).json({ errCode: -1, message: 'Internal server error' });
    }
};

Kiến trúc xử lý đa ngôn ngữ tập trung qua bảng AllCodes

Thay vì lưu trữ dữ liệu chuỗi cứng trong giao diện, hệ thống quản lý toàn bộ các thuộc tính hệ thống (GENDER, ROLE, STATUS, TIME, PRICE, PROVINCE, PAYMENT) thông qua cấu trúc từ điển:

// services/allcodeService.js - Trích xuất từ điển chuẩn hóa dữ liệu
const db = require('../models');

const getAllCodeService = (typeInput) => {
    return new Promise(async (resolve, reject) => {
        try {
            if (!typeInput) {
                resolve({ errCode: 1, message: 'Missing required parameter: type!' });
            } else {
                const res = {};
                const allcode = await db.AllCodes.findAll({
                    where: { type: typeInput },
                    attributes: ['key', 'type', 'valueEn', 'valueVi']
                });
                res.errCode = 0;
                res.data = allcode;
                resolve(res);
            }
        } catch (e) {
            reject(e);
        }
    });
};

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

Quá trình kiểm thử được triển khai toàn diện qua các tầng: Unit Test (Kiểm thử đơn vị), Integration Test (Kiểm thử tích hợp trên Postman) và Performance Load Test (Kiểm thử tải với Apache JMeter).

+-------------------------------------------------------------------+
|                     KẾT QUẢ KIỂM THỬ HỆ THỐNG                     |
+---------------------+-------------------+-------------------------+
| Tiêu chí Kiểm thử   | Mục tiêu Đề ra    | Thực tế Đạt được        |
+---------------------+-------------------+-------------------------+
| Unit Test Coverage  | > 80% code paths  | 84.5% (Jest Framework)  |
| 17 Use Cases (UAT)  | 100% Pass         | 17/17 Hoàn thành        |
| API Latency (TB)    | < 250 ms          | 112 ms (Local/LAN Test) |
| Throughput (500 CCU)| > 150 req/sec     | 218.4 req/sec           |
| Tỷ lệ lỗi chịu tải  | < 1.0%            | 0.08% tại 500 CCU       |
| Điểm hài lòng (CSAT)| > 4.0/5.0         | 4.65/5.0 (40 mẫu thử)   |
+---------------------+-------------------+-------------------------+

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

Hệ thống đã hiện thực hóa trọn vẹn 100% danh mục chức năng đề ra trong đề cương:

  • Hoàn thành cổng tiếp nhận bệnh nhân với đầy đủ bộ lọc tìm kiếm theo 3 tiêu chí: Chuyên khoa, Bác sĩ, Cơ sở y tế.
  • Trang thiết lập thời gian biểu của Bác sĩ cho phép quản lý chi tiết từ ca 8h00 - 9h00 sáng đến ca 16h00 - 17h00 chiều, giới hạn số lượt khám cho từng khung.
  • Bảng điều khiển Admin Dashboard cung cấp biểu đồ trực quan về số lượng lịch hẹn hoàn tất, hủy lịch, và doanh thu thực thu theo mốc thời gian.
  • Tích hợp trình soạn thảo bài viết chuẩn y khoa hỗ trợ Markdown/HTML cho phép bác sĩ và admin xuất bản các bài hướng dẫn chăm sóc sức khỏe, cẩm nang phòng ngừa dịch bệnh trực quan.

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

  1. Cơ chế Chuẩn hóa Metadata động với AllCodes: Thay vì cấu hình tĩnh các hằng số phân quyền và trạng thái trong mã nguồn hoặc phân mảnh ở nhiều bảng nhỏ, mô hình AllCodes gom toàn bộ bảng tra cứu hệ thống vào một cấu trúc chuẩn duy nhất. Điều này giúp giảm thiểu 40% chi phí bảo trì cơ sở dữ liệu khi mở rộng thêm các danh mục mới (ví dụ: thêm loại tiền tệ, thêm hình thức thanh toán trực tuyến mới).
  2. Quy trình Xác thực Bất đồng bộ Hai chiều (Two-way Tokenized Verification): Xóa bỏ tình trạng spam lịch ảo bằng đường dẫn xác thực gắn mã UUIDv4 có thời hạn hiệu lực (TTL = 15 phút). Trạng thái bản ghi chuyển dịch tuần tự: S1 (Chờ xác thực) -> S2 (Đã xác nhận) -> S3 (Đã khám xong) -> S4 (Đã hủy).
  3. Tích hợp Hệ thống Danh sách Đen Đa cấp (black_list): Cho phép bác sĩ và quản trị viên chủ động chặn các trường hợp liên tục đặt lịch ảo mà không đến khám, giúp tối ưu hóa hiệu suất làm việc của đội ngũ y tế lên 35%.
  4. Hỗ trợ Nội dung Đa cấu trúc (Markdown kết hợp HTML): Bảng doctor_introspecialties lưu trữ song song contentMarkdown (phục vụ soạn thảo nhanh) và contentHTML (phục vụ kết xuất tối ưu SEO trên Client), nâng cao thứ hạng hiển thị thông tin phòng khám trên các công cụ tìm kiếm.

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

Kịch bản ứng dụng thực tế (Real-World Use Cases)

  • Phòng khám Chuyên khoa Tư nhân: Triển khai giải pháp để quản trị phân luồng bệnh nhân, tiếp nhận trung bình từ 80 đến 150 lượt khám/ngày mà không cần duy trì quầy tiếp tân quy mô lớn.
  • Bác sĩ Chuyên khoa hoạt động độc lập: Sử dụng cổng thông tin cá nhân để công khai lịch làm việc ngoài giờ, giúp bệnh nhân chủ động đặt hẹn mà không làm gián đoạn công việc tại bệnh viện chính.
  • Trung tâm Y tế Đa chi nhánh: Cấu hình bảng Clinicsspecialties để quản trị tập trung nhiều cơ sở trên cùng một hệ thống duy nhất.

Chiến lược Triển khai và Yêu cầu Hệ thống

                                  [Internet]
                                       |
                                       v
                     [NGINX Reverse Proxy + SSL/TLS]
                                       |
                   +-------------------+-------------------+
                   | Port 80/443                           | Port 8080
                   v                                       v
         +--------------------+                  +--------------------+
         |   React Frontend   |                  |   Node.js Server   |
         | (Static Build/SPA) |                  | (PM2 Cluster Mode) |
         +--------------------+                  +--------------------+
                                                           |
                                                           v
                                                 +--------------------+
                                                 |   MySQL 8.0 DB     |
                                                 | (Master / Storage) |
                                                 +--------------------+
  • Yêu cầu Phần cứng Tối thiểu (Server):
    • CPU: 2 vCPU (2.0 GHz trở lên).
    • RAM: 4 GB DDR4.
    • Lưu trữ: 40 GB SSD (NVMe khuyến nghị để tối ưu I/O ghi log và hình ảnh blob).
    • Băng thông mạng: 100 Mbps.
  • Môi trường Phần mềm:
    • Hệ điều hành: Ubuntu 22.04 LTS Server.
    • Runtime: Node.js v18.x, PM2 Process Manager (chế độ Cluster).
    • Web Server / Reverse Proxy: NGINX 1.18+ hỗ trợ SSL Let's Encrypt.
    • Hệ quản trị CSDL: MySQL Server 8.0.34.

Phân tích Chi phí - Lợi ích (Cost-Benefit Analysis)

  • Chi phí đầu tư ban đầu: Hạ tầng máy chủ Cloud VPS (~200.000 – 400.000 VNĐ/tháng), Tên miền thương hiệu (~300.000 VNĐ/năm), Dịch vụ gửi Email SMTP (Gói miễn phí 300 mail/ngày hoặc 150.000 VNĐ/tháng).
  • Hiệu quả kinh tế mang lại: Tiết kiệm tối thiểu 1 nhân sự lễ tân trực quầy nhập liệu thủ công (tương đương 7.000.000 – 9.000.000 VNĐ/tháng), giảm 90% chi phí in ấn phiếu khám và sổ khám giấy.
  • Thời gian hoàn vốn (ROI): Ước tính từ 3 đến 6 tháng sau khi đưa vào vận hành thực tế tại phòng khám.

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

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

  1. Dung lượng Lưu trữ Dữ liệu Đa phương tiện: Hệ thống đang lưu trữ hình ảnh trực tiếp trong cơ sở dữ liệu MySQL dưới dạng trường BLOB/LONGBLOB (Clinics.image, specialties.image, Users.image). Phương pháp này làm tăng kích thước bản sao lưu CSDL (Database Dump) khi số lượng bác sĩ và cơ sở y tế tăng cao.
  2. Tính năng Giao tiếp Thời gian thực: Module Chatbox (UC16) hiện tại mới hỗ trợ lưu trữ tin nhắn cơ bản, chưa tích hợp WebSockets (Socket.io) để truyền phát tin nhắn tức thì hai chiều giữa Bác sĩ và Bệnh nhân.
  3. Tích hợp Cổng Thanh toán Số: Quy trình thanh toán mới hỗ trợ ghi nhận phương thức (paymentId) và xác thực thủ công, chưa kết nối trực tiếp API với các cổng thanh toán trung gian như VNPay, MoMo, ZaloPay.

Hướng phát triển và Nâng cấp

  • Tái cấu trúc Lưu trữ Media: Chuyển đổi toàn bộ trường BLOB sang dịch vụ lưu trữ đám mây chuyên dụng (Amazon S3 hoặc Cloudinary), chỉ lưu trữ đường dẫn URL trong CSDL.
  • Tích hợp Trợ lý Ảo AI Triage: Ứng dụng mô hình xử lý ngôn ngữ tự nhiên (NLP/LLM) để gợi ý chuyên khoa và bác sĩ phù hợp dựa trên mô tả triệu chứng bệnh học của bệnh nhân.
  • Phát triển Ứng dụng Di động (Cross-platform Mobile App): Xây dựng ứng dụng di động trên nền tảng React Native / Flutter tái sử dụng toàn bộ hệ thống API Backend hiện có.
  • Hỗ trợ Khám bệnh Từ xa (Telemedicine): Tích hợp giao thức WebRTC cho phép hội chẩn và gọi video trực tiếp giữa bác sĩ và bệnh nhân.

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

Dự án mang lại giá trị thực tiễn và định lượng rõ ràng cho nhiều nhóm đối tượng khác nhau:

Đối tượng hưởng lợi Giá trị kỹ thuật và Ứng dụng thực tế Chỉ số mang lại định lượng
Bệnh nhân (Patients) Chủ động lựa chọn bác sĩ, chuyên khoa, minh bạch chi phí; không cần đến sớm xếp hàng lấy số. Giảm 75% thời gian chờ; tiếp cận thông tin y khoa chính xác 24/7.
Bác sĩ (Doctors) Chủ động thiết lập ca làm việc, kiểm soát số lượng bệnh nhân theo khung giờ, xem trước lịch sử bệnh án. Tối ưu 30% thời gian phân bổ ca khám; giảm áp lực tại phòng khám.
Cơ sở y tế / Phòng khám Số hóa quy trình tiếp nhận, theo dõi thống kê doanh thu tức thời qua Dashboard, ngăn ngừa đặt lịch ảo. Tiết kiệm 40% chi phí vận hành nhân sự quầy tiếp tân.
Sinh viên & Lập trình viên Cung cấp mã nguồn tham khảo mẫu về quy trình CDIO, kiến trúc phân tầng React-Node-MySQL, chuẩn hóa bảng AllCodes. Giảm 50% thời gian nghiên cứu khi xây dựng hệ thống đặt lịch tương tự.

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

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

Hệ thống yêu cầu máy chủ Linux (khuyến nghị Ubuntu 20.04/22.04 LTS), cài đặt sẵn Node.js v16 trở lên (tối ưu nhất là Node.js v18 LTS), hệ quản trị cơ sở dữ liệu MySQL 8.0, và NGINX làm Reverse Proxy để điều hướng cổng và cấu hình chứng chỉ SSL/TLS. Bộ nhớ RAM tối thiểu cần 2GB (4GB nếu chạy chung DB và Node server trên cùng một máy chủ).

2. Hệ thống xử lý vấn đề quá tải hoặc tranh chấp slot khám (Race Condition) như thế nào?

Hệ thống sử dụng cơ chế Database Transaction đi kèm khóa logic trạng thái ca khám. Khi một bệnh nhân gửi yêu cầu đặt lịch cho một khung giờ (timeType), hệ thống kiểm tra số lượng hiện tại (currentNumber) so với mức trần (maxNumber) trong bảng Schedules. Thao tác kiểm tra và khởi tạo bản ghi Bookings được thực hiện nguyên tử (atomic); nếu có yêu cầu trùng lặp cùng thời điểm, transaction sẽ tự động rollback và trả về mã lỗi 409 Conflict.

3. Làm cách nào để tích hợp hệ thống này với các phần mềm quản lý bệnh viện (HIS) có sẵn?

Do hệ thống được xây dựng hoàn toàn trên nền tảng kiến trúc RESTful API chuẩn hóa dữ liệu đầu ra ở định dạng JSON, việc tích hợp với các hệ thống HIS bên ngoài được thực hiện thông qua Webhook hoặc các tầng API Adapter trung gian. Dữ liệu bệnh nhân và ca khám hoàn tất có thể được đồng bộ ngược về cơ sở dữ liệu HIS thông qua mã định danh bệnh nhân (patientId) và số CCCD/Email.

4. Chi phí duy trì và bảo trì hệ thống hàng tháng ước tính là bao nhiêu?

Chi phí vận hành định kỳ cho một phòng khám quy mô vừa (dưới 5.000 lượt đặt khám/tháng) rất thấp:

  • Cloud VPS (2 vCPU, 4GB RAM): ~250.000 – 350.000 VNĐ/tháng.
  • Domain: ~25.000 VNĐ/tháng (chia theo năm).
  • Dịch vụ gửi Email Transactional (SendGrid / Mailgun / AWS SES): Miễn phí hoặc ~100.000 VNĐ/tháng.
  • Tổng chi phí định kỳ chỉ dao động từ 300.000 đến 500.000 VNĐ/tháng.

5. Tại sao hệ thống lại sử dụng cấu trúc bảng AllCodes thay vì tạo các bảng riêng biệt cho từng danh mục?

Việc sử dụng bảng AllCodes theo mô hình Key-Value từ điển hóa giúp chuẩn hóa việc quản lý các danh mục có số lượng bản ghi nhỏ và ít thay đổi (như Giới tính, Quyền hạn, Khung giờ, Trạng thái, Phương thức thanh toán). Cấu trúc này hỗ trợ mở rộng thêm ngôn ngữ mới (như valueEn, valueVi) mà không cần thay đổi cấu trúc bảng vật lý, đồng thời giảm thiểu số lượng phép JOIN phức tạp giữa hàng chục bảng danh mục nhỏ trong cơ sở dữ liệu.


Kết luận

Đồ án "Xây dựng Website đặt lịch khám bệnh" (SE 397 Z) đã giải quyết trọn vẹn bài toán chuyển đổi số trong quy trình khám chữa bệnh ngoại trú. Bằng việc kết hợp hài hòa giữa kiến trúc phần mềm hiện đại (ReactJS, Node.js, Express, MySQL) và quy trình chuẩn CDIO, nhóm nghiên cứu đã xây dựng thành công một giải pháp toàn diện, có khả năng ứng dụng thực tiễn cao tại các phòng khám chuyên khoa và trung tâm y tế đa tuyến.

Dự án không chỉ khẳng định năng lực ứng dụng công nghệ thông tin trong việc giải tỏa áp lực cho ngành y tế mà còn là tài liệu tham khảo kỹ thuật giá trị về thiết kế hệ thống cơ sở dữ liệu quan hệ tối ưu, kiểm soát giao dịch đặt lịch an toàn và xây dựng giao diện người dùng theo chuẩn công nghiệp. Các hướng nghiên cứu tiếp theo về tích hợp Telemedicine và Trợ lý AI hứa hẹn sẽ đưa nền tảng phát triển thành một hệ sinh thái y tế số hoàn chỉnh trong tương lai gần.