Repository navigation
feat: per-plan cancellation reasons, renewal reminders, lifecycle history, regional tax - #1846
Merged
github-actions[bot] merged 4 commits intoOct 19, 2026
Conversation
…tdevs17#1728) Plans can register their own cancellation-reason vocabulary and opt in to requiring a reason; unconfigured plans keep the default list and stay optional. Analytics aggregates cancellations by plan and reason and can be filtered to a single plan via GET /cancellation/analytics?planId=. Closes Smartdevs17#1728
…es (Smartdevs17#1730) Reminder lead times (default 30/7/1 days) are now readable and updatable at runtime through GET/PUT /api/v1/calendar/reminders/config. A per-subscription notificationsEnabled flag and an isReminderEnabled(userId, eventType) hook let account-level notification preferences suppress individual reminder types. Closes Smartdevs17#1730
…s17#1729) Every subscription state transition (created, updated, price changed, plan changed, paused, resumed, cancelled) is recorded with a timestamp in the subscription store and shown as a timeline on the detail screen. The history is persisted with the store and exportable as CSV from the UI. Closes Smartdevs17#1729
Region rates are configurable in TaxService (configureRegionRate) with overrides taking precedence over built-in rates and falling back across state/city keys. generateInvoice accepts a region, applies the resolved rate at invoice time, records tax_region/tax_type (migration 016) and labels tax separately on the PDF and in invoice emails. Closes Smartdevs17#1732
|
@OkeyAmy 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! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements four Stellar Wave features as four self-contained commits:
566aac122ff7ab9cacf01f1f65c9No dependency, lockfile or build-config changes.
#1728 — Add per-plan cancellation reasons
CancellationService.configurePlanReasons()registers a per-plan vocabulary (with optionalrequireReason), exposed asGET/PUT /cancellation/plans/:planId/reasonsbyPlanandbyPlanReason;GET /cancellation/analyticsaccepts an optional?planId=filterrequireReason#1730 — Add renewal reminders at T-7 and T-1
GET/PUT /api/v1/calendar/reminders/config(getConfig()/configure()on the scheduler)notificationsEnabledplus an injectableisReminderEnabled(userId, eventType)preference hook#1729 — Add lifecycle state history timeline
subscriptionStorerecordscreated/updated/price_changed/plan_changed/paused/resumed/cancelledevents with timestamps and details, persisted alongside subscriptions (with migration/normalisation of stored state)src/utils/lifecycleHistory.ts#1732 — Add regional tax and VAT calculation
TaxService.configureRegionRate()/getRegionRate()/listRegionRates()overrides, resolved ahead of the existing state/city lookup (resolveRegionTaxRate)generateInvoiceacceptsregion, resolves the rate when no explicittaxRateis given, and persiststax_region/tax_typeviadb/migrations/016_invoice_tax_region.sql(with a-- @downrollback section)Tax (VAT 19.0% · DE)) on the generated PDF and in the invoice email, keeping it distinct from the subtotal/totalVerification
cancellationService,RenewalReminderScheduler,taxService,invoiceGeneration,invoiceControllerAGENTS.md):lifecycleHistory,subscriptionLifecycleHistorymain(the 4 errors / 5 warnings reported there are identical onmain)mainon both configs: roottsc --noEmit(616 pre-existing) andbackend/tsconfig.json(215 pre-existing)Checklist
Notes
cancellationRouterandinvoiceControllerare still not mounted increateApiServer.ts(pre-existing); the new routes/behaviour follow the existing conventions of those modules./api/v1/calendar/reminders/config.Closes #1728
Closes #1730
Closes #1729
Closes #1732