Skip to content
This repository was archived by the owner on May 19, 2026. It is now read-only.

feat(event): refactor event service to support shows and their sections#67

Merged
DungxND merged 4 commits into
mainfrom
refactor/58-be-schema-evolve
Apr 12, 2026
Merged

feat(event): refactor event service to support shows and their sections#67
DungxND merged 4 commits into
mainfrom
refactor/58-be-schema-evolve

Conversation

@DungxND
Copy link
Copy Markdown
Member

@DungxND DungxND commented Apr 12, 2026

Closes #58

Loại thay đổi

  • ✨ Feature mới
  • ♻️ Refactor

Screenshots / Demo

Checklist

  • Code chạy không lỗi (bun run dev)
  • TypeScript check pass (bun run check)
  • Lint pass (bun run lint)
  • Đã format code (bun run format)
  • Đã test thủ công chức năng
  • Commit message đúng convention (feat:, fix:, chore:,...)

Summary by CodeRabbit

  • New Features

    • Events can have multiple shows (dates/times) with per-show itineraries.
    • Per-show seating sections with capacities and configurable sales windows.
    • Added organizer info, terms & conditions, static map images, and amenities.
    • Order items include unique ticket codes.
  • Refactor

    • Event model and UI now present shows under events (earliest show date shown in listings).
    • Simplified order model by removing event-level association.

DungxND added 2 commits April 12, 2026 11:36
- 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.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 12, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0d1fb69e-f563-43c4-9374-11d39f46a2ec

📥 Commits

Reviewing files that changed from the base of the PR and between 7fd3594 and ec39cff.

📒 Files selected for processing (2)
  • src/lib/server/db/seed.ts
  • src/lib/shared/schemas/event.schema.ts

📝 Walkthrough

Walkthrough

This PR refactors the event and seating model from event-scoped to show-scoped: it adds event_shows, moves seat_sections/seats to reference showId, updates orders/order_items and event fields, adds relations, updates seed data and service logic, and rewrites validation schemas to accept multiple shows per event.

Changes

Cohort / File(s) Summary
Database Schema
src/lib/server/db/schema.ts
Added event_shows and show_status enum; removed eventDate and sold_out status; added event-level fields (termsAndConditions, staticMapImageUrl, amenities, organizerInfo); moved seat_sections/seats FKs from eventIdshowId with updated cascade/restrict behaviors; added ticketCode to order_items; updated updatedAt to use .$onUpdate(...); exported Drizzle relations(...).
Seed Data
src/lib/server/db/seed.ts
Replaced createSections with createShowWithSections; seed now creates one or more eventShows per event; sections include capacity and optional salesStartAt/salesEndAt; GA seat generation derives seats from capacity; cleanup deletes eventShows.
Event Service
src/lib/server/services/event.service.ts
Refactored persistence to show-scoped APIs: added insertShowWithSections, changed insertSectionsWithSeats/inserts to accept showId; listEvents computes earliest_show_date; getEventDetail returns shows: [{ sections: [...] }]; renamed updateEventSectionsupdateShowSections; publish flow validates shows and seats across shows.
Validation Schemas & Types
src/lib/shared/schemas/event.schema.ts
Added showSchema, itineraryItemSchema, and showIdSchema; baseSectionSchema now supports rows/cols = 0 and adds capacity, sales_start_at/sales_end_at; validation enforces assigned vs general rules; createEventSchema replaced to require shows[]; updateShowSectionsSchema added; form draft schemas/types updated.
Other / Exports
src/lib/server/db/..., src/lib/server/services/...
Export signatures and returned payload shapes changed to be show-aware (e.g., earliest_show_date, shows arrays); some function names/params adjusted to showId scope.

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
Loading
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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PR #66: Overlapping DB refactor adding event_shows, show-scoped seats/sections, ticketCode, and relations — high code-level overlap.
  • PR #46: Prior addition of create/update/publish event functions in event.service; this PR refactors those to be show-scoped and renames signatures.
  • PR #53: Modifies listEvents behavior in event.service; relates to the listEvents rewrite to compute earliest_show_date and join through shows.

Suggested reviewers

  • HungND-flocus
  • NguyenVanThanhTung

"🐰 I dug new tunnels under the stage,
Shows now bloom from page to page,
Seats align where hours meet,
Multiple nights—each one neat,
Hooray—this rabbit's hop is sage!"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The PR description includes the linked issue number (#58), specifies the type of change (Feature + Refactor), and marks all required checklist items as complete, though it lacks a detailed summary of changes.
Linked Issues check ✅ Passed The PR implements the core coding requirements from issue #58: refactored event service for show-scoped sections, added support for general admission ticketing, updated schema for custom stages, and modified API endpoints/services accordingly.
Out of Scope Changes check ✅ Passed All changes are scoped to the backend schema evolution and event service refactoring. Database schema updates, service layer modifications, and validation schemas all directly support the objective of custom stages and standing-ticket systems.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title accurately describes the main change—refactoring the event service to support shows and their sections—which aligns with the primary objective of transitioning from event-scoped to show-scoped seat/section modeling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/58-be-schema-evolve

Comment @coderabbitai help to get the list of available commands and usage tips.

@DungxND DungxND changed the title refactor(be): refactor event service to support shows and their sections refactor(event): refactor event service to support shows and their sections Apr 12, 2026
@DungxND DungxND changed the title refactor(event): refactor event service to support shows and their sections feat(event): refactor event service to support shows and their sections Apr 12, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟠 Major

Keep the old event_date field until consumers are migrated.

This response now emits only earliest_show_date, but src/routes/(admin)/admin/events/+page.svelte still reads heroEvent.event_date at Line 183 and event.event_date at 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

📥 Commits

Reviewing files that changed from the base of the PR and between 321f58a and 7fd3594.

📒 Files selected for processing (4)
  • src/lib/server/db/schema.ts
  • src/lib/server/db/seed.ts
  • src/lib/server/services/event.service.ts
  • src/lib/shared/schemas/event.schema.ts

Comment on lines +189 to +194
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)],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Suggested change
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.

Comment thread src/lib/server/db/seed.ts
Comment on lines +439 to +440
async updateShowSections(adminId: number, showId: number, data: unknown) {
const { sections } = validateInput(updateShowSectionsSchema, data);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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.

Comment thread src/lib/shared/schemas/event.schema.ts Outdated
DungxND and others added 2 commits April 12, 2026 12:58
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@DungxND DungxND merged commit cc48037 into main Apr 12, 2026
1 of 2 checks passed
@DungxND DungxND deleted the refactor/58-be-schema-evolve branch April 12, 2026 05:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BE] Cập nhật back-end để hỗ trợ để hỗ trợ custom sân khấu và hệ thống vé đứng

1 participant