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
propertyIdcủ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à
DRAFThoặcACTIVE; nếu bỏ trống thì mặc địnhDRAFT. - 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_namevàcontact_phonekhi 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ưucontact_name/contact_phonetrự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
- Là 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ệ.
- Là 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.
- Là user, tôi muốn publish tin ngay khi đủ thông tin, để tin có thể xuất hiện trong danh sách public.
- Là broker, tôi muốn nhập
contact_namevàcontact_phonekhi 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. - Là 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ạoAcceptance Criteria
- AC-1: User có quyền
listing:createcó thể tạo listing mới. - AC-2:
propertyId,title,description,pricelà dữ liệu bắt buộc. - AC-3: Hệ thống chỉ cho phép tạo với status
DRAFThoặcACTIVE; nếu không truyền status thì dùngDRAFT. - 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_namevàcontact_phone;contact_phonelà 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_phonephả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_idtrỏ tới contact tương ứng khi cócontact_phonehợ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.
pricephải là số dương.listingTypesnếu có chỉ nhậnSALEhoặcRENT.imageUrlsnế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
DRAFTkhông xuất hiện trong public search. - Không lưu
contact_name,contact_phonetrực tiếp vào bảnglistings. - Bảng
contactslưu thông tin liên hệ riêng; bảnglistingschỉ lưucontact_iddạ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_idchỉ được set khicontact_phonehợp lệ được cung cấp. - Tra cứu contact theo
contact_phonesau 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 quapropertyId.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_idlà FK nullable trỏ tớicontacts.id.listingskhông lưucontact_name,contact_phonetrực tiếp.- USER tự đăng:
contact_id = null. - BROKER đăng:
contact_idcó 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
- Phụ thuộc: contacts-create
- Ảnh hưởng: listing-list, listing-update, listing-crawl-external-sources