Module Tồn Kho & Giữ Hàng (Inventory & Reservations)
Bài toán của Vicore F&B (TP-LEMON):
Trong dịp Flash Sale ngày Lễ, chỉ có đúng 10 chai Nước ép TP-LEMON 500ml bản giới hạn. Có 100 khách hàng cùng bỏ chai này vào giỏ hàng (Cart). Tuy nhiên, ai nhanh tay bấm "Thanh toán" trước thì mới được mua. Khi 10 người đầu tiên thanh toán thành công, hệ thống phải tự động thông báo "Hết hàng" cho 90 người còn lại và không cho họ thanh toán, dù sản phẩm vẫn đang nằm trong giỏ hàng của họ.
Giải pháp:
Medusa v2 tách biệt hoàn toàn Module Sản phẩm (Product) và Module Tồn kho (Inventory). Nó sử dụng cơ chế Inventory Reservations (Giữ hàng) để xử lý triệt để bài toán tranh giành mua hàng (Race condition) trong E-commerce.
1. Mối quan hệ giữa Variant và Inventory Item
Ngày xưa (Medusa v1), Tồn kho là một con số gắn trực tiếp vào Variant. Tuy nhiên, điều này gây rắc rối khi một sản phẩm được cấu thành từ nhiều linh kiện, hoặc khi bán combo.
Ở Medusa v2:
- Product Variant (Biến thể mặt hàng): Là cái vỏ bán hàng trên web.
- Inventory Item (Mặt hàng Tồn kho): Là thực thể vật lý cất trong kho.
- Một Variant có thể được ánh xạ (map) tới một hoặc nhiều Inventory Items.
Ví dụ: Variant "Combo 2 chai TP-LEMON" sẽ được ánh xạ với 2 Inventory Items của "Chai TP-LEMON". Khi bán được 1 Combo, hệ thống tự trừ 2 chai trong kho.
2. Các trạng thái Tồn Kho
Một Inventory Item sẽ được quản lý qua các con số trạng thái sau:
- In Stock (Hàng có sẵn): Tổng số chai vật lý thực tế đang nằm trong kho (Ví dụ: 10 chai).
- Reserved (Hàng bị giữ): Số lượng chai đã thuộc về khách hàng nhưng chưa được bốc ra khỏi kho đưa cho shipper.
- Available (Hàng khả dụng): Số chai thực sự còn có thể bán trên Web.
- Công thức:
Available = In Stock - Reserved.
- Công thức:
3. Cơ Chế Giữ Hàng (Reservations)
Sự kỳ diệu của hệ thống nằm ở luồng Giữ hàng (Reservation Flow) trong quá trình Checkout.
3.1. Khi nào hệ thống Giữ Hàng?
Medusa KHÔNG giữ hàng khi khách mới bỏ vào Giỏ (Add to Cart). Nếu giữ lúc này, đối thủ có thể viết Bot cho 1000 món vào giỏ hàng và không thanh toán, làm Website tê liệt vì "Hết hàng ảo".
Hệ thống chỉ tạo một Reservation (Lệnh giữ hàng tạm thời) tại thời điểm khách hàng Hoàn tất thanh toán (Payment Authorized) và hệ thống sinh ra Đơn hàng (Order).
- Lúc này: In Stock = 10, Reserved = 1, Available = 9.
3.2. Khi nào hệ thống Trừ Hàng (Deduction)?
Khi nhân viên kho in phiếu xuất kho, bốc hàng bỏ vào hộp và giao cho Shipper (Quá trình này gọi là Fulfillment).
- Hệ thống sẽ xóa lệnh Reservation và trừ trực tiếp vào In Stock.
- Lúc này: In Stock = 9, Reserved = 0, Available = 9.
3.3. Khi đơn hàng bị hủy
Nếu khách hàng đặt xong nhưng hủy đơn trước khi giao, hoặc thanh toán bị từ chối ở phút chót:
- Hệ thống tự động xóa lệnh Reservation.
- Số lượng Available sẽ tự động nhảy ngược lên, trả hàng về cho khách khác mua tiếp.
4. Tổng Kết
- Kiến trúc mới chia tách Product và Inventory giúp quản lý các combo và nguyên vật liệu phức tạp (BOM - Bill of Materials).
- Cơ chế Reservation ngăn chặn hoàn toàn lỗi bán lố (Overselling) trong các dịp Flash Sale lượng truy cập cực cao.