From fa30fe2cff6d7bffeb8b25fd73ad46ee23ca906b Mon Sep 17 00:00:00 2001 From: Jose Selesan Date: Thu, 17 Sep 2026 18:58:00 -0300 Subject: [PATCH] Renamed Student to Attendee --- AGENTS.md | 2 +- .../migration.sql | 16 +++++ apps/backend/prisma/models/domain.prisma | 58 +++++++++---------- apps/backend/src/app.ts | 4 +- .../attendees/features/get-all/route.ts | 18 ++++++ .../features/get-all/use-case.ts | 22 +++---- apps/backend/src/modules/attendees/index.ts | 1 + .../modules/{students => attendees}/routes.ts | 0 .../payments/features/get-all/use-case.ts | 4 +- .../students/features/get-all/route.ts | 18 ------ apps/backend/src/modules/students/index.ts | 1 - .../{students.test.ts => attendees.test.ts} | 38 ++++++------ apps/backend/test/payments.test.ts | 8 +-- apps/backend/test/session-auth.test.ts | 2 +- .../onboarding/ConfirmationStep.tsx | 4 +- .../src/components/onboarding/PaymentStep.tsx | 2 +- .../src/components/onboarding/WelcomeStep.tsx | 2 +- apps/web/src/routes/groups.tsx | 2 +- packages/shared/src/index.ts | 2 +- .../src/schemas/{students.ts => attendees.ts} | 14 ++--- packages/shared/src/schemas/payments.ts | 2 +- stack.md | 4 +- 22 files changed, 120 insertions(+), 104 deletions(-) create mode 100644 apps/backend/prisma/migrations/20260917120000_rename_student_to_attendee/migration.sql create mode 100644 apps/backend/src/modules/attendees/features/get-all/route.ts rename apps/backend/src/modules/{students => attendees}/features/get-all/use-case.ts (67%) create mode 100644 apps/backend/src/modules/attendees/index.ts rename apps/backend/src/modules/{students => attendees}/routes.ts (100%) delete mode 100644 apps/backend/src/modules/students/features/get-all/route.ts delete mode 100644 apps/backend/src/modules/students/index.ts rename apps/backend/test/{students.test.ts => attendees.test.ts} (60%) rename packages/shared/src/schemas/{students.ts => attendees.ts} (66%) diff --git a/AGENTS.md b/AGENTS.md index 95ab8cb..353cc9e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,7 +30,7 @@ bun --filter @gruperly/backend db:* # db:generate / db:migrate / db:push - `src/modules//` — por módulo: `index.ts`, `routes.ts` y `features//{route,use-case}.ts`. **Patrón**: el route valida (`validate.query/json`) y delega en un use-case que devuelve `Result` (`ok`/`err` desde `@gruperly/shared`); el route responde con `resultJson` (o `problemJson`). - `src/lib/` — `prisma.ts` (`getPrismaClient`, proxy `default` y clase `UnitOfWork`), `pagination.ts` (offset/metadata), `email.ts`, `error-message.ts`. - `src/logger.ts` — pino + pino-pretty. - - Módulos existentes: `health-check`, `auth` (**Better Auth 1.7.2 público**, montado en `/api/v1/auth` vía `basePath` del server; cookie de sesión con `path: "/"`), `groups`, `students`, `payments`, `waitlist` (listados paginados `{ data, pagination }`). + - Módulos existentes: `health-check`, `auth` (**Better Auth 1.7.2 público**, montado en `/api/v1/auth` vía `basePath` del server; cookie de sesión con `path: "/"`), `groups`, `attendees`, `payments`, `waitlist` (listados paginados `{ data, pagination }`). - `apps/web` — Frontend React 19 + Vite + Tailwind v4. Entry `src/main.tsx` → `src/router.tsx`. Puerto **6173** (`vite.config.ts`). Auth client con `basePath: '/api/v1/auth'` (`src/lib/auth-client.ts`); el backend llama a `/api/v1/groups/from-organization` (`src/routes/organizations.tsx`). - `packages/shared` — Esquemas Zod (v3.24) + tipos + `Result` + Problem Details. **Se consume como TS fuente directo** (`exports` apunta a `src/index.ts`, sin build previo); se resuelve vía el symlink de bun en `node_modules` (`@gruperly/shared` no está en `paths` de los tsconfig). El `paths` de los tsconfig solo mapea `@/*` → `src/*` y `@generated/*` → `generated/*`. - `packages/config` — `tsconfig.base.json`; tsconfigs lo extienden con `"extends": "@gruperly/config/tsconfig.base.json"` (por eso `@gruperly/config` es devDependency de cada paquete). diff --git a/apps/backend/prisma/migrations/20260917120000_rename_student_to_attendee/migration.sql b/apps/backend/prisma/migrations/20260917120000_rename_student_to_attendee/migration.sql new file mode 100644 index 0000000..377bea5 --- /dev/null +++ b/apps/backend/prisma/migrations/20260917120000_rename_student_to_attendee/migration.sql @@ -0,0 +1,16 @@ +-- Rename Student model (students table) to Attendee (attendees table) + +-- AlterTable +ALTER TABLE "students" RENAME TO "attendees"; + +-- AlterTable +ALTER TABLE "payments" RENAME COLUMN "studentId" TO "attendeeId"; + +-- RenameIndex +ALTER INDEX "students_groupId_idx" RENAME TO "attendees_groupId_idx"; + +-- RenameIndex +ALTER INDEX "payments_studentId_idx" RENAME TO "payments_attendeeId_idx"; + +-- RenameForeignKey +ALTER TABLE "payments" RENAME CONSTRAINT "payments_studentId_fkey" TO "payments_attendeeId_fkey"; \ No newline at end of file diff --git a/apps/backend/prisma/models/domain.prisma b/apps/backend/prisma/models/domain.prisma index e800ccf..fa3fd24 100644 --- a/apps/backend/prisma/models/domain.prisma +++ b/apps/backend/prisma/models/domain.prisma @@ -14,10 +14,10 @@ model Group { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - owner User @relation("OwnerGroups", fields: [createdById], references: [id], onDelete: Cascade) - members GroupMember[] - students Student[] - payments Payment[] + owner User @relation("OwnerGroups", fields: [createdById], references: [id], onDelete: Cascade) + members GroupMember[] + attendees Attendee[] + payments Payment[] @@map("groups") } @@ -57,42 +57,42 @@ enum Role { MEMBER } -model Student { - id String @id @default(cuid()) - groupId String - fullName String - email String? - phone String? - guardianName String? - guardianPhone String? - notes String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt +model Attendee { + id String @id @default(cuid()) + groupId String + fullName String + email String? + phone String? + guardianName String? + guardianPhone String? + notes String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt group Group @relation(fields: [groupId], references: [id], onDelete: Cascade) payments Payment[] @@index([groupId]) - @@map("students") + @@map("attendees") } model Payment { - id String @id @default(cuid()) - groupId String - studentId String - amount Decimal @db.Decimal(10, 2) - currency String @default("MXN") - status PaymentStatus @default(PENDING) // PENDING, PAID, OVERDUE, CANCELLED - dueDate DateTime - paidAt DateTime? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(cuid()) + groupId String + attendeeId String + amount Decimal @db.Decimal(10, 2) + currency String @default("MXN") + status PaymentStatus @default(PENDING) // PENDING, PAID, OVERDUE, CANCELLED + dueDate DateTime + paidAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt - group Group @relation(fields: [groupId], references: [id], onDelete: Cascade) - student Student @relation(fields: [studentId], references: [id], onDelete: Cascade) + group Group @relation(fields: [groupId], references: [id], onDelete: Cascade) + attendee Attendee @relation(fields: [attendeeId], references: [id], onDelete: Cascade) @@index([groupId]) - @@index([studentId]) + @@index([attendeeId]) @@map("payments") } diff --git a/apps/backend/src/app.ts b/apps/backend/src/app.ts index ca64c50..e151244 100644 --- a/apps/backend/src/app.ts +++ b/apps/backend/src/app.ts @@ -10,12 +10,12 @@ import { requestLoggerMiddleware } from '@/http/request-logger'; import { corsMiddleware, securityHeadersMiddleware } from '@/http/security-headers'; import { sessionAuthMiddleware } from '@/http/session-auth'; import { logger } from '@/logger'; +import { attendeesRoutes } from './modules/attendees'; import { authRoutes } from './modules/auth'; import { groupsRoutes } from './modules/groups'; import { healthCheckRoutes } from './modules/health-check'; import { onboardingRoutes } from './modules/onboarding'; import { paymentsRoutes } from './modules/payments'; -import { studentsRoutes } from './modules/students'; import { waitlistRoutes } from './modules/waitlist'; const app = new Hono(); @@ -35,7 +35,7 @@ api.route('/auth', authRoutes); api.route('/health', healthCheckRoutes); api.route('/groups', groupsRoutes); api.route('/onboarding', onboardingRoutes); -api.route('/students', studentsRoutes); +api.route('/attendees', attendeesRoutes); api.route('/payments', paymentsRoutes); api.route('/waitlist', waitlistRoutes); diff --git a/apps/backend/src/modules/attendees/features/get-all/route.ts b/apps/backend/src/modules/attendees/features/get-all/route.ts new file mode 100644 index 0000000..4f91c26 --- /dev/null +++ b/apps/backend/src/modules/attendees/features/get-all/route.ts @@ -0,0 +1,18 @@ +import type { AttendeeQuery } from '@gruperly/shared'; +import { AttendeeQuerySchema } from '@gruperly/shared'; +import { Hono } from 'hono'; +import { resultJson } from '@/http/problem-details'; +import { validate } from '@/http/validate'; +import { ListAttendees } from './use-case'; + +const route = new Hono(); + +route.get('/', validate.query(AttendeeQuerySchema), async (c) => { + const query = c.req.valid('query') as AttendeeQuery; + const useCase = new ListAttendees(); + const result: Awaited> = await useCase.execute(query); + + return resultJson(c, result); +}); + +export default route; \ No newline at end of file diff --git a/apps/backend/src/modules/students/features/get-all/use-case.ts b/apps/backend/src/modules/attendees/features/get-all/use-case.ts similarity index 67% rename from apps/backend/src/modules/students/features/get-all/use-case.ts rename to apps/backend/src/modules/attendees/features/get-all/use-case.ts index e3e9b69..6fde216 100644 --- a/apps/backend/src/modules/students/features/get-all/use-case.ts +++ b/apps/backend/src/modules/attendees/features/get-all/use-case.ts @@ -1,14 +1,14 @@ import type { PrismaClient } from '@generated/prisma/client'; -import type { ProblemDetails, Result, StudentDto, StudentList, StudentQuery } from '@gruperly/shared'; +import type { AttendeeDto, AttendeeList, AttendeeQuery, ProblemDetails, Result } from '@gruperly/shared'; import { ok } from '@gruperly/shared'; import { getPaginationMetadata, getPaginationOffset } from '@/lib/pagination'; import prisma from '@/lib/prisma'; -type ListStudentsDeps = { - db?: Pick; +type ListAttendeesDeps = { + db?: Pick; }; -type StudentRecord = { +type AttendeeRecord = { id: string; groupId: string; fullName: string; @@ -21,7 +21,7 @@ type StudentRecord = { updatedAt: Date; }; -function toStudentDto(record: StudentRecord): StudentDto { +function toAttendeeDto(record: AttendeeRecord): AttendeeDto { return { id: record.id, groupId: record.groupId, @@ -36,22 +36,22 @@ function toStudentDto(record: StudentRecord): StudentDto { }; } -export class ListStudents { - constructor(private readonly deps: ListStudentsDeps = {}) {} +export class ListAttendees { + constructor(private readonly deps: ListAttendeesDeps = {}) {} - async execute(query: StudentQuery): Promise> { + async execute(query: AttendeeQuery): Promise> { const db = this.deps.db ?? prisma; const [records, total] = await Promise.all([ - db.student.findMany({ + db.attendee.findMany({ skip: getPaginationOffset(query), take: query.pageSize, orderBy: { createdAt: 'desc' }, }), - db.student.count(), + db.attendee.count(), ]); return ok({ - data: records.map(toStudentDto), + data: records.map(toAttendeeDto), pagination: getPaginationMetadata(query, total), }); } diff --git a/apps/backend/src/modules/attendees/index.ts b/apps/backend/src/modules/attendees/index.ts new file mode 100644 index 0000000..ef72296 --- /dev/null +++ b/apps/backend/src/modules/attendees/index.ts @@ -0,0 +1 @@ +export { default as attendeesRoutes } from './routes'; \ No newline at end of file diff --git a/apps/backend/src/modules/students/routes.ts b/apps/backend/src/modules/attendees/routes.ts similarity index 100% rename from apps/backend/src/modules/students/routes.ts rename to apps/backend/src/modules/attendees/routes.ts diff --git a/apps/backend/src/modules/payments/features/get-all/use-case.ts b/apps/backend/src/modules/payments/features/get-all/use-case.ts index d0bc158..3de8323 100644 --- a/apps/backend/src/modules/payments/features/get-all/use-case.ts +++ b/apps/backend/src/modules/payments/features/get-all/use-case.ts @@ -11,7 +11,7 @@ type ListPaymentsDeps = { type PaymentRecord = { id: string; groupId: string; - studentId: string; + attendeeId: string; amount: { toString(): string }; currency: string; status: PaymentDto['status']; @@ -25,7 +25,7 @@ function toPaymentDto(record: PaymentRecord): PaymentDto { return { id: record.id, groupId: record.groupId, - studentId: record.studentId, + attendeeId: record.attendeeId, amount: Number(record.amount.toString()), currency: record.currency, status: record.status, diff --git a/apps/backend/src/modules/students/features/get-all/route.ts b/apps/backend/src/modules/students/features/get-all/route.ts deleted file mode 100644 index 1a7db3b..0000000 --- a/apps/backend/src/modules/students/features/get-all/route.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { StudentQuery } from '@gruperly/shared'; -import { StudentQuerySchema } from '@gruperly/shared'; -import { Hono } from 'hono'; -import { resultJson } from '@/http/problem-details'; -import { validate } from '@/http/validate'; -import { ListStudents } from './use-case'; - -const route = new Hono(); - -route.get('/', validate.query(StudentQuerySchema), async (c) => { - const query = c.req.valid('query') as StudentQuery; - const useCase = new ListStudents(); - const result: Awaited> = await useCase.execute(query); - - return resultJson(c, result); -}); - -export default route; \ No newline at end of file diff --git a/apps/backend/src/modules/students/index.ts b/apps/backend/src/modules/students/index.ts deleted file mode 100644 index 008c587..0000000 --- a/apps/backend/src/modules/students/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as studentsRoutes } from './routes'; \ No newline at end of file diff --git a/apps/backend/test/students.test.ts b/apps/backend/test/attendees.test.ts similarity index 60% rename from apps/backend/test/students.test.ts rename to apps/backend/test/attendees.test.ts index 6dfd088..60e49d8 100644 --- a/apps/backend/test/students.test.ts +++ b/apps/backend/test/attendees.test.ts @@ -3,7 +3,7 @@ import { Hono } from 'hono'; mock.module('@/lib/prisma', () => ({ default: { - student: { + attendee: { findMany: mock(), count: mock(), }, @@ -13,13 +13,13 @@ mock.module('@/lib/prisma', () => ({ })); import prisma from '@/lib/prisma'; -import { studentsRoutes } from '@/modules/students'; +import { attendeesRoutes } from '@/modules/attendees'; const app = new Hono(); -app.route('/students', studentsRoutes); +app.route('/attendees', attendeesRoutes); -const student = { - id: 'student-1', +const attendee = { + id: 'attendee-1', groupId: 'group-1', fullName: 'Ana Pérez', email: 'ana@example.com', @@ -31,41 +31,41 @@ const student = { updatedAt: new Date('2026-08-01T10:00:00.000Z'), }; -describe('students routes', () => { +describe('attendees routes', () => { beforeEach(() => { vi.clearAllMocks(); }); - it('lists students with pagination', async () => { - prisma.student.findMany.mockResolvedValue([student]); - prisma.student.count.mockResolvedValue(21); + it('lists attendees with pagination', async () => { + prisma.attendee.findMany.mockResolvedValue([attendee]); + prisma.attendee.count.mockResolvedValue(21); - const res = await app.request('/students?page=2&pageSize=10'); + const res = await app.request('/attendees?page=2&pageSize=10'); expect(res.status).toBe(200); expect(await res.json()).toEqual({ data: [ { - ...student, - createdAt: student.createdAt.toISOString(), - updatedAt: student.updatedAt.toISOString(), + ...attendee, + createdAt: attendee.createdAt.toISOString(), + updatedAt: attendee.updatedAt.toISOString(), }, ], pagination: { page: 2, pageSize: 10, total: 21, totalPages: 3 }, }); - expect(prisma.student.findMany).toHaveBeenCalledWith({ + expect(prisma.attendee.findMany).toHaveBeenCalledWith({ skip: 10, take: 10, orderBy: { createdAt: 'desc' }, }); - expect(prisma.student.count).toHaveBeenCalledWith(); + expect(prisma.attendee.count).toHaveBeenCalledWith(); }); it('uses default pagination', async () => { - prisma.student.findMany.mockResolvedValue([]); - prisma.student.count.mockResolvedValue(0); + prisma.attendee.findMany.mockResolvedValue([]); + prisma.attendee.count.mockResolvedValue(0); - const res = await app.request('/students'); + const res = await app.request('/attendees'); expect(res.status).toBe(200); expect(await res.json()).toEqual({ @@ -75,7 +75,7 @@ describe('students routes', () => { }); it('rejects invalid pagination query parameters', async () => { - const res = await app.request('/students?page=0&pageSize=25'); + const res = await app.request('/attendees?page=0&pageSize=25'); expect(res.status).toBe(400); expect(await res.json()).toMatchObject({ status: 400, title: 'Bad Request' }); diff --git a/apps/backend/test/payments.test.ts b/apps/backend/test/payments.test.ts index 22a1e27..197a23e 100644 --- a/apps/backend/test/payments.test.ts +++ b/apps/backend/test/payments.test.ts @@ -20,8 +20,8 @@ app.route('/payments', paymentsRoutes); const payment = { id: 'payment-1', - groupId: 'group-1', - studentId: 'student-1', +groupId: 'group-1', + attendeeId: 'attendee-1', amount: { toString: () => '150.50' } as { toString(): string }, currency: 'MXN', status: 'pending', @@ -47,8 +47,8 @@ describe('payments routes', () => { data: [ { id: 'payment-1', - groupId: 'group-1', - studentId: 'student-1', +groupId: 'group-1', + attendeeId: 'attendee-1', amount: 150.5, currency: 'MXN', status: 'pending', diff --git a/apps/backend/test/session-auth.test.ts b/apps/backend/test/session-auth.test.ts index 8876781..6662b01 100644 --- a/apps/backend/test/session-auth.test.ts +++ b/apps/backend/test/session-auth.test.ts @@ -35,7 +35,7 @@ describe('session auth', () => { expect(isPublicApiRequest('GET', '/api/v1/health')).toBe(true); expect(isPublicApiRequest('POST', '/api/v1/auth/sign-in/email')).toBe(true); expect(isPublicApiRequest('GET', '/api/v1/groups')).toBe(false); - expect(isPublicApiRequest('GET', '/api/v1/students')).toBe(false); + expect(isPublicApiRequest('GET', '/api/v1/attendees')).toBe(false); }); it('allows public requests without a session', async () => { diff --git a/apps/web/src/components/onboarding/ConfirmationStep.tsx b/apps/web/src/components/onboarding/ConfirmationStep.tsx index 22e3a0e..0060bdb 100644 --- a/apps/web/src/components/onboarding/ConfirmationStep.tsx +++ b/apps/web/src/components/onboarding/ConfirmationStep.tsx @@ -31,7 +31,7 @@ export function ConfirmationStep({ group, providerName }: ConfirmationStepProps)

