diff --git a/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx b/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx index d5ea97cfa5..784fa5d926 100644 --- a/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx +++ b/apps/web/src/app/admin/coding-plans/CodingPlansOperationsContent.tsx @@ -611,6 +611,8 @@ type AdminCodingPlanSubscriptionItem = { canceledAt: string | null; createdAt: string; costKiloCredits: number; + inventoryKeyId: string | null; + upstreamPlanId: string | null; }; const INVENTORY_STATUS_ORDER = [ @@ -1092,6 +1094,7 @@ function SubscriptionsTable({ User Subscription Provider / plan + Inventory / upstream Status Billing date Price @@ -1101,13 +1104,13 @@ function SubscriptionsTable({ {isError ? ( - + Unable to load subscriptions. ) : items.length === 0 ? ( - + {isLoading ? 'Loading subscriptions...' : 'No subscriptions recorded.'} @@ -1121,6 +1124,8 @@ function SubscriptionsTable({ : formatDateLabel(billingDate.date); const canCancel = item.status === 'active' && !item.cancelAtPeriodEnd; const canExtend = item.status === 'active'; + const inventoryKeyId = item.inventoryKeyId; + const upstreamPlanId = item.upstreamPlanId; return ( @@ -1153,6 +1158,44 @@ function SubscriptionsTable({
{item.providerName}
{item.planName}
+ +
+ + Inventory key + + {inventoryKeyId ?? '—'} + {inventoryKeyId ? ( + + ) : null} +
+
+ + Upstream plan + + {upstreamPlanId ?? '—'} + {upstreamPlanId ? ( + + ) : null} +
+
@@ -1219,11 +1262,15 @@ function SubscriptionsTable({ } async function copySubscriptionId(subscriptionId: string): Promise { + await copyIdentifier(subscriptionId, 'Subscription ID'); +} + +async function copyIdentifier(value: string, label: string): Promise { try { - await navigator.clipboard.writeText(subscriptionId); - toast.success('Subscription ID copied'); + await navigator.clipboard.writeText(value); + toast.success(`${label} copied`); } catch { - toast.error('Failed to copy subscription ID'); + toast.error(`Failed to copy ${label.toLowerCase()}`); } } diff --git a/apps/web/src/routers/coding-plans-router.test.ts b/apps/web/src/routers/coding-plans-router.test.ts index 9ba54d8934..fc281ae3ec 100644 --- a/apps/web/src/routers/coding-plans-router.test.ts +++ b/apps/web/src/routers/coding-plans-router.test.ts @@ -1073,6 +1073,31 @@ describe('coding plans router', () => { expect(secondPage.pagination).toEqual({ page: 2, total: 23, totalPages: 2 }); }); + it('includes inventory and upstream plan identifiers in admin subscriptions', async () => { + const admin = await insertTestUser({ is_admin: true }); + const user = await insertTestUser(); + const inventory = await insertInventory({ + status: 'assigned', + assigned_to_user_id: user.id, + upstream_plan_id: 'upstream-plan-admin-display', + }); + await db.insert(coding_plan_subscriptions).values( + subscriptionValues(user.id, { + key_inventory_id: inventory.id, + }) + ); + const caller = await createCallerForUser(admin.id); + + const result = await caller.codingPlans.adminListSubscriptions({}); + + expect(result.items).toEqual([ + expect.objectContaining({ + inventoryKeyId: inventory.id, + upstreamPlanId: 'upstream-plan-admin-display', + }), + ]); + }); + it('searches admin subscriptions by user id and email substring', async () => { const admin = await insertTestUser({ is_admin: true }); const emailUser = await insertTestUser({ diff --git a/apps/web/src/routers/coding-plans-router.ts b/apps/web/src/routers/coding-plans-router.ts index 2ebe107a4d..c42b45897f 100644 --- a/apps/web/src/routers/coding-plans-router.ts +++ b/apps/web/src/routers/coding-plans-router.ts @@ -604,6 +604,7 @@ export const codingPlansRouter = createTRPCRouter({ const subscriptions = await db .select({ ...codingPlanSubscriptionColumns, + upstreamPlanId: coding_plan_key_inventory.upstream_plan_id, userName: kilocode_users.google_user_name, userEmail: kilocode_users.google_user_email, }) @@ -624,6 +625,8 @@ export const codingPlansRouter = createTRPCRouter({ userId: subscription.userId, userName: subscription.userName, userEmail: subscription.userEmail, + inventoryKeyId: subscription.keyInventoryId, + upstreamPlanId: subscription.upstreamPlanId, })), pagination: { page, total, totalPages }, };