URD: Thiết bị
| Module | Phiên bản | Cập nhật |
|---|---|---|
CORE-04 | v0.5 | 2026-07-21 |
Module Thiết bị làm gì
Xác định các yêu cầu hướng người dùng cho quản lý thiết bị và tích hợp phần cứng - cách một organizer đăng ký, quản lý và giám sát thiết bị vật lý (máy POS, ứng dụng di động, client web), và cách nền tảng tích hợp thiết bị ngoại vi (máy in, máy quét mã vạch, SoundBox, SoftPOS/NFC, màn hình phụ).
Thiết bị không chỉ là một bản ghi quản lý - nó là điểm neo runtime mà một phiên đăng nhập, một ca bán hàng, một ngăn kéo tiền và một báo cáo đều gắn vào (xem chương DSX). Vì vậy, thiết bị phải được nhận diện đúng và chỉ một lần trên mỗi phần cứng vật lý - nhận diện sai sinh ra thiết bị trùng, mất dấu vết ca và báo cáo.
Bốn ý cần hiểu trước
Đây là phần quan trọng nhất của tài liệu. Hiểu bốn ý dưới đây là hiểu phần lõi của module.
1. Một thiết bị, một định danh bền vững
Mỗi thiết bị mang một Định danh thiết bị (D_YYYYMMDD_<snowflakeId>) sinh đúng một lần khi thiết bị được tạo, và không đổi qua các lần gỡ cài đặt / cài đặt lại ứng dụng trên cùng phần cứng. Đây là bất biến quan trọng nhất của toàn module: nếu định danh trôi qua mỗi lần cài lại, cùng một cái máy POS sẽ bị hệ thống hiểu nhầm thành nhiều thiết bị khác nhau, mỗi lần lại là một bản ghi mới, một vòng đời mới, một lịch sử ca rời rạc.
Vì vậy định danh không được phép chỉ sống trong local storage của ứng dụng (thứ biến mất khi gỡ cài đặt hoặc khi trình duyệt xóa dữ liệu) - nó phải suy ra được từ chính phần cứng hoặc được phục hồi bằng một cơ chế không phụ thuộc bộ nhớ cục bộ (xem ý 3).
2. Đăng nhập là kiểm tra trước, tạo mới sau
Thiết bị không tự động có mặt trong hệ thống chỉ vì ai đó cài app lên nó. Mỗi lần đăng nhập, ứng dụng gọi một API hỏi: "định danh này đã thuộc merchant hiện tại chưa?"
- Có → thiết bị đã được biết đến, mọi thứ hoạt động bình thường, không có gì được tạo mới.
- Chưa → hệ thống tạo một bản ghi thiết bị mới, ở trạng thái
NEW(chưa kích hoạt).
Phép kiểm tra này chạy trên mọi loại client (POS, di động, trình duyệt), không riêng gì một nền tảng.
3. Kích hoạt là một hành động rời rạc, không phải một bước ẩn
Đây là chỗ dễ hiểu lầm nhất: tạo thiết bị mới không đồng nghĩa với kích hoạt nó. Một thiết bị NEW chỉ trở thành ACTIVATED qua đúng một con đường: ai đó quét hoặc nhập Mã kích hoạt của thiết bị đó rồi bấm "Kích hoạt".
Khi một thiết bị mới được tạo, hệ thống tự sinh Mã kích hoạt dưới hai dạng song song - một mã QR (quét bằng camera) và một mã Barcode (quét bằng máy quét mã vạch hoặc gõ tay). Có hai dạng vì hai lý do khác nhau:
- Không phải thiết bị nào cũng có camera để quét QR - Barcode phục vụ đúng nhóm thiết bị đó (máy POS chuyên dụng, máy tính không webcam).
- Trình duyệt đôi khi không giữ được định danh do chính sách ITP (Intelligent Tracking Prevention) - chặn cookie hoặc tập lệnh theo dõi hành vi giữa các trang web khác nhau, kéo theo giới hạn thời gian lưu trữ phía client - khi đó phép kiểm tra tự động ở ý 2 không đáng tin cậy, và việc kích hoạt bằng mã cho một con đường không phụ thuộc bộ nhớ trình duyệt để hoàn tất.
Mỗi Mã kích hoạt chỉ dùng được đúng một lần - dùng lại bị từ chối, kể cả trên chính thiết bị đó.
4. Vòng đời vận hành và tình trạng vật lý là hai trục khác nhau
Trạng thái vận hành (NEW → ACTIVATED → DEACTIVATED → SUSPENDED → ARCHIVED) trả lời câu "thiết bị này được phép giao dịch không". Tình trạng vật lý (Đang hoạt động / Đang bảo trì / Hư hỏng) trả lời một câu khác hẳn: "cái máy này có đang chạy tốt không". Một thiết bị có thể ACTIVATED (được phép bán hàng) trong khi Hư hỏng (hỏng thật) - và chính khoảng trống đó là lý do Tình trạng thiết bị tồn tại như một trục riêng, không lẫn vào Trạng thái vận hành.
1. Định nghĩa
| Thuật ngữ | Định nghĩa |
|---|---|
| Device | Một đơn vị phần cứng đã đăng ký (máy POS, thiết bị di động, máy trạm) tương tác với nền tảng |
| Định danh thiết bị (Device Identifier) | Chuỗi định danh duy nhất do hệ thống sinh D_YYYYMMDD_<snowflakeId>, gán một lần khi tạo thiết bị và không đổi qua các lần cài đặt lại |
| Device Code | Mã dễ đọc tùy chọn, duy nhất trong phạm vi merchant |
| Organization | Cấp cao nhất sở hữu một hoặc nhiều merchant và thiết bị |
| Merchant | Một đơn vị kinh doanh trong organizer; mỗi thiết bị được gán bắt buộc vào đúng một merchant |
| Hardware Info | Nhà sản xuất, mẫu mã, số serial, IMEI, MAC, bộ xử lý, RAM, lưu trữ, màn hình, pin |
| Software Info | Hệ điều hành, phiên bản OS, phiên bản app, firmware, lần cập nhật cuối, driver thiết bị ngoại vi |
| Device Status | Trạng thái vận hành theo vòng đời: NEW → ACTIVATED → DEACTIVATED → SUSPENDED → ARCHIVED |
| Device Condition (mới) | Tình trạng vật lý: Đang hoạt động / Đang bảo trì / Hư hỏng - độc lập với Device Status |
| Mã kích hoạt (Activation Code) (mới) | Mã dùng một lần, sinh khi tạo thiết bị mới, thể hiện dưới dạng QR và Barcode, dùng để chuyển thiết bị từ NEW sang ACTIVATED |
| Heartbeat | Ping online định kỳ (mỗi 5 phút); offline sau 15 phút im lặng |
| Machine UID | Định danh suy ra từ phần cứng, gửi trong header HTTP x-device-info |
| ITP (Intelligent Tracking Prevention) | Chính sách trình duyệt (mặc định trên Safari) chặn cookie hoặc tập lệnh theo dõi hành vi giữa các trang web khác nhau; hệ quả là giới hạn thời gian lưu trữ phía client, khiến định danh lưu trong trình duyệt (IndexedDB - xem WEB) có thể không được giữ ổn định giữa các phiên |
| ESC/POS | Ngôn ngữ lệnh máy in nhiệt |
| HID Keyboard-Wedge | Chế độ máy quét USB/Bluetooth mô phỏng nhập liệu bàn phím |
| SoftPOS | Chấp nhận thẻ không tiếp xúc NFC trên điện thoại Android, kích hoạt qua VNPAY KYC |
| SoundBox | Loa Bluetooth VNPAY phát thông báo xác nhận thanh toán |
| POS Point | Trạm bán hàng logic mà thiết bị phải được gán vào trước khi xử lý bán hàng |
2. Mô hình Khái niệm
Chỉ mang tính khái niệm - schema đầy đủ nằm trong mô hình miền Commerce.
3. Feature
DEV - Đăng ký, Định danh & Kích hoạt Thiết bị Một phần
Mã Tính năng: device/DEV · Phase: P2 · PRDs: PRD-DEV-001 · Dev: @nx/commerce
Tính năng này mang lại gì cho người dùng: chủ sở hữu đăng ký từng thiết bị phần cứng với tên i18n, loại và merchant bắt buộc; mỗi thiết bị mang một định danh bền vững không đổi qua các lần cài đặt lại; đăng nhập trên một thiết bị mới tự tạo bản ghi chờ kích hoạt; kích hoạt hoàn tất bằng cách quét/nhập một mã dùng-một-lần; thiết bị đi qua vòng đời trạng thái; và chủ sở hữu ghi nhận chi tiết phần cứng, phần mềm, bảo trì, tìm kiếm và xuất/nhập danh sách thiết bị của mình.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-DEV-001 | Bắt buộc | Chủ sở hữu có thể đăng ký thiết bị với tên, loại và gán merchant bắt buộc | Đã dựng |
URD-DEV-002 | Bắt buộc | Hệ thống tự sinh Định danh thiết bị duy nhất D_YYYYMMDD_<snowflakeId> khi tạo thiết bị | Đã dựng |
URD-DEV-003 | Bắt buộc | Tên thiết bị hỗ trợ i18n (tiếng Anh + tiếng Việt) | Đã dựng |
URD-DEV-004 | Bắt buộc | Trạng thái vận hành nhận 5 giá trị theo thứ tự: NEW → ACTIVATED → DEACTIVATED → SUSPENDED → ARCHIVED. • Kiểm tra chuyển trạng thái hợp lệ chưa được áp dụng - có thể đặt sang bất kỳ giá trị nào bất kể giá trị hiện tại. | Một phần |
URD-DEV-005 | Bắt buộc | Chủ sở hữu có thể kích hoạt thiết bị đã đăng ký (NEW → ACTIVATED) qua Mã kích hoạt (xem URD-DEV-027/028) | Một phần |
URD-DEV-006 | Bắt buộc | Chủ sở hữu có thể vô hiệu hóa (ACTIVATED → DEACTIVATED) và kích hoạt lại (DEACTIVATED → ACTIVATED) thiết bị | Đã dựng |
URD-DEV-007 | Bắt buộc | Chủ sở hữu có thể tạm ngưng thiết bị (ACTIVATED → SUSPENDED) vì lý do bảo mật | Đã dựng |
URD-DEV-008 | Bắt buộc | Chủ sở hữu có thể lưu trữ thiết bị (chỉ đọc vĩnh viễn, ẩn khỏi POS), kèm chọn Lý do ngừng dùng (xem URD-DEV-023) | Một phần |
URD-DEV-009 | Bắt buộc | Mọi bản ghi thiết bị dùng soft-delete; không bao giờ xóa vật lý | Đã dựng |
URD-DEV-010 | Bắt buộc | Truy cập API thiết bị yêu cầu xác thực (JWT hoặc Basic Auth) | Đã dựng |
URD-DEV-011 | Bắt buộc | Mã thiết bị, khi được cung cấp, phải duy nhất trong phạm vi merchant | Đã dựng |
URD-DEV-012 | Nên có | Chủ sở hữu có thể ghi thông tin bảo trì (ngày mua, hết hạn bảo hành, nhà cung cấp, ngày bảo trì gần nhất/kế tiếp, ghi chú) | Đã dựng |
URD-DEV-013 | Bắt buộc | Khi đăng nhập app, thiết bị được tự động kiểm tra và đăng ký nếu chưa thuộc merchant hiện tại (xem URD-DEV-026); thiết bị đã tồn tại được tái sử dụng nguyên trạng, không tạo bản ghi mới | Một phần |
URD-DEV-014 | Bắt buộc | Chủ sở hữu có thể tìm thiết bị theo tên, định danh, mã, trạng thái và loại | Đã dựng |
URD-DEV-015 | Nên có | Chủ sở hữu có thể nhập và xuất bản ghi thiết bị qua CSV | Đã dựng |
URD-DEV-016 | Bắt buộc | Chủ sở hữu có thể gán / gán lại thiết bị vào merchant khác; mỗi thiết bị luôn thuộc đúng một merchant | Đã dựng |
URD-DEV-017 | Nên có | Chủ sở hữu có thể ghi thông tin phần cứng cho thiết bị | Đã dựng |
URD-DEV-018 | Nên có | Chủ sở hữu có thể ghi thông tin phần mềm cho thiết bị | Đã dựng |
URD-DEV-019 | Nên có | Chủ sở hữu có thể đặt mã PIN trên thiết bị để xác thực cục bộ | Một phần |
URD-DEV-020 | Nên có | Danh sách đội thiết bị đánh dấu đến hạn/quá hạn bảo trì khi ngày hiện tại vượt qua ngày bảo trì kế tiếp đã ghi nhận, kèm thông báo nhắc nhở khi ngày đó sắp tới | Chưa dựng |
URD-DEV-021 | Bắt buộc | Thiết bị mang một thuộc tính Tình trạng (Đang hoạt động / Đang bảo trì / Hư hỏng), độc lập với Trạng thái vận hành; đánh dấu Hư hỏng chặn thiết bị khỏi mở phiên POS mới hoặc xử lý bán hàng cho đến khi gỡ về Đang hoạt động | Chưa dựng |
URD-DEV-022 | Nên có | Đánh dấu một thiết bị Hư hỏng phát một sự kiện thông báo thời gian thực đến đầu mối phụ trách thiết bị/bảo trì của merchant | Chưa dựng |
URD-DEV-023 | Bắt buộc | Lưu trữ một thiết bị yêu cầu chọn Lý do ngừng dùng (Đã thanh lý / Thất lạc / Bị mất cắp / Đã thay thế / Khác); lọc/báo cáo được theo lý do này | Chưa dựng |
URD-DEV-024 | Bắt buộc | Ngăn kéo tiền (Cash Drawer) đăng ký như một loại thiết bị riêng, đi qua đúng luồng tạo/sửa/vòng đời/tìm kiếm như mọi thiết bị khác; được đưa ra làm danh sách chọn khi mở ca trên một máy POS đã bật ngăn kéo tiền | Đã dựng |
URD-DEV-025 | Bắt buộc | Định danh thiết bị phải bền vững qua vòng đời cài đặt của cùng một phần cứng vật lý - suy ra hoặc phục hồi được từ chính phần cứng, không chỉ sống trong local storage của ứng dụng. • Gỡ cài đặt rồi cài đặt lại app trên cùng máy phải nhận lại đúng định danh cũ, không sinh định danh mới. | Chưa dựng |
URD-DEV-026 | Bắt buộc | Khi đăng nhập, ứng dụng gọi API kiểm tra thiết bị (theo Định danh thiết bị) đã thuộc merchant hiện tại hay chưa. • Nếu đã thuộc - thiết bị hoạt động bình thường, không tạo bản ghi mới. • Nếu chưa thuộc - hệ thống tạo một bản ghi thiết bị mới ở trạng thái NEW cho merchant đó; thiết bị mới này chưa được phép giao dịch cho đến khi kích hoạt (URD-DEV-028). | Chưa dựng |
URD-DEV-027 | Bắt buộc | Khi tạo một thiết bị mới (theo URD-DEV-026), hệ thống tự sinh một Mã kích hoạt duy nhất, thể hiện dưới hai dạng song song: mã QR (quét bằng camera) và mã Barcode (quét bằng máy quét mã vạch hoặc nhập tay). • Bản Barcode tồn tại song song QR để phục vụ kết nối cho thiết bị không có camera/chức năng scan QR. • Cơ chế này không phụ thuộc việc trình duyệt lưu giữ được định danh hay không, nên vẫn hoạt động khi chính sách ITP giới hạn lưu trữ phía client. | Chưa dựng |
URD-DEV-028 | Bắt buộc | Kích hoạt một thiết bị NEW hoàn tất bằng cách quét hoặc nhập Mã kích hoạt (Barcode/QR) rồi bấm "Kích hoạt"; thao tác này chuyển thiết bị từ NEW sang ACTIVATED. • Mỗi Mã kích hoạt chỉ dùng được đúng một lần - dùng lại (kể cả trên chính thiết bị đó) bị hệ thống từ chối. | Chưa dựng |
Trạng thái Vận hành Thiết bị
| Trạng thái | Ý nghĩa |
|---|---|
| NEW | Đã đăng ký (tự động hoặc thủ công), chưa kích hoạt (mặc định) |
| ACTIVATED | Hoạt động và được phép xử lý giao dịch |
| DEACTIVATED | Tạm vô hiệu hóa; có thể kích hoạt lại |
| SUSPENDED | Tạm ngưng chờ điều tra; không thể giao dịch |
| ARCHIVED | Ngừng vĩnh viễn; chỉ đọc; yêu cầu Lý do ngừng dùng |
Tình trạng Vật lý Thiết bị (mới, khái niệm)
| Tình trạng | Ý nghĩa |
|---|---|
| Đang hoạt động | Vận hành bình thường |
| Đang bảo trì | Đang được kỹ thuật viên xử lý theo lịch |
| Hư hỏng | Hỏng đột xuất; chặn phiên POS mới/bán hàng dù Trạng thái vận hành vẫn ACTIVATED |
Loại Thiết bị
| Mã loại | Nhãn |
|---|---|
| 100_POS_TERMINAL | Máy POS |
| 101_POS_WORKSTATION | Máy trạm POS |
| 200_MOBILE_POS | POS Di động |
| 300_BROWSER | Trình duyệt Web |
| 400_TABLET | Máy tính bảng |
| 401_BARCODE_SCANNER | Thiết bị máy quét mã vạch |
| 500_CASH_DRAWER | Ngăn kéo tiền |
| 999_OTHER | Khác |
AC-DEV-01: Đăng ký thủ công
| Cho trước | Khi | Thì |
|---|---|---|
| Chủ sở hữu | Đăng ký thiết bị với tên + loại + merchant | Thiết bị được tạo với trạng thái NEW; định danh duy nhất tự sinh |
| Có mã được cung cấp | Mã duy nhất trong phạm vi merchant |
AC-DEV-02: Định danh bền vững qua cài đặt lại
| Cho trước | Khi | Thì |
|---|---|---|
| Thiết bị đã kích hoạt trên một máy POS | Gỡ cài đặt rồi cài đặt lại app trên đúng máy đó | Đăng nhập lại nhận đúng Định danh thiết bị cũ, không sinh định danh mới |
AC-DEV-03: Kiểm tra thiết bị thuộc merchant khi đăng nhập
| Cho trước | Khi | Thì |
|---|---|---|
| Định danh thiết bị đã thuộc merchant hiện tại | Đăng nhập | Hệ thống nhận diện thiết bị đã biết; không tạo bản ghi mới; hoạt động bình thường |
| Định danh thiết bị chưa thuộc merchant nào (phần cứng mới, hoặc đổi merchant) | Đăng nhập | Hệ thống tạo một thiết bị mới ở trạng thái NEW cho merchant hiện tại |
AC-DEV-04: Sinh Mã kích hoạt cho thiết bị mới
| Cho trước | Khi | Thì |
|---|---|---|
| Một thiết bị mới vừa được tạo (theo AC-DEV-03) | Hệ thống khởi tạo bản ghi | Một Mã kích hoạt duy nhất được sinh, hiển thị dưới cả hai dạng QR và Barcode |
AC-DEV-05: Kích hoạt bằng Mã kích hoạt, dùng một lần
| Cho trước | Khi | Thì |
|---|---|---|
| Thiết bị NEW mang một Mã kích hoạt còn hiệu lực | Quét/nhập đúng mã rồi bấm "Kích hoạt" | Thiết bị chuyển NEW → ACTIVATED; mã bị vô hiệu hóa ngay sau đó |
| Mã kích hoạt đã được dùng trước đó | Quét/nhập lại đúng mã đó, bấm "Kích hoạt" | Bị từ chối - mã đã sử dụng, kể cả khi thao tác trên chính thiết bị đó |
MOB - Ứng dụng Di động Đã dựng
Mã Tính năng: device/MOB · Phase: P1 · PRDs: - · Dev: sale-renderer
Tính năng này mang lại gì cho người dùng: chủ sở hữu và thu ngân chạy POS, đơn hàng, thanh toán, lập hóa đơn và báo cáo trên ứng dụng iOS/Android xây bằng Tauri, với thiết bị ngoại vi Bluetooth và chế độ offline đồng bộ khi kết nối lại.
Ứng dụng iOS/Android xây bằng Tauri; ứng dụng chính cho chủ sở hữu và thu ngân.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-MOB-001 | Bắt buộc | Ứng dụng có sẵn trên iOS 14+ và Android 8+ | Đã dựng |
URD-MOB-002 | Bắt buộc | Chủ sở hữu có thể đăng nhập và truy cập POS, đơn hàng, thanh toán, lập hóa đơn và báo cáo | Đã dựng |
URD-MOB-003 | Bắt buộc | Thu ngân có thể đăng nhập và truy cập màn hình POS (màn hình chỉ dành cho chủ sở hữu bị hạn chế) | Đã dựng |
URD-MOB-004 | Nên có | Ứng dụng hỗ trợ kết nối thiết bị ngoại vi Bluetooth (máy quét, máy in, SoundBox) | Đã dựng |
URD-MOB-005 | Nên có | Ứng dụng hỗ trợ chế độ offline: giao dịch được lưu cục bộ và đồng bộ khi kết nối lại | Đã dựng |
URD-MOB-006 | Bắt buộc | Đăng nhập tạo một phiên thiết bị liên kết với bản ghi thiết bị, qua luồng kiểm tra-rồi-tạo của DEV | Đã dựng |
AC-MOB-01: Đăng nhập & phiên di động
| Cho trước | Khi | Thì |
|---|---|---|
| Chủ sở hữu hoặc thu ngân trên iOS 14+ / Android 8+ | Đăng nhập vào ứng dụng | Một phiên thiết bị được tạo và liên kết với bản ghi thiết bị (kiểm tra-rồi-tạo theo URD-DEV-026 nếu mới) |
WEB - Ứng dụng Web Đã dựng
Mã Tính năng: device/WEB · Phase: P1 · PRDs: - · Dev: client
Tính năng này mang lại gì cho người dùng: chủ sở hữu chạy quản lý back-office đầy đủ - thiết bị, sản phẩm, đơn hàng, báo cáo, cài đặt - và Web POS cơ bản trên trình duyệt hiện đại, qua HTTPS với hết hạn phiên.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-WEB-001 | Bắt buộc | Ứng dụng web chạy trên trình duyệt hiện đại (Chrome, Edge, Firefox, Safari) | Đã dựng |
URD-WEB-002 | Bắt buộc | Ứng dụng web cung cấp đầy đủ quản lý back-office (thiết bị, sản phẩm, đơn hàng, báo cáo, cài đặt) | Đã dựng |
URD-WEB-003 | Nên có | Ứng dụng web hỗ trợ chế độ Web POS cơ bản | Đã dựng |
URD-WEB-004 | Bắt buộc | Ứng dụng web bắt buộc HTTPS và hết hạn phiên/đăng xuất | Đã dựng |
URD-WEB-005 | Nên có | Ứng dụng web dùng được ở chiều rộng 1024px+; cảnh báo dưới mức tối thiểu | Đã dựng |
URD-WEB-006 | Bắt buộc | Bản web lưu định danh thiết bị trong IndexedDB của trình duyệt, không dùng localStorage. • Khi định danh thiết bị không phục hồi được từ IndexedDB (chính sách ITP), màn hình web đưa ra Mã kích hoạt (URD-DEV-027) như đường kích hoạt thay thế. | Chưa dựng |
AC-WEB-01: Truy cập back-office
| Cho trước | Khi | Thì |
|---|---|---|
| Chủ sở hữu trên trình duyệt hiện đại | Đăng nhập qua HTTPS | Quản lý back-office đầy đủ khả dụng; phiên hết hạn/đăng xuất theo chính sách |
AC-WEB-02: ITP giới hạn lưu trữ, kích hoạt bằng mã thay thế
| Cho trước | Khi | Thì |
|---|---|---|
| Trình duyệt Safari bật ITP, không giữ được định danh cũ giữa các phiên (kể cả từ IndexedDB) | Đăng nhập trên trình duyệt đó | Hệ thống tạo một thiết bị mới và hiển thị Mã kích hoạt; kích hoạt hoàn tất qua quét/nhập mã, không phụ thuộc IndexedDB |
POS - Máy POS Một phần
Mã Tính năng: device/POS · Phase: P2 · PRDs: - · Dev: sale-renderer
Tính năng này mang lại gì cho người dùng: phần cứng Android chuyên dụng chạy ứng dụng POS toàn màn hình với thiết bị ngoại vi tích hợp; thiết bị phải được gán vào một POS Point và giữ một phiên hoạt động trước khi xử lý bán hàng.
Phần cứng Android chuyên dụng chạy ứng dụng POS toàn màn hình với thiết bị ngoại vi tích hợp.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-POS-001 | Bắt buộc | Ứng dụng POS chạy trên Android 8+ với ≥2 GB RAM và ≥16 GB lưu trữ | Đã dựng |
URD-POS-002 | Bắt buộc | Thiết bị phải được gán vào một POS Point trước khi xử lý bán hàng; một phiên hoạt động trên mỗi thiết bị | Đã dựng |
URD-POS-003 | Bắt buộc | Ứng dụng POS hỗ trợ thiết bị ngoại vi tích hợp sẵn (đầu đọc thẻ, máy in, máy quét, ngăn kéo tiền) khi có | Một phần |
URD-POS-004 | Nên có | Ứng dụng POS chạy trên phần cứng được chứng nhận (VNPAY V-POS, Sunmi T2) | Đã dựng |
URD-POS-005 | Bắt buộc | Ứng dụng POS hỗ trợ thiết lập thiết bị ngoại vi qua Cài đặt > Thiết bị | Đã dựng |
AC-POS-01: Gán POS Point
| Cho trước | Khi | Thì |
|---|---|---|
| Thiết bị đã kích hoạt trên Android 8+ | Được gán vào một POS Point | Thiết bị có thể xử lý bán hàng với một phiên hoạt động tại một thời điểm |
PRN - Máy in Một phần
Mã Tính năng: device/PRN · Phase: P2 · PRDs: - · Dev: sale-main
Tính năng này mang lại gì cho người dùng: hệ thống in hóa đơn ESC/POS qua máy in nhiệt USB và mạng - chữ, hình ảnh, QR và mã vạch - với code page 28 tiếng Việt, khổ giấy 58/80mm, tự cắt giấy và kích hoạt ngăn kéo tiền.
Máy in nhiệt USB (Tauri/WebUSB) và mạng (WebSocket); ESC/POS với code page 28 tiếng Việt.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-PRN-001 | Bắt buộc | Hệ thống kết nối máy in qua Bluetooth, USB và mạng | Đã dựng |
URD-PRN-002 | Bắt buộc | Hệ thống phát hiện máy in USB qua USB class code 0x07 | Đã dựng |
URD-PRN-003 | Bắt buộc | Engine ESC/POS in chữ, hình ảnh nhúng, mã QR và mã vạch | Đã dựng |
URD-PRN-004 | Bắt buộc | Markup ESC/POS hỗ trợ căn lề, in đậm, gạch chân, cỡ chữ, mã vạch, QR, hình ảnh | Đã dựng |
URD-PRN-005 | Bắt buộc | Hệ thống raster nội dung PDF bằng Floyd-Steinberg dithering cho đầu ra in nhiệt | Đã dựng |
URD-PRN-006 | Bắt buộc | Ký tự tiếng Việt in đúng qua code page 28 | Đã dựng |
URD-PRN-007 | Bắt buộc | Hệ thống hỗ trợ khổ giấy 58mm và 80mm, cấu hình theo từng máy in | Đã dựng |
URD-PRN-008 | Nên có | Hệ thống hỗ trợ tự cắt giấy và ngăn kéo tiền kích hoạt khi in | Một phần |
URD-PRN-009 | Nên có | Lệnh kích hoạt ngăn kéo tiền được gửi qua máy in khi thanh toán tiền mặt | Một phần |
URD-PRN-010 | Bắt buộc | Vòng đời in (kết nối, ngắt kết nối, gửi lệnh) hiển thị lỗi rõ ràng khi thất bại; không âm thầm bỏ qua | Đã dựng |
URD-PRN-011 | Nên có | Hệ thống kết nối máy in mạng qua WebSocket và xử lý ngắt kết nối một cách mượt mà | Đã dựng |
URD-PRN-012 | Bắt buộc | Hệ thống dự phòng sang WebUSB khi plugin USB Tauri không khả dụng | Đã dựng |
AC-PRN-01: In Hóa đơn
| Cho trước | Khi | Thì |
|---|---|---|
| Máy in đã ghép nối | Giao dịch hoàn tất | Hóa đơn được in (tự động hoặc thủ công) |
| In thất bại | Hiển thị lỗi kèm tùy chọn thử lại | |
| Nội dung tiếng Việt | Code page 28 được đặt tự động |
SCN - Máy quét Mã vạch Một phần
Mã Tính năng: device/SCN · Phase: P2 · PRDs: - · Dev: sale-main
Tính năng này mang lại gì cho người dùng: quét HID keyboard-wedge và camera/QR di động đối chiếu với Product Identifier - một lần quét thành công trên màn hình POS thêm sản phẩm khớp vào giỏ hàng. Cùng phần cứng quét này cũng dùng để nhập Mã kích hoạt thiết bị (xem DEV). Trên desktop, người dùng có phím tắt để chủ động chuyển giữa chế độ quét (nhận input từ máy quét mã vạch) và chế độ nhập tay, tránh xung đột giữa hai nguồn input trên cùng một ô.
HID keyboard-wedge (USB/Bluetooth) và quét camera/QR di động đối chiếu với Product Identifier.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-SCN-001 | Bắt buộc | Hệ thống tự bắt input máy quét HID keyboard-wedge (không có giao diện ghép nối) | Đã dựng |
URD-SCN-002 | Bắt buộc | Input máy quét phải dài 10-20 ký tự, hoàn tất trong timeout phím 100ms | Đã dựng |
URD-SCN-003 | Bắt buộc | Phím Enter (hoặc dừng 100ms) kích hoạt quét và tra cứu | Đã dựng |
URD-SCN-004 | Bắt buộc | Máy quét QR bằng camera khả dụng trên di động qua plugin barcode Tauri | Đã dựng |
URD-SCN-005 | Bắt buộc | Khi quét thành công trên màn hình POS, sản phẩm khớp được thêm vào giỏ hàng | Đã dựng |
URD-SCN-006 | Nên có | Hệ thống hỗ trợ định dạng 1D (EAN-13/8, UPC-A/E, Code 128/39) và 2D (QR, Data Matrix) | Đã dựng |
URD-SCN-007 | Nên có | Quét hoạt động trong nhiều ngữ cảnh (tìm sản phẩm, tra cứu hóa đơn, nhập Mã kích hoạt thiết bị) | Một phần |
URD-SCN-008 | Nên có | Trên desktop, người dùng có phím tắt để chuyển đổi nhanh giữa chế độ quét (nhận input từ máy quét mã vạch HID) và chế độ nhập tay (gõ trực tiếp vào ô tìm kiếm/nhập mã), tránh xung đột giữa hai nguồn input trên cùng một ô | Chưa dựng |
AC-SCN-01: Quét Mã vạch
| Cho trước | Khi | Thì |
|---|---|---|
| Máy quét HID | Quét một mã vạch | Sản phẩm được tra cứu và thêm vào giỏ hàng |
| Máy quét camera (di động) | Quét một mã QR | Sản phẩm/hóa đơn được tra cứu |
| Mã vạch không xác định | Quét | Hiển thị thông báo lỗi rõ ràng |
AC-SCN-02: Phím tắt chuyển chế độ quét/nhập trên desktop
| Cho trước | Khi | Thì |
|---|---|---|
| Màn hình desktop đang ở chế độ quét | Người dùng bấm phím tắt chuyển chế độ | Giao diện chuyển sang chế độ nhập tay; ô nhập nhận focus con trỏ |
| Màn hình desktop đang ở chế độ nhập tay | Người dùng bấm phím tắt chuyển chế độ | Giao diện chuyển về chế độ quét; input từ máy quét HID được lắng nghe lại |
SBX - SoundBox Đã dựng
Mã Tính năng: device/SBX · Phase: P1 · PRDs: - · Dev: sale-renderer
Tính năng này mang lại gì cho người dùng: loa Bluetooth VNPAY phát xác nhận thanh toán bằng tiếng Việt/tiếng Anh - số tiền và phương thức - theo từng thiết bị, với âm lượng cấu hình được, trạng thái LED và xử lý mất kết nối mượt mà.
Loa Bluetooth VNPAY phát xác nhận thanh toán bằng tiếng Việt/tiếng Anh, ghép nối theo từng thiết bị.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-SBX-001 | Bắt buộc | Hệ thống ghép nối VNPAY SoundBox (V1/V2) với thiết bị qua Bluetooth | Đã dựng |
URD-SBX-002 | Bắt buộc | Khi xác nhận thanh toán, hệ thống kích hoạt thông báo giọng nói; nếu mất kết nối, thanh toán vẫn thành công (không có lỗi chặn) | Đã dựng |
URD-SBX-003 | Bắt buộc | Ngôn ngữ thông báo theo cấu hình (tiếng Việt / tiếng Anh), gồm số tiền và phương thức | Đã dựng |
URD-SBX-004 | Nên có | Trạng thái LED của SoundBox phản ánh trạng thái: xanh nhấp nháy (ghép nối), xanh sáng đều (đã kết nối), xanh lá (thành công), đỏ (lỗi/pin yếu) | Đã dựng |
URD-SBX-005 | Nên có | Người dùng có thể cấu hình âm lượng (1-10) và bật/tắt việc đọc số tiền / phương thức | Đã dựng |
URD-SBX-006 | Nên có | SoundBox hoạt động trong phạm vi Bluetooth định mức (~10 m); ngoài phạm vi, mất kết nối được xử lý mượt mà | Đã dựng |
AC-SBX-01: Xác nhận SoundBox
| Cho trước | Khi | Thì |
|---|---|---|
| SoundBox đã ghép nối | Thanh toán được xác nhận | Số tiền + phương thức được đọc bằng ngôn ngữ đã cấu hình |
| SoundBox mất kết nối | Thanh toán được xác nhận | Thanh toán vẫn thành công; thông báo bị bỏ qua âm thầm |
NFC - SoftPOS / NFC Dự kiến
Mã Tính năng: device/NFC · Phase: P3 · PRDs: - · Dev: sale-main
Tính năng này mang lại gì cho người dùng: điện thoại Android chấp nhận thanh toán thẻ không tiếp xúc qua NFC bằng VNPAY sau khi kích hoạt KYC; tùy chọn bị ẩn trên iOS và bị chặn khi NFC không khả dụng.
Chấp nhận NFC không tiếp xúc trên Android qua VNPAY; yêu cầu KYC.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-NFC-001 | Bắt buộc | Hệ thống kiểm tra phần cứng NFC khả dụng trước khi bật SoftPOS | Chưa dựng |
URD-NFC-002 | Bắt buộc | SoftPOS yêu cầu kích hoạt VNPAY KYC trước lần dùng đầu tiên | Chưa dựng |
URD-NFC-003 | Bắt buộc | Kích hoạt SoftPOS bị chặn khi NFC không khả dụng hoặc bị tắt, kèm thông báo rõ ràng | Chưa dựng |
URD-NFC-004 | Nên có | SoftPOS chỉ dành cho Android; tùy chọn bị ẩn trên iOS | Chưa dựng |
AC-NFC-01: Kích hoạt SoftPOS
| Cho trước | Khi | Thì |
|---|---|---|
| Thiết bị Android có NFC khả dụng, đã hoàn tất KYC | SoftPOS được kích hoạt | Chấp nhận thẻ không tiếp xúc được bật |
| NFC không khả dụng hoặc bị tắt | Thử kích hoạt | Kích hoạt bị chặn kèm thông báo rõ ràng |
MON - Giám sát Tình trạng & Thông báo Thiết bị Một phần
Mã Tính năng: device/MON · Phase: P2 · PRDs: PRD-MON-001 · Dev: @nx/commerce · @nx/signal
Tính năng này mang lại gì cho người dùng: quản trị viên xem trạng thái online/offline, lần thấy cuối và phiên bản app của từng thiết bị qua heartbeat 5 phút, có thể vô hiệu hóa hoặc xóa dữ liệu từ xa thiết bị bị xâm phạm, và nhận thông báo thời gian thực khi một thiết bị bị đánh dấu Hư hỏng.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-MON-001 | Bắt buộc | Thiết bị đang hoạt động gửi heartbeat mỗi 5 phút; nền tảng ghi lại hoạt động cuối | Chưa dựng |
URD-MON-002 | Bắt buộc | Nền tảng đánh dấu thiết bị offline sau 15 phút không có heartbeat; online lại ở ping kế tiếp | Chưa dựng |
URD-MON-003 | Bắt buộc | Quản trị viên có thể xem tình trạng thiết bị (online/offline, lần thấy cuối, phiên bản app) và lọc theo trạng thái; nền tảng thông báo thời gian thực (pipeline ingest → worker → lưu → đẩy trực tiếp) đã sẵn sàng chờ producer | Một phần |
URD-MON-004 | Bắt buộc | Hệ thống có thể vô hiệu hóa thiết bị từ xa và thu hồi phiên đang hoạt động của nó | Chưa dựng |
URD-MON-005 | Nên có | Hệ thống hỗ trợ xóa dữ liệu từ xa cho thiết bị bị xâm phạm (xếp hàng nếu offline) | Chưa dựng |
AC-MON-01: Giám sát Tình trạng
| Cho trước | Khi | Thì |
|---|---|---|
| Thiết bị đang hoạt động | Gửi heartbeat | Dấu thời gian hoạt động cuối được cập nhật |
| Không có heartbeat trong 15 phút | Thiết bị bị đánh dấu offline | |
| Admin xem danh sách thiết bị | Trạng thái online/offline hiển thị |
DSX - Ca làm việc theo Thiết bị & Liên kết Máy in Đã dựng
Mã Tính năng: device/DSX · Phase: P2 · PRDs: PRD-DSX-001 · Dev: @nx/sale · @nx/commerce
Tính năng này mang lại gì cho người dùng: thiết bị đã đăng ký trở thành điểm neo runtime của một trạm bán hàng - định danh thiết bị phân giải mọi hành động ca về một thiết bị và suy ra merchant, một ca duy nhất được mở hoặc tham gia theo kênh bán, thiết bị bật ngăn kéo tiền nhận ngăn kéo theo thiết bị, ngữ cảnh hiện tại báo cáo sự tham gia thiết bị, báo cáo X/Z khóa theo thiết bị, và mỗi trạm liên kết với máy in riêng của nó.
| Mã | Ưu tiên | Yêu cầu | Trạng thái |
|---|---|---|---|
URD-DSX-001 | Bắt buộc | Mọi hành động ca theo thiết bị phân giải thiết bị từ header x-device-info; merchant được suy ra từ bản ghi thiết bị đó, không bao giờ do client cung cấp | Đã dựng |
URD-DSX-002 | Bắt buộc | Thiếu header x-device-info trên hành động theo thiết bị bị từ chối với lỗi rõ ràng; back-office đọc (vd. danh sách ca) có thể chạy không cần thiết bị dùng phạm vi merchant đang hoạt động | Đã dựng |
URD-DSX-003 | Bắt buộc | Thiết bị phải tồn tại, được gán merchant, và (khi có merchant cung cấp) khớp với nó; nếu không, hành động bị từ chối | Đã dựng |
URD-DSX-004 | Bắt buộc | Quyền truy cập tenant được áp dụng trên merchant đã phân giải cho mọi hành động ca | Đã dựng |
URD-DSX-005 | Bắt buộc | Mở một ca sẽ mở hoặc tham gia ca mở duy nhất của kênh bán mà thiết bị thuộc về; lần mở đồng thời bởi thiết bị khác tham gia cùng ca thay vì tạo bản trùng | Đã dựng |
URD-DSX-006 | Bắt buộc | Kênh bán cung cấp khi mở phải thuộc về merchant đã phân giải | Đã dựng |
URD-DSX-007 | Bắt buộc | Thiết bị mở/tham gia được ghi danh trong ca, và nhân viên mở được check-in cùng nó | Đã dựng |
URD-DSX-008 | Nên có | Ngăn kéo tiền theo thiết bị chỉ được tạo khi mở cho thiết bị bật ngăn kéo tiền; thiết bị khác tham gia mà không có ngăn kéo | Đã dựng |
URD-DSX-009 | Bắt buộc | Endpoint ngữ cảnh hiện tại trả về ca của thiết bị, ghi danh, ngăn kéo tùy chọn, tiền dự kiến, và sự tham gia thiết bị (số đang hoạt động, số đã tham gia, thiết bị còn chờ) | Đã dựng |
URD-DSX-010 | Bắt buộc | Tiền dự kiến bị bỏ khỏi ngữ cảnh khi chính sách đếm mù của merchant bật hoặc không có ngăn kéo | Đã dựng |
URD-DSX-011 | Bắt buộc | Báo cáo X (giữa ca) và Z (cuối ca) có thể sinh theo thiết bị và theo ca, khóa theo thiết bị đã phân giải | Đã dựng |
URD-DSX-012 | Bắt buộc | Một thiết bị được đăng ký với một merchant; bản ghi thiết bị là điểm neo thuộc phạm vi merchant mà mọi ca, ngăn kéo, báo cáo neo vào | Đã dựng |
URD-DSX-013 | Bắt buộc | Truy cập API thiết bị thuộc phạm vi merchant và đã xác thực (JWT hoặc Basic Auth); tìm kiếm thiết bị giới hạn theo các merchant người dùng đã tham gia | Đã dựng |
URD-DSX-014 | Bắt buộc | Một thiết bị khai báo nó có điều khiển ngăn kéo tiền hay không; cờ này điều phối việc tạo ngăn kéo khi mở ca | Đã dựng |
URD-DSX-015 | Nên có | Đích in được liên kết theo từng trạm bếp (máy in, số bản, tự in); lệnh in định tuyến tới máy in liên kết | Một phần |
AC-DSX-01: Phân giải ca theo thiết bị
| Cho trước | Khi | Thì |
|---|---|---|
Thiết bị đã đăng ký, có header x-device-info | Một hành động ca được gọi | Thiết bị được phân giải, merchant suy ra từ nó, và quyền tenant được áp dụng |
| Thiếu header trên hành động theo thiết bị | Hành động được gọi | Bị từ chối với lỗi rõ ràng |
| Thiết bị thuộc merchant khác | Hành động được gọi | Bị từ chối - merchant không khớp / cấm |
AC-DSX-02: Mở hoặc tham gia một ca mỗi kênh
| Cho trước | Khi | Thì |
|---|---|---|
| Không có ca mở cho kênh | Một thiết bị mở ca | Ca mở mới được tạo và thiết bị được ghi danh |
| Có ca mở cho kênh | Thiết bị khác mở | Nó tham gia cùng ca; không tạo bản trùng |
| Hai thiết bị mở cùng kênh đồng thời | Cả hai mở | Chúng hội tụ về một ca |
AC-DSX-03: Ngăn kéo & sự tham gia
| Cho trước | Khi | Thì |
|---|---|---|
| Thiết bị bật ngăn kéo tiền | Mở một ca | Ngăn kéo theo thiết bị được tạo với tiền đầu ca |
| Thiết bị không ngăn kéo | Mở / tham gia một ca | Nó tham gia mà không có ngăn kéo |
| Merchant bật đếm mù | Đọc ngữ cảnh hiện tại | Tiền dự kiến bị bỏ; sự tham gia vẫn trả về |
AC-DSX-04: Liên kết máy in
| Cho trước | Khi | Thì |
|---|---|---|
| Một trạm bếp liên kết với máy in (máy in, số bản, tự in) | Một lệnh in được tạo cho trạm đó | Lệnh định tuyến tới máy in liên kết với số bản đã cấu hình |
4. Ràng buộc
| Mã | Ràng buộc |
|---|---|
C-01 | Mọi thiết bị phải được đăng ký (tự động hoặc thủ công) trước khi có thể vận hành |
C-02 | Thiết bị phải được gán vào một POS Point trước khi xử lý bán hàng |
C-03 | Chỉ cho phép một phiên hoạt động trên mỗi thiết bị tại một thời điểm |
C-04 | Định danh thiết bị được tự sinh một lần, bất biến, và bền vững qua các lần cài đặt lại trên cùng phần cứng |
C-05 | Mã thiết bị phải duy nhất trong phạm vi merchant |
C-06 | Mọi bản ghi thiết bị dùng soft-delete |
C-07 | Chuyển trạng thái theo vòng đời đã định nghĩa; chuyển trạng thái không hợp lệ nên bị từ chối (kiểm tra hiện chưa được áp dụng - URD-DEV-004) |
C-08 | SoftPOS chỉ dành cho Android và yêu cầu VNPAY KYC |
C-09 | Mỗi POS nên có đúng một máy in mặc định |
C-10 | Số thiết bị tối đa cho mỗi organizer do operator cấu hình |
C-11 | Heartbeat mỗi 5 phút; ngưỡng offline là 15 phút |
C-12 | Input máy quét HID phải dài 10-20 ký tự trong timeout 100ms |
C-13 | Code page 28 (tiếng Việt) của máy in USB được đặt tự động khi kết nối |
C-14 | Đánh dấu thiết bị Hư hỏng khi Trạng thái vận hành vẫn ACTIVATED chỉ chặn phiên POS mới/bán hàng, không tự đổi Trạng thái vận hành bên dưới - quy tắc đề xuất, chờ Thiết kế/Kỹ thuật xác nhận điểm chặn chính xác |
C-15 | Mỗi Mã kích hoạt (Barcode/QR) chỉ dùng được đúng một lần; dùng lại luôn bị từ chối bất kể gọi từ thiết bị nào |
5. Loại trừ
Thiết bị cố ý không làm những việc sau.
| Mã | Việc không làm |
|---|---|
N-01 | Đấu nối API backend VNPAY Terminal (bảng đã có, chưa kết nối - phát hiện QE) |
N-02 | Tích hợp máy in nhãn; hỗ trợ máy POS Windows |
N-03 | Ứng dụng chuyên biệt cho màn hình bếp, phục vụ, giao hàng và kho |
N-04 | Điều khiển vật lý ngăn kéo tiền (kích hoạt tín hiệu bật); giao diện quản lý driver thiết bị ngoại vi nâng cao |
N-05 | Đặc tả API kỹ thuật và chi tiết tích hợp cổng thanh toán |
N-06 | Quy trình phiếu bảo trì / điều phối kỹ thuật viên đầy đủ (phân công, SLA, theo dõi tiến độ sửa chữa) - đi qua module Helpdesk, độc lập với URD này |
Lịch sử phiên bản
| Ngày | Tác giả | Mô tả | Ver |
|---|---|---|---|
| 2026-02-28 | Q. Do - QE | URD ban đầu từ phân tích mức mã nguồn và tài liệu | v0.1 |
| 2026-06-04 | Claude (AI pair) | Tổ chức lại theo tính năng (Feature Spine) | v0.2 |
| 2026-06-15 | Nhóm Sale | Thêm DSX - Ca làm việc theo Thiết bị & Liên kết Máy in (Đã dựng) | v0.3 |
| 2026-07-17 | Claude (AI pair) | Viết lại theo format DocTabs dày đặc (chuẩn Kho). Bổ sung URD-DEV-020..024 (đã được PRD-DEV-001 tham chiếu nhưng thiếu trong URD): đến hạn bảo trì, Tình trạng thiết bị, thông báo hư hỏng, lý do ngừng dùng, Cash Drawer. Thêm mới URD-DEV-025..028 và URD-WEB-006: định danh thiết bị bền vững qua cài đặt lại, luồng kiểm tra-thiết-bị-thuộc-merchant khi đăng nhập, tự sinh Mã kích hoạt (Barcode + QR) khi tạo thiết bị mới, và kích hoạt dùng-một-lần qua quét/nhập mã - làm rõ nghiệp vụ theo yêu cầu PO, thay cho mô tả "tự kích hoạt" mơ hồ trước đây. Thêm chương mental-model "Bốn ý cần hiểu trước". Thêm ràng buộc C-14, C-15. | v0.4 |
| 2026-07-21 | Claude (AI pair) | Làm rõ định nghĩa ITP (chặn cookie/tập lệnh theo dõi hành vi liên trang, không chỉ "chặn lưu trữ") - cập nhật ý 3, thêm thuật ngữ ITP vào bảng Định nghĩa, đồng nhất cách diễn đạt hệ quả (giới hạn lưu trữ phía client) xuyên suốt tài liệu. Đổi cơ chế lưu định danh thiết bị trên bản web từ localStorage sang IndexedDB (URD-WEB-006, AC-WEB-02). Thêm URD-SCN-008 - phím tắt chuyển chế độ quét/nhập trên desktop cho máy quét mã vạch, kèm AC-SCN-02 | v0.5 |