Bỏ qua nội dung

Listings - tạo tin đăng

Feature URL
Module
listing
Status
shipped
Priority
P0
Platforms
fe · be
AC progress
0 / 12
Last reviewed
2026-05-30

Mục tiêu

Cho phép user đã đăng nhập tạo tin đăng bất động sản mới, gắn với một property đang active. Tin mới có thể lưu nháp trước hoặc publish ngay để xuất hiện trong luồng listing public. Hệ thống phân biệt rõ hai loại người tạo — USER tự đăng và BROKER đăng thay — để xử lý thông tin liên hệ phù hợp: USER dùng thông tin tài khoản, BROKER tạo hoặc tái sử dụng contact riêng biệt.

Phạm vi

Trong phạm vi (In scope):

  • Tạo listing qua POST /listings.
  • Gắn listing với propertyId của property đang active.
  • Nhập các trường listing chính: title, description, price, listingTypes, imageUrls.
  • Cho phép trạng thái tạo ban đầu là DRAFT hoặc ACTIVE; nếu bỏ trống thì mặc định DRAFT.
  • Khi tạo ACTIVE, hệ thống tính trust score và đánh giá điều kiện routing liên quan.
  • Phân biệt role người tạo: USER tự đăng và BROKER đăng thay.
  • BROKER có thể truyền contact_namecontact_phone khi tạo listing.
  • Hệ thống tra cứu contact theo contact_phone (sau khi chuẩn hoá); tái sử dụng nếu đã tồn tại, tạo mới nếu chưa có.
  • Listing gắn contact_id (nullable FK) thay vì lưu contact_name/contact_phone trực tiếp.
  • USER tự đăng: không nhập contact, contact_id = null, thông tin liên hệ lấy từ user account.

Ngoài phạm vi (Out of scope):

  • Tạo hoặc cập nhật property.
  • Cập nhật listing sau khi tạo.
  • Xoá hoặc ban listing.
  • Quy trình moderation/admin duyệt tin.
  • Hiển thị thông tin contact trên listing (thuộc luồng listing-list/detail).
  • Merge contact nâng cao ngoài rule trùng số điện thoại.

User Stories

  • user đã đăng nhập, tôi muốn tạo tin đăng mới, để rao bán hoặc cho thuê bất động sản của mình mà không cần nhập thêm thông tin liên hệ.
  • user, tôi muốn lưu tin ở trạng thái nháp, để hoàn thiện nội dung trước khi publish.
  • user, tôi muốn publish tin ngay khi đủ thông tin, để tin có thể xuất hiện trong danh sách public.
  • broker, tôi muốn nhập contact_namecontact_phone khi tạo listing, để gắn thông tin liên hệ riêng biệt không phải từ tài khoản của tôi.
  • broker, tôi muốn hệ thống tự nhận ra contact cũ theo số điện thoại, để không tạo trùng contact trong CRM.

Luồng chức năng

sequenceDiagram
    actor Creator
    participant App
    participant BE
    participant PropSvc as Properties
    participant Contacts
    participant Listings
    participant Trust as Trust Score

    Creator->>App: Nhập thông tin tin đăng
    App->>BE: POST /listings
    BE->>PropSvc: Kiểm tra property active
    PropSvc-->>BE: Property hợp lệ
    alt Creator là BROKER và có contact_phone
        BE->>Contacts: Tra contact theo phone đã chuẩn hoá
        alt Contact chưa tồn tại
            BE->>Contacts: Tạo contact mới
        end
        Contacts-->>BE: contact_id
    end
    BE->>Listings: Tạo listing với contact_id hoặc null
    alt Status ACTIVE
        BE->>Trust: Tính trust score
    end
    BE-->>App: Trả listing đã tạo

Acceptance Criteria

  • AC-1: User có quyền listing:create có thể tạo listing mới.
  • AC-2: propertyId, title, description, price là dữ liệu bắt buộc.
  • AC-3: Hệ thống chỉ cho phép tạo với status DRAFT hoặc ACTIVE; nếu không truyền status thì dùng DRAFT.
  • AC-4: Listing chỉ được tạo khi property tham chiếu tồn tại và đang active.
  • AC-5: Khi tạo listing ACTIVE, hệ thống phải tính trust score sau khi lưu.
  • AC-6: Listing tạo thành công thuộc sở hữu của user đang đăng nhập.
  • AC-7: USER tự đăng bài không cần truyền contact_name/contact_phone; nếu client truyền lên thì bỏ qua; contact_id = null.
  • AC-8: BROKER đăng bài có thể truyền contact_namecontact_phone; contact_phone là bắt buộc nếu muốn gắn contact vào listing.
  • AC-9: Khi BROKER đăng và truyền contact_phone, hệ thống tra cứu contact theo phone sau khi chuẩn hoá; tìm thấy thì tái sử dụng, chưa có thì tạo mới.
  • AC-10: contact_phone phải được chuẩn hoá trước khi tra cứu và lưu.
  • AC-11: Listing do USER đăng có contact_id = null; thông tin liên hệ hiển thị lấy từ profile user.
  • AC-12: Listing do BROKER đăng có contact_id trỏ tới contact tương ứng khi có contact_phone hợp lệ.

Quy tắc nghiệp vụ

  • User không thể tạo listing cho property inactive hoặc không tồn tại.
  • price phải là số dương.
  • listingTypes nếu có chỉ nhận SALE hoặc RENT.
  • imageUrls nếu có phải thuộc nguồn lưu trữ hợp lệ và không vượt quá giới hạn hệ thống.
  • Listing DRAFT không xuất hiện trong public search.
  • Không lưu contact_name, contact_phone trực tiếp vào bảng listings.
  • Bảng contacts lưu thông tin liên hệ riêng; bảng listings chỉ lưu contact_id dạng FK nullable.
  • USER tự đăng: contact_id = null, thông tin liên hệ lấy từ user profile khi cần hiển thị.
  • BROKER đăng: contact_id chỉ được set khi contact_phone hợp lệ được cung cấp.
  • Tra cứu contact theo contact_phone sau khi chuẩn hoá để tránh tạo trùng.
  • Một contact có thể được gắn với nhiều listings (quan hệ contacts 1-n listings).

Dữ liệu & Trạng thái

Entity nghiệp vụ:

  • Listing: tin đăng gồm owner, property, tiêu đề, mô tả, giá, trạng thái, loại giao dịch, hình ảnh và contact_id (nullable FK).
  • Property: bất động sản được listing tham chiếu qua propertyId.
  • Contact: thông tin liên hệ tập trung, gồm tên liên hệ, phone_registry_id, nguồn tạo và owner broker. Quan hệ contacts 1-n listings.

Quan hệ:

  • listings.contact_id là FK nullable trỏ tới contacts.id.
  • listings không lưu contact_name, contact_phone trực tiếp.
  • USER tự đăng: contact_id = null.
  • BROKER đăng: contact_id có giá trị khi có contact tương ứng.

Trạng thái user-facing:

  • DRAFT - tin nháp, chỉ owner xem được.
  • ACTIVE - tin đã publish và có thể hiển thị public theo rule visibility.

Liên quan