250 lines
5.6 KiB
TypeScript
250 lines
5.6 KiB
TypeScript
/**
|
|
* Queries de usuários usando Prisma
|
|
* Migrado de lib/db/queries/users.ts
|
|
*/
|
|
|
|
import type { User } from "@prisma/client";
|
|
import { prisma } from "../app";
|
|
import { getDefaultSubscriptionTier } from "./subscription-tiers";
|
|
|
|
export interface CreateUserData {
|
|
username: string;
|
|
email: string;
|
|
password_hash: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
phone?: string;
|
|
cpf?: string;
|
|
}
|
|
|
|
export interface UpdateUserData {
|
|
first_name?: string;
|
|
last_name?: string;
|
|
phone?: string;
|
|
whatsapp_notifications?: boolean;
|
|
subscription_tier_id?: number | null;
|
|
}
|
|
|
|
/**
|
|
* Cria um novo usuário
|
|
*/
|
|
export async function createUser(
|
|
data: CreateUserData,
|
|
): Promise<{ userId: number; username: string; email: string }> {
|
|
const defaultTier = await getDefaultSubscriptionTier();
|
|
const user = await prisma.user.create({
|
|
data: {
|
|
username: data.username,
|
|
email: data.email,
|
|
password_hash: data.password_hash,
|
|
first_name: data.first_name,
|
|
last_name: data.last_name,
|
|
phone: data.phone || null,
|
|
cpf: data.cpf || null,
|
|
subscription_tier_id: defaultTier?.subscription_tier_id ?? undefined,
|
|
},
|
|
select: {
|
|
user_id: true,
|
|
username: true,
|
|
email: true,
|
|
},
|
|
});
|
|
|
|
return {
|
|
userId: user.user_id,
|
|
username: user.username,
|
|
email: user.email,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Busca usuário por email (inclui password_hash para login)
|
|
*/
|
|
type UserWithTier = User & {
|
|
subscription_tier?: {
|
|
subscription_tier_id: number;
|
|
name: string;
|
|
slug: string;
|
|
level: number;
|
|
} | null;
|
|
};
|
|
|
|
export async function getUserByEmail(
|
|
email: string,
|
|
): Promise<UserWithTier | null> {
|
|
return (await prisma.user.findUnique({
|
|
where: { email },
|
|
include: {
|
|
subscription_tier: {
|
|
select: {
|
|
subscription_tier_id: true,
|
|
name: true,
|
|
slug: true,
|
|
level: true,
|
|
},
|
|
},
|
|
},
|
|
})) as UserWithTier | null;
|
|
}
|
|
|
|
/**
|
|
* Busca usuário por username
|
|
*/
|
|
export async function getUserByUsername(
|
|
username: string,
|
|
): Promise<UserWithTier | null> {
|
|
return (await prisma.user.findUnique({
|
|
where: { username },
|
|
include: {
|
|
subscription_tier: {
|
|
select: {
|
|
subscription_tier_id: true,
|
|
name: true,
|
|
slug: true,
|
|
level: true,
|
|
},
|
|
},
|
|
},
|
|
})) as UserWithTier | null;
|
|
}
|
|
|
|
/**
|
|
* Busca usuário por ID (sem password_hash)
|
|
*/
|
|
type PublicUser = {
|
|
user_id: number;
|
|
username: string;
|
|
email: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
phone: string | null;
|
|
cpf: string | null;
|
|
account_level: string;
|
|
has_donated: boolean;
|
|
whatsapp_notifications: boolean;
|
|
created_at: Date;
|
|
updated_at: Date;
|
|
last_login: Date | null;
|
|
is_active: boolean;
|
|
is_verified: boolean;
|
|
subscription_tier?: {
|
|
subscription_tier_id: number;
|
|
name: string;
|
|
slug: string;
|
|
level: number;
|
|
} | null;
|
|
};
|
|
|
|
export async function getUserById(userId: number): Promise<PublicUser | null> {
|
|
return (await prisma.user.findUnique({
|
|
where: { user_id: userId },
|
|
select: {
|
|
user_id: true,
|
|
username: true,
|
|
email: true,
|
|
first_name: true,
|
|
last_name: true,
|
|
phone: true,
|
|
cpf: true,
|
|
account_level: true,
|
|
has_donated: true,
|
|
whatsapp_notifications: true,
|
|
created_at: true,
|
|
updated_at: true,
|
|
last_login: true,
|
|
is_active: true,
|
|
is_verified: true,
|
|
subscription_tier: {
|
|
select: {
|
|
subscription_tier_id: true,
|
|
name: true,
|
|
slug: true,
|
|
level: true,
|
|
},
|
|
},
|
|
},
|
|
})) as PublicUser | null;
|
|
}
|
|
|
|
/**
|
|
* Busca usuário por CPF (verifica duplicidade)
|
|
*/
|
|
export async function getUserByCpf(
|
|
cpf: string,
|
|
): Promise<Pick<User, "user_id" | "username" | "email"> | null> {
|
|
return (await prisma.user.findUnique({
|
|
where: { cpf },
|
|
select: {
|
|
user_id: true,
|
|
username: true,
|
|
email: true,
|
|
},
|
|
})) as Pick<User, "user_id" | "username" | "email"> | null;
|
|
}
|
|
|
|
/**
|
|
* Atualiza dados do usuário
|
|
*/
|
|
export async function updateUser(
|
|
userId: number,
|
|
data: UpdateUserData,
|
|
): Promise<PublicUser> {
|
|
const updateData: any = {};
|
|
if (data.first_name !== undefined) updateData.first_name = data.first_name;
|
|
if (data.last_name !== undefined) updateData.last_name = data.last_name;
|
|
if (data.phone !== undefined) updateData.phone = data.phone || null;
|
|
if (data.whatsapp_notifications !== undefined)
|
|
updateData.whatsapp_notifications = data.whatsapp_notifications;
|
|
if (data.subscription_tier_id !== undefined) {
|
|
if (data.subscription_tier_id === null) {
|
|
updateData.subscription_tier = { disconnect: true };
|
|
} else {
|
|
updateData.subscription_tier = {
|
|
connect: { subscription_tier_id: data.subscription_tier_id },
|
|
};
|
|
}
|
|
}
|
|
|
|
const user = await prisma.user.update({
|
|
where: { user_id: userId },
|
|
data: updateData,
|
|
select: {
|
|
user_id: true,
|
|
username: true,
|
|
email: true,
|
|
first_name: true,
|
|
last_name: true,
|
|
phone: true,
|
|
cpf: true,
|
|
account_level: true,
|
|
has_donated: true,
|
|
whatsapp_notifications: true,
|
|
created_at: true,
|
|
updated_at: true,
|
|
last_login: true,
|
|
is_active: true,
|
|
is_verified: true,
|
|
subscription_tier: {
|
|
select: {
|
|
subscription_tier_id: true,
|
|
name: true,
|
|
slug: true,
|
|
level: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
return user as PublicUser;
|
|
}
|
|
|
|
/**
|
|
* Atualiza timestamp de último login
|
|
*/
|
|
export async function updateLastLogin(userId: number): Promise<void> {
|
|
await prisma.user.update({
|
|
where: { user_id: userId },
|
|
data: { last_login: new Date() },
|
|
});
|
|
}
|