import { and, eq, lte, desc, subscriptionPlans, type Db } from "@parking/db"; import type { SubscriptionPlan } from "@parking/shared"; // Subscription-plan pricing. The PURE span math (periodsBetween / priceSubscriptionSpan // / addMonths) lives in @parking/shared so it's unit-tested alongside the tariff fee // function; here we add the DB-backed plan-version resolver. A plan is admin-composed, // versioned config (like a tariff) — the operator SELLS from it and never types a // price. See wiki/entities/subscription.md. export { periodsBetween, priceSubscriptionSpan, addMonths } from "@parking/shared"; /** Resolve the plan VERSION in force for `planId` at `asOf`: the latest active row * with effectiveFrom ≤ asOf (the tariff-resolve pattern). null when none applies. */ export function resolvePlanVersion(db: Db, planId: string, asOf: string): SubscriptionPlan | null { const row = db .select() .from(subscriptionPlans) .where( and( eq(subscriptionPlans.planId, planId), eq(subscriptionPlans.active, true), lte(subscriptionPlans.effectiveFrom, asOf), ), ) .orderBy(desc(subscriptionPlans.effectiveFrom)) .limit(1) .get(); return row ? (row as SubscriptionPlan) : null; }