Files
carmanagement/docs/subscription-upgrade-implementation-plan.md
root 7b8f81336a
Build & Push / Pipeline Tests (push) Failing after 2m0s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 53s
Test / API Unit Tests (push) Successful in 1m8s
Test / Homepage Unit Tests (push) Successful in 48s
Test / Carplace Unit Tests (push) Successful in 42s
Test / Admin Unit Tests (push) Successful in 41s
Test / Dashboard Unit Tests (push) Successful in 43s
Test / API Integration Tests (push) Failing after 1m7s
add subscription upgrade plan
2026-08-10 23:23:58 -04:00

26 KiB
Raw Permalink Blame History

Subscription Upgrade Implementation Plan

1. Purpose

Implement a safe subscription-upgrade workflow for companies that already have an active plan and pay manually. The workflow must calculate a defensible upgrade amount, collect payment evidence, require platform-admin verification, activate the new plan without losing history, and communicate in the company's selected language: English (en), French (fr), or Arabic (ar).

2. Product Policy

2.1 Supported upgrade options

Option Billing treatment Activation Renewal date Availability
Upgrade now — prorated Charge the net price difference for the unused part of the current term After payment verification Unchanged Primary self-service option
Upgrade at renewal No immediate charge; schedule the new plan for the next term At renewal Existing renewal date Secondary self-service option
Upgrade now — reset term Credit eligible unused current-plan value and begin a full new term After payment verification Reset to activation date Platform-admin assisted
Temporary add-on Keep the current plan and charge for a defined feature or limit After payment verification Unchanged Out of scope until add-on rules exist

2.2 Mandatory rules

  1. A company may upgrade only from an active or grace-period subscription to a higher eligible plan.
  2. A submitted receipt is evidence, not proof of cleared payment.
  3. Upgraded access is granted only after a platform admin verifies payment.
  4. The existing subscription record and plan history must never be overwritten or deleted.
  5. Only one non-terminal upgrade request may exist per subscription.
  6. An issued quote is immutable. If it expires, create a new quote using current inputs.
  7. Upgrades, renewals, downgrades, add-ons, and plan changes made by platform admins must use distinct actions and audit events.
  8. A term reset requires explicit company confirmation because it changes the renewal date.
  9. Only company billing contacts and company admins receive customer payment communications. Do not notify every company user.
  10. All customer-facing communication uses the company's selected supported language. Arabic content must render in true RTL.

3. Scope

In scope

  • Immediate prorated upgrade.
  • Upgrade scheduled for renewal.
  • Manual payment instructions and receipt upload.
  • Platform-admin review, approval, rejection, and request-for-correction actions.
  • Plan-entitlement activation after verified payment.
  • EN, FR, and AR user interfaces and notifications.
  • Quote expiry, cancellation, audit history, idempotency, and reporting.
  • Migration-safe data changes and automated/manual testing.

Out of scope for the first release

  • Automatic card or bank collection.
  • Automatic refunds or cash credits.
  • Downgrades.
  • Temporary add-ons unless pricing, duration, renewal, and removal behavior are separately defined.
  • Mid-upgrade currency changes.
  • Self-service term resets.
  • Changing the billing cadence during a standard prorated upgrade.

4. Roles and Permissions

Action Company user Billing contact Company admin Platform admin
View current plan and available upgrades Optional Yes Yes Yes
Request an upgrade No Yes Yes Yes, on behalf of company
View quote and payment instructions No Yes Yes Yes
Upload or replace payment evidence No Yes Yes Yes
Cancel an unpaid request No Yes Yes Yes
Verify or reject payment No No No Yes
Activate an upgrade No No No System after verification
Override price, eligibility, or effective date No No No Separate privileged permission plus reason
View internal review notes No No No Yes

Enforce permissions on the server. Hiding a control in the UI is not authorization.

5. Upgrade Eligibility

The eligibility service must check all of the following before showing or quoting a target plan:

  • The subscription exists and belongs to the requesting company.
  • Subscription status is active or an explicitly supported grace_period state.
  • The target plan is active, sellable, and ranked above the current plan.
  • Current and target plans use the same currency and billing cadence for the standard prorated path.
  • The target plan supports the company's region and contractual conditions.
  • No non-terminal upgrade request already exists.
  • The subscription is not suspended for fraud, legal, or administrative reasons.
  • There is enough time remaining to justify an immediate upgrade under the configured minimum-charge policy.
  • Any company-specific contract or negotiated pricing is supported by the quote engine; otherwise route to platform-admin assistance.

Never infer that a more expensive plan is necessarily an upgrade. Use an explicit plan transition matrix or plan rank plus compatibility rules.

