fix(stats): count soft-deleted users in the experiment funnel
The base user query dropped soft-deleted accounts (SoftDeletes scope), so their variant assignment, connection cost and burn vanished from the report - biased asymmetrically (prod: 8/9/10 deleted across control/reduced/pay_now) and precisely on the cohort that most embodies connect-and-leave, since deleting the account is the strongest form of it. Add withTrashed().
This commit is contained in:
parent
ab3fbe38a9
commit
b8e1f9c2d8
|
|
@ -94,6 +94,10 @@ class ExperimentFunnelCollector
|
|||
$monthlyEquiv = $this->monthlyEquivByPriceId();
|
||||
|
||||
User::query()
|
||||
// Soft-deleted accounts still count: they were assigned a variant and
|
||||
// their bank connections incurred real cost, and deleting the account
|
||||
// is itself an experiment outcome (the strongest "connect and leave").
|
||||
->withTrashed()
|
||||
->where('users.created_at', '>=', $startedAt)
|
||||
->when($excluded !== [], fn ($query) => $query->whereNotIn('email', $excluded))
|
||||
->with(['subscriptions' => fn ($query) => $query->where('type', 'default')])
|
||||
|
|
|
|||
|
|
@ -173,6 +173,21 @@ it('computes connection cost, wasted burn and contribution margin', function ()
|
|||
->and($control['activationToPaidRate'])->toBe(0.5); // 1 paid ÷ 2 activated
|
||||
});
|
||||
|
||||
it('still counts soft-deleted users so their assignment and connection cost survive', function () {
|
||||
$signup = CarbonImmutable::parse('2026-06-05');
|
||||
|
||||
$user = experimentUser(SubscriptionExperiment::CONTROL, $signup, null, connections: 2);
|
||||
$user->delete(); // soft delete the account
|
||||
|
||||
$control = app(ExperimentFunnelCollector::class)->collect()['variants'][SubscriptionExperiment::CONTROL];
|
||||
|
||||
expect($control['assigned'])->toBe(1)
|
||||
->and($control['assignedMature'])->toBe(1)
|
||||
->and($control['activated'])->toBe(1) // 2 connections
|
||||
->and($control['costCents'])->toBe(80) // 2 × 40, still charged
|
||||
->and($control['wastedCostCents'])->toBe(80); // never paid → pure burn
|
||||
});
|
||||
|
||||
it('reports a matured-cohort conversion capped at 100% and prints the matured denominator', function () {
|
||||
$signup = CarbonImmutable::parse('2026-06-05'); // control matures by the test clock
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue