Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn đang đọc một cuốn truyện mà không có dấu chấm câu, không biết đâu là chỗ bắt đầu, đâu là chỗ kết thúc, đâu là khoảnh khắc một biến cố quan trọng xảy ra. Bạn sẽ lạc lối ngay. Trong ngôn ngữ BPMN, Event (sự kiện) chính là hệ thống dấu câu đó. Nó cho người đọc biết quy trình khởi động khi nào, kết thúc ra sao, và điều gì xảy ra ở giữa khiến luồng phải dừng lại, rẽ hướng, hoặc phản ứng.
Trong các bài trước, bạn đã làm quen với Pool và Lane (Bài 12) để biểu diễn ai tham gia quy trình. Bây giờ chúng ta đi vào trái tim của sơ đồ: ba loại Event cốt lõi — Start, Intermediate và End. Đây là một trong ba "trụ cột" của BPMN (cùng với Activity và Gateway), và nó là phần mà người mới học hay vẽ sai nhất. Tôi đã đọc hàng trăm sơ đồ của học viên, và lỗi phổ biến số một không nằm ở Gateway phức tạp — mà nằm ở chỗ họ vẽ Event không có điểm bắt đầu, hoặc dùng sai hình tròn.
Nắm chắc bài này, bạn sẽ vẽ được những sơ đồ mà bất kỳ ai — từ nhân viên nghiệp vụ đến lập trình viên engine — đều đọc hiểu giống nhau. Đó chính là mục đích tối thượng của BPMN: một ngôn ngữ chung, không gây hiểu nhầm.
Khái niệm cốt lõi
Event trong BPMN là thứ "xảy ra" trong quá trình quy trình diễn ra. Nó ảnh hưởng đến luồng (flow) và thường có một nguyên nhân (trigger) hoặc một kết quả (result). Về mặt hình vẽ, mọi Event đều là hình tròn — và chính độ dày của đường viền hình tròn cho bạn biết nó thuộc loại nào.
Start Event — điểm khởi động
Start Event được vẽ bằng vòng tròn một nét mảnh, đường liền. Đây là nơi quy trình bắt đầu. Quy tắc vàng: mỗi quy trình (process) nên có một điểm khởi đầu rõ ràng. Start Event không có luồng đi vào (incoming sequence flow) — bởi vì không có gì xảy ra trước nó trong phạm vi quy trình này.
Start Event trả lời câu hỏi: "Điều gì khiến quy trình này bắt đầu chạy?" Nó có thể là:
- None Start (vòng tròn rỗng): khởi động chung chung, thường dùng khi quy trình được gọi thủ công.
- Message Start (có hình phong bì bên trong): bắt đầu khi nhận được một tin nhắn, ví dụ một đơn hàng từ khách.
- Timer Start (có hình đồng hồ): bắt đầu theo lịch, ví dụ "mỗi ngày lúc 8h sáng".
- Conditional, Signal Start: bắt đầu khi một điều kiện đúng hoặc một tín hiệu phát ra.
End Event — điểm kết thúc
End Event được vẽ bằng vòng tròn một nét, nhưng đường viền dày, đậm. Mẹo ghi nhớ đơn giản tôi luôn dạy học viên: "Mảnh là mở, đậm là đóng". Đường viền dày báo hiệu rằng nhánh luồng này đã đi đến cuối.
End Event không có luồng đi ra (outgoing sequence flow). Một quy trình có thể có nhiều End Event khác nhau — điều này hoàn toàn bình thường và thậm chí được khuyến khích, vì nó mô tả rõ các kết cục khác nhau: "Đơn được duyệt", "Đơn bị từ chối", "Khách hủy". Các loại End thường gặp:
- None End: kết thúc đơn thuần.
- Message End: kết thúc bằng việc gửi một tin nhắn (ví dụ email xác nhận cho khách).
- Terminate End (vòng tròn đậm có chấm tròn đặc bên trong): chấm dứt toàn bộ quy trình ngay lập tức, kể cả các nhánh đang chạy song song. Đây là loại rất mạnh, dùng phải cẩn thận.
- Error End: kết thúc bằng cách ném ra một lỗi (chúng ta sẽ đào sâu ở Bài 22).
Intermediate Event — sự kiện ở giữa
Intermediate Event được vẽ bằng vòng tròn hai nét (double line) — hai vòng tròn đồng tâm. Đây là sự kiện xảy ra ở giữa quy trình, sau khi đã bắt đầu nhưng trước khi kết thúc. Vòng tròn hai nét là dấu hiệu nhận biết quan trọng nhất; nhìn thấy hai nét là biết ngay "đây là chuyện xảy ra giữa chừng".
Intermediate Event có hai vai trò, phân biệt qua hình bên trong là rỗng (catch) hay đặc/đen (throw):
- Catch (bắt sự kiện): quy trình dừng lại chờ một điều gì đó xảy ra. Ví dụ: dừng chờ tin nhắn của khách, dừng chờ 3 ngày (Timer), dừng chờ một tín hiệu. Biểu tượng bên trong có nền trắng/rỗng.
- Throw (ném sự kiện): quy trình chủ động phát ra một điều gì đó rồi đi tiếp. Ví dụ: gửi một tin nhắn, phát một tín hiệu cho quy trình khác. Biểu tượng bên trong có nền đen/tô đặc.
- Nằm trên luồng (in the flow): chèn giữa hai Activity, có cả luồng vào và luồng ra.
- Gắn vào viền Activity (boundary): dán lên cạnh một Task để bắt sự kiện xảy ra trong khi Task đang chạy. Loại này rất quan trọng và sẽ được học riêng ở Bài 21.
Tình huống thực tế
Ví dụ 1 — Tiki: quy trình xử lý đơn hàng và mốc "chờ thanh toán"
Đội vận hành của một sàn thương mại điện tử kiểu Tiki mô hình hóa quy trình "Xử lý đơn hàng COD và chuyển khoản". Sơ đồ bắt đầu bằng một Message Start Event (phong bì): quy trình khởi động khi nhận được đơn hàng từ hệ thống website. Đây là lựa chọn đúng — quy trình không tự chạy, mà được kích hoạt bởi tin nhắn "đơn mới".
Với đơn chuyển khoản, sau bước "Tạo mã thanh toán", họ đặt một Intermediate Message Catch Event (vòng tròn hai nét, phong bì rỗng): quy trình dừng lại chờ webhook báo "đã nhận tiền" từ cổng thanh toán. Nếu sau 30 phút chưa có tiền, một Intermediate Timer sẽ kích hoạt nhánh hủy đơn.
Quy trình có ba End Event riêng biệt: "Giao hàng thành công" (None End), "Khách hủy đơn" (None End), và "Hệ thống thanh toán lỗi" (Error End). Trước đây họ chỉ vẽ một End duy nhất với chú thích chữ, khiến đội kế toán không biết phân biệt kết cục nào để đối soát. Sau khi tách ba End rõ ràng, thời gian đối soát cuối ngày giảm khoảng 40%, vì mỗi kết cục map thẳng vào một trạng thái trong hệ thống.
Bài học: Start phải phản ánh đúng cái gì kích hoạt quy trình (ở đây là Message, không phải None). Và nhiều End không phải là lỗi — nó là cách bạn nói rõ "quy trình có thể kết thúc theo nhiều cách".
Ví dụ 2 — Ngân hàng số: mở tài khoản và "chờ định danh eKYC"
Một ngân hàng số tại Việt Nam thiết kế quy trình mở tài khoản online. Start Event là Message (khách bấm "Mở tài khoản" trên app). Sau bước nộp hồ sơ, có một bước eKYC định danh điện tử cần con người duyệt nếu AI không tự tin.
Họ dùng một Intermediate Timer Catch Event đặt sau bước "Gửi hồ sơ cho bộ phận thẩm định": quy trình chờ tối đa 4 giờ làm việc. Đây là một Intermediate trên luồng, đại diện cho khoảng nghỉ có chủ đích, chứ không phải là quy trình bị treo. Khi hồ sơ được duyệt, một Intermediate Message Throw Event (phong bì đen) chủ động gửi tin nhắn sang hệ thống Core Banking để tạo số tài khoản, rồi quy trình đi tiếp.
Kết thúc, quy trình có hai End: "Tài khoản đã kích hoạt" (Message End — gửi SMS chúc mừng cho khách) và "Hồ sơ bị từ chối" (None End). Khi một thành viên mới trong nhóm vẽ nhầm Throw (đen) thành Catch (trắng) ở bước gửi sang Core Banking, engine Camunda chạy thử đã dừng lại chờ mãi không có tin nhắn nào tới — vì Catch nghĩa là "chờ nhận", trong khi ý định thật là "chủ động gửi". Một lỗi tô màu nhỏ làm hỏng cả luồng.
Bài học: Sự khác biệt rỗng/đặc (Catch/Throw) không phải trang trí — nó quyết định engine chờ hay gửi. Tô sai màu là sai logic.
Ví dụ 3 — Quán cà phê chuỗi: quy trình "khuyến mãi giờ vàng" với Timer Start
Một chuỗi cà phê giả định "Cội" có 50 chi nhánh muốn tự động hóa thông báo khuyến mãi giờ vàng. Quy trình "Đẩy ưu đãi happy hour" được khởi động bằng một Timer Start Event (đồng hồ): tự chạy mỗi ngày lúc 14h00. Không cần ai bấm nút, không cần đơn hàng nào — đây chính là tình huống kinh điển cho Timer Start.
Bên trong, sau khi gửi thông báo, họ đặt Intermediate Timer chờ 2 tiếng, rồi mới chạy bước "Tổng hợp số ly bán ra trong khung giờ vàng". Quy trình kết thúc bằng Message End gửi báo cáo cho quản lý vùng.
Bài học: Khi quy trình chạy theo lịch chứ không theo sự kiện bên ngoài, hãy dùng Timer Start. Đừng vẽ None Start rồi viết chú thích "chạy lúc 14h" — thông tin đó phải nằm trong chính biểu tượng Event để máy và người đều hiểu.
Hướng dẫn từng bước
Khi đặt Event vào một sơ đồ, hãy theo trình tự sau:
- Xác định trigger khởi động. Hỏi: "Điều gì làm quy trình này chạy?" Nếu là một tin nhắn/đơn/yêu cầu đến → Message Start. Nếu theo lịch → Timer Start. Nếu được người gọi thủ công → None Start. Vẽ đúng một Start Event (vòng mảnh) làm điểm xuất phát.
- Vẽ luồng chính trước. Nối Start → các Task → End bằng Sequence Flow, theo dòng chảy nghiệp vụ chính (happy path) trước khi lo các nhánh phụ.
- Liệt kê tất cả các kết cục. Mỗi cách quy trình có thể kết thúc nên có một End Event (vòng đậm) riêng, đặt tên động từ + danh từ rõ ràng: "Đơn đã giao", "Hồ sơ bị từ chối". Tránh gộp mọi thứ vào một End.
- Tìm các điểm "dừng chờ". Ở đâu quy trình phải đợi điều gì đó (tiền vào, người duyệt, hết hạn) → đặt một Intermediate Catch Event (vòng hai nét, biểu tượng rỗng).
- Tìm các điểm "chủ động phát đi". Ở đâu quy trình cần báo cho hệ thống/đối tác khác giữa chừng → đặt Intermediate Throw Event (vòng hai nét, biểu tượng đặc).
- Gắn biểu tượng trigger. Đừng để Event trống nếu nó có ý nghĩa cụ thể: thêm phong bì (Message), đồng hồ (Timer), tam giác (Signal)... để diễn đạt rõ bản chất.
- Đặt tên Event như một sự việc đã/đang xảy ra. Ví dụ "Nhận đơn hàng", "Hết hạn 30 phút", "Thanh toán xác nhận" — tên Event mô tả trạng thái/biến cố, khác với Task vốn mô tả hành động.
- Rà soát quy tắc luồng. Start không có mũi tên vào; End không có mũi tên ra; Intermediate có cả vào lẫn ra (trừ loại boundary). Kiểm tra một lượt trước khi chốt.
Lỗi thường gặp & mẹo
- Quên Start hoặc End Event. Nhiều người vẽ sơ đồ "lửng lơ" bắt đầu thẳng bằng một Task. Quy trình hợp lệ luôn có điểm bắt đầu và kết thúc rõ ràng. Mẹo: vẽ Start và End trước, rồi mới điền giữa.
- Nhầm độ dày đường viền. Vẽ End bằng nét mảnh hoặc Start bằng nét đậm. Hãy nhớ câu thần chú: "Mảnh là mở, đậm là đóng, hai nét là giữa chừng".
- Tô sai Catch/Throw. Như ví dụ ngân hàng số: nền trắng = chờ nhận, nền đen = chủ động gửi. Tô nhầm là đảo ngược logic, engine sẽ chạy sai.
- Dùng Activity thay vì Event để biểu diễn "chờ". Một bước "Chờ khách thanh toán" vẽ thành Task hình chữ nhật là sai về ngữ nghĩa. "Chờ" không phải là công việc do ai đó làm, mà là một sự kiện ta đợi — phải dùng Intermediate Catch Event.
- Lạm dụng Terminate End. Terminate (chấm tròn đặc) giết toàn bộ quy trình kể cả nhánh song song. Chỉ dùng khi bạn thực sự muốn "dừng tất cả ngay lập tức", ví dụ phát hiện gian lận. Dùng bừa sẽ làm mất các bước dọn dẹp cần thiết.
- Mẹo đặt tên: Start và End nên đọc lên thành một câu trọn nghĩa với phần giữa. "Nhận đơn hàng → ... → Đơn đã giao" nghe như một câu chuyện. Nếu đọc không thành câu, có thể bạn đặt tên chưa chuẩn.
- Mẹo nhiều End: Đừng sợ vẽ nhiều End. Một sơ đồ có 3–4 End rõ ràng dễ đọc hơn nhiều so với một End duy nhất kèm Gateway rối rắm ở cuối.
Bài tập thực hành
Hãy chọn quy trình "Đặt bàn nhà hàng online" và vẽ sơ đồ BPMN chỉ tập trung vào Event:
- Xác định Start Event: khách đặt bàn qua app gửi tới — đây là Message Start hay None Start? Vẽ và giải thích lựa chọn.
- Thêm một Intermediate Timer Catch Event: hệ thống chờ nhà hàng xác nhận trong tối đa 15 phút. Đặt nó đúng vị trí trên luồng.
- Thêm một Intermediate Message Throw Event: khi xác nhận xong, gửi SMS cho khách. Tô màu biểu tượng đúng (đặc hay rỗng?).
- Tạo ít nhất ba End Event với tên rõ ràng cho ba kết cục: được xác nhận, nhà hàng từ chối, và hết 15 phút không phản hồi.
- Tự kiểm tra: Start có mũi tên đi vào không? Mỗi End có mũi tên đi ra không? (Đáp án đúng: không và không.)
Hãy vẽ tay hoặc dùng draw.io (sẽ học ở Bài 33), rồi tự đối chiếu với phần "Hướng dẫn từng bước" ở trên.
Tóm tắt
Event là hệ thống "dấu câu" của BPMN, cho biết quy trình bắt đầu, kết thúc và phản ứng giữa chừng như thế nào. Ba loại cốt lõi phân biệt qua đường viền hình tròn:
- Start Event — vòng tròn nét mảnh, không có luồng vào, khởi động quy trình. Chọn đúng trigger: None, Message hay Timer.
- Intermediate Event — vòng tròn hai nét, xảy ra giữa chừng. Phân biệt Catch (rỗng — chờ nhận) và Throw (đặc — chủ động gửi).
- End Event — vòng tròn nét đậm, không có luồng ra, mô tả các kết cục. Nên có nhiều End cho nhiều kết quả khác nhau.