This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { getSessionUser } from "@/lib/session";
|
||||
import { listAllInvoiceDrafts } from "@/lib/db";
|
||||
import { getOrgBilling, listAllInvoiceDrafts } from "@/lib/db";
|
||||
import { listTenants } from "@/lib/k8s";
|
||||
import { BackLink } from "@/components/ui/back-link";
|
||||
import { DraftList } from "@/components/admin/billing/draft-list";
|
||||
@@ -14,9 +14,9 @@ import { DraftList } from "@/components/admin/billing/draft-list";
|
||||
* an invoice; visible only to platform admins. From here the admin
|
||||
* can resume editing or discard.
|
||||
*
|
||||
* Building an org-name map by reading tenant labels (same approach
|
||||
* as the existing /admin/billing/orgs endpoint) so the table can
|
||||
* show "Customer X" instead of a raw ZITADEL org id.
|
||||
* Building an org-name map by reading tenant labels (for the set of
|
||||
* known orgs) + getOrgBilling per org (for the actual company name)
|
||||
* so the table can show "Customer X" instead of a raw ZITADEL org id.
|
||||
*/
|
||||
export default async function AdminInvoiceDraftsPage() {
|
||||
const user = await getSessionUser();
|
||||
@@ -29,16 +29,30 @@ export default async function AdminInvoiceDraftsPage() {
|
||||
listTenants().catch(() => []),
|
||||
]);
|
||||
|
||||
// Build org-id → company-name map from tenant labels. Same shape
|
||||
// the existing /api/admin/billing/orgs uses. Falls back to the
|
||||
// raw org id when we don't have a tenant label match.
|
||||
// Build the set of distinct ZITADEL org ids from tenant labels,
|
||||
// PLUS the set referenced by any current draft. Drafts may target
|
||||
// orgs that don't have tenants yet (rare but possible), so we
|
||||
// union both sources before fetching billing rows.
|
||||
const orgIds = new Set<string>();
|
||||
for (const tnt of tenants) {
|
||||
const oid = tnt.metadata.labels?.["pieced.ch/zitadel-org-id"];
|
||||
if (oid) orgIds.add(oid);
|
||||
}
|
||||
for (const d of drafts) {
|
||||
orgIds.add(d.zitadelOrgId);
|
||||
}
|
||||
// Look up billing in parallel — same pattern as
|
||||
// /api/admin/billing/orgs uses. Failure for any single org is
|
||||
// non-fatal (falls back to the raw id in the table).
|
||||
const orgNamePairs = await Promise.all(
|
||||
Array.from(orgIds).map(async (oid) => {
|
||||
const billing = await getOrgBilling(oid).catch(() => null);
|
||||
return [oid, billing?.companyName ?? null] as const;
|
||||
})
|
||||
);
|
||||
const orgNameMap: Record<string, string> = {};
|
||||
for (const t of tenants) {
|
||||
const oid = t.metadata.labels?.["pieced.ch/zitadel-org-id"];
|
||||
const company = t.spec?.billing?.companyName;
|
||||
if (oid && company && !orgNameMap[oid]) {
|
||||
orgNameMap[oid] = company;
|
||||
}
|
||||
for (const [oid, name] of orgNamePairs) {
|
||||
if (name) orgNameMap[oid] = name;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user