Quote Request Copy Rule Details
這份文件提供 POST /quote_requests/copy/{quote_request_id}.json 各規則的可編輯詳細版。
建議維護方式:
rule_catalog.md放精簡索引- 這份檔案放詳細說明
API session / request ownership 驗證
- 舊入口:
QuoteRequestsController::copy() - 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
QuoteRequests其他 action 多半直接用ApiValidation::assertApiSession()QuoteRequests::copy()為了對齊 legacy response shape,改由CopyRequestHandler自行處理 session / blocked user / invalid session
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testReturnsInvalidRequestWhenQuoteRequestIdIsMissing()tests/QuoteRequestCopyIntegrationTest.php::testReturnsInvalidRequestWhenSourceRequestIsNotOwned()
- 備註:
- 先驗 session
- 再驗
quote_requests.id + user_id - 已觀察到 staging caller 使用:
POST /quote_requests/copy/{id}.json- header 帶
X-PRO360-Rest-Api-Key - header 帶
X-PRO360-User-Session-Token - body 可為空 multipart
- 已觀察成功 response:
{"error":0,"message":"success","quote_request_id":"20213"}
quote_request_idresponse shape 目前觀察為字串- 新專案 integration test 已明確斷言
quote_request_id為string - staging DB baseline:
- source request
20212 - copied request
20213 - 兩筆
quote_requests.user_id都是8617
- source request
hash 驗證複製
- 舊入口:
QuoteRequestsController::copy($id, $hash) - 主要表:
security_hashes,quote_requests - 同步 / 非同步:同步
- 新專案現況:
QuoteRequests::copy()已有 hash 分支CopyRequestHandler會驗SecurityHash::getByHash('QuoteRequest', $hash)- 會再比對
foreign_id === sourceRequestId
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesRequestSuccessfullyViaHash()tests/QuoteRequestCopyIntegrationTest.php::testFallsBackToSessionWhenHashIsInvalid()tests/QuoteRequestCopyIntegrationTest.php::testReturnsInvalidSessionWhenHashIsInvalidAndNoSessionExists()
- 備註:
- 目前已觀察到的公開 caller 是 session flow,不是 hash flow
- 新專案目前支援 body 帶
hash - 已對齊舊專案行為:
- hash 成功就走 hash
- hash 失敗時會 fallback session
- hash 與 session 都失敗才回
error = 2
blocked user 擋單
- 舊入口:
BlockedUser->isBlocked($user_id) - 主要表:
blocked_users - 同步 / 非同步:同步
- 新專案現況:
- 已有
Lib/Model/BlockedUser.php search_add也有使用
- 已有
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyGuardIntegrationTest.php::testRejectsBlockedUser()
- 備註:
- 目前實測 response 形狀:
error = 5message = Blocked User- 不包含
quote_request_id
- 已用 legacy staging API 實測確認:
POST /quote_requests/copy/4906.json- response
{"error":5,"message":"Blocked User"}
- 新專案目前已對齊這個 response shape
- 目前實測 response 形狀:
reserve_type_a 過期不可複製
- 舊入口:來源 request 的
quote_form_submission_fields.type = reserve_type_a - 主要表:
quote_form_submission_fields - 同步 / 非同步:同步
- 新專案現況:
QuoteRequests::view()、QuoteBid::handleBidLimit()已有相近判斷
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyGuardIntegrationTest.php::testRejectsExpiredReserveTypeARequest()
- 備註:
- 需用 copy 專用 guard 封裝
category 必須 active
- 舊入口:檢查
quote_categories.is_active = 2 - 主要表:
quote_categories - 同步 / 非同步:同步
- 新專案現況:
- 已有
QuoteCategorymodel
- 已有
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyGuardIntegrationTest.php::testRejectsInactiveCategory()
- 備註:
- 舊版不是只看 category 存在
防重點擊
- 舊入口:Redis key
copy_request__{id}20 秒內限制 - 主要表:Redis
- 同步 / 非同步:同步
- 新專案現況:
- 已有
RedisUtil
- 已有
- Parity 要求:必做
- 測試:待補獨立 case
- 備註:
- 已沿用舊 key 命名:
copy_request__{sourceRequestId} - 目前整合測試會清這個 key 以避免案例互相干擾,但還沒有獨立驗「第二次連點會被擋」的 case
- 已沿用舊 key 命名:
24 小時同 category 複製次數限制
- 舊入口:同 user / category / 非 archived / 非 closed / 24h count < 3
- 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
- 可直接 query
quote_requests
- 可直接 query
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyGuardIntegrationTest.php::testRejectsWhenSameCategoryRequestCountReachedLimit()
- 備註:
- 需確認是否只算 copy 或所有 request
booking user fee 歸零
- 舊入口:若
booking_shop_users有 user,fee set 全部歸零 - 主要表:
booking_shop_users,quote_requests - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler::resolveFeeSet()會在 booking user 時回傳全 0 feeCopyRequestHandler::resolveMatchType()會設BOOKING_ADMIN_USER
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testBookingUserCopyForcesBookingAdminMatchType()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBookingBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- 真實 baseline
14241 -> 14306已驗manual_fee/auto_fee/direct_fee/contact_charge_fee/site_fee = 0 - baseline 也驗
manual_fee_discount = 1.0000與 tag["回客"]
- 真實 baseline
一般 user fee set 設定
- 舊入口:
quote_categories_quote_subscription_types - 主要表:
quote_categories_quote_subscription_types,quote_requests - 同步 / 非同步:同步
- 新專案現況:
CopyRequestFeeUpdater已接入 copy flowQuoteFormField::getVariableQuoteFee()flat row 問題已修正
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesBaseFeesAndExpiredOnForStableFixture()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- staging DB baseline
20212 -> 20213已證實 copy 不是單純沿用來源 fee,也不是只抄 category 固定 fee。- 以
2026-04-29實查為準:- source
manual_fee=53,auto_fee=97,direct_fee=88,contact_charge_fee=96 - copied
manual_fee=81,auto_fee=111,direct_fee=101,contact_charge_fee=122
- source
- 以
- 已確認 fee 來源:
- category
614基本 fee set 是88 / 97 / 88 / 160 quote_form_field_id = 6760的 variable fee options 中,一般居家清潔直接對應manual_fee=101auto_fee=111direct_fee=101contact_charge_fee=152
- 這筆案例的 region 是
台北市,2026-04-29實查對應 discount 結果為0.8 quote_group_variable_fees/quote_fee_adjust_maps/quote_group_variable_fee_logs都沒有命中
- category
- 已修正
QuoteFormField::getVariableQuoteFee()對 flat row 結構失效的問題 - 目前已補穩定 fixture 的 fee integration test,但 staging baseline 仍需持續對表
- 已補
tests/QuoteRequestCopyBaselineIntegrationTest.php驗20212 -> 20213的 fee baseline
- staging DB baseline
建立新 quote_request 主表
- 舊入口:複製原 request 主欄位,重設部分欄位
- 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
- 已用
QuoteRequestsDO與DBFactory::create()建立 copied request
- 已用
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- copied request 會寫
copied_quote_request_id - 一般 copy 不沿用 source
match_type specific_user_tag會清成null
- copied request 會寫
寫入 copied_quote_request_id
- 舊入口:新 request 指向來源 request id
- 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
- schema 已有欄位
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- 這是 downstream 判讀的重要欄位
更新 send_client / request_lang_id
- 舊入口:依 API key 與 header lang 寫入 request
- 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler::createCopiedRequest()直接寫入
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- baseline
20212 -> 20213驗send_client = web、request_lang_id = 1
- baseline
重建 block_provider_ids
- 舊入口:來源 request 的
block_provider_ids加上既有 quoted provider - 主要表:
quote_requests,quote_bids - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler::buildBlockProviderIds()已實作
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testNonProductionCopyDoesNotAppendQuotedProviderIdsToBlockList()
- 備註:
- legacy controller 會把 consumer 歷史已報價 provider 加入 block list
- 新版只有在
site_environment=production時追加歷史已報價 provider - 非 production 環境目前刻意保留 source
block_provider_ids,讓 integration test 不受 shared DB 歷史 bid 影響 - 若要驗完整 legacy 行為,需要 production-like 環境或可控 fixture
強制重設 request flags
- 舊入口:
has_preserve = 0,is_allow_contact_charge = 0,is_expired = 0等 - 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
- create 時可直接指定
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- 已明確斷言
has_preserve = 0 - 已明確斷言
is_allow_contact_charge = 0 - 已明確斷言
is_expired = 0
- 已明確斷言
寫入 multi-request tag
- 舊入口:
ConstJobCenterLabel::MULTI_REQUEST - 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
- 已改成使用
ConstJobCenterLabel::MULTI_REQUEST
- 已改成使用
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()
- 備註:
- staging DB baseline
20212 -> 20213顯示 copied requesttags = ["回客"] ConstJobCenterLabel::MULTI_REQUEST實際值就是回客- 這項目前不是 code parity 差異,先前是被常數名稱誤導
- staging DB baseline
abnormal / keyword / overseas phone 掃描
- 舊入口:
copy()建單後會接異常掃描,命中時停配對 - 主要表:
abnormal_check_items,quote_request_pending_params,quote_requests,user_internal_logs - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler已接AbnormalScanWriteris_scan_found = true時不再跑 auto quote / HK task
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyAbnormalIntegrationTest.php::testPausesMatchingWhenForcedAbnormalScanFound()tests/QuoteRequestCopyAbnormalIntegrationTest.php::testPausesMatchingForHighRiskForeignPhoneScan()tests/QuoteRequestCopyAbnormalIntegrationTest.php::testReturnsSuccessButPausesMatchingForForcedOldKeywordWarning()
- 備註:
- forced abnormal scan 會寫
abnormal_check_items,並把 requestmatch_type改成ABNORMAL_CHECK - foreign phone 高風險會寫
user_internal_logs.note = 提出需求: 使用海外電話,seon偵測高風險 - forced old keyword warning 在 copy 目前仍回
success,但會停配對;不走search_add的 warning payload 形狀
- forced abnormal scan 會寫
recommend_source 紀錄
- 舊入口:
copy()建單成功後,若 request 有帶recommend_source則補寫 log - 主要表:
quote_request_recommend_logs - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler已支援讀取recommend_source- 目前支援 top-level
recommend_source - 也兼容
QuoteRequest[recommend_source]
- Parity 要求:有帶才必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testWritesRecommendSourceLogWhenProvided()
- 備註:
- legacy 寫入欄位為:
quote_request_idrecommend_source
- 不寫回
quote_requests
- legacy 寫入欄位為:
目前測試覆蓋
tests/QuoteRequestCopyIntegrationTest.php- session copy
- hash copy
- recommend_source log
- cloned submission / fields
copied_quote_request_idlast_copied_onCreateRequest- auto quote dispatcher 入口
- HK
newQuoteRequesttask
tests/QuoteRequestCopyAbnormalIntegrationTest.php- abnormal pause matching
- foreign phone high-risk pause matching
- old keyword forced warning 在 copy 仍回 success 但停配對
tests/QuoteRequestCopyGuardIntegrationTest.php- blocked user
- inactive category
- expired
reserve_type_a - 24h same-category limit
auto quote / matching baseline(staging reference 與新專案現況)
- staging reference
20212 -> 20213quote_request_match_infosinfo_type = rinfo_type = scinfo_type = tp
quote_bidstotal_bids = 100auto_quote_bids = 7narrow_bids = 14
quote_activitiesquote_activity_type_id = 1(Create Request) ->1quote_activity_type_id = 2(Submit Quote) ->8quote_activity_type_id = 4(View Match) ->27quote_activity_type_id = 52(Auto Quote Restore Balance) ->7quote_activity_type_id = 55->1
task_queue_logaction = newQuoteRequestvalue = 20213
- auto quote bid 抽樣形狀(staging
20212 -> 20213的 7 筆一致):quote_status_id = 2provider_status_id = 2is_auto_quote = 1is_narrow_match = 0is_want_to_contact_provider = 0total_site_fee = 111pricing_unit = 小時
- narrow match bid 抽樣形狀(staging
20212 -> 20213前 10 筆中可見):quote_status_id = 1provider_status_id = 1is_auto_quote = 0is_narrow_match = 1is_want_to_contact_provider = 1total_site_fee = 101pricing_unit = 小時
- staging 聚合欄位驗證:
- auto quote bids 的
created都是2026-04-27 04:44:22 - narrow match bids 的
created都是2026-04-27 04:49:05 quote_activity_type_id = 2包含 7 筆param1 = auto_quote,另有 1 筆 contact-charge 相關 payloadquote_activity_type_id = 4包含 25 筆param2 = m300,另有 2 筆空param2quote_activity_type_id = 52的param1固定為111
- auto quote bids 的
- 新專案目前已確認的 matching 對齊點:
quote_request_match_infos的同步主線已穩定寫出r / sc / tp- manual handler 已補回
read_segment >= 9分流,不再把這批 service 直接落成一般 bid - related general pool 已補回「其實屬於原 category 的 service 要移除」
- additional narrow 已補回 legacy temp table score boost
- narrow pool 已補回 self-owned service 過濾,不再只在最後建 bid 時才跳過 request owner 自己的 service
- 新專案目前仍保留的驗證註記:
20212 / 8617這組 reference case 受 daily limit 與 repeated-copy 汙染影響,文件不再把「本地已和20212 -> 20213完全同數字」當成既成事實- 其他同 category
614的乾淨樣本可能出現15 narrow,原因是 source user 不一定同時也是 provider;20212的14 narrow與8617自己的quote_service_id = 9930有關 - 另外已確認 reference provider 資料也有漂移:
- 針對 provider
8085,staging reference20213使用的是quote_service_id = 9115 - 但 live DB 目前
9115.confirmed_prohibited_type = 2 - 現行 matching 共同條件為
confirmed_prohibited_type in (0, 3, 4),所以9115現在已不具候選資格 - 同 provider 目前仍可進候選的是
quote_service_id = 9169 - 因此今天即使重跑同一 source request,也不應再假設 narrow provider 集合必然與
20213完全相同
- 針對 provider
- 因此目前應區分:
20212 -> 20213是 staging reference baseline- 新專案規則是否已補齊,要看 code + test 與 runtime 差異解釋
20212 -> 20213是否能在今天的 live DB 上原樣重現,則另外受 provider 資料漂移影響
- 測試註記:
- 這兩類 bid shape 不再依賴不穩定 fixture
18063 - 已改用
QuoteRequestCopyBaselineIntegrationTest直接驗真實 baseline - 目前已補:
- 一般 baseline
20212 -> 20213 - booking baseline
14241 -> 14306 - abnormal baseline
14691 -> 17216 - keyword baseline
10650 -> 10652
- 一般 baseline
- 目前整包
QuoteRequestCopy*測試為OK (32 tests, 288 assertions),沒有skip
- 這兩類 bid shape 不再依賴不穩定 fixture
建立 quote_form_submissions
- 舊入口:為新 request 建一筆 submission
- 主要表:
quote_form_submissions - 同步 / 非同步:同步
- 新專案現況:
FormSubmissionCloner::cloneToRequest()已負責建立新 submission
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()
- 備註:
- copy 不走 search_add payload writer,而是 copy 專用 clone writer
複製 quote_form_submission_fields
- 舊入口:把來源 request 的 field rows 複製到新 request
- 主要表:
quote_form_submission_fields - 同步 / 非同步:同步
- 新專案現況:
FormSubmissionCloner::cloneToRequest()逐筆 insert source fields
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- 欄位值、type、responses 都要對齊
- staging DB baseline
20212 -> 20213:- source / copied 都是
12筆 field rows reserve_type_b也原樣複製
- source / copied 都是
variable fee 更新
- 舊入口:
updateRequestVariableFee() - 主要表:
quote_requests,quote_fee_adjust_maps,quote_group_variable_fee_logs - 同步 / 非同步:同步
- 新專案現況:
CopyRequestFeeUpdater已接入 copy flow
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesBaseFeesAndExpiredOnForStableFixture()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- staging DB baseline
20212 -> 20213:- 以
2026-04-29實查為準,manual_fee_discount從0.6000變成0.8000 - 這表示 copy 後還有額外 fee 調整,不是只複製來源 request 欄位
- 以
- 目前驗收欄位包含
site_fee、manual_fee、auto_fee、direct_fee、contact_charge_fee、manual_fee_discount
- staging DB baseline
reload language summary
- 舊入口:
reload_lang_summary() - 主要表:
quote_requests.language_summary等 - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler::reloadSummary()會清掉 summary cache 後重算
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- baseline 驗
form_summary、language_summary、job_center_summary
- baseline 驗
abnormal / keyword scan
- 舊入口:新戶、關鍵字、海外電話風控
- 主要表:
abnormal_check_items,user_internal_logs等 - 同步 / 非同步:同步
- 新專案現況:
SearchAdd已有AbnormalScanWriter
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyAbnormalIntegrationTest.php::testPausesMatchingWhenForcedAbnormalScanFound()tests/QuoteRequestCopyAbnormalIntegrationTest.php::testPausesMatchingForHighRiskForeignPhoneScan()tests/QuoteRequestCopyAbnormalIntegrationTest.php::testReturnsSuccessButPausesMatchingForForcedOldKeywordWarning()tests/QuoteRequestCopyBaselineIntegrationTest.php::testAbnormalBaselineRequestRowsMatchExpectedCopyRelationship()tests/QuoteRequestCopyBaselineIntegrationTest.php::testKeywordBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- copy 命中 abnormal / keyword 時仍回 success,但會停配對
auto quote
- 舊入口:
handleNewQuoteRequestAutoQuote() - 主要表:
quote_bids,quote_request_match_infos - 同步 / 非同步:同步
- 新專案現況:
- 已有 auto quote 主線
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testDispatchesAutoQuoteAfterCopy()tests/QuoteRequestCopyIntegrationTest.php::testSkipsAutoQuoteWhenSourceRequestWasOriginallyCopied()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineCopiedRequestHasExpectedAutoQuoteBidShape()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineCopiedRequestHasExpectedNarrowMatchBidShape()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineCopiedRequestHasExpectedBidAndActivityAggregateShape()
- 備註:
- staging DB baseline
20212 -> 20213已證實成功 copy 會立刻建立 auto quote:- source
quote_bids:100筆,is_auto_quote = 1有7筆 - copied
quote_bids:100筆,is_auto_quote = 1也有7筆 - copied request 的 auto quote fee 區間為
111
- source
quote_activities也同步出現quote_activity_type_id = 2:- 7 筆
param1 = auto_quote - 1 筆 contact-charge 相關 payload
- 7 筆
- staging DB baseline
HK newQuoteRequest task
- 舊入口:HK area 不延後配對時補 task
- 主要表:
task_queue - 同步 / 非同步:非同步
- 新專案現況:
- 已有
TaskQueue與newQuoteRequesthandler
- 已有
- Parity 要求:必做
- 測試:已有 forced-HK integration test
- 備註:
- QuoteRequestCopyIntegrationTest.php 會以
QUOTE_REQUEST_COPY_TEST_FORCE_AREA=hk驗成功 copy 後有newQuoteRequesttask - 已直接比對 legacy controller 與新 handler,HK 分支主線條件一致:
- 都只在
!is_scan_found時送 task - 都只在
area = hk時送 task
- 都只在
- 仍需真正 HK 區域 baseline,才能證明實際 HK 環境資料也完全一致
- staging DB baseline
20212 -> 20213:task_queue_log有action = newQuoteRequest- source
20212執行時間約在10:04 - copied
20213執行時間約在04:49
- 這表示成功 copy 路徑會送出
newQuoteRequest類型 task,不是只有同步建單
- QuoteRequestCopyIntegrationTest.php 會以
設定 expired_on
- 舊入口:先看
due_datefield,否則取 categoryrequest_expired_days - 主要表:
quote_form_submission_fields,quote_requests,quote_categories - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler::resolveExpiredOn()已接入 copy flow
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesBaseFeesAndExpiredOnForStableFixture()tests/QuoteRequestCopyIntegrationTest.php::testDueDateFieldOverridesCategoryExpiredOn()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- copy 支援
due_dateoverride - staging DB baseline
20212 -> 20213:- source
expired_on = 2026-05-08 10:00:00 - copied
expired_on = 2026-05-11 04:00:00
- source
- copied request 並沒有單純沿用來源
expired_on
- copy 支援
建立 CreateRequest activity
- 舊入口:
createQuoteRequestActivityById(...CreateRequest) - 主要表:
quote_activities - 同步 / 非同步:同步
- 新專案現況:
- 已有
QuoteActivity/RequestActivityWriter
- 已有
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
- staging DB baseline
20212 -> 20213:- copied request 有
quote_activity_type_id = 1 - 但實際寫入順序上,auto quote activity 可能先於
CreateRequest
- copied request 有
- 如果新專案要追到 legacy parity,不能假設
CreateRequest一定是第一筆 activity
- staging DB baseline
更新來源 request last_copied_on
- 舊入口:copy 成功後寫回來源 request
- 主要表:
quote_requests - 同步 / 非同步:同步
- 新專案現況:
- schema 已有欄位
- Parity 要求:必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testCopiesOwnedRequestThroughRouter()tests/QuoteRequestCopyBaselineIntegrationTest.php::testBaselineRequestRowsMatchExpectedCopyRelationship()
- 備註:
allow_copy會讀這欄- staging DB baseline
20212 -> 20213:- source
20212.last_copied_on = 2026-04-27 04:44:23 - copied
20213.last_copied_on = null
- source
recommend source 補充
- 舊入口:從 checklist 來源寫
quote_request_recommend_logs - 主要表:
quote_request_recommend_logs - 同步 / 非同步:同步
- 新專案現況:
CopyRequestHandler::resolveRecommendSource()已支援 copy 對應入口
- Parity 要求:有帶才必做
- 測試:
tests/QuoteRequestCopyIntegrationTest.php::testWritesRecommendSourceLogWhenProvided()
- 備註:
- 舊 controller 只看 top-level
recommend_source - 新版另外兼容
QuoteRequest[recommend_source]
- 舊 controller 只看 top-level