From 92fd88964e7861a517bc5d114755da0b3ca5d073 Mon Sep 17 00:00:00 2001 From: dmitriylaukhin Date: Sat, 11 Jul 2026 19:41:49 +0500 Subject: [PATCH] Accept buyer phone in grant API and enrich existing users payment-router now forwards name/phone from the order. Store phone on create; for existing users fill name (when it is an email placeholder) and phone (when empty) without overwriting meaningful data. Also stop dropping the parsed phone column in CSV import. --- src/app/admin/import-export/import-actions.ts | 7 +++++++ src/app/api/internal/grant/route.ts | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/app/admin/import-export/import-actions.ts b/src/app/admin/import-export/import-actions.ts index 1a45fb0..d714629 100644 --- a/src/app/admin/import-export/import-actions.ts +++ b/src/app/admin/import-export/import-actions.ts @@ -200,6 +200,7 @@ export async function applyImport( data: { name: row.name, email: row.email, + phone: row.phone || null, emailVerified: options.autoVerifyEmail, role: "student", }, @@ -231,10 +232,16 @@ export async function applyImport( created++; } else if (row.status === "update" && row.existingId) { + const existing = await prisma.user.findUnique({ + where: { id: row.existingId }, + select: { phone: true }, + }); await prisma.user.update({ where: { id: row.existingId }, data: { name: row.name || undefined, + // don't overwrite an already-filled phone + phone: existing?.phone ? undefined : row.phone || undefined, }, }); diff --git a/src/app/api/internal/grant/route.ts b/src/app/api/internal/grant/route.ts index a5d87aa..101ab68 100644 --- a/src/app/api/internal/grant/route.ts +++ b/src/app/api/internal/grant/route.ts @@ -19,6 +19,7 @@ export async function POST(request: NextRequest) { let body: { email?: string; name?: string; + phone?: string; course_slugs?: string[]; order_id?: string; }; @@ -30,6 +31,7 @@ export async function POST(request: NextRequest) { const email = (body.email ?? "").trim().toLowerCase(); const name = (body.name ?? "").trim(); + const phone = (body.phone ?? "").trim().slice(0, 30); const slugs = Array.isArray(body.course_slugs) ? body.course_slugs.filter((s) => typeof s === "string" && s.trim()) : []; @@ -66,7 +68,7 @@ export async function POST(request: NextRequest) { // Find or create user let user = await prisma.user.findFirst({ where: { email: { equals: email, mode: "insensitive" } }, - select: { id: true, name: true }, + select: { id: true, name: true, email: true, phone: true }, }); let tempPassword: string | null = null; if (!user) { @@ -76,14 +78,25 @@ export async function POST(request: NextRequest) { data: { email, name: name || email, + phone: phone || null, emailVerified: true, mustChangePassword: true, accounts: { create: { accountId: email, providerId: "credential", password: hash }, }, }, - select: { id: true, name: true }, + select: { id: true, name: true, email: true, phone: true }, }); + } else { + // Enrich existing user from the order, never overwriting meaningful data: + // name only if the current one is empty or an email placeholder, phone only if empty. + const enrich: { name?: string; phone?: string } = {}; + if (name && (!user.name || user.name === user.email)) enrich.name = name; + if (phone && !user.phone) enrich.phone = phone; + if (Object.keys(enrich).length > 0) { + await prisma.user.update({ where: { id: user.id }, data: enrich }); + if (enrich.name) user.name = enrich.name; + } } // Enroll + audit log