fix(ticket): 本地化调整工单时间线状态标签翻译
Some checks failed
lotterLaravel CI / test (push) Has been cancelled
lotterLaravel E2E / e2e-api (push) Has been cancelled

- 将工单时间线中的状态标签改为调用多语言翻译接口
- 新增多语言文件中对应时间线标签的翻译词条
- 统一使用请求中的本地语言环境渲染时间线标签
- 优化代理信用额度校验,抽取公共方法requireProfile
- 抛出更精确的校验异常信息,区分缺失和额度超出情况
This commit is contained in:
2026-07-02 14:39:55 +08:00
parent c7fd38bb08
commit 9d355aa853
5 changed files with 42 additions and 24 deletions

View File

@@ -71,44 +71,47 @@ final class TicketItemShowController extends Controller
: null;
$timeline = [];
$locale = $request->lotteryLocale();
if ($order?->created_at !== null) {
$timeline[] = [
'code' => 'placed',
'label' => '已下注',
'label' => trans('api.ticket_timeline_placed', [], $locale),
'time' => $order->created_at->toIso8601String(),
];
}
if ($betTxn?->created_at !== null) {
$timeline[] = [
'code' => 'deducted',
'label' => '已扣款',
'label' => trans('api.ticket_timeline_deducted', [], $locale),
'time' => $betTxn->created_at->toIso8601String(),
];
}
if ($drawPayload !== null && $draw?->current_result_version !== null) {
$timeline[] = [
'code' => 'draw_published',
'label' => '开奖结果已发布',
'label' => trans('api.ticket_timeline_draw_published', [], $locale),
'time' => $draw->draw_time?->toIso8601String() ?? $draw->updated_at?->toIso8601String(),
];
}
if ($settlementBatch?->started_at !== null) {
$timeline[] = [
'code' => 'settlement_started',
'label' => '结算开始',
'label' => trans('api.ticket_timeline_settlement_started', [], $locale),
'time' => $settlementBatch->started_at->toIso8601String(),
];
}
if ($item->settled_at !== null) {
$timeline[] = [
'code' => 'settled',
'label' => $item->status === 'settled_win' ? '已派彩' : '已结算',
'label' => $item->status === 'settled_win'
? trans('api.ticket_timeline_paid_out', [], $locale)
: trans('api.ticket_timeline_settled', [], $locale),
'time' => $item->settled_at->toIso8601String(),
];
} elseif ($payoutTxn?->created_at !== null) {
$timeline[] = [
'code' => 'settled',
'label' => '已派彩',
'label' => trans('api.ticket_timeline_paid_out', [], $locale),
'time' => $payoutTxn->created_at->toIso8601String(),
];
}

View File

@@ -27,12 +27,7 @@ final class CreditAllocationValidator
$this->allocatedSync->syncForAgent($parent);
$profile = AgentProfile::query()->where('agent_node_id', $parent->id)->first();
if ($profile === null) {
throw ValidationException::withMessages([
'credit_limit' => ['parent_profile_required'],
]);
}
$profile = $this->requireProfile($parent->id, 'parent_profile_required');
$available = max(0, (int) $profile->credit_limit - (int) $profile->allocated_credit);
$floor = $isNewChild ? 0 : max(0, $previousChildLimit);
@@ -49,12 +44,7 @@ final class CreditAllocationValidator
{
$this->allocatedSync->syncForAgent($parent);
$profile = AgentProfile::query()->where('agent_node_id', $parent->id)->first();
if ($profile === null) {
throw ValidationException::withMessages([
'credit_limit' => ['parent_profile_required'],
]);
}
$profile = $this->requireProfile($parent->id, 'parent_profile_required');
$available = max(0, (int) $profile->credit_limit - (int) $profile->allocated_credit);
if ($additionalCredit > $available) {
@@ -85,12 +75,7 @@ final class CreditAllocationValidator
$this->allocatedSync->syncForAgent($agent);
$profile = AgentProfile::query()->where('agent_node_id', $agent->id)->first();
if ($profile === null) {
throw ValidationException::withMessages([
'credit_limit' => ['agent_profile_required'],
]);
}
$profile = $this->requireProfile($agent->id, 'agent_profile_required');
$available = max(0, (int) $profile->credit_limit - (int) $profile->allocated_credit);
if ($additionalCredit > $available) {
@@ -99,4 +84,16 @@ final class CreditAllocationValidator
]);
}
}
private function requireProfile(int $agentNodeId, string $missingKey): AgentProfile
{
$profile = AgentProfile::query()->where('agent_node_id', $agentNodeId)->first();
if ($profile === null) {
throw ValidationException::withMessages([
'credit_limit' => [$missingKey],
]);
}
return $profile;
}
}