From 786f7962230741d42657cf82e33aee95d1b7d4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Sun, 28 Jun 2026 12:49:52 +0300 Subject: [PATCH] =?UTF-8?q?feat(=D0=B0=D0=B2=D1=82=D0=BE=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=B1=D0=BE=D1=80):=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= =?UTF-8?q?=D0=B0=20autopodbor=5Fcompetitors=20+=20RLS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- ...8_100100_create_autopodbor_competitors.php | 43 +++++++++++++++++++ .../AutopodborCompetitorsSchemaTest.php | 11 +++++ 2 files changed, 54 insertions(+) create mode 100644 app/database/migrations/2026_06_28_100100_create_autopodbor_competitors.php create mode 100644 app/tests/Feature/Autopodbor/AutopodborCompetitorsSchemaTest.php diff --git a/app/database/migrations/2026_06_28_100100_create_autopodbor_competitors.php b/app/database/migrations/2026_06_28_100100_create_autopodbor_competitors.php new file mode 100644 index 00000000..610df0ed --- /dev/null +++ b/app/database/migrations/2026_06_28_100100_create_autopodbor_competitors.php @@ -0,0 +1,43 @@ +bigIncrements('id'); + $table->unsignedBigInteger('tenant_id'); + $table->unsignedBigInteger('search_run_id')->nullable(); + $table->string('name', 255); + $table->text('description')->nullable(); + $table->boolean('is_federal')->default(false); + $table->smallInteger('relevance_pct')->nullable(); + $table->string('origin', 16)->default('auto'); // auto|manual|resolve + $table->string('site_url', 255)->nullable(); + $table->jsonb('directory_urls')->default(DB::raw("'[]'::jsonb")); + $table->jsonb('provenance')->default(DB::raw("'{}'::jsonb")); + $table->string('dedup_key', 255); + $table->unsignedBigInteger('study_run_id')->nullable(); + $table->timestampTz('studied_at')->nullable(); + $table->timestampTz('created_at')->useCurrent(); + + $table->foreign('tenant_id')->references('id')->on('tenants')->cascadeOnDelete(); + $table->foreign('search_run_id')->references('id')->on('autopodbor_runs')->nullOnDelete(); + $table->foreign('study_run_id')->references('id')->on('autopodbor_runs')->nullOnDelete(); + $table->index(['tenant_id', 'search_run_id']); + $table->unique(['tenant_id', 'search_run_id', 'dedup_key'], 'autopodbor_competitor_dedup'); + }); + + DB::statement('ALTER TABLE autopodbor_competitors ENABLE ROW LEVEL SECURITY'); + DB::statement('ALTER TABLE autopodbor_competitors FORCE ROW LEVEL SECURITY'); + DB::statement("CREATE POLICY tenant_isolation ON autopodbor_competitors USING (tenant_id = current_setting('app.current_tenant_id')::bigint)"); + } + + public function down(): void + { + Schema::dropIfExists('autopodbor_competitors'); + } +}; diff --git a/app/tests/Feature/Autopodbor/AutopodborCompetitorsSchemaTest.php b/app/tests/Feature/Autopodbor/AutopodborCompetitorsSchemaTest.php new file mode 100644 index 00000000..6b82a156 --- /dev/null +++ b/app/tests/Feature/Autopodbor/AutopodborCompetitorsSchemaTest.php @@ -0,0 +1,11 @@ +hasTable('autopodbor_competitors'))->toBeTrue(); + expect(DB::getSchemaBuilder()->hasColumns('autopodbor_competitors', [ + 'id','tenant_id','search_run_id','name','description','is_federal', + 'relevance_pct','origin','site_url','directory_urls','provenance', + 'dedup_key','study_run_id','studied_at','created_at', + ]))->toBeTrue(); +});