chore(cleanup): dead code removal + DemoSeeder env-conditional + schema header drift
Closes Audit #3 P2 batch (knip dead exports/components, DemoSeeder hygiene, schema header drift). - Remove app/resources/js/views/admin/AdminPlaceholderView.vue (unreferenced placeholder view — confirmed via repo-wide grep, only doc references remain) - npm uninstall concurrently (no script invoked it; --legacy-peer-deps for Histoire 1.0-beta.1 peerDep quirk) - 12 unused exports → internal types (remove `export` keyword): - api/admin.ts: AdminTenantsStats, ApiTenantMetrics, ApiAdminBillingSummary, ApiAdminIncidentsSummary - api/notifications.ts: NotificationEvent - api/reports.ts: ApiReportType, ApiReportFormat, ApiReportParameters, ReportCounts, ReportQuota - composables/mockBilling.ts: TxType - composables/useStatusPill.ts: StatusPillSlug All 12 are used INSIDE their own file (response shapes), just not exported externally — converting to internal types satisfies knip without losing type-checking inside the file. - DatabaseSeeder::run() — DemoSeeder runs only in local+testing envs (`migrate:fresh --seed` in dev now produces demo tenant + admin@demo.local + 3 projects + ~14 demo deals; prod environments skip) - db/schema.sql header line 4: «62 базовые таблицы» → «63 базовые таблицы (61 regular + 2 partitioned parents: deals + supplier_lead_costs)» Closes schema header drift finding from Phase 3. Verification: - vue-tsc --noEmit: 0 errors - ESLint on touched files: 0 errors - Pest --parallel: 742/739/3sk/0 failed (identical to baseline, no regressions) - 2243 assertions / 34.46s Plan: docs/superpowers/plans/2026-05-14-audit3-deferred-fixes.md Task 2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,13 +12,16 @@ class DatabaseSeeder extends Seeder
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*
|
||||
* Note: the Laravel scaffold default User::factory() seed was removed —
|
||||
* наша схема использует first_name/last_name (а не "name"), и заранее
|
||||
* не было сценария, где этот seed реально вызывался. PricingTierSeeder
|
||||
* (Plan 4) — единственный текущий seed для dev/testing.
|
||||
* PricingTierSeeder runs in all environments (prod нуждается в 7-tier
|
||||
* config bootstrap'е). DemoSeeder — только local+testing: создаёт demo
|
||||
* tenant + admin@demo.local + 3 проекта + ~14 demo сделок для UI smoke.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$this->call(PricingTierSeeder::class);
|
||||
|
||||
if (app()->environment('local', 'testing')) {
|
||||
$this->call(DemoSeeder::class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
-138
@@ -15,7 +15,6 @@
|
||||
"@vue/eslint-config-typescript": "^14.7.0",
|
||||
"@vue/test-utils": "^2.4.10",
|
||||
"axios": "^1.16.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^10.3.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
@@ -4319,36 +4318,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/change-case": {
|
||||
"version": "5.4.4",
|
||||
"resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz",
|
||||
@@ -4394,21 +4363,6 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@@ -4470,31 +4424,6 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
|
||||
"integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "4.1.2",
|
||||
"rxjs": "7.8.2",
|
||||
"shell-quote": "1.8.3",
|
||||
"supports-color": "8.1.1",
|
||||
"tree-kill": "1.2.2",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"conc": "dist/bin/concurrently.js",
|
||||
"concurrently": "dist/bin/concurrently.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/config-chain": {
|
||||
"version": "1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
||||
@@ -7975,16 +7904,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
@@ -9214,16 +9133,6 @@
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"tree-kill": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/trim-lines": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
||||
@@ -10103,24 +10012,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs": {
|
||||
"name": "wrap-ansi",
|
||||
"version": "7.0.0",
|
||||
@@ -10222,35 +10113,6 @@
|
||||
"url": "https://github.com/sponsors/eemeli"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
"@vue/eslint-config-typescript": "^14.7.0",
|
||||
"@vue/test-utils": "^2.4.10",
|
||||
"axios": "^1.16.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^10.3.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
|
||||
@@ -113,7 +113,7 @@ export interface AdminTenant {
|
||||
created_at: string | null;
|
||||
}
|
||||
|
||||
export interface AdminTenantsStats {
|
||||
interface AdminTenantsStats {
|
||||
total: number;
|
||||
active: number;
|
||||
trial: number;
|
||||
@@ -182,7 +182,7 @@ export interface ApiTenantActivityEvent {
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface ApiTenantMetrics {
|
||||
interface ApiTenantMetrics {
|
||||
leads_today: number;
|
||||
leads_this_week: number;
|
||||
leads_this_month: number;
|
||||
@@ -224,7 +224,7 @@ export interface ApiAdminBillingTenant {
|
||||
chargeback_unrecovered_rub: string;
|
||||
}
|
||||
|
||||
export interface ApiAdminBillingSummary {
|
||||
interface ApiAdminBillingSummary {
|
||||
total_mrr_rub: string;
|
||||
monthly_revenue_rub: string;
|
||||
overdue_count: number;
|
||||
@@ -262,7 +262,7 @@ export interface ApiAdminIncident {
|
||||
rkn_deadline_at: string | null;
|
||||
}
|
||||
|
||||
export interface ApiAdminIncidentsSummary {
|
||||
interface ApiAdminIncidentsSummary {
|
||||
open: number;
|
||||
investigating: number;
|
||||
rkn_pending: number;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { apiClient, ensureCsrfCookie } from './client';
|
||||
* Mutating-вызовы (mark-read/mark-all-read/destroy) делают ensureCsrfCookie().
|
||||
*/
|
||||
|
||||
export type NotificationEvent =
|
||||
type NotificationEvent =
|
||||
| 'new_lead'
|
||||
| 'reminder'
|
||||
| 'low_balance'
|
||||
|
||||
@@ -12,11 +12,11 @@ import { apiClient, ensureCsrfCookie } from './client';
|
||||
|
||||
export type ApiReportStatus = 'pending' | 'processing' | 'done' | 'failed';
|
||||
|
||||
export type ApiReportType = 'deals_export' | 'managers_summary' | 'sources_summary' | 'billing_summary';
|
||||
type ApiReportType = 'deals_export' | 'managers_summary' | 'sources_summary' | 'billing_summary';
|
||||
|
||||
export type ApiReportFormat = 'csv' | 'xlsx' | 'json' | 'pdf';
|
||||
type ApiReportFormat = 'csv' | 'xlsx' | 'json' | 'pdf';
|
||||
|
||||
export interface ApiReportParameters {
|
||||
interface ApiReportParameters {
|
||||
format: ApiReportFormat;
|
||||
date_from: string;
|
||||
date_to: string;
|
||||
@@ -43,14 +43,14 @@ export interface ApiReportJob {
|
||||
retry_max: number;
|
||||
}
|
||||
|
||||
export interface ReportCounts {
|
||||
interface ReportCounts {
|
||||
pending: number;
|
||||
processing: number;
|
||||
done: number;
|
||||
failed: number;
|
||||
}
|
||||
|
||||
export interface ReportQuota {
|
||||
interface ReportQuota {
|
||||
active: number;
|
||||
max_active: number;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* - invoices (§4.5): type ∈ {invoice, upd}, format ∈ {pdf, xml_1c83}.
|
||||
*/
|
||||
|
||||
export type TxType = 'topup' | 'lead_charge' | 'refund' | 'tariff_charge';
|
||||
type TxType = 'topup' | 'lead_charge' | 'refund' | 'tariff_charge';
|
||||
export type TxStatus = 'pending' | 'completed' | 'rejected';
|
||||
|
||||
export interface BillingTransaction {
|
||||
|
||||
@@ -28,7 +28,7 @@ export const STATUS_PILL_SLUGS = [
|
||||
'archived',
|
||||
] as const;
|
||||
|
||||
export type StatusPillSlug = (typeof STATUS_PILL_SLUGS)[number];
|
||||
type StatusPillSlug = (typeof STATUS_PILL_SLUGS)[number];
|
||||
|
||||
const STYLES: Record<StatusPillSlug, PillStyle> = {
|
||||
new: { bg: 'rgba(15,110,86,0.12)', color: '#0F6E56' },
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* Универсальный placeholder для ещё-не-реализованных admin-разделов
|
||||
* (Биллинг / Инциденты / Система). Конфигурация через `route.meta.title`
|
||||
* и `route.meta.description`.
|
||||
*/
|
||||
import { computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const title = computed(() => (route.meta.title as string | undefined) ?? 'Раздел');
|
||||
const description = computed(
|
||||
() => (route.meta.description as string | undefined) ?? 'Раздел в разработке. Реализуется в следующих коммитах.',
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-container fluid class="admin-placeholder pa-6">
|
||||
<header class="page-head mb-4">
|
||||
<h1 class="text-h4 page-title">{{ title }}</h1>
|
||||
</header>
|
||||
<v-alert type="info" variant="tonal" density="compact">
|
||||
<strong>В разработке.</strong> {{ description }}
|
||||
</v-alert>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.admin-placeholder {
|
||||
max-width: 1200px;
|
||||
}
|
||||
.page-title {
|
||||
font-variation-settings: 'opsz' 28;
|
||||
letter-spacing: -0.018em;
|
||||
}
|
||||
</style>
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
-- =============================================================================
|
||||
-- schema.sql — единая схема БД для SaaS-аналога crm.bp-gr.ru («Лидерра»)
|
||||
-- Версия: v8.20 (11.05.2026 — Plan 5 frontend projects UI: projects.archived_at TIMESTAMPTZ NULL для soft archive flow; tenants.limits JSONB NOT NULL DEFAULT '{}' для per-tenant project/user лимитов)
|
||||
-- Метрики: 62 базовые таблицы + 12 партиций / 117 индексов / 39 RLS-политик / 5 функций / 13 триггеров
|
||||
-- Метрики: 63 базовые таблицы (61 regular + 2 partitioned parents: deals + supplier_lead_costs) + 12 партиций / 117 индексов / 39 RLS-политик / 5 функций / 13 триггеров
|
||||
-- Базовая версия: v8.19 (11.05.2026 — Plan 4 billing+csv+admin: tenants.delivered_in_month, lead_charges.charge_source + CHECK, supplier_leads.recovered_from_csv_at, supplier_csv_reconcile_log)
|
||||
-- Базовая версия: v8.18 (10.05.2026 — Plan 2/5 Task 1: supplier_leads SaaS-level + projects.delivered_today + 2 system_settings rows для supplier-webhook + IP allowlist defense-in-depth)
|
||||
-- Базовая версия: v8.17 (10.05.2026 — Plan 1/5 Task 2 fix: FK projects.supplier_b{1,2,3}_project_id → supplier_projects (ON DELETE SET NULL) + 3 partial index + CHECK chk_projects_b1_not_for_sms (defense-in-depth дублирует chk_supplier_projects_b1_not_for_sms на Project-уровне). Закрывает code-review BLOCKER#1 + WARNING#3 от 10.05.2026 поздний вечер)
|
||||
|
||||
Reference in New Issue
Block a user