Fijar trial a 14 días en alta de tenant y reforzar filtro por tenant en escrituras

This commit is contained in:
Carlos Narro
2026-05-30 20:02:02 +02:00
parent 4f48b1591c
commit b84b2f37a2
3 changed files with 9 additions and 15 deletions

View File

@@ -45,7 +45,10 @@ export async function marcarGanado(leadId: string, precioFinalEuros: number) {
const finalCents = Math.round(precioFinalEuros * 100); const finalCents = Math.round(precioFinalEuros * 100);
const deltaPct = ((finalCents - lead.presupuestoEstimado) / lead.presupuestoEstimado) * 100; const deltaPct = ((finalCents - lead.presupuestoEstimado) / lead.presupuestoEstimado) * 100;
await db.update(leads).set({ estado: 'ganado', updatedAt: new Date() }).where(eq(leads.id, leadId)); await db
.update(leads)
.set({ estado: 'ganado', updatedAt: new Date() })
.where(and(eq(leads.id, leadId), eq(leads.tenantId, tenantId)));
await db.insert(leadEstadoHistory).values({ leadId, estado: 'ganado' }); await db.insert(leadEstadoHistory).values({ leadId, estado: 'ganado' });
await db.insert(precisionHistory).values({ await db.insert(precisionHistory).values({
leadId, leadId,
@@ -88,7 +91,7 @@ export async function recalcularPresupuesto(leadId: string) {
desgloseSnapshot: { stage: lead.pipelineStage, result }, desgloseSnapshot: { stage: lead.pipelineStage, result },
updatedAt: new Date(), updatedAt: new Date(),
}) })
.where(eq(leads.id, leadId)); .where(and(eq(leads.id, leadId), eq(leads.tenantId, tenantId)));
await db.insert(leadPipelineEventos).values({ await db.insert(leadPipelineEventos).values({
leadId, leadId,

View File

@@ -1,16 +1,11 @@
'use server'; 'use server';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
import { eq } from 'drizzle-orm';
import { db } from '@/db';
import { tenants } from '@/db/schema';
import { signupSchema, slugify } from '@/lib/validation/signup'; import { signupSchema, slugify } from '@/lib/validation/signup';
import { getUserByEmail, createTenantWithOwner, slugDisponible } from '@/db/auth-queries'; import { getUserByEmail, createTenantWithOwner, slugDisponible } from '@/db/auth-queries';
import { hashPassword } from '@/lib/auth/password'; import { hashPassword } from '@/lib/auth/password';
import { createSession } from '@/lib/auth/session'; import { createSession } from '@/lib/auth/session';
const TRIAL_MS = 14 * 24 * 60 * 60 * 1000;
export async function signup(_prev: string | null, formData: FormData): Promise<string | null> { export async function signup(_prev: string | null, formData: FormData): Promise<string | null> {
const parsed = signupSchema.safeParse(Object.fromEntries(formData)); const parsed = signupSchema.safeParse(Object.fromEntries(formData));
if (!parsed.success) return parsed.error.issues[0]?.message ?? 'Datos no válidos.'; if (!parsed.success) return parsed.error.issues[0]?.message ?? 'Datos no válidos.';
@@ -23,7 +18,7 @@ export async function signup(_prev: string | null, formData: FormData): Promise<
while (!(await slugDisponible(slug))) slug = `${slugify(data.empresa)}-${++n}`; while (!(await slugDisponible(slug))) slug = `${slugify(data.empresa)}-${++n}`;
const passwordHash = await hashPassword(data.password); const passwordHash = await hashPassword(data.password);
const { tenant, user } = await createTenantWithOwner({ const { user } = await createTenantWithOwner({
nombreEmpresa: data.empresa, nombreEmpresa: data.empresa,
slug, slug,
provincia: data.provincia, provincia: data.provincia,
@@ -32,11 +27,6 @@ export async function signup(_prev: string | null, formData: FormData): Promise<
nombre: data.nombre, nombre: data.nombre,
}); });
await db
.update(tenants)
.set({ trialEndsAt: new Date(Date.now() + TRIAL_MS) })
.where(eq(tenants.id, tenant.id));
await createSession(user.id); await createSession(user.id);
redirect('/panel'); redirect('/panel');
} }

View File

@@ -1,7 +1,8 @@
import { eq } from 'drizzle-orm'; import { eq } from 'drizzle-orm';
import { db } from './index'; import { db } from './index';
import { users, tenants } from './schema'; import { users, tenants } from './schema';
import { sessionExpiry } from '@/lib/auth/tokens';
const TRIAL_MS = 14 * 24 * 60 * 60 * 1000;
export async function getUserByEmail(email: string) { export async function getUserByEmail(email: string) {
const [row] = await db.select().from(users).where(eq(users.email, email)).limit(1); const [row] = await db.select().from(users).where(eq(users.email, email)).limit(1);
@@ -28,7 +29,7 @@ export async function createTenantWithOwner(input: {
nombreEmpresa: input.nombreEmpresa, nombreEmpresa: input.nombreEmpresa,
provincia: input.provincia, provincia: input.provincia,
subscriptionStatus: 'trial', subscriptionStatus: 'trial',
trialEndsAt: sessionExpiry(new Date()), trialEndsAt: new Date(Date.now() + TRIAL_MS),
}) })
.returning(); .returning();