Files
portal/app/app/Console/Commands/ResetMonthlyCountersCommand.php
T
Дмитрий dadfdcaa7e feat(commands): Plan 4 Task 5 — ResetMonthlyCountersCommand + Schedule monthlyOn(1, 00:00) МСК
Месячный cron-сброс tenants.delivered_in_month + projects.delivered_in_month
1-го числа каждого месяца в 00:00 МСК. Идёт через pgsql_supplier BYPASSRLS
connection (паттерн ResetDeliveredTodayCommand). Идемпотентный
(WHERE delivered_in_month <> 0 → повторный запуск 0 affected rows).

4 теста: reset multi-tenant + idempotency + Schedule registration +
BYPASSRLS without SET LOCAL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:28:13 +03:00

43 lines
1.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* Сброс tenants.delivered_in_month + projects.delivered_in_month = 0.
*
* Spec: docs/superpowers/specs/2026-05-11-plan4-billing-csv-admin-design.md §4.1
* Расписание: 1-го числа каждого месяца в 00:00 Europe/Moscow.
*
* Идёт через connection `pgsql_supplier` (BYPASSRLS-роль crm_supplier_worker) —
* паттерн ResetDeliveredTodayCommand. Один statement на таблицу, без SET LOCAL.
*/
class ResetMonthlyCountersCommand extends Command
{
protected $signature = 'projects:reset-monthly';
protected $description = 'Сброс tenants.delivered_in_month + projects.delivered_in_month = 0 (1-го числа в 00:00 МСК, Plan 4)';
public function handle(): int
{
// Без оборачивающего DB::transaction: два UPDATE'а независимо идемпотентны
// (WHERE delivered_in_month <> 0). Если один упадёт, следующий cron-запуск
// довершит сброс. Атомарность не требуется. Дополнительно — оборачивание
// ломает тесты с shared PDO (SharesSupplierPdo trait): PostgreSQL не
// допускает nested transactions без savepoints, см. precedent
// ResetDeliveredTodayCommand (тоже без обёртки).
$tenants = DB::connection('pgsql_supplier')
->update('UPDATE tenants SET delivered_in_month = 0 WHERE delivered_in_month <> 0');
$projects = DB::connection('pgsql_supplier')
->update('UPDATE projects SET delivered_in_month = 0 WHERE delivered_in_month <> 0');
$this->info("Monthly reset: {$tenants} tenants, {$projects} projects.");
return self::SUCCESS;
}
}