62 lines
2.5 KiB
PHP
62 lines
2.5 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
declare(strict_types=1);
|
|||
|
|
|
|||
|
|
namespace App\Console\Commands;
|
|||
|
|
|
|||
|
|
use Carbon\Carbon;
|
|||
|
|
use Illuminate\Console\Command;
|
|||
|
|
use Illuminate\Support\Facades\DB;
|
|||
|
|
use Illuminate\Support\Facades\Log;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Создаёт project_routing_snapshots за указанную дату из текущего live-состояния.
|
|||
|
|
* Используется один раз при выкатке Этапа 2 + для ручного recovery после падения cron'а.
|
|||
|
|
*
|
|||
|
|
* Spec §4.2.6.
|
|||
|
|
*/
|
|||
|
|
final class SnapshotBackfillCommand extends Command
|
|||
|
|
{
|
|||
|
|
protected $signature = 'snapshot:backfill {--date= : YYYY-MM-DD, по умолчанию сегодня}';
|
|||
|
|
|
|||
|
|
protected $description = 'Заполнить project_routing_snapshots за указанную дату из live projects';
|
|||
|
|
|
|||
|
|
public function handle(): int
|
|||
|
|
{
|
|||
|
|
$dateStr = (string) ($this->option('date') ?? Carbon::today('Europe/Moscow')->toDateString());
|
|||
|
|
$date = Carbon::parse($dateStr, 'Europe/Moscow');
|
|||
|
|
$weekdayBit = 1 << ($date->isoWeekday() - 1);
|
|||
|
|
|
|||
|
|
$count = DB::connection('pgsql_supplier')->transaction(function () use ($dateStr, $weekdayBit) {
|
|||
|
|
return DB::connection('pgsql_supplier')->insert(<<<SQL
|
|||
|
|
INSERT INTO project_routing_snapshots (
|
|||
|
|
snapshot_date, project_id, tenant_id,
|
|||
|
|
daily_limit, delivery_days_mask, regions,
|
|||
|
|
signal_type, signal_identifier, sms_senders, sms_keyword,
|
|||
|
|
expected_volume
|
|||
|
|
)
|
|||
|
|
SELECT
|
|||
|
|
?::date,
|
|||
|
|
p.id, p.tenant_id,
|
|||
|
|
COALESCE(p.effective_daily_limit_today, p.daily_limit_target),
|
|||
|
|
p.delivery_days_mask, p.regions,
|
|||
|
|
p.signal_type, p.signal_identifier, p.sms_senders, p.sms_keyword,
|
|||
|
|
COALESCE(p.effective_daily_limit_today, p.daily_limit_target)
|
|||
|
|
FROM projects p
|
|||
|
|
INNER JOIN tenants t ON t.id = p.tenant_id
|
|||
|
|
WHERE p.is_active = true
|
|||
|
|
AND (p.delivery_days_mask & ?::int) <> 0
|
|||
|
|
AND p.preflight_blocked_at IS NULL
|
|||
|
|
AND t.frozen_by_balance_at IS NULL
|
|||
|
|
AND t.deleted_at IS NULL
|
|||
|
|
ON CONFLICT (snapshot_date, project_id) DO NOTHING
|
|||
|
|
SQL, [$dateStr, $weekdayBit]);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
$this->info("Snapshot backfilled for {$dateStr}: {$count} rows.");
|
|||
|
|
Log::info('snapshot.backfill', ['date' => $dateStr, 'rows' => $count]);
|
|||
|
|
|
|||
|
|
return self::SUCCESS;
|
|||
|
|
}
|
|||
|
|
}
|