feat(event): refactor event service to support shows and their sections#67
Conversation
… and seat structures
- Updated event service to handle shows, including inserting and updating sections and seats for each show. - Modified schemas to include show-related fields and validation. - Enhanced section handling to differentiate between assigned and general admission types. - Adjusted database queries to aggregate seat counts per show. - Improved error handling for event visibility and seat availability.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR refactors the event and seating model from event-scoped to show-scoped: it adds Changes
Sequence Diagram(s)sequenceDiagram
actor Admin
participant API as Create Event API
participant Service as Event Service
participant DB as Database
Admin->>API: POST /events { shows: [{show_date,start_time,sections[...]}, ...] }
API->>Service: createEvent(payload)
Service->>DB: INSERT INTO events (...)
DB-->>Service: eventId
Service->>DB: INSERT INTO event_shows (eventId, showDate, startTime, ...)
DB-->>Service: eventShowId
loop per section
Service->>DB: INSERT INTO seat_sections (showId, name, capacity, ...)
DB-->>Service: seatSectionId
Service->>DB: BULK INSERT seats (seatSectionId, showId, label, ...)
DB-->>Service: seatsInserted
end
Service-->>API: { eventId, shows: [{showId, totalSeats, sections...}, ...] }
API-->>Admin: 201 Created
sequenceDiagram
actor Client
participant API as List Events API
participant Service as Event Service
participant DB as Database
Client->>API: GET /events
API->>Service: listEvents()
Service->>DB: SELECT events JOIN event_shows JOIN seat_sections JOIN seats
DB-->>Service: rows
Service->>Service: group by eventId, compute min(eventShows.showDate) as earliest_show_date
Service-->>API: [{id,title,earliest_show_date,...}]
API-->>Client: 200 OK
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/lib/server/services/event.service.ts (1)
217-239:⚠️ Potential issue | 🟠 MajorKeep the old
event_datefield until consumers are migrated.This response now emits only
earliest_show_date, butsrc/routes/(admin)/admin/events/+page.sveltestill readsheroEvent.event_dateat Line 183 andevent.event_dateat Line 306. Without a coordinated UI change, the admin event list loses its date/time display.Backward-compatible option
events: rows.map((r) => ({ id: r.id, title: r.title, venue: r.venue, + event_date: r.earliestShowDate, earliest_show_date: r.earliestShowDate, banner_image_url: r.bannerImageUrl, min_age: r.minAge, max_tickets_per_user: r.maxTicketsPerUser, status: r.status,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/server/services/event.service.ts` around lines 217 - 239, The response removed the legacy event_date property causing the admin UI to break; in the return mapping where rows.map((r) => ({ ... })) is built, keep a backward-compatible event_date field (set it to r.earliestShowDate or the same value as earliest_show_date) so both earliest_show_date and event_date are emitted until consumers are migrated; update the object created in the rows.map to include event_date alongside earliest_show_date and bannerImageUrl.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/server/db/schema.ts`:
- Around line 189-194: The DB schema allows salesEndAt to be earlier than
salesStartAt, enabling invalid sales windows; add a database-level CHECK
constraint in the table definition (the schema that declares salesStartAt and
salesEndAt) that enforces sales_end_at IS NULL OR sales_start_at IS NULL OR
sales_end_at >= sales_start_at, and update any migrations accordingly so
inserts/updates from services like event.service.ts will be rejected when they
violate this rule; reference the salesStartAt and salesEndAt column definitions
(and the table creation where index('idx_seat_sections_show') is declared) when
adding the constraint.
In `@src/lib/server/db/seed.ts`:
- Around line 940-942: Update the completion summary to show the correct total
shows count: replace the string "Shows: 9 total (2+1+1+1+2+1 = 8 shows, Events 1
& 5 have 2 days each)" with a message that reads "Shows: 8 total (2+1+1+1+2+1 =
8 shows, Events 1 & 5 have 2 days each)" so the printed total matches the
breakdown (look for the console.log call that prints the "Shows:" line in
src/lib/server/db/seed.ts).
In `@src/lib/server/services/event.service.ts`:
- Around line 439-440: The service method was renamed and retyped
(updateShowSections) but callers still call updateEventSections with an event
id, breaking the endpoint; either restore the original public API signature by
renaming updateShowSections back to updateEventSections and accept (adminId:
number, eventId: number, data: unknown) with the same semantics, or add a thin
wrapper method named updateEventSections on eventService that forwards to
updateShowSections (or vice versa) so existing callers like
eventService.updateEventSections(admin.id, Number(params.id), body) keep
working; update the parameter name/semantics consistently across the two
functions to match callers.
In `@src/lib/shared/schemas/event.schema.ts`:
- Around line 189-205: The schema currently validates formats but not
cross-field consistency: update showSchema (use a .superRefine on showSchema) to
parse start_time and end_time into Date objects and verify that the date portion
of start_time matches show_date (add a validation issue on show_date or
start_time if mismatched), and if end_time is provided and not the empty string
ensure end_time is after or equal to start_time (add an issue on end_time if
earlier). Use the existing field names (show_date, start_time, end_time) and
z.superRefine + ctx.addIssue to produce field-specific error messages.
---
Outside diff comments:
In `@src/lib/server/services/event.service.ts`:
- Around line 217-239: The response removed the legacy event_date property
causing the admin UI to break; in the return mapping where rows.map((r) => ({
... })) is built, keep a backward-compatible event_date field (set it to
r.earliestShowDate or the same value as earliest_show_date) so both
earliest_show_date and event_date are emitted until consumers are migrated;
update the object created in the rows.map to include event_date alongside
earliest_show_date and bannerImageUrl.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d67cff3a-e14f-40c1-be82-f893b5dc205c
📒 Files selected for processing (4)
src/lib/server/db/schema.tssrc/lib/server/db/seed.tssrc/lib/server/services/event.service.tssrc/lib/shared/schemas/event.schema.ts
| salesStartAt: timestamp('sales_start_at', { withTimezone: true }), | ||
| salesEndAt: timestamp('sales_end_at', { withTimezone: true }), | ||
|
|
||
| createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), | ||
| }, | ||
| (table) => [index('idx_seat_sections_event').on(table.eventId)], | ||
| (table) => [index('idx_seat_sections_show').on(table.showId)], |
There was a problem hiding this comment.
Enforce valid section sales windows at the DB layer.
sales_end_at can currently be earlier than sales_start_at, and src/lib/server/services/event.service.ts persists both values as-is. That allows an impossible sales window to reach stored data and will be painful to recover from later.
Suggested fix
export const seatSections = pgTable(
'seat_sections',
{
@@
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
},
- (table) => [index('idx_seat_sections_show').on(table.showId)],
+ (table) => [
+ index('idx_seat_sections_show').on(table.showId),
+ check(
+ 'chk_seat_section_sales_window',
+ sql`${table.salesStartAt} IS NULL
+ OR ${table.salesEndAt} IS NULL
+ OR ${table.salesEndAt} > ${table.salesStartAt}`,
+ ),
+ ],
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| salesStartAt: timestamp('sales_start_at', { withTimezone: true }), | |
| salesEndAt: timestamp('sales_end_at', { withTimezone: true }), | |
| createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), | |
| }, | |
| (table) => [index('idx_seat_sections_event').on(table.eventId)], | |
| (table) => [index('idx_seat_sections_show').on(table.showId)], | |
| salesStartAt: timestamp('sales_start_at', { withTimezone: true }), | |
| salesEndAt: timestamp('sales_end_at', { withTimezone: true }), | |
| createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), | |
| }, | |
| (table) => [ | |
| index('idx_seat_sections_show').on(table.showId), | |
| check( | |
| 'chk_seat_section_sales_window', | |
| sql`${table.salesStartAt} IS NULL | |
| OR ${table.salesEndAt} IS NULL | |
| OR ${table.salesEndAt} > ${table.salesStartAt}`, | |
| ), | |
| ], |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lib/server/db/schema.ts` around lines 189 - 194, The DB schema allows
salesEndAt to be earlier than salesStartAt, enabling invalid sales windows; add
a database-level CHECK constraint in the table definition (the schema that
declares salesStartAt and salesEndAt) that enforces sales_end_at IS NULL OR
sales_start_at IS NULL OR sales_end_at >= sales_start_at, and update any
migrations accordingly so inserts/updates from services like event.service.ts
will be rejected when they violate this rule; reference the salesStartAt and
salesEndAt column definitions (and the table creation where
index('idx_seat_sections_show') is declared) when adding the constraint.
| async updateShowSections(adminId: number, showId: number, data: unknown) { | ||
| const { sections } = validateInput(updateShowSectionsSchema, data); |
There was a problem hiding this comment.
This public API rename is currently breaking the sections endpoint.
updateShowSections(adminId, showId, ...) changes both the method name and the identifier semantics, but src/routes/api/events/[id]/sections/+server.ts Lines 1-15 still calls eventService.updateEventSections(admin.id, Number(params.id), body) with an event id. That endpoint is now out of sync with the service contract.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lib/server/services/event.service.ts` around lines 439 - 440, The service
method was renamed and retyped (updateShowSections) but callers still call
updateEventSections with an event id, breaking the endpoint; either restore the
original public API signature by renaming updateShowSections back to
updateEventSections and accept (adminId: number, eventId: number, data: unknown)
with the same semantics, or add a thin wrapper method named updateEventSections
on eventService that forwards to updateShowSections (or vice versa) so existing
callers like eventService.updateEventSections(admin.id, Number(params.id), body)
keep working; update the parameter name/semantics consistently across the two
functions to match callers.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Closes #58
Loại thay đổi
Screenshots / Demo
Checklist
bun run dev)bun run check)bun run lint)bun run format)feat:,fix:,chore:,...)Summary by CodeRabbit
New Features
Refactor