6. Pricing and Proration

6.1 Standard formula

Use day-based proration for a same-cadence immediate upgrade:

term_days = renewal_date - term_start_date
remaining_days = renewal_date - effective_date

remaining_new_plan_value = target_net_term_price × remaining_days ÷ term_days
remaining_current_plan_credit = eligible_current_net_term_price × remaining_days ÷ term_days

upgrade_subtotal = max(0, remaining_new_plan_value - remaining_current_plan_credit)
upgrade_total = upgrade_subtotal + taxes + explicit_fees

For a current annual price of $1,200, a target annual price of $2,400, and exactly half the term remaining:

($2,400 - $1,200) × 0.5 = $600

6.2 Pricing rules

  • Store money as integer minor units and use a fixed decimal/rounding policy. Never use binary floating point for billing.
  • Use the subscription's actual eligible net price, not merely the current public catalog price.
  • Decide explicitly whether current-plan discounts carry to the new plan. Default: they do not carry unless contractually marked transferable.
  • Calculate tax using the legally required point and method. Do not assume the simple price difference is tax-complete.
  • Define whether the effective date is the quote date, payment-received date, or approval date. Recommended: approval timestamp, with the quote calculated through a clearly stated valid-until date and recalculated if expired.
  • If partial-day precision is unnecessary, use the company's billing timezone and calendar dates consistently. Do not mix UTC timestamps with local-date proration.
  • Set a minimum charge and rounding rule per currency. If the calculated charge is below the minimum, offer upgrade at renewal or allow a documented admin waiver.
  • Store every pricing input and output in the quote snapshot so later catalog or tax changes cannot rewrite history.

6.3 Quote contents

Each quote must show and store:

  • Current plan and target plan.
  • Current term start and renewal date.
  • Proposed activation method.
  • Proration dates and fraction.
  • Current-plan eligible credit.
  • Target-plan remaining value.
  • Discounts, taxes, fees, subtotal, and total.
  • Currency and rounding result.
  • Quote creation and expiry timestamps.
  • Price-list, tax-rule, and calculation-version identifiers.
  • Terms accepted by the requesting user.

7. State Model

7.1 Upgrade request states

State Meaning Allowed next states
draft Target plan selected; quote not submitted quoted, cancelled
quoted Immutable quote issued payment_pending, expired, cancelled
payment_pending Company accepted quote and received payment instructions payment_review, expired, cancelled
payment_review Evidence submitted for platform review correction_required, approved, rejected, expired
correction_required Evidence or payment details need correction payment_review, expired, cancelled
approved Payment verified and activation transaction authorized activated, activation_failed
activated New plan and entitlements are active Terminal
scheduled Upgrade is scheduled for renewal activated, cancelled, superseded
rejected Payment or request rejected Terminal
expired Quote/request validity elapsed Terminal; requote creates a new request
cancelled Cancelled before activation Terminal
activation_failed Payment approved but activation did not complete activated through idempotent retry or manual incident resolution
superseded Scheduled request replaced by a newer valid request Terminal

Do not encode upgrade progress as the primary subscription status. Keep the subscription active on its existing plan while the upgrade request is pending.

7.2 Transition controls

  • Every transition must validate the current state to prevent stale or duplicate actions.
  • Approval and activation must be idempotent.
  • Only the activation transaction may change the active plan and entitlements.
  • approved must not become rejected; use a reversal/incident process if an approval was mistaken.
  • Scheduled upgrades must be revalidated before renewal activation.

8. Data Model

8.1 subscription_upgrade_requests

  • id
  • company_id
  • subscription_id
  • request_type (immediate_prorated, at_renewal, term_reset)
  • from_plan_id, from_plan_version_id
  • to_plan_id, to_plan_version_id
  • status
  • requested_by_user_id
  • requested_at
  • effective_at
  • scheduled_for
  • quote_id
  • company_language_snapshot
  • billing_timezone_snapshot
  • accepted_terms_version
  • accepted_at
  • cancelled_at, cancelled_by, cancellation_reason
  • expires_at
  • optimistic-lock/version column
  • created/updated timestamps

8.2 subscription_upgrade_quotes

  • id, upgrade_request_id
  • currency
  • current eligible net term price
  • target net term price
  • term start, renewal date, pricing effective date
  • term days, remaining days, proration numerator/denominator
  • current credit, target remaining value
  • discounts, taxes, fees, subtotal, total in minor units
  • calculation version and serialized input snapshot
  • created/expired timestamps
  • immutable hash or integrity field if supported

8.3 Payment evidence and review

