Đặc tả nghiệp vụ quản lý tồn kho
Phiên bản: 1.0
Ngày cập nhật: 12/08/2026
Phạm vi: Nhập kho, xuất kho, kiểm kho, điều chỉnh tồn, số dư tồn kho và nhật ký kho.
1. Mục tiêu và nguyên tắc chung
Hệ thống quản lý tồn kho phải đáp ứng các yêu cầu sau:
- Số dư hiện tại được truy vấn nhanh nhưng vẫn có thể tái dựng từ lịch sử giao dịch.
- Không phát sinh tồn âm trong quy trình thông thường.
- Mọi thay đổi tồn kho đều truy vết được tới chứng từ nguồn, người thao tác và lý do.
- Chứng từ đã hạch toán không được sửa hoặc xóa trực tiếp.
- Sai dữ liệu phải được sửa bằng giao dịch bù hoặc phiếu hoàn tác.
- Các thao tác cập nhật số dư, reservation và ledger phải có tính nguyên tử.
- Một request gửi lại không được hạch toán trùng.
Hiện tại hệ thống chỉ có một kho. UI không cần yêu cầu người dùng chọn kho, nhưng backend vẫn phải lưu:
warehouse_id = DEFAULT_WAREHOUSE
Việc này giúp dữ liệu nhất quán và cho phép mở rộng nhiều kho trong tương lai.
2. Các đại lượng tồn kho
Hệ thống quản lý bốn đại lượng độc lập cho từng cặp warehouse_id + product_id/SKU.
| Đại lượng | Tên hiển thị trên UI | Ý nghĩa | Cách xác định |
|---|---|---|---|
on_hand |
Tồn thực tế | Số lượng hàng hiện đang có trong kho và đã được hạch toán | Tổng delta_on_hand từ stock ledger |
reserved |
Đang giữ hàng | Số lượng vẫn nằm trong kho nhưng đã được dành cho các phiếu xuất ở trạng thái chuẩn bị hàng | Tổng reservation còn hiệu lực |
available |
Có thể xuất | Số lượng còn có thể tiếp tục giữ cho phiếu xuất mới hoặc xuất khỏi kho | on_hand - reserved |
incoming |
Sắp về | Số lượng thuộc các phiếu nhập đã xác nhận nhưng chưa được nhập thực tế vào kho | Tổng số lượng còn lại của các phiếu nhập đã xác nhận |
2.1. Giải thích tên hiển thị trên giao diện
Tồn thực tế (on_hand)
Đây là số lượng đã được ghi nhận chính thức trong kho. Chỉ các nghiệp vụ đã hạch toán như hoàn tất nhập kho, hoàn tất xuất kho, hoàn thành kiểm kho, điều chỉnh tồn hoặc hoàn tác mới làm thay đổi số này.
on_hand không bao gồm hàng mới đặt mua hoặc phiếu nhập chưa hoàn thành.
Đang giữ hàng (reserved)
Đây là hàng vẫn còn trong kho nhưng đã được phân bổ cho phiếu xuất đang chuẩn bị. User khác không được tiếp tục sử dụng phần hàng này để tạo reservation mới.
Khi phiếu xuất hoàn tất, số lượng được giảm đồng thời khỏi on_hand và reserved. Khi phiếu xuất bị hủy trước khi hoàn tất, hệ thống chỉ giải phóng reserved.
Có thể xuất (available)
Đây là số lượng thực sự còn có thể cấp cho phiếu xuất mới:
available = on_hand - reserved
Mọi kiểm tra đủ hàng khi chuyển phiếu xuất sang Chuẩn bị hàng phải sử dụng available, không sử dụng riêng on_hand.
Sắp về (incoming)
incoming tương đương với nhãn Sắp về trên giao diện.
Số này biểu thị hàng dự kiến sẽ vào kho từ các phiếu nhập đã được xác nhận, nhưng chưa được nhận và chưa hạch toán vào tồn thực tế. Vì vậy:
- Sắp về không thuộc Tồn thực tế.
- Sắp về không được cộng vào Có thể xuất.
- Khi phiếu nhập được xác nhận, Sắp về tăng.
- Khi hàng được nhập kho, Sắp về giảm và Tồn thực tế tăng tương ứng.
- Khi phiếu nhập đã xác nhận bị hủy, phần số lượng còn lại được loại khỏi Sắp về.
Tooltip đề xuất trên UI:
Số lượng từ các phiếu nhập đã xác nhận nhưng chưa nhập kho.
Khi nhấn vào giá trị Sắp về, UI nên mở danh sách các phiếu nhập liên quan, gồm mã phiếu, số lượng còn lại, ngày dự kiến nhận và trạng thái. Phiếu quá ngày dự kiến vẫn được tính trong Sắp về, đồng thời hiển thị cảnh báo Trễ dự kiến.
2.2. Công thức chuẩn
available = on_hand - reserved
incoming = Σ(
confirmed_quantity
- received_quantity
- cancelled_quantity
)
incoming không được cộng vào available vì hàng chưa có trong kho.
Nếu UI cần hiển thị số dự báo, sử dụng tên riêng để tránh nhầm với tồn hiện tại:
projected_on_hand = on_hand + incoming
projected_available = available + incoming
2.3. Bất biến dữ liệu
Tại mọi thời điểm, hệ thống phải đảm bảo:
on_hand >= 0
reserved >= 0
reserved <= on_hand
incoming >= 0
available = on_hand - reserved
Backend không được dùng max(0, on_hand - reserved) để che giấu dữ liệu sai.
3. Ma trận ảnh hưởng số dư
Trong bảng dưới đây, q là số lượng trên dòng chứng từ và d là chênh lệch kiểm kho hoặc điều chỉnh.
| Nghiệp vụ | Sự kiện | on_hand |
reserved |
incoming |
available |
|---|---|---|---|---|---|
| Nhập kho | Tạo phiếu mới | 0 | 0 | 0 | 0 |
| Nhập kho | Xác nhận phiếu | 0 | 0 | +q |
0 |
| Nhập kho | Nhập hàng | +q |
0 | -q |
+q |
| Nhập kho | Hủy sau xác nhận | 0 | 0 | -q |
0 |
| Hoàn tác nhập | Hoàn tác phiếu đã nhập | -q |
0 | 0 | -q |
| Xuất kho | Tạo phiếu mới | 0 | 0 | 0 | 0 |
| Xuất kho | Chuẩn bị hàng | 0 | +q |
0 | -q |
| Xuất kho | Hoàn tất | -q |
-q |
0 | 0 |
| Xuất kho | Hủy khi chuẩn bị | 0 | -q |
0 | +q |
| Hoàn tác xuất | Hoàn tác phiếu đã xuất | +q |
0 | 0 | +q |
| Kiểm kho | Bắt đầu kiểm | 0 | 0 | 0 | 0 |
| Kiểm kho | Hoàn thành | +d |
0 | 0 | +d |
| Kiểm kho | Hủy | 0 | 0 | 0 | 0 |
| Điều chỉnh tồn | Hoàn thành | +d |
0 | 0 | +d |
| Hoàn tác điều chỉnh | Hoàn tác phiếu đã hoàn thành | -d |
0 | 0 | -d |
4. Nghiệp vụ nhập kho
4.1. Trạng thái
Mới → Đã xác nhận → Đã nhập hàng
└──────────────→ Đã hủy
| Trạng thái | Ảnh hưởng số dư | Khả năng sửa |
|---|---|---|
| Mới | Không ảnh hưởng | Được sửa toàn bộ |
| Đã xác nhận | Tăng incoming; chưa tăng on_hand |
Hạn chế; không đổi sản phẩm sau khi đã duyệt |
| Đã nhập hàng | Tăng on_hand, giảm incoming |
Không được sửa |
| Đã hủy | Không ảnh hưởng hoặc giải phóng incoming |
Không được sửa |
| Đã hoàn tác | Đã có giao dịch bù ngược dấu | Không được sửa |
4.2. Quy tắc hạch toán
- Chỉ trạng thái Đã nhập hàng mới cộng
on_hand. - Phiếu Đã xác nhận chỉ làm tăng
incoming. - Chuyển sang Đã nhập hàng phải hạch toán toàn bộ dòng sản phẩm trong một database transaction.
- Nếu một dòng thất bại, rollback toàn bộ phiếu.
- Mỗi phiếu chỉ được hạch toán một lần.
- Giá nhập tại thời điểm hoàn tất phải được lưu thành snapshot.
- Giá snapshot không thay đổi khi giá sản phẩm thay đổi sau này.
4.3. Nhập hàng một phần
Phiên bản đầu có thể chỉ hỗ trợ nhập toàn bộ. Nếu hỗ trợ nhập một phần, mỗi lần nhận r sản phẩm:
on_hand += r
incoming -= r
Phiếu chỉ chuyển sang Đã nhập hàng khi toàn bộ số lượng được nhận; nếu chưa đủ có thể sử dụng trạng thái Đã nhập một phần.
Phiếu đã quá ngày dự kiến nhưng chưa nhận đủ vẫn được tính trong incoming và phải được đánh dấu Trễ dự kiến.
4.4. Hủy và hoàn tác nhập kho
- Phiếu mới có thể sửa hoặc hủy.
- Phiếu đã xác nhận có thể hủy nếu chưa hạch toán; hệ thống phải giảm phần
incomingcòn lại. - Phiếu đã nhập hàng không được hủy trực tiếp.
- Muốn sửa phiếu đã nhập phải hoàn tác phiếu cũ, sau đó sao chép thành phiếu mới.
- Không cho hoàn tác nếu kết quả làm
on_hand < reserved.
Điều kiện hoàn tác một dòng nhập:
quantity_to_reverse <= available
5. Nghiệp vụ xuất kho và giữ hàng
5.1. Trạng thái
Mới → Chuẩn bị hàng → Hoàn tất
└───────────────→ Đã hủy
| Trạng thái | Ảnh hưởng số dư |
|---|---|
| Mới | Không ảnh hưởng |
| Chuẩn bị hàng | Tăng reserved, giảm available |
| Hoàn tất | Giảm on_hand, đồng thời giải phóng reserved |
| Hủy khi chuẩn bị | Giải phóng reserved |
| Hoàn tác sau hoàn tất | Cộng lại on_hand bằng giao dịch bù |
5.2. Tạo reservation
Phiếu mới không giữ hàng. Reservation chỉ được tạo khi chuyển sang Chuẩn bị hàng.
Điều kiện:
requested_quantity <= available
Khi thành công:
reserved += requested_quantity
available -= requested_quantity
Reservation phải gắn với từng dòng phiếu xuất để xác định hàng đang được giữ cho phiếu nào.
5.3. Hoàn tất xuất kho
Khi hoàn tất, hệ thống phải xác nhận reservation của chính dòng phiếu vẫn còn đủ:
reservation_quantity >= requested_quantity
on_hand >= requested_quantity
Sau đó thực hiện trong cùng transaction:
on_hand -= requested_quantity
reserved -= requested_quantity
available không thay đổi tại bước hoàn tất vì lượng hàng đó đã được trừ khỏi available khi tạo reservation.
Ví dụ:
Trước chuẩn bị: on_hand = 10, reserved = 0, available = 10
Sau chuẩn bị 6: on_hand = 10, reserved = 6, available = 4
Sau hoàn tất: on_hand = 4, reserved = 0, available = 4
5.4. Hủy và sửa phiếu đang chuẩn bị
Khi hủy phiếu đang chuẩn bị:
reserved -= reserved_quantity
available += reserved_quantity
Nếu cần sửa sản phẩm hoặc số lượng của phiếu đang chuẩn bị, quy trình an toàn là:
- Giải phóng toàn bộ reservation của phiếu.
- Chuyển phiếu về trạng thái được phép sửa.
- Sửa dòng sản phẩm.
- Chuyển lại sang Chuẩn bị hàng.
- Kiểm tra
availablevà tạo reservation mới.
Không được tự động hoàn tất một phần phiếu nếu một dòng không đủ hàng.
5.5. Hoàn tác xuất kho
Phiếu đã hoàn tất không được đổi trạng thái ngược về Chuẩn bị hàng. Hệ thống tạo giao dịch hoàn tác:
original_delta = -q
reversal_delta = +q
Phiếu gốc chuyển sang Đã hoàn tác nhưng không bị xóa.
6. Nghiệp vụ kiểm kho
6.1. Mục tiêu
Kiểm kho dùng để đối chiếu số lượng vật lý với số lượng hệ thống, phù hợp cho kiểm kê định kỳ, kiểm nhiều SKU hoặc kiểm theo đợt.
Kiểm đếm vật lý phải so với on_hand, không so với available. Hàng đang reserved vẫn còn nằm trong kho cho đến khi phiếu xuất hoàn tất.
6.2. Dữ liệu khi bắt đầu
Khi tạo phiếu, hệ thống lưu snapshot:
on_hand_at_start.- Thời điểm bắt đầu.
- Danh sách sản phẩm/SKU.
- Người tạo và người kiểm.
Nhân viên chỉ nhập số lượng kiểm đếm thực tế. Hệ thống tự tính tồn kỳ vọng, chênh lệch và tồn sau điều chỉnh.
6.3. Công thức khi hoàn thành
expected_on_hand =
on_hand_at_start
+ Σ(delta_on_hand phát sinh từ lúc bắt đầu đến lúc hoàn thành)
variance = counted_quantity - expected_on_hand
adjusted_on_hand = expected_on_hand + variance
= counted_quantity
Tổng biến động trong thời gian kiểm phải bao gồm nhập, xuất, hoàn tác và các điều chỉnh khác.
6.4. Trạng thái
| Trạng thái | Ảnh hưởng tồn |
|---|---|
| Đang kiểm hàng | Không ảnh hưởng |
| Hoàn thành | Ghi giao dịch điều chỉnh bằng variance |
| Hủy | Không ảnh hưởng |
| Đã hoàn tác | Ghi giao dịch bù ngược dấu |
Thời gian hoàn thành phải để trống khi tạo và chỉ được hệ thống ghi khi phiếu chuyển sang Hoàn thành.
6.5. Kiểm tra reservation
Trước khi hoàn thành phải đảm bảo:
adjusted_on_hand >= reserved
Nếu số lượng kiểm đếm thấp hơn lượng đang giữ, hệ thống phải chặn và yêu cầu người có quyền xử lý các phiếu xuất liên quan. Không tự động giải phóng hoặc hủy reservation.
Nên chỉ cho phép một phiếu kiểm kho đang hoạt động trên cùng SKU và kho.
7. Điều chỉnh tồn trực tiếp từ quản lý sản phẩm
7.1. Nguyên tắc
Cho phép user thao tác nhanh tại Product Detail, nhưng không cho sửa trực tiếp trường on_hand.
Mỗi lần thay đổi phải tự động tạo một Phiếu điều chỉnh tồn kho. Không ngầm tạo phiếu nhập hoặc phiếu xuất thông thường vì sẽ làm sai bản chất và báo cáo nghiệp vụ.
7.2. Lựa chọn chứng từ
| Tình huống | Chứng từ cần dùng |
|---|---|
| Nhận hàng từ nhà cung cấp hoặc khách trả hàng | Phiếu nhập kho |
| Giao hàng, xuất dùng hoặc trả nhà cung cấp | Phiếu xuất kho |
| Phát hiện thừa/thiếu, hư hỏng, mất hàng hoặc sửa dữ liệu | Phiếu điều chỉnh tồn |
| Kiểm đếm định kỳ hoặc nhiều SKU | Phiếu kiểm kho |
| Khai báo số dư ban đầu | Phiếu điều chỉnh – Tồn đầu kỳ |
7.3. Trạng thái phiếu điều chỉnh
| Trạng thái | Ảnh hưởng tồn |
|---|---|
| Nháp | Không ảnh hưởng |
| Chờ duyệt | Không ảnh hưởng |
| Hoàn thành | Cộng hoặc trừ on_hand |
| Từ chối/Hủy | Không ảnh hưởng |
| Đã hoàn tác | Ghi giao dịch bù ngược dấu |
Nếu user có cả quyền tạo và duyệt, hệ thống có thể tạo rồi hoàn thành phiếu ngay. Nếu chỉ có quyền đề xuất, phiếu phải ở trạng thái Chờ duyệt.
Điều chỉnh vượt ngưỡng số lượng hoặc giá trị cấu hình phải được quản lý phê duyệt.
7.4. Cách nhập số lượng
Modal điều chỉnh hỗ trợ một trong hai cách:
- Nhập Số lượng thực tế mới; hoặc
- Nhập Số lượng tăng/giảm.
Không cho nhập đồng thời cả hai.
Giả sử:
OH = on_hand hiện tại
R = reserved
T = số lượng thực tế mới
D = T - OH
Kết quả:
on_hand' = OH + D
reserved' = R
available' = on_hand' - reserved'
incoming' = incoming
Điều chỉnh tồn không làm thay đổi reserved hoặc incoming.
7.5. Điều kiện giảm tồn
Bắt buộc:
T >= reserved
Tương đương:
abs(negative_delta) <= available
Nếu không đạt, hệ thống phải chặn và hiển thị các phiếu xuất đang giữ hàng. Không tự động giải phóng reservation.
7.6. Lý do điều chỉnh
Bắt buộc chọn một lý do chuẩn hóa:
- Tồn đầu kỳ.
- Phát hiện thừa.
- Phát hiện thiếu.
- Hàng hư hỏng.
- Hàng thất thoát.
- Sửa sai dữ liệu.
- Dùng nội bộ.
- Khác — bắt buộc nhập giải thích.
Nếu tăng tồn và hệ thống quản lý giá vốn, cần lưu giá trị hoặc đơn giá điều chỉnh. Giá có thể mặc định theo giá vốn hiện tại nhưng thay đổi thủ công phải có quyền riêng.
8. Hủy, hoàn tác và mở lại chứng từ
8.1. Trước khi hạch toán
- Phiếu mới có thể sửa hoặc hủy.
- Phiếu nhập đã xác nhận có thể hủy nếu chưa nhập hàng; giải phóng
incoming. - Phiếu xuất đang chuẩn bị có thể hủy; giải phóng
reserved. - Phiếu kiểm đang kiểm có thể hủy; không tạo giao dịch điều chỉnh.
- Phiếu điều chỉnh nháp hoặc chờ duyệt có thể hủy; không ảnh hưởng tồn.
8.2. Sau khi hạch toán
Không cho phép:
- Sửa sản phẩm, số lượng hoặc giá.
- Xóa chứng từ.
- Đổi trực tiếp trạng thái về trước.
- Ghi đè ledger cũ.
- Mở lại chứng từ đã hoàn thành.
Thay vào đó, cung cấp thao tác Yêu cầu hoàn tác.
| Chứng từ gốc | Giao dịch hoàn tác |
|---|---|
Nhập kho +10 |
-10 |
Xuất kho -10 |
+10 |
Kiểm kho điều chỉnh -3 |
+3 |
Điều chỉnh tồn +5 |
-5 |
8.3. Quy trình hoàn tác
- User chọn Yêu cầu hoàn tác.
- User bắt buộc nhập lý do.
- Người có quyền quản lý kho phê duyệt.
- Hệ thống tạo chứng từ hoàn tác mới, tham chiếu chứng từ gốc.
- Hệ thống ghi giao dịch tồn ngược dấu.
- Chứng từ gốc chuyển sang Đã hoàn tác và không bị xóa.
Một chứng từ chỉ được hoàn tác toàn bộ một lần. Nếu hỗ trợ hoàn tác một phần, phải tạo chứng từ mới ghi rõ từng dòng và số lượng hoàn tác.
9. Chống xuất âm và xử lý đồng thời
9.1. Kiểm tra tồn
Không cho phép:
requested_quantity > available
Kiểm tra diễn ra hai lần:
- Trên UI khi user chọn sản phẩm, nhằm cảnh báo sớm.
- Tại backend khi chuyển sang Chuẩn bị hàng, đây là kiểm tra có hiệu lực cuối cùng.
Khi hoàn tất xuất, backend kiểm tra reservation của chính phiếu thay vì trừ thêm từ available.
Thông báo lỗi phải cung cấp đủ ngữ cảnh, ví dụ:
Sản phẩm A yêu cầu 8; tồn thực tế 10;
đang giữ 6; có thể xuất 4.
9.2. Nhiều người thao tác đồng thời
Ví dụ available ban đầu bằng 10:
- User A yêu cầu giữ 7.
- Gần đồng thời, user B yêu cầu giữ 5.
- A thành công trước,
availablecòn 3. - B thất bại do không đủ tồn.
Backend phải:
- Khóa bản ghi stock balance của từng sản phẩm khi kiểm tra và cập nhật.
- Kiểm tra và tạo reservation trong cùng database transaction.
- Khóa SKU theo thứ tự cố định khi chứng từ có nhiều dòng để tránh deadlock.
- Rollback toàn bộ chứng từ nếu bất kỳ dòng nào thất bại.
- Sử dụng
idempotency_keyđể request gửi lại không tạo giao dịch trùng. - Không cho override xuất âm trong quy trình thông thường.
Nếu tương lai cần ngoại lệ xuất âm, đây phải là quyền quản lý riêng và tạo cảnh báo audit mức cao.
10. Stock balance, reservation và incoming
10.1. Stock balance
Stock balance là dữ liệu tổng hợp hiện tại để truy vấn nhanh. Tối thiểu gồm:
warehouse_id
product_id / sku_id
on_hand
reserved
version
updated_at
available nên được tính từ on_hand - reserved, không lưu thành nguồn dữ liệu độc lập nếu không cần tối ưu đặc biệt.
10.2. Reservation
Reservation tối thiểu gồm:
reservation_id
warehouse_id
product_id / sku_id
source_document_type
source_document_id
source_line_id
quantity
status
created_at
released_at
reserved trong stock balance phải bằng tổng reservation đang hiệu lực.
10.3. Incoming
incoming có thể tính từ các dòng phiếu nhập đã xác nhận. Nếu cần cache để truy vấn nhanh, cache phải được cập nhật trong cùng transaction với thay đổi trạng thái phiếu nhập.
11. Stock ledger bất biến
11.1. Mục đích
Cần tách hai lớp dữ liệu:
- Stock balance: số dư hiện tại để truy vấn nhanh.
- Stock ledger: sổ cái bất biến để kiểm tra, audit và tái dựng số dư.
Mọi thay đổi on_hand hoặc reserved phải tạo một dòng ledger. Sự kiện chỉ thay đổi reservation vẫn phải được ghi với delta_on_hand = 0.
11.2. Trường dữ liệu tối thiểu
| Trường | Ý nghĩa |
|---|---|
| Mã giao dịch | ID duy nhất |
| Sản phẩm/SKU | Sản phẩm bị ảnh hưởng |
| Kho | DEFAULT_WAREHOUSE trong phiên bản hiện tại |
| Loại giao dịch | Nhập, xuất, giữ hàng, giải phóng, kiểm kho, điều chỉnh, hoàn tác |
| Nguồn | Loại chứng từ và mã chứng từ |
| Dòng nguồn | ID dòng sản phẩm trong chứng từ |
delta_on_hand |
Số lượng thay đổi tồn thực tế |
on_hand_before/after |
Tồn thực tế trước và sau |
reserved_before/after |
Giữ hàng trước và sau |
| Người thực hiện | Tài khoản thao tác |
| Thời điểm nghiệp vụ | Khi nghiệp vụ có hiệu lực |
| Thời điểm ghi hệ thống | Khi dữ liệu được lưu |
| Lý do | Bắt buộc với kiểm kho, điều chỉnh và hoàn tác |
| Giao dịch gốc | Bắt buộc với giao dịch hoàn tác |
idempotency_key |
Chống ghi trùng |
11.3. Quy tắc ledger
- Không được update hoặc delete ledger.
- Sai dữ liệu phải sửa bằng giao dịch bù.
- Cập nhật balance, reservation và ghi ledger nằm trong cùng transaction.
- Từ ledger phải tái dựng được cả
on_handvàreserved. - Mỗi thay đổi trạng thái chứng từ phải có audit log riêng, kể cả trạng thái không ảnh hưởng số dư.
12. Quyền và phê duyệt
Nên tách các quyền:
inventory.view
inventory.receive.create
inventory.receive.complete
inventory.issue.create
inventory.issue.reserve
inventory.issue.complete
inventory.count.create
inventory.count.complete
inventory.adjust.create
inventory.adjust.approve
inventory.reverse.request
inventory.reverse.approve
Các trường hợp cần phê duyệt quản lý:
- Điều chỉnh vượt ngưỡng số lượng hoặc giá trị.
- Hoàn tác chứng từ đã hạch toán.
- Thay đổi giá trị tồn khi tăng điều chỉnh.
- Ngoại lệ xuất âm nếu được hỗ trợ trong tương lai.
13. Yêu cầu UI tại Product Detail
13.1. Khối kho hàng
Hiển thị rõ bốn chỉ số:
Tồn thực tế 123
Đang giữ hàng 8
Có thể xuất 115
Sắp về 50
on_hand,reserved,available,incomingđều là read-only.- Đang giữ hàng có link tới các phiếu xuất đang chuẩn bị.
- Sắp về có link tới các phiếu nhập đã xác nhận.
- Cung cấp nút Điều chỉnh tồn cho user có quyền.
13.2. Modal điều chỉnh tồn
Hiển thị:
- SKU và tên sản phẩm.
- Tồn thực tế hiện tại.
- Đang giữ hàng.
- Có thể xuất.
- Số lượng thực tế mới hoặc số lượng tăng/giảm.
- Bản xem trước tồn sau điều chỉnh.
- Lý do bắt buộc.
- Ghi chú và chứng từ đính kèm.
- Giá/giá trị điều chỉnh khi tăng tồn nếu quản lý giá vốn.
13.3. Lịch sử kho
Lịch sử mặc định ở trạng thái collapsed. Khi mở rộng, bảng tối thiểu có:
- Thời gian nghiệp vụ.
- Loại giao dịch.
- Mã chứng từ.
- Số lượng thay đổi.
- Tồn trước.
- Tồn sau.
- Giữ hàng trước/sau khi cần.
- Người thực hiện.
- Lý do.
Mã phiếu nhập, xuất, kiểm kho và điều chỉnh phải là link mở trực tiếp chứng từ nguồn.
14. Ví dụ tổng hợp
Trạng thái ban đầu:
on_hand = 100
reserved = 10
available = 90
incoming = 50
Bước 1 — Xác nhận thêm phiếu nhập 20
on_hand = 100
reserved = 10
available = 90
incoming = 70
Bước 2 — Chuẩn bị phiếu xuất 15
on_hand = 100
reserved = 25
available = 75
incoming = 70
Bước 3 — Hoàn tất phiếu xuất 15
on_hand = 85
reserved = 10
available = 75
incoming = 70
Bước 4 — Nhập hàng 20
on_hand = 105
reserved = 10
available = 95
incoming = 50
Bước 5 — Điều chỉnh giảm 5 do hư hỏng
on_hand = 100
reserved = 10
available = 90
incoming = 50
Hệ thống tạo phiếu điều chỉnh, ghi ledger delta_on_hand = -5 và bắt buộc lưu lý do Hàng hư hỏng.
15. Tiêu chí nghiệm thu cốt lõi
- Chỉ phiếu nhập đã hạch toán mới tăng
on_hand. - Phiếu nhập đã xác nhận tăng
incoming, không tăngavailable. - Chuẩn bị xuất tăng
reservedvà giảmavailable. - Hoàn tất xuất giảm đồng thời
on_handvàreserved. - Kiểm kho dùng
on_hand, không dùngavailable, làm số đối chiếu. - Điều chỉnh trực tiếp luôn tạo phiếu điều chỉnh và ledger; không ghi đè số dư.
- Không thao tác nào được làm
reserved > on_handhoặcavailable < 0. - Không hoàn tác nhập/điều chỉnh giảm nếu ảnh hưởng hàng đang giữ.
- Một request lặp lại không được hạch toán lần thứ hai.
- Chứng từ nhiều dòng được hạch toán toàn bộ hoặc rollback toàn bộ.
- Ledger không thể sửa hoặc xóa và tái dựng được số dư.
- Mọi thay đổi trạng thái chứng từ có audit log.