'X']); $firm->warmup_started_at = Carbon::parse('2026-07-18 12:00:00'); // 4 дня назад $decider = new PlatformWarmingDecider; $long = new SalesAdAudiencePlatform(['platform' => 'yandex']); $long->warmup_days = 5; $short = new SalesAdAudiencePlatform(['platform' => 'vk']); $short->warmup_days = 3; expect($decider->decide($firm, $long, null, $now)['state'])->toBe('active'); $shortDecision = $decider->decide($firm, $short, null, $now); expect($shortDecision['state'])->toBe('stopped'); expect($shortDecision['reason'])->toBe('ready_for_manager'); }); it('flat active: строка канала mode=flat, flat_days больше прошедшего срока — active', function () { $now = CarbonImmutable::parse('2026-07-22 12:00:00'); $firm = new SalesAdAudienceFirm(['firm_name' => 'X']); $platform = new SalesAdAudiencePlatform(['platform' => 'yandex']); $platform->warmup_days = 3; $row = new SalesAdAudienceFirmChannel([ 'channel' => 'yandex', 'status' => 'warming', 'mode' => 'flat', 'flat_days' => 10, ]); $row->warming_started_at = Carbon::parse('2026-07-18 12:00:00'); // 4 дня назад $decider = new PlatformWarmingDecider; $decision = $decider->decideForChannelRow($firm, $platform, null, $row, $now); expect($decision['state'])->toBe('active'); }); it('flat done: строка канала mode=flat, flat_days меньше прошедшего срока — stopped(flat_done)', function () { $now = CarbonImmutable::parse('2026-07-22 12:00:00'); $firm = new SalesAdAudienceFirm(['firm_name' => 'X']); $platform = new SalesAdAudiencePlatform(['platform' => 'yandex']); $platform->warmup_days = 3; $row = new SalesAdAudienceFirmChannel([ 'channel' => 'yandex', 'status' => 'warming', 'mode' => 'flat', 'flat_days' => 3, ]); $row->warming_started_at = Carbon::parse('2026-07-17 12:00:00'); // 5 дней назад $decider = new PlatformWarmingDecider; $decision = $decider->decideForChannelRow($firm, $platform, null, $row, $now); expect($decision['state'])->toBe('stopped'); expect($decision['reason'])->toBe('flat_done'); }); it('funnel из строки: срок берётся из warming_started_at строки канала, не из firm.warmup_started_at', function () { $now = CarbonImmutable::parse('2026-07-22 12:00:00'); $firm = new SalesAdAudienceFirm(['firm_name' => 'X']); // Умышленно НЕ ставим firm->warmup_started_at — decideForChannelRow должен // взять срок из строки канала, а не из фирмы. $platform = new SalesAdAudiencePlatform(['platform' => 'yandex']); $platform->warmup_days = 3; $decider = new PlatformWarmingDecider; $rowActive = new SalesAdAudienceFirmChannel([ 'channel' => 'yandex', 'status' => 'warming', 'mode' => 'funnel', ]); $rowActive->warming_started_at = Carbon::parse('2026-07-20 12:00:00'); // 2 дня назад $activeDecision = $decider->decideForChannelRow($firm, $platform, null, $rowActive, $now); expect($activeDecision['state'])->toBe('active'); $rowStopped = new SalesAdAudienceFirmChannel([ 'channel' => 'yandex', 'status' => 'warming', 'mode' => 'funnel', ]); $rowStopped->warming_started_at = Carbon::parse('2026-07-17 12:00:00'); // 5 дней назад $stoppedDecision = $decider->decideForChannelRow($firm, $platform, null, $rowStopped, $now); expect($stoppedDecision['state'])->toBe('stopped'); expect($stoppedDecision['reason'])->toBe('ready_for_manager'); });