Favorite listing - lưu và theo dõi tin yêu thích
Feature URL
Module
listing
Status
draft
Priority
P2
Platforms
fe · be
AC progress
0 / 11
Last reviewed
2026-05-29
Mục tiêu
Favorite listing cho phép người dùng lưu (yêu thích) một tin đăng bất động sản để xem lại sau và theo dõi các tin quan tâm ở một nơi. Feature giúp người mua/thuê không bị lạc tin trong quá trình tìm kiếm, đồng thời cung cấp cho chủ tin tín hiệu mức độ quan tâm thông qua số lượt thích và thông báo khi tin được yêu thích.
Phạm vi
Trong phạm vi (In scope):
- Cho phép người dùng đã đăng nhập lưu (favorite) và bỏ lưu (unfavorite) một listing.
- Thao tác lưu/bỏ lưu là idempotent: lặp lại cùng thao tác không tạo bản ghi trùng hoặc làm sai số đếm.
- Hiển thị danh sách các listings mà người dùng đã thích, sắp xếp theo thời điểm thích gần nhất.
- Khi duyệt danh sách hoặc xem chi tiết listing, hiển thị trạng thái “đã thích / chưa thích” theo người dùng hiện tại.
- Hiển thị số lượt thích (
favorite_count) trên mỗi listing. - Gửi thông báo cho chủ tin khi tin của họ được người khác yêu thích, áp dụng cơ chế gộp thông báo (“A và N người khác đã thích tin của bạn”).
- Giới hạn tần suất thao tác lưu/bỏ lưu để chống spam.
Ngoài phạm vi (Out of scope):
- Định nghĩa chi tiết schema vật lý, kiểu dữ liệu, index và migration.
- Gợi ý listing dựa trên hành vi yêu thích (recommendation).
- Chia sẻ hoặc công khai danh sách yêu thích cho người dùng khác.
- Nhóm/đặt tên thư mục cho các tin đã thích (collections, saved searches).
- Thông báo cho chủ tin khi tin bị bỏ thích.
- Yêu thích cho người dùng ẩn danh (chưa đăng nhập).
User Stories
- Là người tìm bất động sản, tôi muốn lưu một listing đang quan tâm, để xem lại sau mà không phải tìm lại từ đầu.
- Là người tìm bất động sản, tôi muốn xem danh sách tất cả listings đã thích, để so sánh và theo dõi các tin quan tâm ở một nơi.
- Là người tìm bất động sản, tôi muốn biết ngay tin nào mình đã thích khi duyệt danh sách, để không thích trùng và dễ nhận diện.
- Là người tìm bất động sản, tôi muốn bỏ lưu một tin không còn quan tâm, để danh sách yêu thích luôn gọn gàng.
- Là chủ tin, tôi muốn được thông báo khi tin của mình được yêu thích, để biết mức độ quan tâm của thị trường.
- Là chủ tin, tôi muốn các lượt thích gần nhau được gộp thành một thông báo, để không bị làm phiền bởi quá nhiều thông báo lẻ.
Luồng chức năng
sequenceDiagram
actor User
participant FE as Frontend
participant BE as Backend
participant Fav as Favorites
participant Listing as Listings
participant Notif as Notifications
User->>FE: Nhấn "Thích" trên một listing
FE->>BE: Yêu cầu lưu listing
BE->>Fav: Kiểm tra đã thích chưa
alt Chưa thích
BE->>Fav: Tạo bản ghi favorite (user + listing)
BE-->>FE: Đã lưu (isFavorited = true)
Note over BE,Listing: Cập nhật số lượt thích chạy nền
BE->>Listing: Tăng favorite_count
alt Người thích khác chủ tin
BE->>Notif: Gửi thông báo (gộp) cho chủ tin
end
else Đã thích (idempotent)
BE-->>FE: Giữ nguyên trạng thái đã thích
end
User->>FE: Nhấn "Bỏ thích"
FE->>BE: Yêu cầu bỏ lưu listing
BE->>Fav: Xóa bản ghi favorite nếu tồn tại
BE-->>FE: Đã bỏ lưu (isFavorited = false)
Note over BE,Listing: Giảm favorite_count chạy nền
User->>FE: Mở "Danh sách đã thích"
FE->>BE: Lấy listings đã thích
BE->>Fav: Truy vấn favorites của user
BE-->>FE: Danh sách listings (mới thích trước)Acceptance Criteria
- AC-1: Người dùng đã đăng nhập có thể lưu một listing đang hoạt động (ACTIVE); sau đó trạng thái của listing với người dùng này là “đã thích”.
- AC-2: Lưu lại một listing đã thích trước đó không tạo bản ghi trùng và không làm tăng số lượt thích thêm lần nữa (idempotent).
- AC-3: Người dùng có thể bỏ lưu một listing đã thích; sau đó trạng thái trở về “chưa thích”.
- AC-4: Bỏ lưu một listing chưa từng thích là thao tác hợp lệ và không làm thay đổi số lượt thích.
- AC-5: Người dùng xem được danh sách listings đã thích, sắp xếp theo thời điểm thích gần nhất trước.
- AC-6: Khi duyệt danh sách/tìm kiếm listing trong trạng thái đăng nhập, mỗi listing thể hiện đúng trạng thái “đã thích / chưa thích” của người dùng hiện tại.
- AC-7: Người dùng ẩn danh (chưa đăng nhập) luôn thấy trạng thái “chưa thích” và không thể thực hiện thao tác lưu/bỏ lưu.
- AC-8: Mỗi listing hiển thị số lượt thích phản ánh đúng tổng số người đã thích (cho phép cập nhật trễ vài giây do xử lý nền).
- AC-9: Khi một người dùng (không phải chủ tin) thích tin, chủ tin nhận được thông báo; nhiều lượt thích gần nhau được gộp thành một thông báo.
- AC-10: Khi chủ tin tự thích tin của chính mình, hệ thống không gửi thông báo.
- AC-11: Khi thao tác lưu/bỏ lưu vượt ngưỡng tần suất cho phép, hệ thống từ chối tạm thời và yêu cầu thử lại sau.
Quy tắc nghiệp vụ
- Một người dùng chỉ có thể thích một listing tối đa một lần; cặp (người dùng, listing) là duy nhất.
- Chỉ người dùng đã đăng nhập mới được thực hiện lưu/bỏ lưu; ẩn danh chỉ được xem.
- Thao tác lưu và bỏ lưu đều idempotent: trạng thái cuối cùng phụ thuộc hành động, không phụ thuộc số lần lặp.
- Số lượt thích (
favorite_count) được cập nhật theo cơ chế nền (eventually consistent); giá trị hiển thị có thể trễ một khoảng ngắn so với thời điểm thao tác. - Danh sách bản ghi favorite là nguồn dữ liệu chuẩn để xác định một listing đã được thích hay chưa;
favorite_countlà giá trị tổng hợp phục vụ hiển thị. - Thông báo cho chủ tin chỉ phát sinh khi người thích khác với chủ tin; chủ tin tự thích không tạo thông báo.
- Các lượt thích gần nhau cho cùng một tin được gộp thành một thông báo để tránh làm phiền chủ tin.
- Tần suất thao tác lưu/bỏ lưu của mỗi người dùng bị giới hạn để chống spam và lạm dụng.
- Việc thích/bỏ thích không làm thay đổi nội dung hay trạng thái hiển thị công khai của listing (ngoài số lượt thích).
Dữ liệu & Trạng thái
Entity nghiệp vụ:
Favorite: liên kết giữa một người dùng và một listing mà họ đã thích. Thuộc tính nghiệp vụ gồm người dùng, listing và thời điểm thích. Mỗi cặp (người dùng, listing) là duy nhất.Listing: tin đăng bất động sản; bổ sung thuộc tính tổng hợpfavorite_countthể hiện tổng số lượt thích.User: người dùng đã đăng nhập có thể sở hữu nhiều favorites; chủ tin là người nhận thông báo khi tin được thích.
Quan hệ dữ liệu:
- Một
usercó nhiềufavorites; mộtlistingcó nhiềufavorites. - Một
favoritegắn đúng mộtuservới đúng mộtlisting.
Trạng thái user-facing:
favorited- listing đang nằm trong danh sách yêu thích của người dùng hiện tại.not_favorited- listing chưa được người dùng hiện tại thích (hoặc người dùng ẩn danh).
Liên quan
- Liên quan: listing-crawl-external-sources
- Liên quan: contacts