quote_bid_contact

文件狀態:草稿 / 部分已對 new API / 待補付款與 transaction 實測來源
最後驗證:2026-05-07
來源:Common Process Documents 整理、quote_bids migration docs;待補 legacy / new code 逐段來源與 PHPUnit 對照

目的

quote_bid_contact 是 consumer 從 quote card 正式聯絡 provider 的業務流程。

主要 API:

POST /quote_bids/want_to_contact_provider/{quote_bid_id}.json

這份文件是完整業務 trace 入口,回答「consumer 正式聯絡 provider 後,哪些資料表與 downstream side effect 會發生」。單張 table 的欄位細節請看 quote_bids/want_to_contact_provider;扣款分支請看 quote_bid_contact_charge

不回答什麼

  • 不收錄 migration 狀態、PHPUnit 覆蓋狀態、正式機 access log 統計。
  • 不完整重寫 transactions 金流分支。
  • 不描述 search_add 如何建立 quote card;search_add 見 search_add

主流程簡圖

consumer 在 quote card 按聯絡 provider
-> 驗 API key 與 user session
-> 確認 session user 是 quote_requests.user_id
-> 讀取 quote_bids / quote_requests / provider
-> 若有 message,先寫 message / activity
-> 若有 message,做 message classification
-> message rejected / insignificant 時回 error 17,不成立正式聯絡
-> message 通過或無 message,進入 processWantToContactProvider
-> 更新 quote_bids contact 狀態
-> provider contact charge / transaction
-> 建 AutoQuoteContact activity
-> 送 task_event_queue / event_queue
-> 補 requestor note conversation
-> 回 success

Actor 與身份

角色判斷方式
consumer / requestorsession user 必須是 quote_requests.user_id
providerquote_bids.provider_user_id
contact targetquote_bids.id 指到的 provider bid
payerprovider,contact charge 不是扣 consumer

不要把「consumer 發起聯絡」誤解為 consumer 付款。這條流程的扣款主體是 provider,因為正式接觸新客源會進入 quote bid contact charge。

主要資料表順序

階段資料表說明
bid / request guardquote_bids, quote_requests確認 bid、request owner、provider、request 狀態
messagemessages, message_contents, quote_activitiesconsumer message 可能先寫入,即使最後 error 17
classificationquote_bid_classify_contacts記錄 message 分類結果
contact statequote_bidsis_want_to_contact_provider, contact_provider_on, reason
chargetransactions, users, stripe_customersprovider wallet / card / transaction
activityquote_activitiesAutoQuoteContact 等正式聯絡活動
asynctask_event_queue, event_queuecounter、SMS、provider notification

Message classification

如果 request body 有 message,流程會先寫入聊天室,再做分類。

classes意義是否成立正式聯絡
not-reject訊息有效
insignificant訊息過於空泛
rejected訊息不符合規則

insignificant / rejected 時,legacy 對外 response:

{"error":17,"status":""}

此時可能已存在:

messages
message_contents
message 類型 quote_activities
quote_bid_classify_contacts

但正式聯絡不成立,通常不應看到:

quote_bids.is_want_to_contact_provider = 1
quote_bids.contact_provider_on 有值
quote_activities.AutoQuoteContact
正式 contact charge transaction

成功狀態

正式聯絡成功後,重點欄位:

quote_bids.is_want_to_contact_provider = 1
quote_bids.contact_provider_on = NOW()
quote_bids.is_interested = 1
quote_bids.reason = <reason>

若流程有扣款或 subscription:

quote_bids.total_site_fee
quote_bids.quote_user_subscription_log_id
transactions.class = QuoteBid
transactions.foreign_id = quote_bid_id

扣款成功與否不要只看 quote_user_subscription_log_id,要搭配 transaction real_pay_date 與 application log 判讀。完整規則見 quote_bid_contact_charge

Activity / Queue

成功正式聯絡 provider 時,常見 side effect:

quote_activities.AutoQuoteContact
task_event_queue.bid_contact_count
task_event_queue.sent_contact_provider_sms
event_queue.Contact_Pro

AutoQuoteContact activity 在非 narrow match contact 時:

param1 = NULL
param2 = reason

narrow match accept 轉進 contact 主線時,activity 參數語意不同,請看 narrow_matchprovider_accept_narrow_match

Queue 可能已被 worker 搬到 log table,驗 downstream 時要接受:

event_queue OR event_queue_log_1..event_queue_log_4
task_event_queue OR task_event_queue_log

第一輪排查順序

  1. quote_bids contact state。
  2. 若 request 有帶 message,查 quote_bid_classify_contacts
  3. quote_activities 是否有 AutoQuoteContact
  4. transactions 與付款 log。
  5. 查 queue 或 log。

查 bid 與 request

SELECT
  qb.id,
  qb.quote_request_id,
  qr.user_id AS requestor_user_id,
  qb.provider_user_id,
  qb.quote_service_id,
  qb.is_auto_quote,
  qb.is_contact_charge,
  qb.is_want_to_contact_provider,
  qb.contact_provider_on,
  qb.reason,
  qb.total_site_fee,
  qb.quote_user_subscription_log_id,
  qr.auto_quote_contact_count
FROM quote_bids qb
INNER JOIN quote_requests qr ON qr.id = qb.quote_request_id
WHERE qb.id = <quote_bid_id>;

查 message classification

SELECT
  id,
  quote_bid_id,
  message,
  model_version,
  classes,
  params,
  created
FROM quote_bid_classify_contacts
WHERE quote_bid_id = <quote_bid_id>
ORDER BY id DESC
LIMIT 10;

查 transaction

SELECT
  id,
  created,
  user_id,
  foreign_id,
  class,
  transaction_type_id,
  amount,
  real_pay_amount,
  real_pay_date,
  stripe_charge_id,
  wallet_balance
FROM transactions
WHERE class = 'QuoteBid'
  AND foreign_id = <quote_bid_id>
ORDER BY id DESC;

判讀原則

  • 有 message 不代表正式聯絡成功。
  • error=17 代表 message 分類擋下,通常不進 contact charge。
  • 正式聯絡成功先看 is_want_to_contact_providercontact_provider_on
  • 付款異常先看 Log 與告警流程quote_bid_contact_charge
  • downstream queue 驗證要接受 queue 或 log 任一存在。