Reuse the existing manual-payment model when possible. It must relate evidence to the exact upgrade request and quote, and record:

  • Evidence file metadata and secure storage reference.
  • Amount claimed, currency, payment method, reference number, and claimed payment date.
  • Uploader and upload time.
  • Review status, reviewer, review time, internal notes, and rejection/correction reason.
  • Verified amount and currency.
  • Malware-scan status and access controls.

Do not store sensitive full bank-account or payment-card data in notes or uploaded filenames.

8.4 subscription_plan_history

  • subscription, company, previous plan/version, new plan/version
  • change type (upgrade)
  • source upgrade request and approved payment references
  • effective timestamp
  • previous and new term dates
  • actor and approving platform admin
  • entitlement snapshot or version references
  • audit correlation ID

8.5 Constraints and indexes

  • Partial unique constraint: one non-terminal upgrade request per subscription.
  • Unique activation key per upgrade request.
  • Foreign keys to company, subscription, immutable plan versions, quote, and payment review.
  • Indexes for company/status, subscription/status, expiry, scheduled activation, and admin review queue.

9. Backend Services and API

9.1 Services

  • Eligibility service: returns permitted plan transitions and reasons for ineligibility.
  • Quote service: calculates and freezes price snapshots.
  • Upgrade workflow service: validates transitions and authorization.
  • Manual-payment service: issues instructions and manages evidence/review.
  • Activation service: atomically changes plan history, active plan/version, entitlements, and audit events.
  • Notification service: selects recipients, language, template, and channel.
  • Expiry/scheduling worker: expires quotes and activates renewal-scheduled upgrades safely.

9.2 Suggested endpoints

GET    /api/subscriptions/{id}/upgrade-options
POST   /api/subscriptions/{id}/upgrade-quotes
POST   /api/upgrade-requests/{id}/accept
POST   /api/upgrade-requests/{id}/payment-evidence
POST   /api/upgrade-requests/{id}/cancel
GET    /api/upgrade-requests/{id}

GET    /api/admin/upgrade-requests?status=payment_review
POST   /api/admin/upgrade-requests/{id}/request-correction
POST   /api/admin/upgrade-requests/{id}/approve-payment
POST   /api/admin/upgrade-requests/{id}/reject-payment
POST   /api/admin/upgrade-requests/{id}/retry-activation

Mutation endpoints must accept an idempotency key and reject stale version numbers.

9.3 Activation transaction

In one database transaction or equivalent consistency boundary:

  1. Lock the upgrade request and subscription.
  2. Confirm request state is approved and not already activated.
  3. Recheck company/subscription ownership and target-plan validity.
  4. Write the subscription plan-history record.
  5. Set the active immutable plan version.
  6. Apply new entitlements and limits.
  7. Preserve or reset term dates according to the accepted request type.
  8. Mark the request activated.
  9. Write audit/outbox events.

Send notifications after commit through an outbox/queue. A failed email must not roll back an activated subscription.

10. User Experience

10.1 Company flow

  1. Billing contact/admin opens Billing > Current plan.
  2. System displays eligible higher plans and a comparison of entitlements and limits.
  3. User selects Upgrade now or Upgrade at renewal.
  4. System displays a transparent quote, effective-date policy, renewal-date effect, and expiry.
  5. User accepts the upgrade terms.
  6. For immediate upgrade, system displays localized manual-payment instructions.
  7. User uploads payment evidence and can see review status.
  8. Platform admin reviews payment.
  9. After approval, the system activates the plan and displays confirmation, effective date, next renewal date, and new limits.

The confirmation screen must not imply immediate access before payment verification.

10.2 Platform-admin flow

  • Review queue sorted by aging and quote expiry risk.
  • Company, current/target plan, quote breakdown, claimed and expected payment, evidence, and previous attempts visible in one view.
  • Actions: approve, request correction, reject, or open company/contact record.
  • Approval requires confirmation of amount, currency, cleared-payment reference, and reviewer identity.
  • Overrides require elevated permission and a mandatory reason.
  • Approved-but-failed activations appear in a separate incident queue and must not invite a second approval.

10.3 Accessibility and responsiveness

  • Keyboard-accessible comparison, forms, uploads, dialogs, and admin actions.
  • Visible focus, descriptive validation, status announcements, and sufficient contrast.
  • Do not encode status by color alone.
  • Responsive layouts for company and admin flows.
  • Currency, dates, and numbers formatted for the selected locale while stored canonically.

11. Localization and Notifications

