Skip to content

feat(trials): add per-plan configurable trial periods with conversion (#1722) - #1839

Merged
github-actions[bot] merged 3 commits into
Smartdevs17:mainfrom
Clement-coder:feat/1722-per-plan-trial-periods
Oct 19, 2026
Merged

github-actions[bot] merged 3 commits into
Smartdevs17:mainfrom
Clement-coder:feat/1722-per-plan-trial-periods

Conversation

@Clement-coder

Copy link
Copy Markdown
Contributor

Summary

Resolves #1722. Trial length was hardcoded to 14 days for every plan. This PR makes it fully configurable per plan and adds automatic trial-to-paid conversion at expiry.


Changes

backend/subscription/domain/trialManagementService.ts

New: PlanTrialConfig interface

interface PlanTrialConfig {
  planId: string;
  trialDurationDays: number;   // must be > 0
  autoConvertOnExpiry: boolean;
  description?: string;
}

New methods on TrialManagementService

  • registerPlanTrialConfig(config) — register or replace a plan's trial policy; validates trialDurationDays > 0
  • getPlanTrialConfig(planId) — retrieve config; returns undefined if not registered
  • listPlanTrialConfigs() — enumerate all registered configs

Updated: startTrial() — duration resolution order:

  1. Explicit durationDays param (call-site override)
  2. Registered PlanTrialConfig.trialDurationDays for the plan
  3. DEFAULT_TRIAL_DURATION_DAYS (14) — global fallback, preserves all existing behaviour

Updated: processExpirations() — now returns { converted: TrialRecord[], expired: TrialRecord[] }:

  • When a plan has autoConvertOnExpiry: true → sets status = 'converted', conversionTrigger = 'automatic_time_based', emits trial_converted + payment_completed events
  • Otherwise → sets status = 'expired', emits trial_expired (previous behaviour)
  • Trials not yet past endDate and already-terminal trials are skipped

backend/migrations/006_plan_trial_configs.sql

  • plan_trial_configs table with plan_id FK, trial_duration_days CHECK (> 0), auto_convert_on_expiry, description, timestamps
  • Auto-update trigger for updated_at
  • @down rollback section
  • Migration dry-run: 0 errors

backend/subscription/__tests__/trialManagementService.test.ts

  • Fixed existing processExpirations test to destructure { expired, converted }
  • Added 18 new tests covering all three acceptance criteria

Acceptance criteria

  • Length configurable per plan (registerPlanTrialConfig + PlanTrialConfig.trialDurationDays)
  • Converts to paid at expiry (processExpirations auto-converts when autoConvertOnExpiry: true)
  • Tested (36/36 tests pass: 18 existing + 18 new)

Test output

Tests: 36 passed, 36 total

github-actions Bot and others added 3 commits October 19, 2026 11:10
…Smartdevs17#1722)

Trials were hardcoded to 14 days globally. This PR makes trial length
and auto-conversion configurable per subscription plan.

Changes to backend/subscription/domain/trialManagementService.ts:
- Add PlanTrialConfig interface (planId, trialDurationDays, autoConvertOnExpiry)
- Add DEFAULT_TRIAL_DURATION_DAYS = 14 constant
- Add planTrialConfigs Map to TrialManagementService
- Add registerPlanTrialConfig() — register/replace a plan's trial policy;
  validates trialDurationDays is a positive finite number
- Add getPlanTrialConfig() / listPlanTrialConfigs() accessors
- Update startTrial() duration resolution order:
    1. explicit durationDays param (call-site override)
    2. registered PlanTrialConfig for the planId
    3. DEFAULT_TRIAL_DURATION_DAYS (14) global fallback
- Update processExpirations() to auto-convert instead of expiring when
  the plan's autoConvertOnExpiry is true; returns { converted, expired }
  so callers can act on each group; records trial_converted +
  payment_completed events on auto-convert

Add backend/migrations/006_plan_trial_configs.sql:
- plan_trial_configs table (plan_id FK, trial_duration_days CHECK > 0,
  auto_convert_on_expiry, description, timestamps)
- auto-update trigger for updated_at
- @down rollback section

Update backend/subscription/__tests__/trialManagementService.test.ts:
- Fix existing processExpirations test to destructure { expired, converted }
- Add 18 new tests covering:
    registerPlanTrialConfig / getPlanTrialConfig (6 tests)
    startTrial per-plan duration resolution (4 tests)
    processExpirations auto-convert on expiry (8 tests)

Tests: 36 passed, 36 total (18 existing + 18 new)

Closes Smartdevs17#1722
@drips-wave

drips-wave Bot commented Oct 19, 2026

Copy link
Copy Markdown

@Clement-coder Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@github-actions
github-actions Bot merged commit 9ab1775 into Smartdevs17:main Oct 19, 2026
12 of 31 checks passed
@Clement-coder
Clement-coder deployed to security-review October 19, 2026 12:35 — with GitHub Actions Active

This branch was successfully deployed

1 active deployment
security-review — a764c8d3 Deployed Oct 19, 2026 by Clement-coder via Security Dashboard #1392
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add trial periods with configurable length per plan

1 participant