diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/layout-menu.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/layout-menu.tsx
index 16c905ce..3f0d51ef 100644
--- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/layout-menu.tsx
+++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/layout-menu.tsx
@@ -135,7 +135,8 @@ export default function LayoutMenu({
Subscription expired
- {differenceInDays(new Date(), subscriptionEndsAt)} days ago
+ You can still use OpenPanel but you won't have access to new
+ incoming data.
diff --git a/packages/db/src/services/organization.service.ts b/packages/db/src/services/organization.service.ts
index 3a9f6895..66f8dfae 100644
--- a/packages/db/src/services/organization.service.ts
+++ b/packages/db/src/services/organization.service.ts
@@ -237,3 +237,22 @@ export const getOrganizationBillingEventsCountSerieCached = cacheable(
getOrganizationBillingEventsCountSerie,
60 * 10,
);
+
+export async function getOrganizationSubscriptionChartEndDate(
+ projectId: string,
+ endDate: string,
+) {
+ const organization = await getOrganizationByProjectIdCached(projectId);
+ if (!organization) {
+ return null;
+ }
+ // If the current period end date is after the subscription chart end date, we need to use the subscription chart end date
+ if (
+ organization.subscriptionChartEndDate &&
+ new Date(endDate) > organization.subscriptionChartEndDate
+ ) {
+ return organization.subscriptionChartEndDate.toISOString();
+ }
+
+ return endDate;
+}
diff --git a/packages/trpc/src/routers/chart.helpers.ts b/packages/trpc/src/routers/chart.helpers.ts
index b0fd17d6..0218fb27 100644
--- a/packages/trpc/src/routers/chart.helpers.ts
+++ b/packages/trpc/src/routers/chart.helpers.ts
@@ -38,6 +38,7 @@ import {
getEventFiltersWhereClause,
getOrganizationByProjectId,
getOrganizationByProjectIdCached,
+ getOrganizationSubscriptionChartEndDate,
getProfiles,
} from '@openpanel/db';
import type {
@@ -509,23 +510,16 @@ export async function getChartSeries(input: IChartInputWithDates) {
}
export async function getChart(input: IChartInput) {
- const organization = await getOrganizationByProjectIdCached(input.projectId);
-
- if (!organization) {
- throw TRPCNotFoundError(
- `Organization not found by project id ${input.projectId} in getChart`,
- );
- }
-
const currentPeriod = getChartStartEndDate(input);
const previousPeriod = getChartPrevStartEndDate(currentPeriod);
- // If the current period end date is after the subscription chart end date, we need to use the subscription chart end date
- if (
- organization.subscriptionChartEndDate &&
- new Date(currentPeriod.endDate) > organization.subscriptionChartEndDate
- ) {
- currentPeriod.endDate = organization.subscriptionChartEndDate.toISOString();
+ const endDate = await getOrganizationSubscriptionChartEndDate(
+ input.projectId,
+ currentPeriod.endDate,
+ );
+
+ if (endDate) {
+ currentPeriod.endDate = endDate;
}
const promises = [getChartSeries({ ...input, ...currentPeriod })];
diff --git a/packages/trpc/src/routers/overview.ts b/packages/trpc/src/routers/overview.ts
index 2eb37014..81310623 100644
--- a/packages/trpc/src/routers/overview.ts
+++ b/packages/trpc/src/routers/overview.ts
@@ -1,10 +1,13 @@
import {
+ getOrganizationByProjectIdCached,
+ getOrganizationSubscriptionChartEndDate,
overviewService,
zGetMetricsInput,
zGetTopGenericInput,
zGetTopPagesInput,
} from '@openpanel/db';
import { type IChartRange, zRange } from '@openpanel/validation';
+import { TRPCError } from '@trpc/server';
import { z } from 'zod';
import { cacheMiddleware, createTRPCRouter, publicProcedure } from '../trpc';
import {
@@ -29,6 +32,7 @@ function getCurrentAndPrevious<
startDate?: string | null;
endDate?: string | null;
range: IChartRange;
+ projectId: string;
},
>(input: T, fetchPrevious = false) {
const current = getChartStartEndDate(input);
@@ -40,6 +44,13 @@ function getCurrentAndPrevious<
current: R;
previous: R | null;
}> => {
+ const endDate = await getOrganizationSubscriptionChartEndDate(
+ input.projectId,
+ current.endDate,
+ );
+ if (endDate) {
+ current.endDate = endDate;
+ }
const res = await Promise.all([
fn({
...input,