QuoteServices External Review Invite

API:

POST /quote_services/external_review/invite/{quote_service_id}.json

功能說明

provider 對外寄送服務評價邀請 email。request 支援單一 email 與多筆 emails;每個收件人各寫一筆 External_Review event queue,template key 是 390 External Review Invite

這支是 legacy external_reviewinvite 分支;目前正式流量與 web-app caller 未看到使用,但 legacy 有完整分支,因此新版補成 explicit route,避免舊 client 或未覆蓋入口打到空 route。

目前狀態

已補 action、routing 與 PHPUnit。

legacy QuoteServicesController::external_review($action, $id) 有三條分支:

  • submit:已搬到 POST /quote_services/external_review/submit.json
  • invite:已搬到 POST /quote_services/external_review/invite/{quote_service_id}.json
  • 預設分支:已搬到 GET /quote_services/external_review/link/{quote_service_id}.json

Legacy Rule

legacy controller:

/Users/mattsu/Documents/Site/get-lancer-php56/app/Plugin/Quotes/Controller/QuoteServicesController.php

已確認規則:

  1. 預設 response 是 {"error":1,"message":"Invalid session"}
  2. session 有效後,預設改為 {"error":2,"message":"Invalid data"}
  3. input 支援:
    • email
    • emails
  4. 不做 service owner guard;只要 session 有效,就使用 path 的 quote_service_id 取得 external review URL。新版照 legacy 對齊。
  5. 會呼叫 QuoteService::getExternalReviewUrl() 取得外部評價 short URL。
  6. legacy 會先取得 external review URL,再判斷是否有收件人;因此沒有收件人時仍可能建立 / 寫回 quote_services.external_review_url。新版照 legacy 順序。
  7. email replacement 需要:
    • ##PROVIDER_NAME##
    • ##EXTERNAL_REVIEW_URL##
    • ##PROVIDER_PHOTO##
    • ##STAR_ICON##
    • QuoteCategoryGroup::addRecommendFeature() 補推薦功能文案
  8. 每個 email 都會建立一筆 EventQueue,channel 為 External_Review,template key 是 390 External Review Invite
  9. 有 email 收件人時回 {"error":0,"message":"Success"}

新舊程式對照

Legacy PHP 5.6

legacy 行號職責
3571-3578external_review('invite', $id) dispatch 到 _invite_external_review($id)
3673-3683_invite_external_review() 入口;預設 Invalid session,session 有效後預設 Invalid data。
3684-3688收集單一 email 與多筆 emails
3690-3697載入 email template、取得 external review URL、provider name、service photo helper。
3698-3711組 email replacement,包含 mail.icon.star_full 與推薦功能文案。
3713-3729建立 EmailParameterDO / EventParameterDO,寫入 EventQueue::insertEvent('External_Review', ...)
3732-3737有收件人時回 success,最後 render JSON。
QuoteUtil.php:30-60provider name 取 last_name first_name,空值時 fallback username,再 fallback User
QuoteCategoryGroup.php:141-155addRecommendFeature()##FEATURE_PAGE_PHOTO_{1..3}####FEATURE_PAGE_NAME_{1..3}####FEATURE_PAGE_URL_{1..3}##

New PHP 8.2

new 檔案行號對應 legacy職責
Lib/Common/RouterRule/Mapping.php:57-603571-3578route /quote_services/external_review/invite/{quote_service_id}.jsonQuoteServices::external_review_invite()
Endpoint/V1/QuoteServices.php:177-2413673-3737session guard、收件人 input、URL / replacement、event queue、response。
Endpoint/V1/QuoteServices.php:330-362QuoteUtil.php:30-60provider name helper;保留 legacy name fallback。
Lib/Model/QuoteService.php:1697-17353690-3691取得 / 建立 external review short URL。
Lib/Model/QuoteService.php:1681-16953706取得 service photo,沒有 service photo 時 fallback user avatar,再 fallback default profile image。
Lib/Model/QuoteCategoryGroup.php:90-1043709-3711, QuoteCategoryGroup.php:141-155補推薦功能 replacement。
Lib/DataObject/Task/EmailTaskDO.php:4-263721-3725email task payload,包含 templateType=emailtemplateKeytoreplaceContentlangId
Lib/DataObject/Task/EventTaskDO.php:4-143727-3728event payload;新版多帶 user_id / quote_service_id 方便追蹤。
Lib/Model/EventQueue.php:19-313729External_Review event queue。
tests/QuoteServicesExternalReviewInviteTest.php:69-1223684-3733單一 email + 多筆 emails 成功寄送,每個收件人各一筆 event。
tests/QuoteServicesExternalReviewInviteTest.php:124-1343682-3688, 3732-3737有 session 但無收件人,回 Invalid data,不寫 event。
tests/QuoteServicesExternalReviewInviteTest.php:136-1473675-3680無 session 回 Invalid session,不寫 event。

逐段對照

new 行號對應 legacy職責
Mapping.php:57-603571-3578將 legacy invite path 拆成新版 explicit route。
QuoteServices.php:179-1863675-3680預設 Invalid session;REST API key + session token 無效時直接回 error=1
QuoteServices.php:188-1933681-3683session 有效後設定 user_idquote_service_id,預設 response 改為 Invalid data。
QuoteServices.php:195-2043684-3688保留 emailemails 兩種 input,合併為收件人清單。
QuoteServices.php:206-2173690-3711先取得 external review URL,再組 template replacement;包含 star icon、service photo、推薦功能。
QuoteServices.php:219-2343713-3729每個收件人建立 EmailTaskDO,包成 EventTaskDO,寫 External_Review event。
QuoteServices.php:236-2403732-3737有收件人時回 success;無收件人時維持 Invalid data。
QuoteServices.php:330-362QuoteUtil.php:30-60provider name fallback 與 legacy 一致。

Config 切換檢查

這支 template 直接需要:

\ProConfig::get('mail.icon.star_full')

已確認目前設定:

  • Lib/Common/Configuration.php:288
  • docker/staging/Configuration.php:279
  • value:https://s3-ap-northeast-1.amazonaws.com/pro360/images/icon/star_full.png

切 staging / production 時要確認實際部署 config 也有同 key;不可只看本地 legacy checkout 判斷設定不存在。

流量與前端呼叫

2026-06-04 正式機 quote_services/external_review 統計只看到 linksubmit,未列出 invite path。web-app 目前也只找到 getExternalReviewLink()postExternalReview() caller。

仍補 invite 的原因:legacy controller 有完整 invite 分支,且 external review 已拆成 explicit routes;補齊可避免舊 client 或未覆蓋入口打到空 route。

測試

2026-06-04:

php -l Endpoint/V1/QuoteServices.php
php -l Lib/Common/RouterRule/Mapping.php
php -l tests/QuoteServicesExternalReviewInviteTest.php
docker exec -w /project-data cd63f9147e8d vendor/bin/phpunit tests/QuoteServicesExternalReviewInviteTest.php

結果:

OK (3 tests, 64 assertions)

測試刻意使用既有 external_review_url fixture,不觸發外部短網址服務。