/** * The provisioned expansion tracker and its trial clock. One row per expansion, written when CS * activates the device. Every scheduled sweep reads only this table. * * Trial lengths differ by arm, and `free_loaner`'s is the non-obvious one: * - `free_subscription` — `trial_end = activation + 6 months`. * - `free_loaner` — `trial_end = shipped + 75 days`, not 60. The offer is advertised as 60 days with * a 15-day return grace, and Notion US-04 is explicit that no charge applies until day 75, which * is also what the confirmation checkbox authorises. Setting the trial to the full 75 makes a * return a cancel-*during*-trial instead of a bill-then-refund, and means the subscription starts * on time without anyone having to act. * * So for a loaner `graceEndsAt === trialEndAt` by construction. Both are kept: the sweeps read * `graceEndsAt`, Stripe owns `trialEndAt`, and a divergence between them is a bug worth catching. * * At day 75 two things happen with different actors — Stripe converts the subscription by itself, * while the one-time hardware fee is an explicit call somebody has to make from the CS queue * (`billingCampaignExpansionOrder.deviceFeeChargedAt`). Only the second one can be forgotten. */ export declare class BillingCampaignExpansionDevice { id: number; /** FK to `billingCampaignExpansion.id`. */ expansionId: number; /** The expansion tracker itself. Unknown until CS activates — see `qualifyingImei` for the other one. */ imei: string | null; subscriptionId: string | null; subscriptionCreatedAt: Date | null; trialStartAt: Date | null; trialEndAt: Date | null; /** Trial flipped to active and the subscription started billing. */ convertedAt: Date | null; canceledAt: Date | null; activatedAt: Date | null; /** * `free_subscription` only — delivery + 30 days. The device has to report by then or the offer * expires and the trial subscription is cancelled. */ activationDeadlineAt: Date | null; firstPingAt: Date | null; lastPingCheckedAt: Date | null; pingDetected: boolean; /** `free_loaner` — shipped + 60 days. The advertised trial end; nothing bills here. */ returnDueAt: Date | null; /** `free_loaner` — shipped + 75 days. Equals `trialEndAt`; see the class comment. */ graceEndsAt: Date | null; /** Always a CS stamp — no system of ours observes a physical return. */ returnedAt: Date | null; /** Set when day 75 passes with no return stamped and no fee charged. Surfaced in the CS queue. */ returnNeedsManualVerification: boolean; /** `free_loaner` day 50 — keep/return reminder. */ reminderD50SentAt: Date | null; /** Informational heads-up before billing starts. No opt-out prompt on either arm. */ preBillingFyiSentAt: Date | null; csReminderSentAt: Date | null; csReminderCount: number; createdAt: Date | null; updatedAt: Date | null; }