| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- <?php
- namespace App\Services;
- use Carbon\CarbonInterface;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Validation\Rule;
- use InvalidArgumentException;
- class RewardGrantSettingsService
- {
- public const TYPES = ['rebate', 'backflow'];
- public const TIMEZONE = 'Asia/Shanghai';
- public static function get(string $type): array
- {
- self::checkType($type);
- $row = DB::table('reward_grant_settings')->where('type', $type)->first();
- return [
- 'type' => $type,
- 'auto_enabled' => (int) ($row->auto_enabled ?? 0),
- 'grant_time' => $row->grant_time ?? '03:00',
- 'timezone' => self::TIMEZONE,
- ];
- }
- public static function save(string $type, array $params): array
- {
- self::checkType($type);
- // Validate here so HTTP and other callers share the same write rules.
- $params = validator($params, [
- 'auto_enabled' => ['required', 'boolean'],
- 'grant_time' => [Rule::requiredIf(fn () => in_array($params['auto_enabled'] ?? null, [1, '1', true], true)),
- 'nullable', 'date_format:H:i'],
- ])->validate();
- return DB::transaction(function () use ($type, $params) {
- $values = ['type' => $type, 'auto_enabled' => (bool) $params['auto_enabled'],
- 'created_at' => now(), 'updated_at' => now()];
- $updates = ['auto_enabled', 'updated_at'];
- if (!empty($params['grant_time'])) {
- $values['grant_time'] = $params['grant_time'];
- $updates[] = 'grant_time';
- }
- DB::table('reward_grant_settings')->upsert([$values], ['type'], $updates);
- return self::get($type);
- });
- }
- public static function dueAt(?object $setting, CarbonInterface $now): ?CarbonInterface
- {
- if (!$setting || (int) $setting->auto_enabled !== 1
- || !preg_match('/^(?:[01]\d|2[0-3]):[0-5]\d$/D', (string) $setting->grant_time)) {
- return null;
- }
- $local = $now->copy()->setTimezone(self::TIMEZONE);
- [$hour, $minute] = array_map('intval', explode(':', $setting->grant_time));
- $scheduled = $local->copy()->setTime($hour, $minute, 0);
- return $local->greaterThanOrEqualTo($scheduled) ? $scheduled : null;
- }
- private static function checkType(string $type): void
- {
- if (!in_array($type, self::TYPES, true)) throw new InvalidArgumentException('奖励类型错误');
- }
- }
|