MemberBonusLogService.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <?php
  2. namespace App\Services;
  3. use App\Support\PromotionRules;
  4. use Illuminate\Database\Eloquent\Builder;
  5. use Illuminate\Database\Query\Builder as QueryBuilder;
  6. use Illuminate\Support\Facades\DB;
  7. use Illuminate\Support\Facades\Schema;
  8. /** 会员彩金的展示类型与筛选共用映射,资金账本仍保留原记账类型。 */
  9. final class MemberBonusLogService
  10. {
  11. public const LEDGER_TYPES = ['即充即送', '老用户回归', '余额宝利息', '注册赠送', '优惠活动', '充值返现'];
  12. private const PROMOTIONS = [
  13. PromotionRules::LOSS => '净亏邀请',
  14. PromotionRules::FIRST_DEPOSIT => '首充奖励',
  15. PromotionRules::WHEEL => '转盘',
  16. PromotionRules::UPGRADE_INVITE => '邀请升级奖励',
  17. ];
  18. private bool $hasPromotions;
  19. private bool $hasRechargeBonuses;
  20. public function __construct()
  21. {
  22. $this->hasPromotions = Schema::hasTable('promotion_rewards') && Schema::hasTable('promotion_activities');
  23. $this->hasRechargeBonuses = Schema::hasTable('recharge_bonus_rewards');
  24. }
  25. public static function types(): array
  26. {
  27. return ['即充即送', '转盘', '老用户回归', '余额宝利息', '净亏邀请', '首充奖励',
  28. '邀请升级奖励', '充值渠道赠送', '注册赠送', '优惠活动', '充值返现'];
  29. }
  30. private function promotionLogs(?int $type = null): QueryBuilder
  31. {
  32. return DB::table('promotion_rewards as pr')
  33. ->join('promotion_activities as pa', 'pa.id', '=', 'pr.activity_id')
  34. ->whereIn('pa.type', $type === null ? array_keys(self::PROMOTIONS) : [$type])
  35. ->whereNotNull('pr.credited_log_id')->select('pr.credited_log_id');
  36. }
  37. private function rechargeLogs(): QueryBuilder
  38. {
  39. return DB::table('recharge_bonus_rewards')->whereNotNull('credited_log_id')->select('credited_log_id');
  40. }
  41. public function filter(Builder $query, ?string $type): void
  42. {
  43. if ($type === null || $type === '') return;
  44. $promotionType = array_search($type, self::PROMOTIONS, true);
  45. if ($promotionType !== false) {
  46. $query->where('balance_logs.change_type', '优惠活动');
  47. if ($this->hasPromotions) $query->whereIn('balance_logs.id', $this->promotionLogs($promotionType));
  48. else $query->whereRaw('1 = 0');
  49. return;
  50. }
  51. if ($type === '充值渠道赠送') {
  52. $query->where('balance_logs.change_type', '优惠活动');
  53. if ($this->hasRechargeBonuses) $query->whereIn('balance_logs.id', $this->rechargeLogs());
  54. else $query->whereRaw('1 = 0');
  55. // 与展示时一致:独立活动关联优先。
  56. if ($this->hasPromotions) $query->whereNotIn('balance_logs.id', $this->promotionLogs());
  57. return;
  58. }
  59. $query->where('balance_logs.change_type', $type);
  60. if ($type === '优惠活动') {
  61. if ($this->hasPromotions) $query->whereNotIn('balance_logs.id', $this->promotionLogs());
  62. if ($this->hasRechargeBonuses) $query->whereNotIn('balance_logs.id', $this->rechargeLogs());
  63. }
  64. }
  65. public function decorate(array $rows): array
  66. {
  67. $ids = array_column(array_filter($rows, fn ($row) => $row['change_type'] === '优惠活动'), 'id');
  68. if (!$ids) return $rows;
  69. $promotions = $this->hasPromotions ? DB::table('promotion_rewards as pr')
  70. ->join('promotion_activities as pa', 'pa.id', '=', 'pr.activity_id')
  71. ->whereIn('pr.credited_log_id', $ids)->whereIn('pa.type', array_keys(self::PROMOTIONS))
  72. ->pluck('pa.type', 'pr.credited_log_id')->all() : [];
  73. $recharges = $this->hasRechargeBonuses ? array_fill_keys(DB::table('recharge_bonus_rewards')
  74. ->whereIn('credited_log_id', $ids)->pluck('credited_log_id')->all(), true) : [];
  75. foreach ($rows as &$row) {
  76. if ($row['change_type'] !== '优惠活动') continue;
  77. if (isset($promotions[$row['id']])) $row['change_type'] = self::PROMOTIONS[(int)$promotions[$row['id']]];
  78. elseif (isset($recharges[$row['id']])) $row['change_type'] = '充值渠道赠送';
  79. }
  80. unset($row);
  81. return $rows;
  82. }
  83. }