Giới thiệu dự án
Sự bùng phát của các đợt dịch bệnh cùng áp lực quá tải cục bộ tại các cơ sở y tế tuyến đầu đã thúc đẩy mạnh mẽ tiến trình chuyển đổi số trong lĩnh vực chăm sóc sức khỏe (HealthTech). Theo thống kê từ Bộ Y tế và các tổ chức y tế quốc tế năm 2022, 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 truyền thống dao động từ 1.5 đến 3 giờ, trong đó thời gian tiếp xúc lâm sàng với bác sĩ chỉ chiếm khoảng 10-15 phút. Sự bất cập này xuất phát từ quy trình tiếp đón phân luồng thủ công, thiếu hụt kênh tương tác thời gian thực giữa bác sĩ và người bệnh.
Đề tài "Trang web đặt lịch khám trực tuyến" do sinh viên Đặng Huỳnh Hoàng Long và Phạm Ngọc Tiến (Ngành Công nghệ Thông tin - Chuyên ngành Công nghệ Phần mềm, Trường Đại học Sư phạm Kỹ thuật TP.HCM) thực hiện dưới sự hướng dẫn của TS. Nguyễn Thiên Bảo nhằm giải quyết triệt để bài toán phân luồng lịch khám, tối ưu hóa thời gian đặt hẹn và hiện đại hóa quản trị y tế tư nhân lẫn công lập.
+-----------------------------------------------------------------------------------+
| CÁC MỤC TIÊU CỐT LÕI CỦA DỰ ÁN |
+-----------------------------------------------------------------------------------+
| 1. Xây dựng nền tảng Web App đặt lịch theo thời gian thực (Real-time Booking). |
| 2. Chuẩn hóa kiến trúc RESTful API phục vụ luồng dữ liệu y tế đa tác nhân. |
| 3. Triển khai thuật toán khóa khung giờ linh hoạt (Dynamic Time-Slot Locking). |
| 4. Thiết lập hệ thống quản trị 3 phân quyền: Quản trị viên, Bác sĩ và Bệnh nhân. |
| 5. Tích hợp cổng thanh toán và xác thực qua email tự động khép kín. |
+-----------------------------------------------------------------------------------+
Giải pháp được xây dựng dựa trên kiến trúc phân tách Client-Server hiện đại: Phía máy chủ sử dụng Node.js kết hợp framework Express và Strapi CMS nhằm khai thác tối đa cơ chế Non-blocking I/O và Event Loop; phía máy khách xây dựng ứng dụng Single Page Application (SPA) trên nền React.js sử dụng React Hooks; tầng lưu trữ dữ liệu triển khai trên hệ quản trị cơ sở dữ liệu quan hệ MySQL.
Kỳ vọng định lượng của hệ thống:
- Giảm thời gian chờ đợi tại phòng khám xuống dưới 15 phút.
- Tốc độ phản hồi API trung bình đạt < 180ms với tải đồng thời 500 CCU.
- Tự động hóa 100% quy trình gửi email xác nhận đặt chỗ và phân phối link thanh toán.
Phạm vi và giới hạn: Hệ thống tập trung giải quyết quy trình đăng ký, phân bổ lịch khám ngoại trú theo chuyên khoa/tỉnh thành, kiểm soát đơn đặt lịch và đối soát doanh thu. Hệ thống chưa tích hợp hồ sơ bệnh án điện tử (EMR) chuyên sâu và chưa chẩn đoán từ xa qua video call trực tiếp.
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 nền tảng đặt lịch khám hàng đầu tại Việt Nam như BookingCare và JioHealth cho thấy nhiều điểm mạnh nhưng vẫn tồn tại các rào cản kỹ thuật và trải nghiệm người dùng:
| Tiêu chí |
BookingCare |
JioHealth |
Giải pháp đề xuất của đồ án |
| Giao diện & UX |
Bố cục thông tin dày đặc, độ tương phản cao |
Đẹp, hiện đại nhưng nhiều chi tiết nhỏ gây rối mắt |
Giao diện tối giản, phân cấp rõ ràng theo Step-by-Step |
| Phân quyền Bác sĩ |
Phụ thuộc hoàn toàn vào hệ thống vận hành trung tâm |
Tập trung vào đội ngũ bác sĩ nội bộ của hệ thống |
Bác sĩ tự đăng ký, chủ động cấu hình ca khám và duyệt đơn |
| Cơ chế Khóa Slot |
Cập nhật định kỳ (Polling) |
WebSocket theo phiên |
Khóa slot tự động theo trạng thái giao dịch & Email Token |
| Chi phí vận hành |
Cao (hạ tầng đám mây phức tạp) |
Rất cao (hệ sinh thái khép kín) |
Tối ưu với Node.js runtime, MySQL và Strapi CMS linh hoạt |
Phân tích yêu cầu chức năng theo mô hình MoSCoW:
- Must have (Bắt buộc): Xác thực đa quyền (Admin/Doctor/Patient), tìm kiếm bác sĩ theo chuyên khoa & tỉnh thành, tạo/sửa lịch khám, khóa khung giờ tự động, gửi email kích hoạt/hủy hẹn, xử lý thanh toán hóa đơn.
- Should have (Nên có): Bảng điều khiển (Dashboard) thống kê doanh thu cho Admin, duyệt tài khoản bác sĩ tự động/bán tự động, giao diện quản lý lịch khám dạng Timeline.
- Could have (Có thể có): Gợi ý bác sĩ nổi bật ở trang chủ, tính năng lọc nâng cao theo mức giá khám.
- Won't have (Chưa làm đợt này): Kê đơn thuốc điện tử, tư vấn trực tuyến qua WebRTC.
Thiết kế hệ thống
Kiến trúc hệ thống tuân thủ mô hình phân tầng Client - Server tách biệt, giao tiếp qua giao thức HTTP/HTTPS với định dạng dữ liệu chuẩn JSON.
graph TD
subgraph Client_Layer ["Client Layer (React.js SPA)"]
UI_User["Giao diện Bệnh nhân (Booking, Filter)"]
UI_Doctor["Giao diện Bác sĩ (Schedule, Approve)"]
UI_Admin["Giao diện Quản trị (CMS, Analytics)"]
end
subgraph API_Gateway ["API Gateway & Controller"]
Express_Router["Express.js Router / Middlewares"]
Auth_Guard["JWT / Session Authentication Guard"]
end
subgraph Service_Layer ["Business Logic & Framework"]
Strapi_Service["Strapi Headless CMS Engine"]
Doctor_Service["Doctor & Clinic Service"]
Booking_Service["Slot Locking & Booking Logic"]
Mail_Service["Nodemailer Notification Engine"]
end
subgraph Data_Layer ["Persistence Layer"]
MySQL_DB[("MySQL Database (doctor, schedule, booking...)")]
end
UI_User -->|RESTful Requests| Express_Router
UI_Doctor -->|RESTful Requests| Express_Router
UI_Admin -->|RESTful Requests| Express_Router
Express_Router --> Auth_Guard
Auth_Guard --> Doctor_Service
Auth_Guard --> Booking_Service
Auth_Guard --> Strapi_Service
Booking_Service --> Mail_Service
Doctor_Service --> MySQL_DB
Booking_Service --> MySQL_DB
Strapi_Service --> MySQL_DB
Technology Stack & Versions:
- Frontend: React.js
v16.8.0+ (sử dụng Functional Components, React Hooks: useState, useEffect, useCallback), Webpack v4.44.x, Babel v7.x, Axios v0.21.x.
- Backend Runtime: Node.js
v14.x (LTS), Express Framework v4.17.x, Strapi Headless CMS v3.x / v4.x.
- Database Management System: MySQL
v8.0 / MariaDB v10.4 thông qua môi trường mô phỏng XAMPP.
Thiết kế cơ sở dữ liệu quan hệ (RDBMS Schema core tables):
-- Cấu trúc các bảng cốt lõi của hệ thống đặt lịch
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role_id ENUM('ADMIN', 'DOCTOR', 'PATIENT') NOT NULL,
full_name VARCHAR(255) NOT NULL,
phone_number VARCHAR(20),
status ENUM('PENDING', 'ACTIVE', 'BLOCKED') DEFAULT 'ACTIVE'
);
CREATE TABLE doctor_clinic_specialty (
id INT AUTO_INCREMENT PRIMARY KEY,
doctor_id INT NOT NULL,
specialty_id INT NOT NULL,
clinic_id INT NOT NULL,
price INT NOT NULL,
payment_method VARCHAR(50),
province_id VARCHAR(50),
FOREIGN KEY (doctor_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE schedules (
id INT AUTO_INCREMENT PRIMARY KEY,
doctor_id INT NOT NULL,
date DATE NOT NULL,
time_type VARCHAR(20) NOT NULL, -- e.g., 'T1' (8:00-9:00), 'T2' (9:00-10:00)
max_number INT DEFAULT 1,
current_number INT DEFAULT 0,
status ENUM('AVAILABLE', 'LOCKED', 'FULL') DEFAULT 'AVAILABLE',
FOREIGN KEY (doctor_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE bookings (
id INT AUTO_INCREMENT PRIMARY KEY,
status_id ENUM('NEW', 'CONFIRMED', 'PAID', 'CANCELLED') DEFAULT 'NEW',
doctor_id INT NOT NULL,
patient_id INT NOT NULL,
schedule_id INT NOT NULL,
token VARCHAR(255),
payment_status ENUM('UNPAID', 'PAID') DEFAULT 'UNPAID',
FOREIGN KEY (schedule_id) REFERENCES schedules(id)
);
Đặc tả RESTful API Endpoints tiêu biểu:
| Method |
Endpoint URI |
Phân quyền |
Mô tả nghiệp vụ |
POST |
/api/v1/auth/login |
Public |
Đăng nhập hệ thống, cấp mã định danh |
POST |
/api/v1/auth/register-doctor |
Public |
Bác sĩ gửi hồ sơ đăng ký (chờ duyệt) |
GET |
/api/v1/doctors/specialty/:id |
Public |
Lấy danh sách bác sĩ theo chuyên khoa & tỉnh thành |
POST |
/api/v1/bookings/reserve |
Patient |
Khóa tạm thời khung giờ & gửi email xác nhận |
POST |
/api/v1/bookings/doctor-confirm |
Doctor |
Bác sĩ phê duyệt lịch hẹn, gửi link thanh toán |
POST |
/api/v1/admin/doctors/approve |
Admin |
Phê duyệt hoặc từ chối tài khoản bác sĩ |
Phương pháp 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) kéo dài trong 14 tuần (07/03/2022 – 18/06/2022), chia thành 4 Sprint chính:
- Sprint 1 (Tuần 1-3): Khảo sát nghiệp vụ y tế, lập bảng đặc tả Use Case, thiết kế cơ sở dữ liệu và dựng khung hạ tầng Node.js / React.js.
- Sprint 2 (Tuần 4-7): Xây dựng Authentication, phân quyền Admin, tính năng quản lý bác sĩ, chuyên khoa và CRUD phòng khám.
- Sprint 3 (Tuần 8-11): Triển khai Module đặt lịch, giải thuật khóa khung giờ (
Dynamic Slot Locking), tích hợp Mail Service và Mock Payment Gateway.
- Sprint 4 (Tuần 12-14): Kiểm thử tích hợp (Integration Testing), tối ưu hiệu năng tải trang, vá lỗi và đóng gói tài liệu nghiệm thu.
Implementation và kết quả
Quá trình phát triển & Kỹ thuật cốt lõi
Trọng tâm xử lý nghiệp vụ của hệ thống là Cơ chế kiểm soát tranh chấp khung giờ khám (Slot Locking Mechanism) nhằm loại bỏ hoàn toàn lỗi đặt trùng lặp (Double Booking). Khi người dùng chọn một khung giờ, hệ thống sẽ thực hiện truy vấn nguyên tử (Atomic Check-and-Lock) để tạm khóa schedule_id.
/**
* Controller xử lý đặt lịch và khóa khung giờ khám bệnh
* Ngăn chặn xung đột đặt trùng lịch (Race Condition Mitigation)
*/
const handleBookingTransaction = async (req, res) => {
const { doctorId, patientId, scheduleId, bookingDate, timeType } = req.body;
const connection = await db.getConnection();
try {
await connection.beginTransaction();
// 1. Kiểm tra tính khả dụng của khung giờ với cờ khóa FOR UPDATE
const [slot] = await connection.query(
`SELECT id, status, current_number, max_number
FROM schedules
WHERE id = ? AND doctor_id = ? AND date = ? AND time_type = ?
FOR UPDATE`,
[scheduleId, doctorId, bookingDate, timeType]
);
if (!slot || slot.length === 0 || slot[0].status !== 'AVAILABLE') {
await connection.rollback();
return res.status(409).json({
errCode: 1,
message: 'Khung giờ khám này đã được người khác giữ chỗ hoặc đã đầy!'
});
}
// 2. Chuyển trạng thái khung giờ sang LOCKED
await connection.query(
`UPDATE schedules
SET status = 'LOCKED', current_number = current_number + 1
WHERE id = ?`,
[scheduleId]
);
// 3. Khởi tạo bản ghi Booking với trạng thái chờ xác nhận
const verifyToken = crypto.randomBytes(32).toString('hex');
const [bookingResult] = await connection.query(
`INSERT INTO bookings (status_id, doctor_id, patient_id, schedule_id, token, payment_status)
VALUES ('NEW', ?, ?, ?, ?, 'UNPAID')`,
[doctorId, patientId, scheduleId, verifyToken]
);
await connection.commit();
// 4. Kích hoạt dịch vụ gửi mail bất đồng bộ qua Nodemailer
await sendVerificationEmail({
to: req.body.email,
token: verifyToken,
bookingId: bookingResult.insertId,
doctorName: req.body.doctorName,
timeSlot: timeType
});
return res.status(200).json({
errCode: 0,
message: 'Đăng ký giữ chỗ thành công. Vui lòng kiểm tra email xác nhận!'
});
} catch (error) {
await connection.rollback();
console.error('Booking Transaction Error:', error);
return res.status(500).json({ errCode: -1, message: 'Lỗi máy chủ nội bộ' });
} finally {
connection.release();
}
};
Tại tầng máy khách (React.js), các trạng thái được cô lập hoàn toàn trong Functional Components thông qua useEffect hook để tải danh sách khung giờ thực tế theo từng ngày được chọn:
// React Component hiển thị danh sách slot khám động
import React, { useState, useEffect } from 'react';
import { getDoctorScheduleByDate } from '../../services/userService';
const DoctorSchedule = ({ doctorIdFromParent }) => {
const [allDays, setAllDays] = useState([]);
const [availableSlots, setAvailableSlots] = useState([]);
useEffect(() => {
// Khởi tạo danh sách ngày (7 ngày kế tiếp)
const days = generateNext7Days();
setAllDays(days);
if (days.length > 0) {
fetchSchedule(days[0].value);
}
}, [doctorIdFromParent]);
const fetchSchedule = async (selectedDate) => {
const res = await getDoctorScheduleByDate(doctorIdFromParent, selectedDate);
if (res && res.errCode === 0) {
// Lọc các khung giờ còn khả dụng (status === 'AVAILABLE')
setAvailableSlots(res.data.filter(slot => slot.status === 'AVAILABLE'));
}
};
return (
<div className="schedule-container">
<div className="slots-grid">
{availableSlots.length > 0 ? (
availableSlots.map((item, index) => (
<button key={index} className="btn-slot" onClick={() => handleBooking(item)}>
{item.timeType}
</button>
))
) : (
<p className="no-slot">Bác sĩ không có lịch hẹn trong ngày này.</p>
)}
</div>
</div>
);
};
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 Black-box Testing), kiểm thử API với Postman và kiểm thử tải trọng:
- Độ bao phủ Use Case: Hoàn thành kiểm thử 24/24 Use Case đã đặc tả (từ
UC_01 Đăng nhập đến UC_24 Bác sĩ duyệt lịch hẹn) với tỷ lệ Passed đạt 100% trong giai đoạn nghiệm thu.
- Hiệu năng chịu tải: Sử dụng công cụ Apache Benchmark kiểm thử máy chủ Node.js cục bộ:
- Tốc độ xử lý trung bình: 650 Requests/giây.
- Thời gian phản hồi trung bình (Latency): 154ms tại mức 200 kết nối đồng thời.
- Tỷ lệ lỗi gói tin (Error Rate): 0.00% trong điều kiện vận hành chuẩn.
- Kiểm thử trải nghiệm người dùng (UAT): Thực nghiệm trên nhóm 40 người dùng ngẫu nhiên (sinh viên, nhân viên y tế) đạt điểm chỉ số độ hài lòng (CSAT) 4.65/5.0 điểm, trong đó tiêu chí "Bố cục rõ ràng và tốc độ đặt hẹn nhanh" được đánh giá cao nhất.
Đổi mới và đóng góp
- Quy trình xác thực khép kín 3 bên (Patient - Doctor - Admin): Khác biệt với mô hình tiếp nhận một chiều, hệ thống tích hợp luồng phê duyệt tương tác: Bệnh nhân đăng ký -> Bác sĩ kiểm tra lịch và duyệt chuyên môn -> Hệ thống kích hoạt thanh toán.
- Cơ chế giải phóng Slot thông minh: Nếu bệnh nhân không xác nhận email hoặc không thanh toán trong vòng 15 phút, Cron Job của Node.js sẽ tự động chuyển trạng thái
schedules từ LOCKED về AVAILABLE, tối ưu hóa công suất làm việc của bác sĩ lên đến 35%.
- Lọc địa lý kết hợp chuyên khoa: Thuật toán lọc kết hợp bảng nối
doctor_clinic_specialty với chỉ mục (Index) theo province_id giúp rút ngắn thời gian tìm kiếm bác sĩ phù hợp từ 5 phút xuống còn dưới 10 giây.
Ứng dụng thực tế và triển khai
Hướng dẫn triển khai hạ tầng
Yêu cầu môi trường tối thiểu:
- Phần cứng: CPU 2 Cores, RAM 4GB, Dung lượng đĩa trống 20GB SSD.
- Phần mềm: Ubuntu Linux 20.04 LTS / Windows Server, Node.js
v14.17.0+, MySQL Server v8.0, Git runtime.
Các bước cấu hình và triển khai:
# 1. Khởi tạo cơ sở dữ liệu trên MySQL
mysql -u root -p -e "CREATE DATABASE medical_booking CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
# 2. Cài đặt và cấu hình Server Backend
cd backend/
npm install
cp .env.example .env # Cấu hình PORT=8080, DB_HOST=localhost, DB_NAME=medical_booking, EMAIL_APP_PASSWORD=...
npm run build && npm start
# 3. Cài đặt và dựng Client Frontend
cd ../frontend/
npm install
npm run build
# Phục vụ file tĩnh thông qua Nginx Reverse Proxy
sudo cp -r build/* /var/www/html/medical-booking/
Bài toán Chi phí - Hiệu quả (ROI):
Với một phòng khám vừa và nhỏ tiếp nhận trung bình 80 lượt khám/ngày, việc đưa trang web vào vận hành giúp:
- Cắt giảm 01 nhân sự trực tổng đài tiếp nhận lịch (tiết kiệm khoảng 80.000.000 VNĐ/năm).
- Hạn chế tình trạng hủy hẹn vào giờ chót (No-show rate) giảm từ 22% xuống còn dưới 6% nhờ cơ chế giữ chỗ và xác nhận qua thư điện tử.
Hạn chế và hướng phát triển
Hạn chế kỹ thuật
- Dự án chạy trên nền tảng Node.js v14 và kiến trúc cơ sở dữ liệu đơn khối (Monolithic Database), chưa phân tầng Caching với Redis để xử lý tải đột biến khi mở cổng tiêm chủng/khám cộng đồng.
- Module thanh toán đang ở giai đoạn tích hợp thử nghiệm (Sandbox Simulation), chưa kết nối trực tiếp cổng trung gian chính thức như VNPay, MoMo hay ZaloPay.
Hướng phát triển mở rộng
- Nâng cấp hệ thống Backend lên phiên bản Node.js LTS mới nhất, phân tách cấu trúc thành các Microservices (Auth Service, Schedule Service, Payment Service).
- Tích hợp công nghệ gọi video thời gian thực thông qua WebRTC để triển khai dịch vụ Telemedicine (Khám bệnh trực tuyến từ xa).
- Tích hợp ứng dụng di động đa nền tảng sử dụng React Native nhằm đồng bộ trải nghiệm thông báo đẩy (Push Notifications) cho bệnh nhân.
Đối tượng hưởng lợi
- Bệnh nhân & Người dùng: Chủ động lựa chọn bác sĩ, khung giờ khám chính xác, xóa bỏ 100% tình trạng xếp hàng lấy số truyền thống.
- Bác sĩ & Cơ sở Y tế: Tối ưu hóa quỹ thời gian làm việc, quản lý lịch trình trực quan, nâng cao uy tín thương hiệu cá nhân trên môi trường số.
- Lập trình viên & Sinh viên: Đồ án cung cấp tài liệu tham khảo hoàn chỉnh về kiến trúc Fullstack Node.js + React.js, xử lý Transaction trong cơ sở dữ liệu quan hệ MySQL và kỹ thuật xử lý bất đồng bộ.
Câu hỏi thường gặp
1. Hệ thống xử lý thế nào nếu hai người cùng bấm đặt một khung giờ cùng một tích tắc?
Hệ thống sử dụng kỹ thuật Transaction trong MySQL với câu lệnh truy vấn khóa hàng SELECT ... FOR UPDATE. Khi request thứ nhất kích hoạt transaction, hàng dữ liệu schedule đó sẽ bị khóa tạm thời. Request thứ hai buộc phải đợi, sau khi request thứ nhất hoàn tất và chuyển trạng thái thành LOCKED, request thứ hai sẽ nhận ngay thông báo lỗi xung đột (HTTP 409 Conflict) và yêu cầu chọn giờ khác.
2. Có thể triển khai hệ thống này trên hạ tầng Docker được không?
Hoàn toàn khả thi. Hệ thống dễ dàng đóng gói thành 3 container riêng biệt gồm: client-container (Nginx serve React build), server-container (Node.js runtime) và db-container (MySQL official image) thông qua tệp docker-compose.yml.
3. Trang web bảo mật thông tin tài khoản người dùng và bác sĩ như thế nào?
Mật khẩu người dùng được băm một chiều (Hash) bằng thuật toán bcrypt với muối (Salt round = 10) trước khi lưu vào MySQL. Toàn bộ API nghiệp vụ được bảo vệ thông qua cơ chế kiểm tra quyền hạn (Role-based Authorization Middleware).
4. Quy trình bác sĩ đăng ký tài khoản diễn ra như thế nào?
Bác sĩ đăng ký tài khoản trực tuyến trên trang /register-doctor, dữ liệu ban đầu sẽ có trạng thái PENDING. Sau khi Admin kiểm tra bằng cấp/thông tin hành nghề và phê duyệt trong trang quản trị, tài khoản mới chuyển sang ACTIVE và bác sĩ mới có thể đăng nhập vào hệ thống để tạo lịch khám.
5. Chi phí duy trì hạ tầng vận hành cho một phòng khám đơn lẻ là bao nhiêu?
Với lưu lượng khám khoảng 100-200 lượt/ngày, phòng khám chỉ cần thuê 01 gói Cloud VPS (2 Core CPU, 4GB RAM) với chi phí khoảng 200.000 - 350.000 VNĐ/tháng, cùng chi phí tên miền khoảng 250.000 VNĐ/năm.
Kết luận
Khóa luận tốt nghiệp "Trang web đặt lịch khám trực tuyến" của nhóm sinh viên Đặng Huỳnh Hoàng Long và Phạm Ngọc Tiến đã giải quyết xuất sắc bài toán số hóa quy trình y tế thông qua sự kết hợp hài hòa giữa bộ ba công nghệ Node.js - React.js - MySQL. Đồ án không chỉ hoàn thành trọn vẹn 24 Use Case nghiệp vụ từ quản trị, bác sĩ đến bệnh nhân mà còn đưa ra giải pháp giải quyết triệt để vấn đề xung đột lịch hẹn bằng kỹ thuật khóa khung giờ và xác thực đa lớp. Đây là tài liệu nghiên cứu và sản phẩm ứng dụng có giá trị thực tiễn cao, đóng góp thiết thực cho quá trình chuyển đổi số ngành y tế nước nhà.