Files
portal/app/tests/Feature/Jobs/RouteSupplierLeadJobSnapshotTest.php
T

135 lines
4.9 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Jobs\RouteSupplierLeadJob;
use App\Models\Project;
use App\Models\SupplierLead;
use App\Models\SupplierProject;
use App\Models\Tenant;
use App\Services\Billing\LedgerService;
use App\Services\LeadDistributor;
use App\Services\LeadRouter;
use App\Services\NotificationService;
use App\Services\RegionTagResolver;
use App\Services\SupplierProjects\SupplierProjectResolver;
use Carbon\Carbon;
use Database\Seeders\PricingTierSeeder;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SharesSupplierPdo;
uses(DatabaseTransactions::class);
uses(SharesSupplierPdo::class);
beforeEach(function (): void {
$this->seed(PricingTierSeeder::class);
DB::statement("SELECT set_config('app.current_tenant_id', '0', true)");
});
function runSnapshotRouteJob(int $supplierLeadId): void
{
(new RouteSupplierLeadJob($supplierLeadId))->handle(
app(LeadRouter::class),
app(SupplierProjectResolver::class),
app(NotificationService::class),
app(LedgerService::class),
app(LeadDistributor::class),
app(RegionTagResolver::class),
);
}
it('uses snapshot daily_limit, not live daily_limit_target (R-04/R-06)', function (): void {
Carbon::setTestNow('2026-05-28 12:00:00', 'Europe/Moscow');
$tenant = Tenant::factory()->create(['balance_rub' => '500.00', 'frozen_by_balance_at' => null]);
$project = Project::factory()->for($tenant)->create([
'is_active' => true,
'delivery_days_mask' => 127,
'daily_limit_target' => 100, // live limit big
'delivered_today' => 4,
'delivered_in_month' => 0,
]);
$sp = SupplierProject::factory()->create(['signal_type' => 'site']);
linkProjectToSupplier($project, $sp);
// Snapshot имеет МАЛЕНЬКИЙ daily_limit=5 — после доставки 1 deal'a должно стать 5.
createRoutingSnapshotFromProject(
$project,
date: '2026-05-28',
signalType: 'site',
signalIdentifier: $sp->unique_key,
dailyLimit: 5,
);
$lead = SupplierLead::factory()->create([
'supplier_project_id' => $sp->id,
'raw_payload' => ['project' => $sp->platform.'_'.$sp->unique_key, 'phones' => ['79161234567']],
'phone' => '79161234567',
'vid' => 1001,
]);
runSnapshotRouteJob($lead->id);
expect(DB::table('deals')->where('tenant_id', $tenant->id)->count())->toBe(1);
// delivered_today инкрементнут на live, delivered_count на snapshot.
expect((int) DB::table('projects')->where('id', $project->id)->value('delivered_today'))->toBe(5);
$snap = DB::table('project_routing_snapshots')
->where('snapshot_date', '2026-05-28')
->where('project_id', $project->id)
->first();
expect((int) $snap->delivered_count)->toBe(1);
Carbon::setTestNow();
});
it('rejects lead when is_active becomes false under lock (R-09)', function (): void {
Carbon::setTestNow('2026-05-28 12:00:00', 'Europe/Moscow');
$tenant = Tenant::factory()->create(['balance_rub' => '500.00', 'frozen_by_balance_at' => null]);
// Live state: is_active=true для snapshot:backfill, но потом клиент нажмёт «пауза»
// (между matchEligibleProjects и handle). Имитируем это inline UPDATE'ом.
$project = Project::factory()->for($tenant)->create([
'is_active' => true,
'delivery_days_mask' => 127,
'daily_limit_target' => 10,
'delivered_today' => 0,
'delivered_in_month' => 0,
]);
$sp = SupplierProject::factory()->create(['signal_type' => 'site']);
linkProjectToSupplier($project, $sp);
// Snapshot НЕ paused (fixed до момента pause'а).
createRoutingSnapshotFromProject(
$project,
date: '2026-05-28',
signalType: 'site',
signalIdentifier: $sp->unique_key,
dailyLimit: 10,
);
// ↓ Имитация: клиент paused проект в окне между matchEligible и handle.
DB::table('projects')->where('id', $project->id)->update(['is_active' => false]);
$lead = SupplierLead::factory()->create([
'supplier_project_id' => $sp->id,
'raw_payload' => ['project' => $sp->platform.'_'.$sp->unique_key, 'phones' => ['79161234567']],
'phone' => '79161234567',
'vid' => 1002,
]);
runSnapshotRouteJob($lead->id);
// Snapshot говорит «доставлять», но live is_active=false под lock'ом — НЕ доставляем.
expect(DB::table('deals')->where('tenant_id', $tenant->id)->count())->toBe(0);
expect((int) DB::table('projects')->where('id', $project->id)->value('delivered_today'))->toBe(0);
$snap = DB::table('project_routing_snapshots')
->where('snapshot_date', '2026-05-28')
->where('project_id', $project->id)
->first();
expect((int) $snap->delivered_count)->toBe(0);
Carbon::setTestNow();
});