fix(after-sale): 售后工单已完结即不可再申请,不看订单是否另标已退款
原来的重复申请闸门只看「进行中」的工单(find_active = pending/processing), 于是工单已 completed、但订单没被另标「已退款」时,订单还能再发起一次售后。 已退款订单之所以不能再申请,是因为 status_group 变了导致 enabled 为 false, 属于间接效果;工单层面的规则一直是漏的。 - create() 改为以 latest_for_order() 为准:completed 直接挡掉;待审核/处理中 仍走同人同因幂等(返回原工单),rejected / cancelled 放行再次发起 - after_sale_state() 的 can_apply 同步收紧,与 can_reapply 同一口径: 有工单时只有 rejected / cancelled 才放行,completed 不再漏过去 - 界面上售后详细弹窗的「再次申请」本就只对 rejected / cancelled 渲染, 这条改动把服务端与 API 口径补齐,堵住绕过前端直接打 REST 的口子 harness 补两个场景:completed 挡住而 rejected / cancelled 放行;待审核工单 同因幂等返回原单、换因挡住。 验证:tests/widget-system/ 462 项、tests/admin/ 76 项通过;after-sale-log-harness 7/7(新增两场景);dev harness 渲染两个后台页面与 unchecked 处理场景均正常。 未做浏览器视觉验收。
This commit is contained in:
@@ -214,6 +214,40 @@ namespace {
|
||||
&& $broken === [],
|
||||
'detail' => ['normalized' => $normalized, 'broken_json' => $broken]];
|
||||
|
||||
// 6) 再次申请的闸门看「最新一条工单」,不是只看进行中的:completed 一律挡住,
|
||||
// rejected / cancelled 放行;订单有没有另标已退款不影响这条。
|
||||
$gate = static function (string $status) use ($service, $wpdb, $order) {
|
||||
$wpdb->rows = [];
|
||||
$wpdb->rows[950] = ['id' => 950, 'order_number' => $order['order_number'], 'user_id' => 7, 'status' => $status,
|
||||
'reason' => '旧申请', 'handling_log' => wp_json_encode([['status' => $status, 'note' => '', 'source' => 'admin', 'created_at' => '2026-10-01 10:00:00']]),
|
||||
'created_at' => '2026-10-01 10:00:00'];
|
||||
return $service->create(7, $order['order_number'], '新的申请原因');
|
||||
};
|
||||
$completed = $gate('completed');
|
||||
$rejected = $gate('rejected');
|
||||
$cancelled = $gate('cancelled');
|
||||
$results[] = ['name' => 'completed_ticket_blocks_reapply', 'ok' => $completed instanceof \WP_Error
|
||||
&& $completed->get_error_code() === 'aksrt_after_sale_exists'
|
||||
&& !$rejected instanceof \WP_Error
|
||||
&& !$cancelled instanceof \WP_Error,
|
||||
'detail' => [
|
||||
'completed' => $completed instanceof \WP_Error ? $completed->get_error_code() : 'created',
|
||||
'rejected' => $rejected instanceof \WP_Error ? $rejected->get_error_code() : 'created',
|
||||
'cancelled' => $cancelled instanceof \WP_Error ? $cancelled->get_error_code() : 'created',
|
||||
]];
|
||||
|
||||
// 待审核:同人同因幂等返回原工单,换原因则挡住
|
||||
$wpdb->rows = [];
|
||||
$wpdb->rows[951] = ['id' => 951, 'order_number' => $order['order_number'], 'user_id' => 7, 'status' => 'pending',
|
||||
'reason' => '同一个原因', 'handling_log' => '[]', 'created_at' => '2026-10-01 10:00:00'];
|
||||
$same = $service->create(7, $order['order_number'], '同一个原因');
|
||||
$other = $service->create(7, $order['order_number'], '换了个原因');
|
||||
$results[] = ['name' => 'open_ticket_blocks_duplicate_apply', 'ok' => is_array($same)
|
||||
&& (int) $same['id'] === 951
|
||||
&& $other instanceof \WP_Error
|
||||
&& $other->get_error_code() === 'aksrt_after_sale_exists',
|
||||
'detail' => ['same' => is_array($same) ? (int) $same['id'] : 'error', 'other' => $other instanceof \WP_Error ? $other->get_error_code() : 'created']];
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user