diff --git a/app/Console/Commands/SendAiCohortReportCommand.php b/app/Console/Commands/SendAiCohortReportCommand.php index dda26f0a..2d28911f 100644 --- a/app/Console/Commands/SendAiCohortReportCommand.php +++ b/app/Console/Commands/SendAiCohortReportCommand.php @@ -23,6 +23,12 @@ class SendAiCohortReportCommand extends Command public function handle(): int { + if (! config('subscriptions.enabled')) { + $this->info('Subscriptions are disabled; skipping the AI cohort report.'); + + return self::SUCCESS; + } + $weeks = $this->option('weeks') !== null ? (int) $this->option('weeks') : null; $report = $this->collector->collect($weeks); diff --git a/app/Console/Commands/SendDailyStatsReportCommand.php b/app/Console/Commands/SendDailyStatsReportCommand.php index 64b2e545..ad284618 100644 --- a/app/Console/Commands/SendDailyStatsReportCommand.php +++ b/app/Console/Commands/SendDailyStatsReportCommand.php @@ -30,6 +30,12 @@ class SendDailyStatsReportCommand extends Command public function handle(): int { + if (! config('subscriptions.enabled')) { + $this->info('Subscriptions are disabled; skipping the daily stats report.'); + + return self::SUCCESS; + } + try { $stats = $this->collector->collect(); } catch (ApiErrorException $exception) { diff --git a/app/Console/Commands/SendExperimentFunnelReportCommand.php b/app/Console/Commands/SendExperimentFunnelReportCommand.php index 56f56b2f..37859c29 100644 --- a/app/Console/Commands/SendExperimentFunnelReportCommand.php +++ b/app/Console/Commands/SendExperimentFunnelReportCommand.php @@ -34,6 +34,12 @@ class SendExperimentFunnelReportCommand extends Command public function handle(): int { + if (! config('subscriptions.enabled')) { + $this->info('Subscriptions are disabled; skipping the experiment funnel report.'); + + return self::SUCCESS; + } + $costPerConnectionCents = (int) round(((float) $this->option('cost-per-connection')) * 100); $report = $this->collector->collect($costPerConnectionCents); diff --git a/app/Console/Commands/SendSubscriptionFunnelReportCommand.php b/app/Console/Commands/SendSubscriptionFunnelReportCommand.php index e8541d9b..bf91525a 100644 --- a/app/Console/Commands/SendSubscriptionFunnelReportCommand.php +++ b/app/Console/Commands/SendSubscriptionFunnelReportCommand.php @@ -19,6 +19,12 @@ class SendSubscriptionFunnelReportCommand extends Command public function handle(): int { + if (! config('subscriptions.enabled')) { + $this->info('Subscriptions are disabled; skipping the subscription funnel report.'); + + return self::SUCCESS; + } + $weeks = $this->option('weeks') !== null ? (int) $this->option('weeks') : null; $report = $this->collector->collect($weeks); diff --git a/docker/supervisor/supervisord.conf b/docker/supervisor/supervisord.conf index 9f7bd766..7ff9b7e1 100644 --- a/docker/supervisor/supervisord.conf +++ b/docker/supervisor/supervisord.conf @@ -87,3 +87,14 @@ redirect_stderr=true stdout_logfile=/var/log/queue-worker-ai.log stopwaitsecs=3600 numprocs=2 + +[program:scheduler] +process_name=%(program_name)s +command=php /app/artisan schedule:work +user=www-data +autostart=true +autorestart=true +redirect_stderr=true +stdout_logfile=/var/log/scheduler.log +stopwaitsecs=60 +numprocs=1 diff --git a/tests/Feature/SendAiCohortReportCommandTest.php b/tests/Feature/SendAiCohortReportCommandTest.php index 4f97cde4..73b0baf3 100644 --- a/tests/Feature/SendAiCohortReportCommandTest.php +++ b/tests/Feature/SendAiCohortReportCommandTest.php @@ -76,10 +76,23 @@ function rowForWeek(array $report, CarbonImmutable $signup): array beforeEach(function () { Carbon::setTestNow(referenceNow()); + config(['subscriptions.enabled' => true]); config(['ai_suggestions.eligibility_min_transactions' => 3]); config(['ai_suggestions.report.excluded_emails' => []]); }); +it('skips the report and hits no external service when subscriptions are disabled', function () { + config(['subscriptions.enabled' => false]); + + Http::fake(); + + artisan('stats:ai-cohort-report') + ->expectsOutputToContain('Subscriptions are disabled; skipping the AI cohort report.') + ->assertSuccessful(); + + Http::assertNothingSent(); +}); + it('only counts users who imported enough transactions within their first week', function () { $signup = referenceNow()->subWeeks(6); diff --git a/tests/Feature/SendDailyStatsReportCommandTest.php b/tests/Feature/SendDailyStatsReportCommandTest.php index 953720c6..37f13280 100644 --- a/tests/Feature/SendDailyStatsReportCommandTest.php +++ b/tests/Feature/SendDailyStatsReportCommandTest.php @@ -5,9 +5,22 @@ use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Http; beforeEach(function () { + config()->set('subscriptions.enabled', true); config()->set('services.discord.webhook_url', 'https://discord.test/webhook'); }); +test('skips the report and hits no external service when subscriptions are disabled', function () { + config()->set('subscriptions.enabled', false); + + Http::fake(); + + $this->artisan('stats:daily-report') + ->expectsOutputToContain('Subscriptions are disabled; skipping the daily stats report.') + ->assertSuccessful(); + + Http::assertNothingSent(); +}); + test('posts yesterday user counts and stripe stats to discord', function () { Http::fake(); bindMockStripeClientForStats([ diff --git a/tests/Feature/SendExperimentFunnelReportCommandTest.php b/tests/Feature/SendExperimentFunnelReportCommandTest.php index b5ea26c9..58dd1e00 100644 --- a/tests/Feature/SendExperimentFunnelReportCommandTest.php +++ b/tests/Feature/SendExperimentFunnelReportCommandTest.php @@ -31,6 +31,18 @@ beforeEach(function () { Cache::put('experiment_funnel_monthly_equiv', ['price_test' => 399], now()->addHour()); }); +it('skips the report and hits no external service when subscriptions are disabled', function () { + config(['subscriptions.enabled' => false]); + + Http::fake(); + + artisan('stats:experiment-funnel') + ->expectsOutputToContain('Subscriptions are disabled; skipping the experiment funnel report.') + ->assertSuccessful(); + + Http::assertNothingSent(); +}); + /** * Create a user whose id buckets into the wanted variant, anchored to a signup, * with an optional default subscription and any bank connections / AI consent diff --git a/tests/Feature/SendSubscriptionFunnelReportCommandTest.php b/tests/Feature/SendSubscriptionFunnelReportCommandTest.php index 4e001cd1..a11f8654 100644 --- a/tests/Feature/SendSubscriptionFunnelReportCommandTest.php +++ b/tests/Feature/SendSubscriptionFunnelReportCommandTest.php @@ -59,9 +59,22 @@ function funnelRow(array $report, CarbonImmutable $signup): array beforeEach(function () { Carbon::setTestNow(funnelNow()); + config(['subscriptions.enabled' => true]); config(['ai_suggestions.report.excluded_emails' => []]); }); +it('skips the report and hits no external service when subscriptions are disabled', function () { + config(['subscriptions.enabled' => false]); + + Http::fake(); + + artisan('stats:subscription-funnel') + ->expectsOutputToContain('Subscriptions are disabled; skipping the subscription funnel report.') + ->assertSuccessful(); + + Http::assertNothingSent(); +}); + it('counts registrations, subscriptions and paid conversions per signup week', function () { $signup = funnelNow()->subWeeks(10); // old enough to be paid-mature