PRD: Luồng điều chỉnh & hủy hóa đơn
| Module | Thuế & Hóa đơn (CORE-10) | PRD ID | PRD-INV-003 |
| Status | Shipped | Owner | Tổ Thuế & Hóa đơn |
| Date | 2026-06-15 | Version | v1.0 |
| Packages | @nx/invoice · @nx/core · @nx/iiapi | URD | INV |
TL;DR
Một khi hóa đơn điện tử đã phát hành, không thể sửa tại chỗ - luật Việt Nam yêu cầu một bản sửa hoặc một thao tác hủy, mỗi cái đều kèm lý do và liên kết tới bản gốc. Increment này biến cả hai thành first-class. Một điều chỉnh tạo một hóa đơn sửa mới trỏ ngược về bản gốc và được phát hành bất đồng bộ qua nhà cung cấp, tham chiếu lần phát hành gốc để cơ quan thuế gắn chúng với nhau. Một thao tác hủy đánh dấu hóa đơn là đã hủy kèm lý do bắt buộc - và với một hóa đơn đã phát hành thì còn gọi nhà cung cấp để hủy nó - được chốt sao cho không bao giờ va chạm với một lần phát hành đang chạy và lũy đẳng để một yêu cầu lặp lại là vô hại. Mọi điều chỉnh và hủy đều ghi một mục kiểm toán bất biến và đẩy một cập nhật trực tiếp tới các client đang kết nối.
1. Bối cảnh & Vấn đề
Increment vòng đời & phát hành hóa đơn (PRD-INV-001) biến một đơn đã thanh toán thành một hóa đơn điện tử đã phát hành, có số, và ghi mọi sự kiện bất biến. Nó xác lập rằng một hóa đơn đã phát hành có thể được điều chỉnh, thay thế, hoặc hủy kèm lý do - nhưng chỉ nêu điều đó bằng một dòng. Cơ chế làm thế nào một bản sửa được tạo, phát hành, và gắn với bản gốc, và làm thế nào một thao tác hủy giữ an toàn trước đường ống phát hành bất đồng bộ, được để lại cho increment này.
Khoảng trống đó quan trọng vì sửa và hủy chính là chỗ dễ sai về tuân thủ. Một bản sửa phải tham chiếu lần phát hành gốc để nhà cung cấp và cơ quan thuế liên kết chúng; nó không được phát hành hai lần nếu một job thử lại; và nó không được áp lên một hóa đơn chưa từng được phát hành thành công. Một thao tác hủy không được chạy khi một worker đang giữa lần phát hành, phải lặp lại được mà không hủy hai lần, và - với một hóa đơn đã phát hành - phải tới được nhà cung cấp, chứ không chỉ lật một cờ cục bộ. PRD này đặc tả những luồng đó trên nền vòng đời hiện có.
2. Mục tiêu & Ngoài phạm vi
Mục tiêu
- Điều chỉnh một hóa đơn đã phát hành (SUCCESS) bằng cách tạo một hóa đơn sửa mới liên kết tới bản gốc, xử lý bất đồng bộ qua hàng đợi phát hành.
- Phát hành bản sửa qua nhà cung cấp tham chiếu lần phát hành gốc, để bản gốc và bản sửa được gắn ở phía nhà cung cấp / cơ quan thuế.
- Hỗ trợ điều chỉnh cho các loại hóa đơn VAT, POS-VAT, và ticket-VAT; từ chối các loại không có đường sửa của nhà cung cấp.
- Hủy một hóa đơn kèm lý do bắt buộc; với một hóa đơn đã phát hành, còn gọi hủy phía nhà cung cấp.
- Làm cho hủy lũy đẳng và bị chặn khi hóa đơn đang xử lý, để nó không bao giờ đua với worker phát hành.
- Ghi một mục kiểm toán bất biến cho mọi sự kiện điều chỉnh và hủy và đẩy một cập nhật thời gian thực tới các client đang kết nối.
Ngoài phạm vi
- Engine phát hành nền, chính sách thử lại, nộp cơ quan thuế, và xử lý webhook - đặc tả trong PRD-INV-001.
- Hóa đơn thay thế -
replacementlà một nguồn gốc hóa đơn được công nhận trong mô hình dữ liệu, nhưng việc phát hành một bản thay thế không được giao trong increment này. - Giao diện owner / thu ngân để chọn và xem một bản sửa - trải nghiệm quản lý được theo dõi dưới
ISS(PRD-ISS-001). - Tính lại dòng hàng, thuế, hoặc tổng cho bản sửa - bên gọi cung cấp các con số đã sửa; luồng này mang và phát hành chúng.
- Kết xuất PDF của bản sửa hoặc thông báo hủy - do nhà cung cấp tạo.
3. Chỉ số Thành công
| Chỉ số | Mục tiêu / tín hiệu |
|---|---|
| Liên kết bản sửa | Mọi hóa đơn sửa tham chiếu bản gốc và lần phát hành của bản gốc; không cái nào mồ côi |
| Không phát hành hai lần | Một job điều chỉnh bị thử lại hoặc nhân đôi phát hành bản sửa nhiều nhất một lần |
| An toàn khi hủy | Không có thao tác hủy nào áp lên một hóa đơn khi nó đang được xử lý |
| Lũy đẳng | Hủy lại một hóa đơn đã hủy không thay đổi gì và không gây lỗi |
| Đầy đủ kiểm toán | Mọi điều chỉnh và hủy có một mục dấu vết kiểm toán bất biến tương ứng |
4. Chân dung & Trường hợp dùng
| Chân dung | Mục tiêu trong tính năng này |
|---|---|
| Owner / Quản lý | Sửa hoặc hủy một hóa đơn đã phát hành một cách hợp pháp, kèm lý do, khi phát hiện sai sót |
| Thu ngân | Kích hoạt một bản sửa cho một hóa đơn phát hành tại quầy mà không phải tạo lại đơn bán |
| Kế toán (hạ nguồn) | Dựa vào liên kết bản gốc ↔ bản sửa và dấu vết kiểm toán để báo cáo thuế |
| Người mua | Nhận một hóa đơn đã sửa / đã hủy mà cơ quan thuế công nhận là liên kết với bản gốc |
Kịch bản chính: một owner phát hiện giá sai trên một hóa đơn đã phát hành → yêu cầu một điều chỉnh với các dòng hàng đã sửa và một mô tả → một hóa đơn sửa được tạo liên kết tới bản gốc và đưa vào hàng đợi → một worker phát hành nó qua nhà cung cấp tham chiếu lần phát hành gốc → trạng thái của nó chuyển sang success và các client cập nhật trực tiếp. Hoặc: một owner hủy một hóa đơn đã phát hành kèm lý do → hủy phía nhà cung cấp được gọi → hóa đơn được đánh dấu đã hủy và lý do được ghi. Hủy một hóa đơn còn đang xử lý bị từ chối; hủy một hóa đơn đã hủy thì không làm gì.
5. Câu chuyện Người dùng
- Là một owner, tôi muốn sửa một hóa đơn đã phát hành bằng cách phát hành một điều chỉnh liên kết, để bản ghi được sửa mà không sửa bản gốc.
- Là một owner, tôi muốn bản sửa gắn với bản gốc ở phía nhà cung cấp, để cơ quan thuế thấy chúng là một chuỗi.
- Là một owner, tôi muốn điều chỉnh chạy nền và không phát hành hai lần nếu một job thử lại, để bản sửa đáng tin cậy.
- Là một owner, tôi muốn hủy một hóa đơn đã phát hành kèm lý do và để việc hủy phía nhà cung cấp thực sự xảy ra, để việc hủy hợp pháp thật.
- Là một owner, tôi muốn hủy bị từ chối khi một hóa đơn còn đang được phát hành, để tôi không bao giờ làm hỏng một hóa đơn đang chạy.
- Là một owner, tôi muốn gửi lại một yêu cầu hủy là vô hại, để thử lại hoặc nhấp đúp không gây lỗi.
- Là một owner, tôi muốn mọi bản sửa và hủy được ghi bất biến và hiển thị trực tiếp, để lịch sử hóa đơn luôn kiểm chứng được.
6. Yêu cầu Chức năng
| # | Yêu cầu | URD ref |
|---|---|---|
| FR-1 | Chỉ một hóa đơn đã phát hành (SUCCESS) mới được điều chỉnh hoặc hủy; bản sửa luôn liên kết ngược về bản gốc | URD-INV-010 |
| FR-2 | Một điều chỉnh tạo một hóa đơn sửa mới (nguồn gốc adjustment) liên kết tới bản gốc và được xử lý bất đồng bộ qua hàng đợi phát hành | URD-INV-011 · URD-INV-007 |
| FR-3 | Bản sửa mang dòng hàng, mô tả, và tổng riêng của nó, và được phát hành qua nhà cung cấp tham chiếu lần phát hành gốc | URD-INV-012 |
| FR-4 | Điều chỉnh được hỗ trợ cho các loại hóa đơn VAT, POS-VAT, và ticket-VAT; một loại không hỗ trợ bị từ chối | URD-INV-013 |
| FR-5 | Worker bất đồng bộ giành một điều chỉnh đang chờ dưới một khóa lạc quan để một job bị thử lại hoặc nhân đôi phát hành bản sửa nhiều nhất một lần | URD-INV-011 |
| FR-6 | Hủy đánh dấu hóa đơn là đã hủy kèm lý do bắt buộc; với một hóa đơn đã phát hành còn gọi hủy phía nhà cung cấp | URD-INV-014 · URD-INV-008 |
| FR-7 | Hủy là lũy đẳng (hủy lại là no-op) và bị chặn khi hóa đơn đang được xử lý | URD-INV-015 |
| FR-8 | Mọi điều chỉnh và hủy ghi một mục kiểm toán bất biến và thông báo cho các client đang kết nối thời gian thực | URD-INV-016 · URD-INV-006 |
Toàn văn yêu cầu và tiêu chí chấp nhận nằm trong URD Thuế & Hóa đơn - INV. PRD này tham chiếu chúng thay vì nêu lại. Các yêu cầu vòng đời nền (URD-INV-001..009) được đặc tả trong PRD-INV-001.
7. Yêu cầu Phi chức năng
| Khía cạnh | Yêu cầu |
|---|---|
| Độ tin cậy | Điều chỉnh chạy qua hàng đợi phát hành với xử lý lũy đẳng; worker giành một bản sửa đang chờ dưới một chuyển trạng thái lạc quan (pending → processing) để một job phát lại không thể phát hành hai lần |
| Bất biến | Bản gốc không bao giờ bị sửa; bản sửa và hủy là các bản ghi mới / mục kiểm toán mới, chỉ thêm |
| Toàn vẹn liên kết | Một bản sửa lưu bản gốc của nó làm cha và phát hành với id tham chiếu của lần phát hành gốc; lý do hủy được lưu trên hóa đơn |
| An toàn trạng thái | Hủy từ chối một hóa đơn ở processing và chập mạch một hóa đơn đã cancelled; điều chỉnh từ chối một bản gốc không ở success |
| Đa thuê & phân quyền | Điều chỉnh và hủy được phân phạm vi theo merchant và được kiểm soát bởi quyền hóa đơn adjust / cancel chuyên biệt; quyền truy cập hóa đơn đích được xác nhận trước mọi thao tác |
| Thời gian thực | Kết quả của một bản sửa hoặc hủy được đẩy tới các client đang kết nối qua kênh trực tiếp |
| i18n | Nhãn / trạng thái hướng người dùng là song ngữ ({ en, vi }) |
8. UX & Luồng
Điều chỉnh - bản sửa bất đồng bộ
Hủy - có chốt trạng thái, lũy đẳng
Owner kích hoạt điều chỉnh hoặc hủy từ một hóa đơn đã phát hành; điều chỉnh trả về ngay trong khi bản sửa được phát hành ở nền, còn hủy hoàn tất đồng bộ. Bề mặt quản lý trình bày các thao tác này và kết quả của chúng được theo dõi dưới ISS.
9. Dữ liệu & Miền
| Thực thể | Vai trò trong các luồng này |
|---|---|
Invoice | Cả bản gốc và bản sửa; một bản sửa mang nguồn gốc adjustment và một liên kết cha tới bản gốc, cùng các dòng hàng / tổng đã sửa và (với hủy) lý do |
InvoiceIssuance | Bản ghi phát hành của bản gốc mà id tham chiếu của nó được bản sửa trích để nhà cung cấp và cơ quan thuế liên kết |
InvoiceAuditTracing | Mục bất biến theo từng sự kiện được ghi cho vòng đời của bản sửa và cho thao tác hủy |
Nguồn gốc hóa đơn là một trong
origin,adjustment, hoặcreplacement; increment này dùngorigin(hóa đơn nguồn) vàadjustment(bản sửa). Chỉ là khái niệm - schema và bất biến đầy đủ nằm trong mô hình miền invoice.
10. Phụ thuộc & Giả định
Phụ thuộc vào
- Vòng đời & phát hành hóa đơn (PRD-INV-001, URD-INV-001..009) - engine phát hành, dấu vết kiểm toán, và hóa đơn gốc + bản ghi phát hành của nó.
- Cấu hình hóa đơn (URD-CFG) - config nhà cung cấp của bản gốc được phân giải để phát hành bản sửa và để gọi hủy phía nhà cung cấp.
- Cổng nhà cung cấp (
@nx/iiapi) - adapter phát hành bản sửa và thực hiện hủy phía nhà cung cấp theo loại hóa đơn. @nx/core- hằng số nguồn gốc / trạng thái hóa đơn và mô hình hóa đơn dùng chung.
Giả định
- Hóa đơn gốc đã được phát hành thành công và giữ lại tham chiếu phát hành và config nhà cung cấp của nó.
- Bên gọi cung cấp các dòng hàng, mô tả, và tổng đã sửa; luồng này không tính lại chúng.
- Các client đang kết nối lắng nghe trên kênh trực tiếp để cập nhật hóa đơn.
11. Rủi ro & Câu hỏi mở
| Rủi ro / câu hỏi | Giảm thiểu / trạng thái |
|---|---|
| Job điều chỉnh nhân đôi / thử lại phát hành bản sửa hai lần | Worker giành bản sửa đang chờ dưới một chuyển trạng thái lạc quan pending → processing; worker thứ hai bỏ qua |
| Hủy đua với một lần phát hành đang chạy | Hủy từ chối một hóa đơn ở processing; worker điều chỉnh cũng bỏ qua một bản sửa bị hủy khi còn trong hàng đợi |
| Yêu cầu hủy lặp lại | Lũy đẳng - một hóa đơn đã hủy chập mạch mà không lỗi |
| Bản sửa không được cơ quan thuế công nhận là liên kết | Bản sửa trích tham chiếu phát hành gốc để nhà cung cấp và CQT gắn chúng |
| Điều chỉnh một loại hóa đơn không hỗ trợ | Chỉ VAT / POS-VAT / ticket-VAT có đường sửa của nhà cung cấp; các loại khác bị từ chối |
| Hóa đơn thay thế | Nguồn gốc replacement được mô hình hóa nhưng việc phát hành một bản thay thế ngoài phạm vi increment này |
12. Kế hoạch Phát hành & Tiêu chí Ra mắt
| Khía cạnh | Kế hoạch |
|---|---|
| Phase | P1 (nền tảng) - một phần của INV trong danh mục tính năng URD |
| Rollout | Mọi merchant có hồ sơ hóa đơn đang hoạt động; kiểm soát bởi quyền hóa đơn adjust / cancel |
| Migration | Không - bản sửa tái dùng thực thể hóa đơn hiện có (nguồn adjustment + liên kết cha) và hàng đợi phát hành |
| Tiêu chí ra mắt | Điều chỉnh một hóa đơn đã phát hành tạo một bản sửa liên kết, đưa vào hàng đợi, và phát hành nó qua nhà cung cấp tham chiếu bản gốc; một job thử lại không phát hành hai lần; hủy một hóa đơn đã phát hành gọi nhà cung cấp và ghi trạng thái + lý do; hủy bị từ chối khi đang xử lý và là no-op khi đã hủy; mọi thao tác ghi một mục kiểm toán và thông báo client |
| Giám sát | Tỉ lệ thành công / thất bại điều chỉnh, số lần bỏ qua giành kép, kết quả hủy (nhà cung cấp vs cục bộ), độ phủ mục kiểm toán |
13. FAQ
Một hóa đơn đã phát hành có thể sửa không? Không. Nó được sửa bằng cách phát hành một hóa đơn điều chỉnh liên kết, hoặc hủy kèm lý do. Bản gốc không bao giờ bị thay đổi.
Cái gì gắn một bản sửa với bản gốc của nó? Bản sửa lưu bản gốc làm cha và được phát hành trích tham chiếu phát hành của bản gốc, để nhà cung cấp và cơ quan thuế coi chúng là một chuỗi.
Nếu job điều chỉnh chạy hai lần thì sao? Nó không thể phát hành hai lần. Một worker giành bản sửa đang chờ dưới một khóa lạc quan; bất kỳ nỗ lực thứ hai nào thấy nó không còn đang chờ và bỏ qua.
Tôi có thể điều chỉnh những hóa đơn nào? Chỉ những cái đã phát hành thành công (SUCCESS), và chỉ loại VAT, POS-VAT, hoặc ticket-VAT - các loại khác không có đường sửa của nhà cung cấp và bị từ chối.
Tôi có thể hủy một hóa đơn còn đang được phát hành không? Không - hủy bị từ chối khi hóa đơn ở processing. Đợi phát hành xong, rồi hủy.
Hủy hai lần có vấn đề không? Không - hủy là lũy đẳng. Một yêu cầu thứ hai trên một hóa đơn đã hủy không làm gì và trả về sạch.
Hủy một hóa đơn đã phát hành có tới được nhà cung cấp không? Có - với một hóa đơn đã phát hành (SUCCESS) việc hủy phía nhà cung cấp được gọi trước khi hóa đơn được đánh dấu đã hủy cục bộ và lý do được ghi.
Tham chiếu
- URD: Thuế & Hóa đơn - Vòng đời Hóa đơn
- PRD liên quan: Vòng đời & phát hành hóa đơn · Tích hợp nhà cung cấp hóa đơn điện tử · Trải nghiệm phát hành hóa đơn
- Module: Thuế & Hóa đơn - tổng quan + truy vết
- Developer: @nx/invoice · @nx/core · iiapi