diff --git a/app/app/Console/Commands/PhoneRangesImportCommand.php b/app/app/Console/Commands/PhoneRangesImportCommand.php index ffe7c9f4..aed96c8d 100644 --- a/app/app/Console/Commands/PhoneRangesImportCommand.php +++ b/app/app/Console/Commands/PhoneRangesImportCommand.php @@ -6,6 +6,7 @@ namespace App\Console\Commands; use App\Support\RussianRegions; use Illuminate\Console\Command; +use Illuminate\Database\Connection; use Illuminate\Support\Facades\DB; use OpenSpout\Reader\XLSX\Reader as XlsxReader; @@ -135,7 +136,7 @@ class PhoneRangesImportCommand extends Command 'error' => trim('dry-run (swap не выполнен). '.$unmatchedNote), 'completed_at' => now(), ]); - $this->info('dry-run: '.count($rows)." строк в phone_ranges_staging, swap не выполнен."); + $this->info('dry-run: '.count($rows).' строк в phone_ranges_staging, swap не выполнен.'); if ($unmatchedNote !== '') { $this->warn($unmatchedNote); } @@ -171,7 +172,7 @@ class PhoneRangesImportCommand extends Command } /** - * @return list|null Список файлов или null при ошибке валидации опций. + * @return list|null Список файлов или null при ошибке валидации опций. */ private function resolveFiles(): ?array { @@ -294,7 +295,7 @@ class PhoneRangesImportCommand extends Command */ private function parseXlsx(string $path): array { - $reader = new XlsxReader(); + $reader = new XlsxReader; $reader->open($path); $out = []; @@ -430,7 +431,7 @@ class PhoneRangesImportCommand extends Command * SET ROLE crm_migrator для корректного ownership на проде; на dev/test роль * отсутствует → RESET и работаем как superuser (зеркало миграционного паттерна). */ - private function elevate(\Illuminate\Database\Connection $c): void + private function elevate(Connection $c): void { try { $c->statement('SET ROLE crm_migrator'); diff --git a/app/app/Console/Commands/SnapshotBackfillCommand.php b/app/app/Console/Commands/SnapshotBackfillCommand.php index c92e510a..4cc67c42 100644 --- a/app/app/Console/Commands/SnapshotBackfillCommand.php +++ b/app/app/Console/Commands/SnapshotBackfillCommand.php @@ -28,7 +28,7 @@ final class SnapshotBackfillCommand extends Command $weekdayBit = 1 << ($date->isoWeekday() - 1); $count = DB::connection('pgsql_supplier')->transaction(function () use ($dateStr, $weekdayBit) { - return DB::connection('pgsql_supplier')->insert(<<insert(<<<'SQL' INSERT INTO project_routing_snapshots ( snapshot_date, project_id, tenant_id, daily_limit, delivery_days_mask, regions, diff --git a/app/app/Console/Commands/SnapshotRebuildCommand.php b/app/app/Console/Commands/SnapshotRebuildCommand.php index ef680732..f7d6c1ff 100644 --- a/app/app/Console/Commands/SnapshotRebuildCommand.php +++ b/app/app/Console/Commands/SnapshotRebuildCommand.php @@ -47,7 +47,7 @@ final class SnapshotRebuildCommand extends Command ->where('snapshot_date', $dateStr) ->delete(); - $inserted = DB::connection('pgsql_supplier')->insert(<<insert(<<<'SQL' INSERT INTO project_routing_snapshots ( snapshot_date, project_id, tenant_id, daily_limit, delivery_days_mask, regions, diff --git a/app/app/Jobs/RouteSupplierLeadJob.php b/app/app/Jobs/RouteSupplierLeadJob.php index 4a661d67..ddbfe235 100644 --- a/app/app/Jobs/RouteSupplierLeadJob.php +++ b/app/app/Jobs/RouteSupplierLeadJob.php @@ -605,7 +605,7 @@ class RouteSupplierLeadJob implements ShouldQueue } /** - * @return list '{82,83}' → [82,83]; '{}'/'' → [] + * @return list '{82,83}' → [82,83]; '{}'/'' → [] */ private function parseSubjectCodes(string $regionsLiteral): array { diff --git a/app/app/Jobs/SnapshotProjectRoutingJob.php b/app/app/Jobs/SnapshotProjectRoutingJob.php index 1ed86762..8664c8a5 100644 --- a/app/app/Jobs/SnapshotProjectRoutingJob.php +++ b/app/app/Jobs/SnapshotProjectRoutingJob.php @@ -20,7 +20,7 @@ use Illuminate\Support\Facades\Log; */ final class SnapshotProjectRoutingJob implements ShouldQueue { - use Dispatchable, Queueable, InteractsWithQueue, SerializesModels; + use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public const DB_CONNECTION = 'pgsql_supplier'; // BYPASSRLS @@ -38,10 +38,11 @@ final class SnapshotProjectRoutingJob implements ShouldQueue ->exists(); if ($exists) { Log::info('snapshot.already_exists', ['date' => $snapshotDate]); + return; } - $count = DB::connection(self::DB_CONNECTION)->insert(<<insert(<<<'SQL' INSERT INTO project_routing_snapshots ( snapshot_date, project_id, tenant_id, daily_limit, delivery_days_mask, regions, diff --git a/app/app/Jobs/Supplier/CsvReconcileJob.php b/app/app/Jobs/Supplier/CsvReconcileJob.php index f40b8aa4..6f8b0298 100644 --- a/app/app/Jobs/Supplier/CsvReconcileJob.php +++ b/app/app/Jobs/Supplier/CsvReconcileJob.php @@ -6,9 +6,11 @@ namespace App\Jobs\Supplier; use App\Jobs\RouteSupplierLeadJob; use App\Mail\CsvDriftAlertMail; +use App\Mail\TenantBusinessDriftAlertMail; use App\Models\SupplierLead; use App\Services\Supplier\SupplierCsvParser; use App\Services\Supplier\SupplierPortalClient; +use Carbon\CarbonInterface; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Cache\LockProvider; use Illuminate\Contracts\Mail\Mailer; @@ -274,8 +276,8 @@ final class CsvReconcileJob implements ShouldQueue private function detectAndAlertBusinessDrift( Mailer $mailer, - \Carbon\CarbonInterface $windowStart, - \Carbon\CarbonInterface $windowEnd, + CarbonInterface $windowStart, + CarbonInterface $windowEnd, ): void { $from = $windowStart->toDateString(); $to = $windowEnd->toDateString(); @@ -300,7 +302,7 @@ final class CsvReconcileJob implements ShouldQueue } $mailer->to((string) config('services.supplier.alert_email')) - ->send(new \App\Mail\TenantBusinessDriftAlertMail( + ->send(new TenantBusinessDriftAlertMail( tenantId: (int) $row->tenant_id, snapshotDate: (string) $row->snapshot_date, expected: $expected, diff --git a/app/app/Services/LeadRegionResolver.php b/app/app/Services/LeadRegionResolver.php index f1ad734d..e0b1f9b9 100644 --- a/app/app/Services/LeadRegionResolver.php +++ b/app/app/Services/LeadRegionResolver.php @@ -152,7 +152,7 @@ class LeadRegionResolver } /** - * @return array сырой ответ DaData с маскированным телефоном (§7.1) + * @return array сырой ответ DaData с маскированным телефоном (§7.1) */ private function maskResponse(DaDataPhoneResponse $response): array { diff --git a/app/database/migrations/2026_05_26_120000_add_paused_at_to_projects.php b/app/database/migrations/2026_05_26_120000_add_paused_at_to_projects.php index 51d48039..be3c8590 100644 --- a/app/database/migrations/2026_05_26_120000_add_paused_at_to_projects.php +++ b/app/database/migrations/2026_05_26_120000_add_paused_at_to_projects.php @@ -4,8 +4,8 @@ declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Schema; return new class extends Migration { diff --git a/app/database/migrations/2026_05_27_120000_create_project_routing_snapshots_table.php b/app/database/migrations/2026_05_27_120000_create_project_routing_snapshots_table.php index 44df0618..4a98c460 100644 --- a/app/database/migrations/2026_05_27_120000_create_project_routing_snapshots_table.php +++ b/app/database/migrations/2026_05_27_120000_create_project_routing_snapshots_table.php @@ -5,7 +5,8 @@ declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Support\Facades\DB; -return new class extends Migration { +return new class extends Migration +{ public function up(): void { // SET ROLE crm_migrator для прода (postgres superuser может SET ROLE). @@ -13,10 +14,10 @@ return new class extends Migration { try { DB::statement('SET ROLE crm_migrator'); $canCreate = DB::selectOne("SELECT has_schema_privilege('crm_migrator', 'public', 'CREATE') AS ok"); - if (!$canCreate || !$canCreate->ok) { + if (! $canCreate || ! $canCreate->ok) { DB::statement('RESET ROLE'); } - } catch (\Throwable) { + } catch (Throwable) { // На окружениях без роли — продолжаем как postgres superuser. } @@ -83,10 +84,10 @@ return new class extends Migration { try { DB::statement('SET ROLE crm_migrator'); $canCreate = DB::selectOne("SELECT has_schema_privilege('crm_migrator', 'public', 'CREATE') AS ok"); - if (!$canCreate || !$canCreate->ok) { + if (! $canCreate || ! $canCreate->ok) { DB::statement('RESET ROLE'); } - } catch (\Throwable) { + } catch (Throwable) { // На окружениях без роли — продолжаем как postgres superuser. } DB::statement('DROP TABLE IF EXISTS project_routing_snapshots CASCADE'); diff --git a/app/database/migrations/2026_05_31_100000_create_phone_ranges_and_resolution_log.php b/app/database/migrations/2026_05_31_100000_create_phone_ranges_and_resolution_log.php index 1d73d941..5d89ff04 100644 --- a/app/database/migrations/2026_05_31_100000_create_phone_ranges_and_resolution_log.php +++ b/app/database/migrations/2026_05_31_100000_create_phone_ranges_and_resolution_log.php @@ -5,7 +5,8 @@ declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Support\Facades\DB; -return new class extends Migration { +return new class extends Migration +{ public function up(): void { // SET ROLE crm_migrator на проде (postgres superuser может SET ROLE). @@ -14,10 +15,10 @@ return new class extends Migration { try { DB::statement('SET ROLE crm_migrator'); $canCreate = DB::selectOne("SELECT has_schema_privilege('crm_migrator', 'public', 'CREATE') AS ok"); - if (!$canCreate || !$canCreate->ok) { + if (! $canCreate || ! $canCreate->ok) { DB::statement('RESET ROLE'); } - } catch (\Throwable) { + } catch (Throwable) { // окружение без роли — продолжаем как superuser } @@ -139,10 +140,10 @@ return new class extends Migration { try { DB::statement('SET ROLE crm_migrator'); $canCreate = DB::selectOne("SELECT has_schema_privilege('crm_migrator', 'public', 'CREATE') AS ok"); - if (!$canCreate || !$canCreate->ok) { + if (! $canCreate || ! $canCreate->ok) { DB::statement('RESET ROLE'); } - } catch (\Throwable) { + } catch (Throwable) { // окружение без роли — продолжаем как superuser } diff --git a/app/resources/js/api/admin.ts b/app/resources/js/api/admin.ts index 2810cfbd..0c4a777a 100644 --- a/app/resources/js/api/admin.ts +++ b/app/resources/js/api/admin.ts @@ -351,10 +351,10 @@ export async function updateTenantStatus( reason: string, ): Promise<{ id: number; status: string }> { await ensureCsrfCookie(); - const { data } = await apiClient.patch<{ id: number; status: string }>( - `/api/admin/billing/tenants/${id}/status`, - { status, reason }, - ); + const { data } = await apiClient.patch<{ id: number; status: string }>(`/api/admin/billing/tenants/${id}/status`, { + status, + reason, + }); return data; } @@ -567,9 +567,6 @@ export async function createPdSubjectRequest(payload: CreatePdRequestPayload): P export async function executePdErasure(id: number, adminUserId?: number): Promise { await ensureCsrfCookie(); const payload = adminUserId !== undefined ? { admin_user_id: adminUserId } : {}; - const { data } = await apiClient.post( - `/api/admin/pd-subject-requests/${id}/erase`, - payload, - ); + const { data } = await apiClient.post(`/api/admin/pd-subject-requests/${id}/erase`, payload); return data; } diff --git a/app/resources/js/components/admin/TenantBalanceDialog.vue b/app/resources/js/components/admin/TenantBalanceDialog.vue index 3e21b0a4..cc21719b 100644 --- a/app/resources/js/components/admin/TenantBalanceDialog.vue +++ b/app/resources/js/components/admin/TenantBalanceDialog.vue @@ -75,11 +75,7 @@ function close(): void { diff --git a/app/resources/js/components/billing/TopupDialog.vue b/app/resources/js/components/billing/TopupDialog.vue index 7987ed33..66041618 100644 --- a/app/resources/js/components/billing/TopupDialog.vue +++ b/app/resources/js/components/billing/TopupDialog.vue @@ -26,9 +26,7 @@ const amountError = computed(() => { return null; }); -const canSubmit = computed( - () => Number.isFinite(amount.value) && amountError.value === null && !submitting.value, -); +const canSubmit = computed(() => Number.isFinite(amount.value) && amountError.value === null && !submitting.value); // Сброс состояния при каждом открытии диалога (паттерн ReminderDialog/ // NewDealDialog) — нет префилла прошлой суммы и нет всплытия устаревшей ошибки. @@ -85,20 +83,13 @@ defineExpose({ amount, submit, canSubmit, errorMsg }); />
- + {{ new Intl.NumberFormat('ru-RU').format(p) }} ₽
- Платёжный шлюз подключается после регистрации юр. лица — на текущем этапе баланс - пополняется сразу. + Платёжный шлюз подключается после регистрации юр. лица — на текущем этапе баланс пополняется сразу. diff --git a/app/resources/js/components/billing/TransactionsTable.vue b/app/resources/js/components/billing/TransactionsTable.vue index 3a566d8e..ba21c023 100644 --- a/app/resources/js/components/billing/TransactionsTable.vue +++ b/app/resources/js/components/billing/TransactionsTable.vue @@ -99,20 +99,8 @@ defineExpose({ load, refresh, changeTab, activeTab, total, rows });

История транзакций

- - + + {{ tab.label }} diff --git a/app/resources/js/components/dashboard/DashboardPageHead.vue b/app/resources/js/components/dashboard/DashboardPageHead.vue index 22d238a1..e6bb1beb 100644 --- a/app/resources/js/components/dashboard/DashboardPageHead.vue +++ b/app/resources/js/components/dashboard/DashboardPageHead.vue @@ -29,7 +29,9 @@ const greeting = computed(() => { @@ -317,7 +310,9 @@ defineExpose({ rows, loading, fetchError, loadRows }); @@ -352,13 +342,7 @@ defineExpose({ rows, loading, fetchError, loadRows }); Новое обращение субъекта ПДн - + {{ createError }} @@ -366,10 +350,10 @@ defineExpose({ rows, loading, fetchError, loadRows }); v-model="createForm.request_type" label="Тип обращения *" :items="[ - { title: 'Доступ к данным', value: 'access' }, + { title: 'Доступ к данным', value: 'access' }, { title: 'Исправление данных', value: 'rectification' }, - { title: 'Удаление данных', value: 'deletion' }, - { title: 'Возражение', value: 'objection' }, + { title: 'Удаление данных', value: 'deletion' }, + { title: 'Возражение', value: 'objection' }, ]" density="compact" variant="outlined" @@ -418,7 +402,14 @@ defineExpose({ rows, loading, fetchError, loadRows }); /> - Отмена + Отмена - - Анонимизировать данные субъекта - + Анонимизировать данные субъекта - + {{ eraseResult ? 'Закрыть' : 'Отмена' }} Удалить запланированный набор? - Запланированная сетка с {{ deleteTarget }} будет удалена. - Действие необратимо. + Запланированная сетка с {{ deleteTarget }} будет удалена. Действие необратимо. @@ -141,7 +140,13 @@