RewardGrantSettingsService.php 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. <?php
  2. namespace App\Services;
  3. use Carbon\CarbonInterface;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Validation\Rule;
  6. use InvalidArgumentException;
  7. class RewardGrantSettingsService
  8. {
  9. public const TYPES = ['rebate', 'backflow'];
  10. public const TIMEZONE = 'Asia/Shanghai';
  11. public static function get(string $type): array
  12. {
  13. self::checkType($type);
  14. $row = DB::table('reward_grant_settings')->where('type', $type)->first();
  15. return [
  16. 'type' => $type,
  17. 'auto_enabled' => (int) ($row->auto_enabled ?? 0),
  18. 'grant_time' => $row->grant_time ?? '03:00',
  19. 'timezone' => self::TIMEZONE,
  20. ];
  21. }
  22. public static function save(string $type, array $params): array
  23. {
  24. self::checkType($type);
  25. // Validate here so HTTP and other callers share the same write rules.
  26. $params = validator($params, [
  27. 'auto_enabled' => ['required', 'boolean'],
  28. 'grant_time' => [Rule::requiredIf(fn () => in_array($params['auto_enabled'] ?? null, [1, '1', true], true)),
  29. 'nullable', 'date_format:H:i'],
  30. ])->validate();
  31. return DB::transaction(function () use ($type, $params) {
  32. $values = ['type' => $type, 'auto_enabled' => (bool) $params['auto_enabled'],
  33. 'created_at' => now(), 'updated_at' => now()];
  34. $updates = ['auto_enabled', 'updated_at'];
  35. if (!empty($params['grant_time'])) {
  36. $values['grant_time'] = $params['grant_time'];
  37. $updates[] = 'grant_time';
  38. }
  39. DB::table('reward_grant_settings')->upsert([$values], ['type'], $updates);
  40. return self::get($type);
  41. });
  42. }
  43. public static function dueAt(?object $setting, CarbonInterface $now): ?CarbonInterface
  44. {
  45. if (!$setting || (int) $setting->auto_enabled !== 1
  46. || !preg_match('/^(?:[01]\d|2[0-3]):[0-5]\d$/D', (string) $setting->grant_time)) {
  47. return null;
  48. }
  49. $local = $now->copy()->setTimezone(self::TIMEZONE);
  50. [$hour, $minute] = array_map('intval', explode(':', $setting->grant_time));
  51. $scheduled = $local->copy()->setTime($hour, $minute, 0);
  52. return $local->greaterThanOrEqualTo($scheduled) ? $scheduled : null;
  53. }
  54. private static function checkType(string $type): void
  55. {
  56. if (!in_array($type, self::TYPES, true)) throw new InvalidArgumentException('奖励类型错误');
  57. }
  58. }