¡Todo listo!

- Tu grupo se creó y ya podés empezar a cobrar a tus alumnos. + Tu grupo se creó y ya podés empezar a cobrar a tus miembros.

@@ -56,7 +56,7 @@ export function ConfirmationStep({ group, providerName }: ConfirmationStepProps)
Cupo
-
{group.capacity ?? '—'} alumnos
+
{group.capacity ?? '—'} miembros
Vencimiento
diff --git a/apps/web/src/components/onboarding/PaymentStep.tsx b/apps/web/src/components/onboarding/PaymentStep.tsx index 107ab3c..8f59e12 100644 --- a/apps/web/src/components/onboarding/PaymentStep.tsx +++ b/apps/web/src/components/onboarding/PaymentStep.tsx @@ -81,7 +81,7 @@ export function PaymentStep({ initialResult, onConnected, onBack }: PaymentStepP

Elegí tu procesador de cobro

- Los pagos de tus alumnos van a llegar por esta plataforma. + Los pagos de tus miembros van a llegar por esta plataforma.

diff --git a/apps/web/src/components/onboarding/WelcomeStep.tsx b/apps/web/src/components/onboarding/WelcomeStep.tsx index 0b207c6..3a219ca 100644 --- a/apps/web/src/components/onboarding/WelcomeStep.tsx +++ b/apps/web/src/components/onboarding/WelcomeStep.tsx @@ -20,7 +20,7 @@ const STEPS_TO_SETUP = [ { icon: Rocket, title: 'Empezá a cobrar', - description: 'Todo listo para sumar alumnos y cobrar al instante.', + description: 'Todo listo para sumar miembros y cobrar al instante.', }, ] diff --git a/apps/web/src/routes/groups.tsx b/apps/web/src/routes/groups.tsx index e6f8080..9a1bae2 100644 --- a/apps/web/src/routes/groups.tsx +++ b/apps/web/src/routes/groups.tsx @@ -30,7 +30,7 @@ function GroupCard({ group }: { group: GroupDto }) {
- Cupo {group.capacity ?? '—'} alumnos + Cupo {group.capacity ?? '—'} miembros {group.price != null ? ` · ${formatPrice(group.price)}${group.billingType ? ` · ${BILLING_LABELS[group.billingType]}` : ''}` : ''} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 24678cb..caf13a3 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,5 +1,6 @@ export * from './lib/problem-details.js'; export * from './lib/result.js'; +export * from './schemas/attendees.js'; export * from './schemas/enums.js'; export * from './schemas/groups.js'; export * from './schemas/health-check.js'; @@ -7,5 +8,4 @@ export * from './schemas/onboarding.js'; export * from './schemas/pagination.js'; export * from './schemas/payments.js'; export * from './schemas/problem-details.js'; -export * from './schemas/students.js'; export * from './schemas/waitlist.js'; \ No newline at end of file diff --git a/packages/shared/src/schemas/students.ts b/packages/shared/src/schemas/attendees.ts similarity index 66% rename from packages/shared/src/schemas/students.ts rename to packages/shared/src/schemas/attendees.ts index 768d584..b079c80 100644 --- a/packages/shared/src/schemas/students.ts +++ b/packages/shared/src/schemas/attendees.ts @@ -6,7 +6,7 @@ const pageSchema = createPageSchema(); const pageSizeSchema = createPageSizeSchema(10); const paginationSchema = createPaginationSchema(); -export const StudentDtoSchema = z.object({ +export const AttendeeDtoSchema = z.object({ id: z.string(), groupId: z.string(), fullName: z.string(), @@ -18,16 +18,16 @@ export const StudentDtoSchema = z.object({ createdAt: isoDateTimeSchema, updatedAt: isoDateTimeSchema, }); -export type StudentDto = z.output; +export type AttendeeDto = z.output; -export const StudentQuerySchema = z.object({ +export const AttendeeQuerySchema = z.object({ page: pageSchema, pageSize: pageSizeSchema, }); -export type StudentQuery = z.output; +export type AttendeeQuery = z.output; -export const StudentListSchema = z.object({ - data: z.array(StudentDtoSchema), +export const AttendeeListSchema = z.object({ + data: z.array(AttendeeDtoSchema), pagination: paginationSchema, }); -export type StudentList = z.output; \ No newline at end of file +export type AttendeeList = z.output; \ No newline at end of file diff --git a/packages/shared/src/schemas/payments.ts b/packages/shared/src/schemas/payments.ts index cb0d4c4..8069d53 100644 --- a/packages/shared/src/schemas/payments.ts +++ b/packages/shared/src/schemas/payments.ts @@ -11,7 +11,7 @@ export const paymentStatusSchema = z.enum(['PENDING', 'PAID', 'OVERDUE', 'CANCEL export const PaymentDtoSchema = z.object({ id: z.string(), groupId: z.string(), - studentId: z.string(), + attendeeId: z.string(), amount: z.coerce.number().positive(), currency: z.string(), status: paymentStatusSchema, diff --git a/stack.md b/stack.md index e84cc3b..9f2139f 100644 --- a/stack.md +++ b/stack.md @@ -41,7 +41,7 @@ gruperly/ │ │ ├── src/ │ │ │ ├── http/ # Infraestructura HTTP (validate, problem-details, session-auth, ...) │ │ │ ├── lib/ # Prisma (cliente + UnitOfWork), pagination, email, helpers -│ │ │ ├── modules/ # Módulos: health-check, auth, groups, students, payments, waitlist +│ │ │ ├── modules/ # Módulos: health-check, auth, groups, attendees, payments, waitlist │ │ │ │ └── / │ │ │ │ ├── routes.ts │ │ │ │ └── features//{route,use-case}.ts @@ -73,7 +73,7 @@ gruperly/ │ │ ├── src/ │ │ │ ├── schemas/ # Validaciones Zod compartidas │ │ │ │ ├── group.schema.ts -│ │ │ │ ├── student.schema.ts +│ │ │ │ ├── attendee.schema.ts │ │ │ │ └── payment.schema.ts │ │ │ └── index.ts │ │ ├── tsconfig.json