11.1 Language selection

  • Resolve the company's selected communication language at request creation and store a snapshot.
  • Use only en, fr, or ar; define a deliberate fallback, recommended en, and log missing translations.
  • Use company language for shared company communications. If future requirements demand per-recipient language, make that a separate policy decision.
  • Arabic templates, PDFs, email layouts, and in-app screens must use RTL layout, not merely translated strings.

11.2 Notification events

Event Company billing contact/admin Platform admin
Quote created In-app + email Optional in-app
Payment instructions issued In-app + email Optional in-app
Evidence submitted In-app confirmation In-app queue notification
Correction required In-app + email In-app status
Payment rejected In-app + email In-app status
Upgrade activated In-app + email In-app confirmation
Quote/request expiring soon In-app + email In-app for aging requests
Quote/request expired In-app + email In-app status
Activation failed after approval Generic processing message only Urgent in-app + operational alert

Templates must include company name, current and target plans, amount/currency where appropriate, quote expiry, effective-date rule, renewal-date effect, and a safe deep link. Never attach raw payment evidence to email.

12. Limits and Entitlements

Define behavior for every entitlement before implementation:

  • Higher quantitative limits become available only at activation.
  • Feature flags follow the immutable target plan version.
  • Existing usage is preserved.
  • No destructive data migration may occur during an upgrade.
  • Cache invalidation must occur immediately after commit.
  • Active sessions must receive updated authorization without requiring an unsafe manual workaround.
  • If entitlement propagation fails, mark activation as failed or partially failed according to a defined recovery policy; do not silently claim success.

13. Expiry, Cancellation, and Recovery

  • Recommended quote validity: configurable, initially 7 calendar days, capped by renewal date.
  • Send an expiry warning 48 hours before expiry when the request is still actionable.
  • Expiry workers must be idempotent and must not expire an already approved request.
  • Company cancellation is allowed only before approval/activation and does not delete history or evidence.
  • Requoting creates a new request or quote version linked to the expired one; it never mutates the expired quote.
  • A rejected payment cannot be reopened silently. Start a new review attempt or request according to the audit policy.
  • Activation retry uses the same activation key and cannot create duplicate plan history.
  • Define an operational reversal procedure for mistaken approval; do not improvise a downgrade through the upgrade endpoint.

14. Security and Audit

  • Validate company tenancy on every company endpoint.
  • Apply least-privilege permissions to payment evidence and internal notes.
  • Restrict file type and size; scan uploads before review/download.
  • Use signed, short-lived file access rather than public URLs.
  • Rate-limit quote generation, evidence uploads, and admin mutations.
  • Record actor, timestamp, previous state, next state, reason, IP/session metadata where permitted, and correlation ID for every material action.
  • Make financial/audit records append-only where practical.
  • Redact sensitive data from logs, analytics, and notification payloads.
  • Define retention rules for evidence and audit data according to applicable law and contract requirements.

15. Observability and Reporting

Track at minimum:

  • Upgrade options viewed.
  • Quote creation, acceptance, expiry, and cancellation rates.
  • Payment-review turnaround time.
  • Correction and rejection reasons.
  • Approval-to-activation latency.
  • Activation failures and retries.
  • Upgrade conversion by current plan, target plan, cadence, language, and company segment.
  • Incremental recurring/contract value, calculated from plan history rather than UI analytics.

Alert on approved requests stuck before activation, repeated worker failures, duplicate-transition errors, unusual override volume, and notification failure spikes.

16. Testing Strategy

16.1 Unit tests

  • Full, half, one-day, leap-year, and boundary-date proration.
  • Currency rounding and minimum-charge rules.
  • Discounts, taxes, fees, and negotiated-price eligibility.
  • Valid and invalid plan transitions.
  • State-transition guards and idempotency.
  • Language selection and fallback.

16.2 Integration tests

  • Quote snapshot remains unchanged after catalog price changes.
  • Duplicate active request is rejected under concurrency.
  • Evidence upload is tied to the correct company, request, and quote.
  • Only authorized platform admins can approve.
  • Approval triggers exactly one activation.
  • Activation atomically writes plan history and entitlements.
  • Notification failures do not roll back activation.
  • Expiry and scheduled-renewal workers are idempotent.
  • Stale admin screens cannot approve an already changed request.

16.3 End-to-end scenarios

  1. Immediate annual upgrade with exact half-term proration.
  2. Immediate upgrade near renewal using minimum-charge behavior.
  3. Upgrade at renewal, then successful scheduled activation.
  4. Correction required, replacement evidence, approval, and activation.
  5. Rejected evidence with no entitlement change.
  6. Quote expires before approval and requires requoting.
  7. Two admins approve concurrently; only one activation occurs.
  8. Company changes language after quote; existing communication follows the documented snapshot policy.
  9. Arabic flow verifies translations, RTL layout, dates, currency, email, and PDF/payment instructions.
  10. Activation fails after approval and succeeds through idempotent retry.
  11. Unauthorized user and cross-tenant access attempts are denied.
  12. Catalog plan changes while a quote is pending; frozen quote and plan versions remain reproducible.

