diff --git a/app/super-admin/tenants/new/page.tsx b/app/super-admin/tenants/new/page.tsx index ab80186..ed474bc 100644 --- a/app/super-admin/tenants/new/page.tsx +++ b/app/super-admin/tenants/new/page.tsx @@ -15,10 +15,22 @@ export default async function NewTenantPage({ redirect("/unauthorized"); } - const [plans, params] = await Promise.all([ - prisma.subscriptionPlan.findMany({ orderBy: { priceMonthly: "asc" } }), - searchParams ?? Promise.resolve({ error: undefined }) - ]); + const params = await (searchParams ?? Promise.resolve({ error: undefined })); + let plans: Array<{ + id: string; + name: string; + code: string; + priceMonthly: number; + }> = []; + + try { + plans = await prisma.subscriptionPlan.findMany({ orderBy: { priceMonthly: "asc" } }); + } catch (error) { + console.error("[tenant/new] load plans failed", { + actorUserId: session.userId, + error: error instanceof Error ? error.message : String(error) + }); + } const error = params.error; const errorMessage = @@ -30,6 +42,10 @@ export default async function NewTenantPage({ ? "Slug tenant sudah dipakai." : error === "admin_email_exists" ? "Email admin awal sudah terpakai." + : error === "tenant_creation_failed" + ? "Tidak bisa membuat tenant, silakan cek log server untuk detail error." + : error === "plans_fetch_failed" + ? "Tidak dapat memuat daftar plan. Cek log server/DB koneksi." : null; return ( @@ -37,6 +53,11 @@ export default async function NewTenantPage({
{errorMessage ?

{errorMessage}

: null} + {plans.length === 0 ? ( +

+ Belum ada data plan. Isi dulu plan pada Catalog Plan sebelum membuat tenant. +

+ ) : null} diff --git a/lib/admin-crud.ts b/lib/admin-crud.ts index b7ffe9f..d1cc510 100644 --- a/lib/admin-crud.ts +++ b/lib/admin-crud.ts @@ -1153,13 +1153,13 @@ export async function createTenant(formData: FormData) { const session = await requireSuperAdminSession(); const auditContext = await getAuditContext(session); - const name = formValue(formData, "name"); - const companyName = formValue(formData, "companyName") || name; - const slug = formValue(formData, "slug").toLowerCase(); - const timezone = formValue(formData, "timezone"); + const name = formValue(formData, "name").trim(); + const companyName = (formValue(formData, "companyName") || name).trim(); + const slug = formValue(formData, "slug").trim().toLowerCase(); + const timezone = formValue(formData, "timezone").trim(); const planId = formValue(formData, "planId"); - const adminFullName = formValue(formData, "adminFullName") || `Admin ${name}`; - const adminEmail = formValue(formData, "adminEmail"); + const adminFullName = (formValue(formData, "adminFullName") || `Admin ${name}`).trim(); + const adminEmail = formValue(formData, "adminEmail").trim() || undefined; const adminPassword = formValue(formData, "adminPassword"); if (!name || !slug || !timezone || !planId) { @@ -1191,17 +1191,33 @@ export async function createTenant(formData: FormData) { adminEmail: string; }; - const tenantCreation = await prisma.$transaction(async (tx) => { - const createdTenant = await tx.tenant.create({ - data: { - name, - companyName: companyName || name, - slug, - timezone, - status: TenantStatus.ACTIVE, - planId - } - }); + let tenantCreation: { + tenant: { + id: string; + name: string; + slug: string; + planId: string; + timezone: string; + status: TenantStatus; + createdAt: Date; + updatedAt: Date; + companyName: string; + }; + adminInvite: AdminInvitePayload | null; + }; + + try { + tenantCreation = await prisma.$transaction(async (tx) => { + const createdTenant = await tx.tenant.create({ + data: { + name, + companyName: companyName || name, + slug, + timezone, + status: TenantStatus.ACTIVE, + planId + } + }); if (adminEmail) { const shouldInviteAdmin = !adminPassword; @@ -1243,11 +1259,21 @@ export async function createTenant(formData: FormData) { } } - return { - tenant: createdTenant, - adminInvite: null - }; - }); + return { + tenant: createdTenant, + adminInvite: null + }; + }); + } catch (error) { + console.error("[createTenant] transaction failed", { + actorUserId: session.userId, + tenantName: name, + tenantSlug: slug, + planId, + error: error instanceof Error ? error.message : String(error) + }); + redirect("/super-admin/tenants/new?error=tenant_creation_failed"); + } const tenant = tenantCreation.tenant; const adminInvite = tenantCreation.adminInvite;