|
|
@@ -439,21 +439,41 @@ class PromotionService
|
|
|
$activityId = (int) ($choice->activity_id ?? 0);
|
|
|
if (!$activityId && FirstDepositChoice::ready() && !FirstDepositChoice::legacyOrder($orderSource, (int) $deposit->related_id)) return;
|
|
|
|
|
|
- $activities = ActivityPeriod::active(PromotionActivity::where('type', Rules::FIRST_DEPOSIT)->where('status', 1), now()->timestamp);
|
|
|
- $ids = $activityId ? [$activityId] : $activities->orderByDesc('sort')->orderByDesc('id')->pluck('id');
|
|
|
+ // 多个首充活动按档位发放:在所有可参加的首充活动里,取充值金额达到门槛、奖励最高的一个(份数或额度用完时取下一档)。
|
|
|
+ // 会员确认的禁止游戏大类(全部首充活动统一)沿用确认时的快照;选中的那个活动沿用确认时的完整规则。
|
|
|
+ // 只在会员确认时所在的端(PC/H5/APP/TG)发布的活动里选;上线前的选择没有记录端,按会员确认的那个活动发布的端。
|
|
|
+ $snapshot = $activityId ? $this->json($choice->rule_snapshot) : null;
|
|
|
+ $platforms = isset($snapshot['platform']) ? [$snapshot['platform']] : [];
|
|
|
+ unset($snapshot['platform']);
|
|
|
+ if ($activityId && !$platforms && ($confirmed = PromotionActivity::find($activityId))) {
|
|
|
+ $platforms = array_values(array_filter(['PC', 'H5', 'APP', 'TG'], fn ($p) => ActivityEligibilityService::isPublishedOn($confirmed, $p)));
|
|
|
+ }
|
|
|
+ $ids = ActivityPeriod::active(PromotionActivity::where('type', Rules::FIRST_DEPOSIT)->where('status', 1), now()->timestamp)
|
|
|
+ ->orderByDesc('sort')->orderByDesc('id')->pluck('id')->all();
|
|
|
+ if ($activityId) $ids = array_values(array_unique(array_merge([$activityId], $ids)));
|
|
|
+ $creditedAt = (string)$deposit->getRawOriginal('created_at');
|
|
|
+ $candidates = [];
|
|
|
foreach ($ids as $id) {
|
|
|
$activity = PromotionActivity::whereKey($id)->lockForUpdate()->first();
|
|
|
if (!$activity || (int)$activity->status !== 1 || (int)$activity->type !== Rules::FIRST_DEPOSIT
|
|
|
|| !ActivityPeriod::contains($activity->start_time, $activity->end_time, now()->timestamp)) continue;
|
|
|
- if (!$activityId && !PromotionTranslations::select($activity->toArray(), $member->language ?: 'zh')) continue;
|
|
|
+ if ((int)$activity->id !== $activityId && !PromotionTranslations::select($activity->toArray(), $member->language ?: 'zh')) continue;
|
|
|
+ if ($activityId && (int)$activity->id !== $activityId
|
|
|
+ && !array_filter($platforms, fn ($p) => ActivityEligibilityService::isPublishedOn($activity, $p))) continue;
|
|
|
$published = DB::table('promotion_campaigns')->where('activity_id', $activity->id)->sharedLock()->value('first_published_at');
|
|
|
- $creditedAt = (string)$deposit->getRawOriginal('created_at');
|
|
|
if (!$published || $creditedAt < $published || !ActivityPeriod::contains($activity->start_time, $activity->end_time, strtotime($creditedAt))) continue;
|
|
|
if (!ActivityEligibilityService::evaluate($activity, ActivityEligibilityService::memberContext($member->member_id))['is_eligible']) continue;
|
|
|
- // The member accepted one set of rules. Pre-cutover orders keep their legacy reward without new restrictions.
|
|
|
- $rules = $activityId ? $this->json($choice->rule_snapshot) : array_replace($this->rules($activity), ['forbidden_categories' => []]);
|
|
|
- if (!$rules) continue;
|
|
|
- if (bccomp((string)$deposit->amount, $rules['min_deposit'], 10) < 0) continue;
|
|
|
+ // Pre-cutover orders keep their legacy reward without new restrictions.
|
|
|
+ if ($snapshot === null) $rules = array_replace($this->rules($activity), ['forbidden_categories' => []]);
|
|
|
+ elseif ((int)$activity->id === $activityId) $rules = $snapshot;
|
|
|
+ else $rules = array_replace($this->rules($activity), ['forbidden_categories' => $snapshot['forbidden_categories'] ?? []]);
|
|
|
+ if (!$rules || bccomp((string)$deposit->amount, (string)$rules['min_deposit'], 10) < 0) continue;
|
|
|
+ $candidates[] = [$activity, $rules];
|
|
|
+ }
|
|
|
+ // 奖励高的优先;奖励相同时会员确认的活动优先,其次按活动排序。
|
|
|
+ usort($candidates, fn ($a, $b) => bccomp((string)$b[1]['reward_amount'], (string)$a[1]['reward_amount'], 10)
|
|
|
+ ?: (((int)$b[0]->id === $activityId) <=> ((int)$a[0]->id === $activityId)));
|
|
|
+ foreach ($candidates as [$activity, $rules]) {
|
|
|
try { $this->capacity($activity, $member, $rules['reward_amount']); } catch (ValidationException $e) { continue; }
|
|
|
$account = $this->account($activity, $member);
|
|
|
$reward = $this->reserve($activity, $member, $account, 1, $rules['reward_amount'], $rules + ['deposit_log_id' => $deposit->id]);
|