16.4 Manual UI testing

  • Desktop, tablet, and mobile widths.
  • EN/FR LTR and AR RTL.
  • Light and dark themes if supported by the product.
  • Keyboard-only and screen-reader-critical flows.
  • Long French and Arabic content, large currency values, error messages, empty states, upload progress, and slow network behavior.

17. Delivery Phases

Phase 1 — Policy and contract decisions

  • Approve proration basis, effective-date rule, quote validity, minimum charges, discount transfer, tax treatment, cancellation, and admin override policy.
  • Define eligible plan transition matrix.
  • Inventory current subscription, plan, payment, role, localization, notification, and entitlement architecture.

Exit criterion: no unresolved decision can change stored financial amounts, renewal dates, or activation authorization.

Phase 2 — Data and domain foundation

  • Add upgrade request, quote, plan history, payment linkage, constraints, indexes, and migrations.
  • Implement state machine, eligibility, quote calculation, and audit events.
  • Add backfill only where required; do not fabricate historical quotes.

Exit criterion: domain and migration tests pass, including rollback/forward compatibility.

Phase 3 — Company workflow

  • Build plan comparison, quote review, acceptance, payment instructions, evidence upload, status tracking, cancellation, and scheduled-upgrade flow.
  • Add EN/FR/AR copy and RTL behavior.

Exit criterion: a company admin can complete each allowed path without platform-admin database intervention.

Phase 4 — Platform-admin workflow

  • Build review queue, evidence review, correction, rejection, approval, override controls, audit view, and activation incident queue.

Exit criterion: payment review and recovery are fully operable through authorized product interfaces.

Phase 5 — Activation and communication

  • Implement atomic activation, entitlement refresh, outbox processing, notifications, expiry worker, and scheduled-renewal activation.

Exit criterion: exactly-once business effects are demonstrated under retries and concurrent actions.

Phase 6 — Hardening and release

  • Complete security review, accessibility audit, localization QA, performance tests, operational dashboards, alerts, runbook, and staged rollout.
  • Pilot with internal/test companies before general availability.

Exit criterion: all release blockers are closed and rollback/recovery has been rehearsed.

18. Definition of Done

  • All product-policy decisions in Phase 1 are documented and approved.
  • Immediate prorated and renewal-scheduled upgrades work for eligible subscriptions.
  • Financial calculations are reproducible from immutable snapshots.
  • No upgraded feature is accessible before verified payment and successful activation.
  • Subscription and plan history are preserved and auditable.
  • Duplicate requests, duplicate approvals, and duplicate activations are prevented.
  • EN, FR, and AR flows are complete; Arabic is verified RTL.
  • Correct recipients receive localized notifications; ordinary company users do not receive billing notices.
  • Security, accessibility, automated, and manual tests pass.
  • Monitoring, alerts, support documentation, and recovery runbook are operational.
  • Release can be rolled back without corrupting active subscriptions or losing approved-payment records.

19. Decisions Required Before Coding

  1. Is proration based on calendar days, exact timestamps, or whole billing months? Recommendation: calendar days in the billing timezone.
  2. Which date controls the price: quote creation, claimed payment, cleared payment, or admin approval? Recommendation: quote is valid through a fixed expiry; after expiry, requote.
  3. How long is a quote valid? Recommendation: 7 days, capped at renewal.
  4. Are taxes included in displayed plan prices, and how is tax recomputed for upgrades?
  5. Do negotiated discounts transfer to target plans? Recommendation: only when explicitly marked transferable.
  6. What is the minimum charge per currency?
  7. Can grace-period subscriptions upgrade, or must overdue balances be cleared first? Recommendation: clear overdue balances first unless a platform admin approves a combined settlement.
  8. Can platform admins override the calculated amount? Recommendation: only with a separate permission, reason, and audit event.
  9. What happens if the company pays after quote expiry? Recommendation: do not activate automatically; reconcile payment against a new approved quote.
  10. Does the company language snapshot remain fixed for the request, or follow later company-language changes? Recommendation: snapshot financial documents; use the current company language for later status notifications only if this distinction is clearly implemented.

These are blocking business rules, not implementation details. Coding before resolving them risks incorrect charges, disputed renewal dates, and unauthorized access.