Per skills/skill.md + ROADMAP.md mục 7 (Checklist module mới): - SYSTEM_CODE=LD, SUBSYSTEM_CODE=A0, FUNCTION_ID=LDA0_0100 - Full module: LDA0_0100_pg.java + LDA0_0100_trx.java + LDA0_0100_mod.java + LDA0_0100.html + lead.js - Migration V11__create_lead_table.sql: LD_LEAD table (15 cols + 5 index) - FK logic ASSIGNED_STAFF_ID → ST_STAFF (nullable) - FK logic CONVERTED_CLIENT_ID → CL_CLIENT (nullable, UQ — 1 lead = 1 client) - Migration V12__seed_lead_data.sql: 3 SYS_FUNCTION (LD, LD_A0, LDA0_0100) + 2 SYS_ROLE_FUNCTION (R0002 ADMIN, R0003 STAFF) - 11 API endpoints: - prompt (list + filter with JOIN staff + converted client) - get, create, update - changeStatus (NEW/CONTACTED/QUALIFIED/LOST; CONVERTED only via /convert) - assignStaff (validate staff exists + ACTIVE) - convert (transactional: SYS_USER + R0005 + CL_CLIENT + LD_LEAD update) - listStaff, listSources, stats (6 status counts + conversionRate + bySource) - delete (block if CONVERTED — history preservation) - Business rules: 9 rules, status lifecycle NEW→CONTACTED→QUALIFIED→CONVERTED/LOST - Lead does NOT create SYS_USER — only convert does (transactional) - Block update/changeStatus/delete/convert for CONVERTED leads - CONTACTED_AT set on changeStatus to CONTACTED, CONVERTED_AT set on convert (NOW()) - Documentation: docs/features/LEAD/LEAD.md + report_session_01.md - ROADMAP.md updated: LEAD=DONE, next=CHAT Bug fixed during testing: ST_STAFF table uses EMPLOYEE_CODE (not STAFF_CODE). Fixed by aliasing EMPLOYEE_CODE AS staff_code in list/get/listStaff queries. Smoke test 18/18 PASS: create lead → changeStatus NEW→CONTACTED→QUALIFIED → convert (transactional: CL0003 + U0009 + HV_LEAD1, status=CONVERTED, CONVERTED_AT set) → block update/changeStatus/delete/convert for CONVERTED → stats (1 converted, conversionRate=100.0). Build: mvn clean package -> target/drivemaster.jar Run: java -jar target/drivemaster.jar (NO Docker) Flyway: V11+V12 applied OK, schema now at v12
DriveMaster — Hệ thống Quản lý và Đào tạo Lái xe
Project: DriveMaster v1.0 Stack: Java 21 + Spring Boot 3.3 + Embedded Tomcat + MySQL 8 + Flyway + Thymeleaf + Bootstrap 5 Architecture: Clean Architecture, module-based, Filter-based RBAC, DataSetRegistry (NO JPA) Run mode:
mvn clean package→java -jar target/drivemaster.jar(NO Docker, NO external Tomcat)
1. MỤC ĐÍCH
DriveMaster là hệ thống quản lý và đào tạo lái xe. Repository này chứa mã nguồn + documentation của dự án, được thiết kế để mọi AI/Agent hoặc Developer tiếp theo có thể tiếp nhận mà không cần đọc lịch sử hội thoại cũ.
Tài liệu điều phối chính: ROADMAP.md — BẮT BUỘC ĐỌC TRƯỚC KHI CODE.
Tài liệu convention: skills/skill.md — BẮT BUỘC TUÂN THỦ 100%, KHÔNG ĐƯỢC XÓA.
2. CẤU TRÚC PROJECT
DriveMaster/
│
├── ROADMAP.md ⭐ SOURCE OF TRUTH cấp project
├── README.md (file này)
├── pom.xml Maven build config
│
├── skills/
│ └── skill.md ⭐ Convention cốt lõi — KHÔNG XÓA
│
├── docs/
│ ├── architecture/ architecture.md, security.md, database.md, deployment.md
│ ├── database/ schema.md
│ └── features/
│ └── DM/ DM system
│ ├── DM.md ⭐ SOURCE OF TRUTH của DM feature
│ └── report/ Lịch sử phát triển DM
│ └── report_session_01.md
│
├── src/main/java/com/drivemaster/io/vn/
│ ├── DriveMasterApplication.java
│ ├── config/ SecurityConfig, WebConfig
│ ├── common/ DataSetRegistry, ApiResponse, PageResult
│ ├── security/ SecurityContext
│ ├── filter/ DriveMasterPermissionFilter
│ ├── exception/ BusinessException, GlobalExceptionHandler
│ ├── controller/ *_pg.java — chỉ mapping URL + trả HTML
│ │ ├── BaseController.java
│ │ └── DM/A0/DMA0_xxxx/
│ ├── api/ *_trx.java (REST) + *_mod.java (business)
│ │ └── DM/A0/DMA0_xxxx/
│ └── service/ MenuService, UploadService
│
├── src/main/resources/
│ ├── application.yml Config (DB, server, Thymeleaf, Flyway, upload)
│ ├── templates/
│ │ ├── common/layout.html Navbar + Sidebar + Footer fragments
│ │ └── DM/A0/DMA0_xxxx/ 7 trang HTML (DMA0_0001 → DMA0_0600)
│ ├── static/
│ │ ├── css/app.css Common CSS
│ │ └── js/ app.js + 6 file JS theo feature
│ └── db/migration/ Flyway V1, V2 (KHÔNG sửa)
│
└── uploads/ Local file storage (mặc định)
3. ĐỌC THEO THỨ TỰ
Lần đầu tiếp nhận project:
skills/skill.md— conventionROADMAP.md— trạng thái projectdocs/architecture/architecture.md→security.md→database.md→deployment.mddocs/features/DM/DM.md— feature cần làmdocs/features/DM/report/report_session_01.md— report gần nhất- Source code + DB migration liên quan
Khi làm feature mới:
skills/skill.mdROADMAP.mddocs/features/<FEATURE>/<FEATURE>.md(nếu tồn tại)- Latest report của feature
- Source code
- DB migration liên quan
4. CHẠY PROJECT
Yêu cầu môi trường
- Java 21+ (JDK, có javac)
- Maven 3.9+
- MySQL 8+ (hoặc dùng DB staging có sẵn)
Build & Run
# Build
mvn clean package -DskipTests
# Run (Embedded Tomcat ở port 8080)
java -jar target/drivemaster.jar
App tự động:
- Start Embedded Tomcat ở port 8080
- Connect MySQL (theo
application.ymlhoặc env var) - Run Flyway migration
- Start DriveMaster
Truy cập
Mở browser: http://localhost:8080/login
Default credentials: admin / admin123 (SUPERADMIN — toàn quyền)
Production deployment
KHÔNG dùng Docker. Chạy trực tiếp:
DB_URL=jdbc:mysql://<prod-host>:3306/drivemaster \
DB_USER=<prod-user> \
DB_PASSWORD=<prod-pass> \
java -jar target/drivemaster.jar
Khuyến nghị: chạy dưới systemd / supervisord, đặt sau nginx reverse proxy.
5. CẤU HÌNH DATABASE
DB connection trong application.yml:
spring:
datasource:
url: ${DB_URL:jdbc:mysql://stag.mysql.devhub.io.vn:3306/drivemaster?...}
username: ${DB_USER:admin}
password: ${DB_PASSWORD:MatKhau123!}
Để đổi DB, set env var DB_URL, DB_USER, DB_PASSWORD — KHÔNG cần sửa code.
6. ARCHITECTURE HIGHLIGHTS
- NO JPA / Repository / EntityManager / Hibernate / JdbcTemplate — chỉ dùng
DataSetRegistry(raw JDBC wrapper). - Module structure: mỗi function =
*_pg.java(controller HTML) +*_trx.java(REST API) +*_mod.java(business) +.html(Thymeleaf). - Filter-based RBAC:
DriveMasterPermissionFiltercheckSYS_FUNCTION→ROLE_USER→ROLE_FUNCTION. Controller/Mod KHÔNG kiểm tra quyền. - Menu dynamic: sidebar đọc từ
SYS_FUNCTION(KHÔNG hardcode). - Unified JSON:
{code, message, data, list, total}— per skills/skill.md. - Lowercase keys:
DataSetRegistry.searchAndRetrieve()trả về Map với key LOWERCASE — JS frontend phải đọc lowercase.
7. FEATURE ĐÃ HOÀN THÀNH
| SYSTEM | Feature | Function IDs | Status |
|---|---|---|---|
| DM | Hệ thống Quản trị (Admin) | DMA0_0001, DMA0_0100, DMA0_0200, DMA0_0300, DMA0_0400, DMA0_0500, DMA0_0600 | DONE |
Xem chi tiết trong ROADMAP.md mục 4.
8. DOCUMENTATION MODEL
DriveMaster dùng mô hình 3 tầng tài liệu:
ROADMAP.md (project-level)
↓
docs/features/<F>/<F>.md (feature-level current state)
↓
docs/features/<F>/report/ (feature-level history)
Quy tắc:
ROADMAP.md= bộ não toàn projectFEATURE.md= bộ nhớ dài hạn của feature (trạng thái hiện tại)report/= lịch sử phát triển của feature (session-by-session)- Ba thứ KHÔNG thay thế cho nhau
- KHÔNG tạo
work_reports/hoặcreports/ở root để chứa report chung
9. LICENSE
Proprietary — DriveMaster Project.
10. CONTACT
Đây là project được phát triển bởi AI Agent. Mọi thay đổi phải được ghi lại trong report của feature tương ứng.