fix(after-sale): 售后工单已完结仍可再次申请,改由订单是否已退款决定
上一个提交把「工单 completed」当成了不能再申请售后的判据,方向搞反了: 能否再售后应该看订单有没有被标「已退款」,而不是看工单状态。订单已退款时 status_group 变成 refunded、enabled 直接为 false,那道闸门本来就够用;用工单 状态再判一次,反而把「工单已完结但订单没退款」的用户堵死,售后详细弹窗底部 也只剩下一个「我知道了」死胡同。 - reapplyable_statuses 补上 STATUS_COMPLETED:rejected / cancelled / completed 一律放行再次申请,售后详细弹窗底部按钮对已完成订单渲染「再次申请售后」 - can_apply 还原为只看有没有进行中的工单(!open),不再二次校验工单状态 - create() 的重复申请闸门还原为 find_active():只挡仍在流转的工单, completed 不挡;订单已退款由上面的 STATUS_PAID 校验先挡掉 - 点「再次申请售后」后清 has_application 落回申请表单,提交走 create() 新建工单,链路本来就通,无需改动 harness 场景名改为 settled_ticket_still_allows_reapply,断言 completed / rejected / cancelled 三种已终结状态都能新建工单;待审核工单同因幂等、换因 挡住的场景保留。 验证:tests/widget-system/ 462 项、tests/admin/ 76 项通过;after-sale-log-harness 7/7。未做浏览器视觉验收。
This commit is contained in:
@@ -149,23 +149,14 @@ final class AfterSaleService {
|
||||
try {
|
||||
$order = OrderRepository::get_instance()->get_user_order($user_id, $order_number);
|
||||
if (!$order || (string) ($order['status'] ?? '') !== Order::STATUS_PAID) return new \WP_Error('aksrt_after_sale_order', __('只有已支付订单可以申请售后', 'aksrt'), ['status' => 409]);
|
||||
// 以「最新一条工单」为准,而不是只看进行中的:已完结的工单同样要挡住再次申请。
|
||||
// 订单有没有另标「已退款」不影响这条——工单 completed 即售后已终结。
|
||||
$latest = $this->latest_for_order($order_number);
|
||||
if ($latest !== null) {
|
||||
$latest_status = (string) ($latest['status'] ?? '');
|
||||
// 待审核 / 处理中:工单仍在流转,挡住重复申请;同人同因视为重复提交,幂等返回原工单。
|
||||
if (in_array($latest_status, [self::STATUS_PENDING, self::STATUS_PROCESSING], true)) {
|
||||
if ((int) ($latest['user_id'] ?? 0) === $user_id && hash_equals((string) ($latest['reason'] ?? ''), $reason)) {
|
||||
return $latest;
|
||||
}
|
||||
return new \WP_Error('aksrt_after_sale_exists', __('该订单已有未结束售后申请', 'aksrt'), ['status' => 409]);
|
||||
// 只挡「仍在流转」的工单。已完结(completed)的工单不挡——能否再售后由
|
||||
// 「订单是否已退款」决定,而订单已退款时上面的 STATUS_PAID 校验已先挡掉。
|
||||
$active = $this->find_active($order_number);
|
||||
if ($active) {
|
||||
if ((int) ($active['user_id'] ?? 0) === $user_id && hash_equals((string) ($active['reason'] ?? ''), $reason)) {
|
||||
return $active;
|
||||
}
|
||||
// 已完成:售后已终结,不再受理新的申请。
|
||||
if ($latest_status === self::STATUS_COMPLETED) {
|
||||
return new \WP_Error('aksrt_after_sale_exists', __('该订单的售后申请已完结,不能再次申请', 'aksrt'), ['status' => 409]);
|
||||
}
|
||||
// rejected / cancelled:允许补充资料后再次发起。
|
||||
return new \WP_Error('aksrt_after_sale_exists', __('该订单已有未结束售后申请', 'aksrt'), ['status' => 409]);
|
||||
}
|
||||
$amount = $this->refund_amount($order);
|
||||
if ($amount === null) return new \WP_Error('aksrt_after_sale_amount', __('订单退款金额无效', 'aksrt'), ['status' => 400]);
|
||||
|
||||
@@ -290,19 +290,22 @@ class UserOrders {
|
||||
// - pending / processing:工单仍在流转(待审核 / 处理中),不允许重复申请;
|
||||
// - rejected:审核未通过,允许补充资料后再次申请;
|
||||
// - cancelled:用户自行取消,允许重新发起;
|
||||
// - completed:退款已完成,工单终结,不允许再次申请。
|
||||
$reapplyable_statuses = [AfterSaleService::STATUS_REJECTED, AfterSaleService::STATUS_CANCELLED];
|
||||
// - completed:工单已完结,但只要订单没被另标「已退款」(enabled 仍为 true),
|
||||
// 依旧允许再次申请。能否再售后由「订单是否已退款」决定,不由工单状态决定:
|
||||
// 订单已退款时 $group 变成 refunded、enabled 直接为 false,上面那条自然挡死。
|
||||
$latest_status = (string) ($latest['status'] ?? '');
|
||||
// 有工单时只有 rejected / cancelled 才放行再次申请:completed 的工单已终结,
|
||||
// 订单有没有另标「已退款」都不影响——AfterSaleService::create() 按同一口径拦截。
|
||||
$reapplyable = !$has_application || in_array($latest_status, $reapplyable_statuses, true);
|
||||
$reapplyable_statuses = [
|
||||
AfterSaleService::STATUS_REJECTED,
|
||||
AfterSaleService::STATUS_CANCELLED,
|
||||
AfterSaleService::STATUS_COMPLETED,
|
||||
];
|
||||
|
||||
return [
|
||||
'enabled' => $enabled,
|
||||
'expired' => (bool) $expired,
|
||||
'has_application' => $has_application,
|
||||
'open' => $open,
|
||||
'can_apply' => $enabled && !$expired && !$open && $reapplyable,
|
||||
'can_apply' => $enabled && !$expired && !$open,
|
||||
'can_reapply' => $enabled && !$expired && $has_application && in_array($latest_status, $reapplyable_statuses, true),
|
||||
'latest' => $has_application ? [
|
||||
'status' => (string) ($latest['status'] ?? ''),
|
||||
|
||||
Reference in New Issue
Block a user