Tài liệu hướng dẫn tích hợp các API quy trình phê duyệt thông qua Mobile Gateway Transaction Codes (MBGW TranCode) dành cho Website Client và ứng dụng di động.
PENDING_APPROVAL, PENDING_REVIEW,
DELEGATED, DELEGATED_BY_ME, PROCESSED).ALL), hệ thống sẽ lấy hợp nhất 4 nhóm công
việc cần xử lý / theo dõi và không bao gồm nhóm đã xử lý
(PROCESSED).
Authorization: Bearer <token>).
PENDING_APPROVAL (Chờ tôi phê duyệt): Các tờ trình có bước Phê duyệt
(APPROVE) được gán trực tiếp cho bạn và chưa hoàn tất. Nếu bạn đã ủy quyền bước
này cho người khác (và ủy quyền còn hiệu lực), tờ trình sẽ tự động chuyển sang tab "Tôi đã
ủy quyền".
PENDING_REVIEW (Chờ tôi thẩm định): Các tờ trình có bước Thẩm định
(REVIEW) được gán trực tiếp cho bạn và chưa hoàn tất.
DELEGATED (Được ủy quyền duyệt thay): Các tờ trình mà bạn được người
khác ủy quyền xử lý thay, giấy ủy quyền đang còn hiệu lực và bước đó chưa hoàn
tất.DELEGATED_BY_ME (Tôi đã ủy quyền): Danh sách các tờ trình do bạn trực tiếp phụ
trách nhưng bạn đã bàn giao ủy quyền cho người khác xử lý (dùng để theo dõi tiến độ công
việc đã ủy quyền).PROCESSED (Đã xử lý xong): Danh sách các tờ trình mà bạn đã trực tiếp
tham gia xử lý hoàn tất (hoặc nhận ủy quyền và đã xử lý xong). Mỗi tờ trình chỉ
hiển thị 1 dòng duy nhất.ALL. Client bắt buộc phải truyền rõ ràng filter: ["PROCESSED"]
khi muốn xem danh sách này.
ALL (hoặc mảng rỗng [] / không truyền): Tự động lấy hợp nhất
4 nhóm công việc cần xử lý / theo dõi (PENDING_APPROVAL,
PENDING_REVIEW, DELEGATED, DELEGATED_BY_ME) trong một
query tối ưu. ALL tuyệt đối không bao gồm
PROCESSED.
["PENDING_APPROVAL", "PENDING_REVIEW"]), hệ thống sẽ tự động gộp và loại
bỏ các bước/tờ trình trùng lặp.canProcess (Quyền thao tác): Trả về true
(1) khi bước công việc đang thực sự đến lượt xử lý (status = PROCESSING). Ở
nhóm "Tôi đã ủy quyền" và "Đã xử lý", giá trị này luôn trả về
false (0).
| Field | Type | Description |
|---|---|---|
filter |
Array<String> Optional | Một hoặc nhiều mã: PENDING_APPROVAL, PENDING_REVIEW,
DELEGATED, DELEGATED_BY_ME, PROCESSED,
ALL. Mặc định (hoặc khi chọn ALL), hệ thống lấy 4 nhóm công
việc cần xử lý (không bao gồm PROCESSED). Chuỗi đơn vẫn
được nhận tạm thời để tương thích client cũ.
|
keyword |
String Optional | Từ khóa tìm kiếm không phân biệt hoa thường trên Số tờ trình (number) và
Trích yếu (subjectMatter). |
currentPage |
Integer Optional | Trang hiện tại (mặc định: 1, số bản ghi mỗi trang cố định
perPage = 10).
|
{
"filter": ["PENDING_APPROVAL"],
"keyword": "0045/2026",
"currentPage": 1
}
{
"success": true,
"code": "200",
"message": "Lấy danh sách phê duyệt/review thành công.",
"data": {
"items": [
{
"proposalId": 45,
"stepId": 120,
"number": "0045/2026/TT",
"subjectMatter": "Rà soát chi phí hạ tầng máy chủ",
"proposalStatus": "UNDER_APPROVAL",
"stepType": "APPROVE",
"stepStatus": "PROCESSING",
"stepResult": null,
"assigneeEmail": "checker@example.com",
"assigneeName": "Người duyệt",
"isDelegated": false,
"canProcess": true,
"updatedAt": "2026-08-24T08:30:00+07:00"
}
],
"pagination": {
"currentPage": 1,
"perPage": 10,
"totalItems": 1,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}
steps và
bước con childSteps), danh sách các bước đang chờ xử lý (currentSteps) và các
hành động mà người dùng hiện tại được phép bấm (currentUserAllowedActions).
Authorization: Bearer <token>).
createdBy) hoặc người lập tờ trình
(makerEmail).coRequesters).assignee) của ít nhất một bước active
trong quy trình.delegatedApprover) của ít nhất một
bước trong quy trình.403 Forbidden.
steps chỉ chứa các bước gốc theo đúng thứ tự prevStepId /
nextStepId. Mỗi bước gốc có mảng childSteps chứa các bước review
con.
currentSteps luôn là danh sách toàn bộ các bước PROCESSING. Nhiều
bước processing chỉ hợp lệ khi tất cả là REVIEW và có cùng
parentStepId.
assignedByEmail. Field này chứa email của actor đã tạo step
qua need_review/need_checker; các step thông thường trả
null.
PROCESSING cùng lúc trong cùng tờ trình, API trả về lỗi
409 Conflict (do payload perform-action không truyền
stepId).
| Field | Type | Description |
|---|---|---|
proposalId |
Integer Required | ID của tờ trình cần lấy thông tin quy trình. Phải là số nguyên dương
(>= 1). |
{
"proposalId": 123
}
{
"success": true,
"code": "200",
"message": "Lấy thông tin quy trình và hành động được phép thành công.",
"data": {
"proposalId": 123,
"proposalStatus": "UNDER_APPROVAL",
"workflowCompleted": false,
"requesterPermissions": [
{ "permission": "PROPOSAL.CREATE", "granted": true },
{ "permission": "PROPOSAL.APPROVE", "granted": true },
{ "permission": "PROPOSAL.REVIEW", "granted": false }
],
"steps": [
{
"stepId": 1,
"proposalId": 123,
"nextStepId": 2,
"prevStepId": null,
"parentStepId": null,
"stepType": "APPROVE",
"assignedByEmail": null,
"status": "PROCESSED",
"result": "APPROVED",
"note": "Đồng ý phê duyệt",
"assignee": {
"email": "user1@example.com",
"name": "Nguyễn Văn A",
"title": "Trưởng phòng",
"department": "Phòng IT",
"company": "Công ty ABC"
},
"delegatedApprover": null,
"isCurrent": false,
"isAssignedToRequester": false,
"createdAt": "2026-08-24T08:00:00+07:00",
"createdBy": "creator@example.com",
"updatedAt": "2026-08-24T09:00:00+07:00",
"updatedBy": "user1@example.com",
"childSteps": []
},
{
"stepId": 2,
"proposalId": 123,
"nextStepId": null,
"prevStepId": 1,
"parentStepId": null,
"stepType": "APPROVE",
"assignedByEmail": "user1@example.com",
"status": "PROCESSING",
"result": null,
"note": null,
"assignee": {
"email": "user2@example.com",
"name": "Trần Thị B",
"title": "Phó Giám đốc",
"department": "Khối Vận hành",
"company": "Công ty ABC"
},
"delegatedApprover": null,
"isCurrent": true,
"isAssignedToRequester": true,
"createdAt": "2026-08-24T08:00:00+07:00",
"createdBy": "creator@example.com",
"updatedAt": "2026-08-24T09:00:00+07:00",
"updatedBy": "user1@example.com",
"childSteps": []
}
],
"currentSteps": [
{
"stepId": 2,
"proposalId": 123,
"stepType": "APPROVE",
"assignedByEmail": "user1@example.com",
"status": "PROCESSING",
"result": null,
"note": null,
"assignee": {
"email": "user2@example.com",
"name": "Trần Thị B",
"title": "Phó Giám đốc",
"department": "Khối Vận hành",
"company": "Công ty ABC"
},
"delegatedApprover": null,
"isCurrent": true,
"isAssignedToRequester": true,
"requiredPermission": "PROPOSAL.APPROVE",
"currentUserAllowedActions": [
"approve",
"reject",
"need_rework",
"need_review",
"need_checker",
"delegate_approver"
],
"createdAt": "2026-08-24T08:00:00+07:00",
"createdBy": "creator@example.com",
"updatedAt": "2026-08-24T09:00:00+07:00",
"updatedBy": "user1@example.com"
}
]
}
}
PROPOSAL.REVIEW trên hệ thống
IAM để phục vụ chức năng yêu cầu thêm người thẩm định (action need_review) trên màn hình
phê duyệt.
Authorization: Bearer <token>).
403 Forbidden.
REVIEW đối với module phê duyệt tờ
trình.
API này không yêu cầu tham số
payload trong body (truyền JSON rỗng {} hoặc body trống).
{}
{
"success": true,
"code": "200",
"message": "Lấy danh sách reviewer hợp lệ thành công.",
"data": {
"items": [
{
"email": "reviewer1@example.com",
"name": "Đặng Thị Thảo",
"title": "Chuyên viên Thẩm định Rủi ro",
"department": "Ban Thẩm định",
"company": "Công ty ABC"
},
{
"email": "reviewer2@example.com",
"name": "Nguyễn Văn Hùng",
"title": "Trưởng nhóm Pháp chế",
"department": "Phòng Pháp chế",
"company": "Công ty ABC"
}
]
}
}
approve (Phê duyệt), reject (Từ chối), need_rework (Yêu cầu làm
lại), need_review (Yêu cầu thêm thẩm định),
need_checker (Yêu cầu thêm người duyệt), reviewed (Đã thẩm định xong),
documents_request (Yêu cầu bổ sung hồ sơ),
delegate_approver (Ủy quyền xử lý).data.note.
PROCESSING và chưa có kết quả (result == null). User phải là
effective assignee (hoặc người nhận ủy quyền hợp lệ).
409 Conflict.
need_review / need_checker):
Lời nhắn trong data.note của người giao việc sẽ được hệ thống lưu lại thành ý
kiến chỉ đạo kèm thời gian giao.reviewed /
documents_request...): Nhận xét trong data.note của
người được giao sẽ được lưu lại thành ý kiến phản hồi kèm thời gian hoàn tất.data.note cho mọi thao tác; hệ thống sẽ tự động xử lý và lưu trữ theo đúng
luồng giao việc hay phản hồi.
UNDER_APPROVAL.
403.createdBy) KHÔNG ĐƯỢC PHÉP thực hiện phê duyệt
(approve) tờ trình của chính mình. Vi phạm sẽ bị trả về mã lỗi
01.
REVIEW mới ngay TRƯỚC bước
Approve hiện tại, chuyển step Review sang PROCESSING, khóa step Approve sang
LOCKED và đưa proposal về PENDING_REVIEW. Reviewer phải có quyền
PROPOSAL.REVIEW trong IAM.
APPROVE mới ngay TRƯỚC bước
hiện tại, chuyển step mới sang PROCESSING, step hiện tại sang
LOCKED; proposal giữ nguyên UNDER_APPROVAL. Checker phải có quyền
PROPOSAL.APPROVE trong IAM và KHÔNG ĐƯỢC là người tạo tờ
trình.
perpro_approval_step.assigned_by_email của step mới và trả về field
assignedByEmail.
APPROVE/PROCESSING mới được ủy quyền. Người nhận ủy
quyền không được ủy quyền tiếp.perpro_delegation_recipient của
actor, có quyền PROPOSAL.APPROVE trong IAM và KHÔNG ĐƯỢC là người tạo
tờ trình.| Field | Type | Description |
|---|---|---|
proposalId |
Integer Required | ID của tờ trình. Phải là số nguyên dương. |
action |
String Required | Loại hành động: approve, reject, need_rework,
need_review, need_checker, reviewed,
documents_request, delegate_approver.
|
data |
Object Conditional | Đối tượng dữ liệu đính kèm. Bắt buộc truyền khi action là
need_review, need_checker hoặc delegate_approver.
Tùy chọn truyền khi muốn gửi note cho các action khác.
|
approve (Phê duyệt){
"proposalId": 123,
"action": "approve",
"data": {
"note": "Đồng ý phê duyệt phần hạn mức bổ sung theo biên bản họp."
}
}
reject (Từ chối){
"proposalId": 123,
"action": "reject",
"data": {
"note": "Không đồng ý phê duyệt do rủi ro tài chính cao."
}
}
need_rework (Yêu cầu làm lại){
"proposalId": 123,
"action": "need_rework",
"data": {
"note": "Đề nghị bổ sung thêm tài liệu đánh giá rủi ro."
}
}
need_review (Yêu cầu thêm người thẩm
định){
"proposalId": 123,
"action": "need_review",
"data": {
"reviewers": [
{ "email": "reviewer@example.com" }
],
"note": "Nhờ anh xem giúp phần đánh giá rủi ro và các cam kết tài chính."
}
}
need_checker (Yêu cầu thêm người phê
duyệt){
"proposalId": 123,
"action": "need_checker",
"data": {
"checkers": [
{ "email": "checker@example.com" }
],
"note": "Nhờ anh duyệt bổ sung phần hạn mức tín dụng vượt thẩm quyền."
}
}
reviewed (Đã thẩm định xong){
"proposalId": 123,
"action": "reviewed",
"data": {
"note": "Đã xem xét và đánh giá hồ sơ đầy đủ."
}
}
documents_request (Yêu cầu bổ sung hồ sơ)
{
"proposalId": 123,
"action": "documents_request",
"data": {
"note": "Bổ sung thêm bản sao kê tài khoản ngân hàng."
}
}
delegate_approver (Ủy quyền bước phê
duyệt){
"proposalId": 123,
"action": "delegate_approver",
"data": {
"delegatedApprover": {
"email": "delegate@example.com"
},
"validTo": "2026-12-31T23:59:59+07:00",
"note": "Đồng ý ủy quyền xử lý bước phê duyệt hiện tại."
}
}
{
"success": true,
"code": "200",
"message": "Phê duyệt bước hiện tại thành công.",
"data": {
"proposalId": 123,
"performedAction": "approve",
"proposalStatus": "UNDER_APPROVAL",
"workflowCompleted": false,
"requesterPermissions": [
{ "permission": "PROPOSAL.CREATE", "granted": true },
{ "permission": "PROPOSAL.APPROVE", "granted": true },
{ "permission": "PROPOSAL.REVIEW", "granted": false }
],
"steps": [ "...danh sách các steps sau khi cập nhật..." ],
"currentSteps": [ "...danh sách các bước đang chờ xử lý tiếp theo..." ]
}
}
POST /api/v1/private/approval-steps/create (Hỗ trợ định dạng response list phẳng cho các
component Portal phiên bản cũ).
createdBy) mới được phép chỉnh sửa danh sách bước phê duyệt.DRAFT hoặc
LOCKED.
steps: Bắt buộc là một mảng JSON danh sách, có ít nhất 1 bước
(count >= 1).stepType = APPROVE.createdBy) KHÔNG
ĐƯỢC gán chính mình vào bất kỳ bước nào có stepType = APPROVE. Vi
phạm trả lỗi 01 ngay lập tức.| Field | Type | Description |
|---|---|---|
proposalId |
Integer Required | ID của tờ trình. |
steps |
Array Required | Danh sách các bước phê duyệt mới theo đúng thứ tự linked-list. Phải có ít nhất 1 bước. |
{
"proposalId": 20,
"steps": [
{
"stepId": 113,
"stepType": "REVIEW",
"assignee": {
"email": "reviewer@example.com"
},
"note": "Thẩm định hồ sơ ban đầu"
},
{
"stepId": null,
"stepType": "APPROVE",
"assignee": {
"email": "approver@example.com"
},
"note": "Phê duyệt tờ trình"
}
]
}
{
"success": true,
"code": "200",
"message": "Lưu danh sách quy trình phê duyệt thành công.",
"data": {
"proposalId": 20,
"modifiedStepCount": 2,
"deletedStepCount": 0,
"proposalStatus": "DRAFT",
"workflowCompleted": false,
"requesterPermissions": [
{ "permission": "PROPOSAL.CREATE", "granted": true },
{ "permission": "PROPOSAL.APPROVE", "granted": true },
{ "permission": "PROPOSAL.REVIEW", "granted": false }
],
"steps": [ "...danh sách steps sau khi lưu..." ],
"currentSteps": []
}
}
submit), gửi lại tờ trình sau khi đã chỉnh sửa
(rework-submit), hoặc gửi thông báo đã bổ sung tài liệu/chứng từ
(additional_documents_submit).
DRAFT.steps trong request.DRAFT và chưa có kết quả. Bước cuối cùng bắt buộc
là APPROVE.PROCESSING, các bước sau thành LOCKED;
proposal chuyển thành UNDER_APPROVAL (hoặc PENDING_REVIEW nếu bước
đầu là Review).REVISION_REQUIRED.steps chứa danh sách root steps
mới/chỉnh sửa.PENDING_DOCUMENTS.PROCESSING với kết quả
REQUEST_DOCUMENTS.
null (tiếp tục PROCESSING), chuyển tờ
trình về PENDING_REVIEW.submit (Gửi duyệt lần đầu){
"proposalId": 123,
"action": "submit"
}
rework-submit (Gửi lại sau khi chỉnh sửa)
{
"proposalId": 123,
"action": "rework-submit",
"steps": [
{
"stepId": 1,
"stepType": "APPROVE",
"assignee": { "email": "approver1@example.com" },
"note": "Phê duyệt bước 1"
},
{
"stepId": null,
"stepType": "APPROVE",
"assignee": { "email": "approver2@example.com" },
"note": "Phê duyệt bước 2"
}
]
}
additional_documents_submit (Gửi bổ sung
chứng từ){
"proposalId": 123,
"action": "additional_documents_submit"
}
Danh mục 6 mã giao dịch trên
Mobile Gateway ánh xạ tới API PerPro Upstream (cấu hình trong mg_transaction,
mg_integration và mg_transaction_component theo migration
Version20260825171306.php):
MBGW TranCode (TRANSACTIONS.code) |
PerPro Upstream Endpoint | Tên Transaction & Chức năng nghiệp vụ |
|---|---|---|
| PP_PROPOSAL_CHECK_LIST | /api/v1/private/proposal-review-inbox/list |
Lấy danh sách tờ trình phê duyệt/review PerPro |
| PP_PROPOSAL_APPROVALS_AVAILABLE_ACTIONS | /api/v1/private/proposal-approvals/available-actions |
Lấy quy trình và thao tác phê duyệt khả dụng PerPro |
| PP_PROPOSAL_APPROVALS_ELIGIBLE_REVIEWERS | /api/v1/private/proposal-approvals/eligible-reviewers |
Lấy danh sách reviewer hợp lệ PerPro |
| PP_PROPOSAL_APPROVALS_PERFORM_ACTION | /api/v1/private/proposal-approvals/perform-action |
Thực hiện thao tác phê duyệt/review PerPro |
| PP_PROPOSAL_APPROVALS_MODIFY_STEPS | /api/v1/private/proposal-approvals/modify-steps |
Chỉnh sửa các bước phê duyệt PerPro |
| PP_PROPOSAL_APPROVALS_TRIGGER_STEP_FLOW | /api/v1/private/proposal-approvals/trigger-step-flow |
Khởi chạy quy trình phê duyệt PerPro |
Mọi lỗi phát sinh sau khi
request vào Controller đều trả HTTP Status 200 kèm mã lỗi tương ứng trong response envelope
code để Client dễ dàng xử lý:
| Mã lỗi (Code) | Tên lỗi | Mô tả chi tiết & Trường hợp xảy ra |
|---|---|---|
01 |
Creator Cannot Approve | Người tạo tờ trình vi phạm quy tắc chống tự phê duyệt (cố tình thực hiện duyệt, gán mình làm người duyệt hoặc nhận ủy quyền). |
400 |
Bad Request | Payload JSON không hợp lệ, thiếu trường bắt buộc, sai định dạng email/validTo, sai kiểu dữ liệu, hoặc assignee không có quyền IAM tương ứng. |
401 |
Unauthorized | Phiên đăng nhập không hợp lệ, thiếu Bearer Token hoặc token đã hết hạn. |
403 |
Forbidden | Người dùng không có quyền truy cập tờ trình, không phải người tạo tờ trình khi modify/submit, không được giao xử lý bước hiện tại, hoặc cấu hình ủy quyền trong danh bạ đã bị xóa/thu hồi. |
404 |
Not Found | Không tìm thấy tờ trình (Proposal ID không tồn tại hoặc đã bị soft-delete). |
409 |
Conflict | Xung đột trạng thái: Bước phê duyệt đã bị người khác xử lý trước đó, trạng thái tờ trình không phù hợp với hành động, user được giao nhiều hơn 1 bước processing, hoặc vi phạm tính liên tục của linked-list. |
503 |
Service Unavailable | Dịch vụ IAM tạm thời không khả dụng khi xác thực quyền của assignee/reviewer/checker. |
99 |
System Error | Lỗi hệ thống không xác định trong quá trình xử lý. |
| Action | Step Type | Trạng thái trước | Hành vi & Kết quả sau khi thực hiện |
|---|---|---|---|
approve |
APPROVE |
UNDER_APPROVAL |
Cập nhật note nếu có data.note; Current step thành
PROCESSED/APPROVED. Mở bước kế tiếp thành PROCESSING, hoặc
chuyển proposal thành APPROVED nếu là bước cuối cùng (kết thúc workflow).
|
reject |
APPROVE |
UNDER_APPROVAL |
Cập nhật note nếu có data.note; Tất cả các bước chưa xử lý thành
PROCESSED/REJECTED; Proposal chuyển sang REJECTED (kết thúc
quy trình).
|
need_rework |
APPROVE |
UNDER_APPROVAL |
Cập nhật note nếu có data.note; Current step giữ PROCESSING
với
kết quả result = REWORK; Proposal chuyển sang
REVISION_REQUIRED để người tạo sửa lại.
|
need_review |
APPROVE |
UNDER_APPROVAL |
Lưu data.note dạng JSON trên step mới; Chèn 1 root step
REVIEW/PROCESSING ngay
trước step Approve hiện tại; Step Approve chuyển sang LOCKED; Proposal
chuyển sang PENDING_REVIEW.
|
need_checker |
APPROVE |
UNDER_APPROVAL |
Lưu data.note dạng JSON trên step mới; Chèn 1 root step
APPROVE/PROCESSING ngay
trước step Approve hiện tại; Step Approve chuyển sang LOCKED; Proposal giữ
nguyên UNDER_APPROVAL.
|
delegate_approver |
APPROVE |
UNDER_APPROVAL |
Cập nhật note nếu có data.note; Tạo mapping ủy quyền có hiệu lực trong bảng
perpro_approval_step_delegated_approver; Giữ nguyên trạng thái step và
proposal.
|
reviewed |
REVIEW |
PENDING_REVIEW |
Cập nhật assignee_note/processed_at nếu step dùng JSON;
Current step thành
PROCESSED/REVIEWED; Mở lại bước Approve tiếp theo thành
PROCESSING; Proposal chuyển về UNDER_APPROVAL.
|
documents_request |
REVIEW |
PENDING_REVIEW |
Cập nhật assignee_note/processed_at nếu step dùng JSON;
Current step giữ PROCESSING với
kết quả result = REQUEST_DOCUMENTS; Proposal chuyển sang
PENDING_DOCUMENTS để người tạo nộp thêm hồ sơ.
|
submit |
— | DRAFT |
Kích hoạt bước đầu tiên thành PROCESSING, các bước sau LOCKED;
Proposal chuyển sang UNDER_APPROVAL (hoặc PENDING_REVIEW nếu
bước 1 là Review). |
rework-submit |
— | REVISION_REQUIRED |
Thu hồi các ủy quyền cũ, cập nhật lại danh sách steps, reset kết quả; Bước 1 chuyển sang
PROCESSING; Proposal chuyển sang UNDER_APPROVAL (hoặc
PENDING_REVIEW).
|
additional_documents_submit |
— | PENDING_DOCUMENTS |
Reset kết quả của bước Review đang request documents về null (tiếp tục
PROCESSING); Proposal chuyển về PENDING_REVIEW.
|