SearchAdd Bid Finalize
快速結論
這段負責把已建立的 bid 補成前端可用的報價內容,例如 price note、pricing unit、detect content、activity、cache。
current 入口:
SearchAddHandler::handle()
-> QuoteBidFinalizer::finalize()新舊程式對應
Current Legacy
主要入口:
/Users/mattsu/Documents/Site/get-lancer-docker-2/get-lancer/app/Plugin/Quotes/Model/QuoteService.php::handleAutoQuote()| legacy 區段 | 職責 |
|---|---|
handleAutoQuote() | auto quote bid 後處理。 |
| pricing / price note | 補 quote amount、pricing unit、price note。 |
| detect / activity / cache | 補內容偵測、activity、cache queue。 |
Current PHP 8.2
| current 位置 | 職責 |
|---|---|
Lib/SearchAdd/SearchAddHandler.php:317-320 | 呼叫 QuoteBidFinalizer::finalize()。 |
Lib/SearchAdd/QuoteBidFinalizer.php | bid finalize orchestration。 |
Lib/SearchAdd/BidPricingResolver.php | pricing unit / quote amount / price note。 |
Lib/SearchAdd/BidDetectContentWriter.php | bid detect content。 |
Lib/SearchAdd/BidActivityWriter.php | bid activity。 |
Lib/SearchAdd/BidCacheQueueWriter.php | cache queue。 |
行號對照
| new 行號 | 對應 legacy | 職責 |
|---|---|---|
SearchAddHandler.php:317-320 | QuoteService.php:3155-3158 | matcher 建 bid 後呼叫 bid finalize。 |
QuoteBidFinalizer.php:43-53 | QuoteService.php:1567-1595 | 讀 request 與要 finalize 的 bids;沒有 bid 時不處理。 |
QuoteBidFinalizer.php:56-63 | QuoteService.php:1597-1648, 1663-1683 | 逐筆 bid 讀 service category,準備 pricing context。 |
BidPricingResolver.php:27-76 | QuoteService.php:1624-1655, 1679-1857 | 決定 price_display、price_note、quote_amount、pricing_unit、pricing 成功旗標。 |
BidPricingResolver.php:78-140 | QuoteService.php:1624-1628, 1737-1752, 1853-1860 | requestor lang、consumer name、default price display/note、consumer name replacement。 |
BidPricingResolver.php:175-204 | QuoteService.php:1638-1648, 1737-1747 | 從 pricing form submission 反推 pricing unit。 |
BidPricingResolver.php:213-260 | QuoteService.php:1679-1724 | precise pricing:quote pricing route、form submission order、getPrice。 |
QuoteBidFinalizer.php:66-89 | QuoteService.php:1892-1929 | 組 quote bid update 欄位;narrow 不提升狀態、不帶 price_note。 |
QuoteBidFinalizer.php:98-100 | QuoteService.php:1931 | 更新 quote_bids。 |
QuoteBidFinalizer.php:102-104 | QuoteService.php:1932-1936 | 非 narrow 寫 SubmitQuote activity。 |
QuoteBidFinalizer.php:106-112 | QuoteService.php:1864-1890 | price note detect content。 |
QuoteBidFinalizer.php:115-117 | QuoteService.php:1942-1945 | 寫 cache queue 更新 counter。 |
QuoteBidFinalizer.php:119 | QuoteRequestsController.php:3345-3383, 3389-3398 | reload bids,補 response 需要的 service / attachment data。 |
第 6 組:excluded critical pricing option(已完成,commit 5a1cd38b)
差異與根因
Current Legacy cfa660b0c:
QuoteFormField.php:373-432:input.type != large_image或exclude_pricing = 1的 option,在is_show_exclude = false時直接continue;critical 沒有例外。QuoteService.php:1644-1653,1698-1705:search_add 與 copy 都把上述 pricing form fields 送進 submission order 與 precise pricing。QuoteServiceCategory.php:2126-2187:只有答案完整等於仍存在的 option title 才形成 route;含|不做前段 fallback。- 這是
98c518ca3(BAC-3592 rollback)後的現行規則。
修正前 PHP 8:
QuoteFormField.php:533-581:shared method 對 critical 保留 excluded option,並標記is_exclude=1。BidPricingResolver.php:175-203,213-269:pricing unit 與 precise pricing 都直接使用 shared method 的結果,所以 excluded critical answer 仍可能形成 route。- 本地 DB category
159/field2227可重現:其他(order3)仍留在format_options。
修正後 PHP 8:
Lib/Model/QuoteFormField.php:534-546:新增 defaultfalse的 scoped 參數$exclude_critical_pricing_options;啟用時改用_exclude_criticalRedis hash field。Lib/Model/QuoteFormField.php:583-591:scoped 模式下,excluded critical option 與 Legacy 一樣直接continue。Lib/SearchAdd/BidPricingResolver.php:185-191,240-246:pricing unit 與 precise pricing 兩個入口都明確啟用 scoped 模式。
Shared caller 與 scoped 決定
QuoteFormField::getPricingFormField() 另有 QuoteServiceCategory 與 QuoteServiceCategories endpoint caller,不直接改預設行為。
已新增 optional scoped 參數:
getPricingFormField(..., $exclude_critical_pricing_options = false)- 預設
false:其他 PHP 8 caller 維持現況。 BidPricingResolver的兩個呼叫明確傳true,對齊 current Legacy。- scoped 結果使用獨立 Redis hash field suffix,不能覆蓋 default caller 的既有 cache。
BidPricingResolver同時由 search_add 與 quote request copy 的QuoteBidFinalizer使用;Legacy 兩條流程都進同一個handleNewQuoteRequestAutoQuote()->handleAutoQuote(),因此 scope 一致。
預期流程與結果
excluded critical answer
-> scoped pricing form 不含該 option
-> submission order 不產生 critical order
-> 不可進該 critical precise-pricing route
-> 沿用 Legacy fallback:quote_amount=0、需要更多資訊/現場評估 flag=1本組只改 pricing form read/cache field 與既有 bid finalize 計算;不新增 DB write、log、queue、activity、payment、notification、response 欄位或 config。
測試結果
Core 2 tests / 30 assertions:
- category
280正常 precise pricing 仍得到quote_amount=1350。 - category
159/critical field2227回其他;即使 provider 的quote_pricing.critical.3有價格999,仍不可使用該 price note 或 route,結果為quote_amount=0、flat_rate_at=0、兩個 more-information/on-site flag 為1。
Other 4 tests / 50 assertions:
- default shared caller 仍保留
其他,確保未擴大修改。 - scoped caller 移除
其他,但保留正常 critical options。 - scoped/default cache field 互不污染。
- category
159negotiable route、fixed pricing fallback/detect content、narrow bid regression 不變。
整支 SearchAddStep6IntegrationTest 共 6 tests / 80 assertions;全部已歸到 core 或 other。既有固定 session fixture 改為測試自行建立與清理的暫時帳號,避免 session 過期造成假失敗。
Side Effects
同步可能更新:
quote_bids- bid detect content 相關資料
quote_activitiescache_queues
不可改變的契約
- finalize 只處理已建立 bid。
- narrow bid 不應被 finalize 錯誤提升成 auto quote sent 狀態。
- pricing / price note / pricing unit 要和 legacy 相同。
- finalize 後仍可能再進 special post-flow。
Verification
主要測試:
docker exec -w /project-data cd63f9147e8d \
vendor/bin/phpunit tests/SearchAddStep6IntegrationTest.php --group core
docker exec -w /project-data cd63f9147e8d \
vendor/bin/phpunit tests/SearchAddStep6IntegrationTest.php --group otherPHP 8.2 結果:Core 2 tests / 30 assertions、Other 4 tests / 50 assertions,全數通過。三個修改檔案 php -l 均通過。
待確認 / 風險
- staging/production 的 category/field 資料仍需上線前確認;本組不需要新增 deployment config。