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_review 的 invite 分支;目前正式流量與 web-app caller 未看到使用,但 legacy 有完整分支,因此新版補成 explicit route,避免舊 client 或未覆蓋入口打到空 route。
目前狀態
已補 action、routing 與 PHPUnit。
legacy QuoteServicesController::external_review($action, $id) 有三條分支:
submit:已搬到POST /quote_services/external_review/submit.jsoninvite:已搬到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已確認規則:
- 預設 response 是
{"error":1,"message":"Invalid session"}。 - session 有效後,預設改為
{"error":2,"message":"Invalid data"}。 - input 支援:
emailemails
- 不做 service owner guard;只要 session 有效,就使用 path 的
quote_service_id取得 external review URL。新版照 legacy 對齊。 - 會呼叫
QuoteService::getExternalReviewUrl()取得外部評價 short URL。 - legacy 會先取得 external review URL,再判斷是否有收件人;因此沒有收件人時仍可能建立 / 寫回
quote_services.external_review_url。新版照 legacy 順序。 - email replacement 需要:
##PROVIDER_NAME####EXTERNAL_REVIEW_URL####PROVIDER_PHOTO####STAR_ICON##QuoteCategoryGroup::addRecommendFeature()補推薦功能文案
- 每個 email 都會建立一筆
EventQueue,channel 為External_Review,template key 是390 External Review Invite。 - 有 email 收件人時回
{"error":0,"message":"Success"}。
新舊程式對照
Legacy PHP 5.6
| legacy 行號 | 職責 |
|---|---|
3571-3578 | external_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-60 | provider name 取 last_name first_name,空值時 fallback username,再 fallback User。 |
QuoteCategoryGroup.php:141-155 | addRecommendFeature() 補 ##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-60 | 3571-3578 | route /quote_services/external_review/invite/{quote_service_id}.json 到 QuoteServices::external_review_invite()。 |
Endpoint/V1/QuoteServices.php:177-241 | 3673-3737 | session guard、收件人 input、URL / replacement、event queue、response。 |
Endpoint/V1/QuoteServices.php:330-362 | QuoteUtil.php:30-60 | provider name helper;保留 legacy name fallback。 |
Lib/Model/QuoteService.php:1697-1735 | 3690-3691 | 取得 / 建立 external review short URL。 |
Lib/Model/QuoteService.php:1681-1695 | 3706 | 取得 service photo,沒有 service photo 時 fallback user avatar,再 fallback default profile image。 |
Lib/Model/QuoteCategoryGroup.php:90-104 | 3709-3711, QuoteCategoryGroup.php:141-155 | 補推薦功能 replacement。 |
Lib/DataObject/Task/EmailTaskDO.php:4-26 | 3721-3725 | email task payload,包含 templateType=email、templateKey、to、replaceContent、langId。 |
Lib/DataObject/Task/EventTaskDO.php:4-14 | 3727-3728 | event payload;新版多帶 user_id / quote_service_id 方便追蹤。 |
Lib/Model/EventQueue.php:19-31 | 3729 | 寫 External_Review event queue。 |
tests/QuoteServicesExternalReviewInviteTest.php:69-122 | 3684-3733 | 單一 email + 多筆 emails 成功寄送,每個收件人各一筆 event。 |
tests/QuoteServicesExternalReviewInviteTest.php:124-134 | 3682-3688, 3732-3737 | 有 session 但無收件人,回 Invalid data,不寫 event。 |
tests/QuoteServicesExternalReviewInviteTest.php:136-147 | 3675-3680 | 無 session 回 Invalid session,不寫 event。 |
逐段對照
| new 行號 | 對應 legacy | 職責 |
|---|---|---|
Mapping.php:57-60 | 3571-3578 | 將 legacy invite path 拆成新版 explicit route。 |
QuoteServices.php:179-186 | 3675-3680 | 預設 Invalid session;REST API key + session token 無效時直接回 error=1。 |
QuoteServices.php:188-193 | 3681-3683 | session 有效後設定 user_id、quote_service_id,預設 response 改為 Invalid data。 |
QuoteServices.php:195-204 | 3684-3688 | 保留 email 與 emails 兩種 input,合併為收件人清單。 |
QuoteServices.php:206-217 | 3690-3711 | 先取得 external review URL,再組 template replacement;包含 star icon、service photo、推薦功能。 |
QuoteServices.php:219-234 | 3713-3729 | 每個收件人建立 EmailTaskDO,包成 EventTaskDO,寫 External_Review event。 |
QuoteServices.php:236-240 | 3732-3737 | 有收件人時回 success;無收件人時維持 Invalid data。 |
QuoteServices.php:330-362 | QuoteUtil.php:30-60 | provider name fallback 與 legacy 一致。 |
Config 切換檢查
這支 template 直接需要:
\ProConfig::get('mail.icon.star_full')已確認目前設定:
Lib/Common/Configuration.php:288docker/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 統計只看到 link 與 submit,未列出 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,不觸發外部短網址服務。