Merge pull request #25 from CoralMinister/feat/slepok-stage-1

Feat/slepok stage 1
This commit is contained in:
CoralMinister
2026-05-27 04:58:23 +03:00
committed by GitHub
5 changed files with 119 additions and 14 deletions
@@ -59,19 +59,14 @@ class CleanupInactiveSupplierProjectsJob implements ShouldQueue
{
$client ??= app(SupplierPortalClient::class);
// Подзапрос — DISTINCT id'шники supplier_projects, на которые ссылается
// хотя бы один Лидерра-project с is_active=true через любой из трёх FK.
// Источник истинности активности — `project_supplier_links` pivot (Plan 3+).
// Legacy FK `supplier_b{1,2,3}_project_id` оставлены для read-compat,
// но не определяют активность.
$activeIdsSubquery = <<<'SQL'
SELECT DISTINCT id FROM (
SELECT supplier_b1_project_id AS id FROM projects
WHERE is_active = true AND supplier_b1_project_id IS NOT NULL
UNION
SELECT supplier_b2_project_id FROM projects
WHERE is_active = true AND supplier_b2_project_id IS NOT NULL
UNION
SELECT supplier_b3_project_id FROM projects
WHERE is_active = true AND supplier_b3_project_id IS NOT NULL
) AS active_supplier_ids
SELECT DISTINCT psl.supplier_project_id AS id
FROM project_supplier_links psl
INNER JOIN projects p ON p.id = psl.project_id
WHERE p.is_active = true
SQL;
// Phase A — re-activate (СНАЧАЛА для safety: до Phase C, чтобы недавно
+2 -2
View File
@@ -63,7 +63,7 @@ class LeadRouter
AND EXISTS (
SELECT 1 FROM tenants
WHERE tenants.id = projects.tenant_id
AND (tenants.balance_leads > 0 OR tenants.balance_rub > 0)
AND tenants.balance_rub > 0
)
ORDER BY
projects.tenant_id,
@@ -94,7 +94,7 @@ class LeadRouter
AND EXISTS (
SELECT 1 FROM tenants
WHERE tenants.id = projects.tenant_id
AND (tenants.balance_leads > 0 OR tenants.balance_rub > 0)
AND tenants.balance_rub > 0
)
ORDER BY
projects.tenant_id,
@@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
use App\Models\Project;
use App\Models\SupplierProject;
use App\Models\Tenant;
use App\Services\LeadRouter;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SharesSupplierPdo;
uses(DatabaseTransactions::class);
uses(SharesSupplierPdo::class);
beforeEach(function (): void {
// Clear tenant context — LeadRouter operates without it (sharing across tenants).
DB::statement("SELECT set_config('app.current_tenant_id', '0', true)");
});
it('does not match project for tenant with only balance_leads (no balance_rub)', function () {
$tenant = Tenant::factory()->create([
'balance_rub' => '0.00',
'balance_leads' => 999, // legacy — должно игнорироваться после фикса
]);
$project = Project::factory()->for($tenant)->create([
'is_active' => true,
'delivery_days_mask' => 127,
'daily_limit_target' => 10,
'delivered_today' => 0,
]);
$sp = SupplierProject::factory()->create();
\DB::table('project_supplier_links')->insert([
'project_id' => $project->id,
'supplier_project_id' => $sp->id,
'platform' => $sp->platform,
'subject_code' => null,
]);
$matched = app(LeadRouter::class)->matchEligibleProjects($sp);
expect($matched)->toHaveCount(0); // balance_rub=0 → не eligible
});
it('matches project for tenant with balance_rub > 0 (balance_leads ignored)', function () {
$tenant = Tenant::factory()->create([
'balance_rub' => '500.00',
'balance_leads' => 0,
]);
$project = Project::factory()->for($tenant)->create([
'is_active' => true,
'delivery_days_mask' => 127,
'daily_limit_target' => 10,
'delivered_today' => 0,
]);
$sp = SupplierProject::factory()->create();
\DB::table('project_supplier_links')->insert([
'project_id' => $project->id,
'supplier_project_id' => $sp->id,
'platform' => $sp->platform,
'subject_code' => null,
]);
$matched = app(LeadRouter::class)->matchEligibleProjects($sp);
expect($matched)->toHaveCount(1);
});
@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
use App\Jobs\Supplier\CleanupInactiveSupplierProjectsJob;
use App\Models\Project;
use App\Models\SupplierProject;
use App\Models\Tenant;
it('does not mark inactive supplier_project that has pivot link to active project', function () {
$tenant = Tenant::factory()->create();
$project = Project::factory()->for($tenant)->create([
'is_active' => true,
// легаси FK НЕ заполнены (Plan 3+ архитектура):
'supplier_b1_project_id' => null,
'supplier_b2_project_id' => null,
'supplier_b3_project_id' => null,
]);
$sp = SupplierProject::factory()->create([
'inactive_since' => null,
]);
\DB::table('project_supplier_links')->insert([
'project_id' => $project->id,
'supplier_project_id' => $sp->id,
'platform' => $sp->platform,
'subject_code' => null,
]);
(new CleanupInactiveSupplierProjectsJob)->handle(app(\App\Services\Supplier\SupplierPortalClient::class));
expect($sp->fresh()->inactive_since)->toBeNull();
});
it('marks supplier_project inactive when no pivot link exists', function () {
$sp = SupplierProject::factory()->create(['inactive_since' => null]);
// нет project_supplier_links
(new CleanupInactiveSupplierProjectsJob)->handle(app(\App\Services\Supplier\SupplierPortalClient::class));
expect($sp->fresh()->inactive_since)->not->toBeNull();
});
+2
View File
File diff suppressed because one or more lines are too long