chore: [Booking Cancellation Refactor - 2] Inject repositories and use them instead of Prisma in cancellation flow#30
Conversation
WalkthroughThis PR refactors the booking cancellation system by implementing the repository pattern with dependency injection. Five new repository classes are created (BookingAttendee, BookingReference, Profile in API v2 and base packages), corresponding DI modules and tokens are established, and BookingCancelService is updated to accept repository dependencies instead of direct Prisma client usage. The handleCancelBooking handler is modified to accept injected repository dependencies and use them for data access. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleCancelBooking.ts (1)
500-520: Align the post‑update fetch range with the cancellation range.
updateManyusesgte(now vs booking start), but the follow‑up fetch always usesbookingToDelete.startTime. WhenallRemainingBookingsis true and the cancelled occurrence isn’t the earliest upcoming one, some cancelled bookings won’t be included inupdatedBookings, so reminders/webhooks can be left behind.💡 Suggested fix
- const allUpdatedBookings = await bookingRepository.findManyIncludeWorkflowRemindersAndReferences({ - where: { - recurringEventId: bookingToDelete.recurringEventId, - startTime: { - gte: bookingToDelete.startTime, - }, - }, - }); + const allUpdatedBookings = await bookingRepository.findManyIncludeWorkflowRemindersAndReferences({ + where: { + recurringEventId, + startTime: { + gte, + }, + }, + });
🤖 Fix all issues with AI agents
In `@packages/features/bookings/repositories/BookingRepository.ts`:
- Around line 1502-1507: The updateMany implementation in BookingRepository
currently awaits but does not return the Prisma result, violating
IBookingRepository.updateMany's Promise<{ count: number }> contract; modify
BookingRepository.updateMany so it returns the result of
this.prismaClient.booking.updateMany(...) (i.e., replace the lone await with a
return of prismaClient.booking.updateMany) so callers can receive the { count }
response consistent with the IBookingRepository interface.
🧹 Nitpick comments (2)
packages/lib/server/repository/dto/IBookingReferenceRepository.ts (1)
6-8: Remove the placeholder comment in the public interface.The TODO-style comment can go stale; either replace it with concrete methods or remove it.
🧹 Proposed cleanup
export interface IBookingReferenceRepository { - // ... Add existing methods as well here /** * Update all booking references associated with a booking * Used during booking cancellation cleanup to soft-delete references */packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.ts (1)
1057-1516: Add assertions for the behaviors named in these tests.
These new tests mostly assertsuccessand IDs but don’t verify attendee deletion, recurring booking status updates, or reference cleanup. Consider asserting the underlying state (attendee count, booking statuses, references marked deleted) to make the tests meaningful.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (23)
apps/api/v2/src/lib/modules/booking-cancel.module.tsapps/api/v2/src/lib/repositories/prisma-booking-attendee.repository.tsapps/api/v2/src/lib/repositories/prisma-booking-reference.repository.tsapps/api/v2/src/lib/repositories/prisma-profile.repository.tsapps/api/v2/src/lib/services/booking-cancel.service.tspackages/features/bookingReference/repositories/BookingReferenceRepository.tspackages/features/bookings/di/BookingAttendeeRepository.module.tspackages/features/bookings/di/BookingCancelService.module.tspackages/features/bookings/di/BookingReferenceRepository.module.tspackages/features/bookings/di/tokens.tspackages/features/bookings/lib/dto/IBookingAttendeeRepository.tspackages/features/bookings/lib/handleCancelBooking.tspackages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.tspackages/features/bookings/repositories/BookingRepository.tspackages/features/bookings/repositories/PrismaBookingAttendeeRepository.tspackages/features/di/tokens.tspackages/features/profile/repositories/ProfileRepository.tspackages/features/users/di/Profile.module.tspackages/features/users/repositories/UserRepository.tspackages/lib/server/repository/dto/IBookingReferenceRepository.tspackages/lib/server/repository/dto/IBookingRepository.tspackages/lib/server/repository/dto/IProfileRepository.tspackages/platform/libraries/repositories.ts
💤 Files with no reviewable changes (1)
- packages/features/users/repositories/UserRepository.ts
🧰 Additional context used
🧬 Code graph analysis (4)
packages/features/bookings/di/BookingAttendeeRepository.module.ts (5)
packages/features/di/tokens.ts (1)
DI_TOKENS(10-84)packages/features/bookings/repositories/PrismaBookingAttendeeRepository.ts (1)
PrismaBookingAttendeeRepository(5-15)packages/features/bookings/di/BookingCancelService.module.ts (1)
moduleLoader(28-31)packages/features/bookings/di/BookingReferenceRepository.module.ts (1)
moduleLoader(19-22)packages/features/users/di/Profile.module.ts (1)
moduleLoader(19-22)
apps/api/v2/src/lib/repositories/prisma-booking-reference.repository.ts (3)
apps/api/v2/src/lib/repositories/prisma-booking-attendee.repository.ts (1)
Injectable(6-11)apps/api/v2/src/lib/repositories/prisma-profile.repository.ts (1)
Injectable(6-11)apps/api/v2/src/lib/services/booking-cancel.service.ts (1)
Injectable(10-27)
packages/features/bookings/repositories/BookingRepository.ts (2)
packages/platform/libraries/repositories.ts (1)
BookingRepository(5-5)packages/lib/server/repository/dto/IBookingRepository.ts (4)
IBookingRepository(46-55)BookingWhereInput(4-11)BookingUpdateData(21-26)BookingWhereUniqueInput(13-19)
packages/features/bookings/lib/handleCancelBooking.ts (5)
packages/features/users/repositories/UserRepository.ts (1)
UserRepository(124-1372)packages/features/bookings/repositories/BookingRepository.ts (1)
BookingRepository(347-2017)packages/features/profile/repositories/ProfileRepository.ts (1)
ProfileRepository(100-1042)packages/features/bookingReference/repositories/BookingReferenceRepository.ts (1)
BookingReferenceRepository(18-79)packages/features/bookings/repositories/PrismaBookingAttendeeRepository.ts (1)
PrismaBookingAttendeeRepository(5-15)
🔇 Additional comments (34)
packages/features/bookings/lib/dto/IBookingAttendeeRepository.ts (1)
1-3: Clear repository contract.Looks good as a minimal interface for the cancellation flow.
packages/features/di/tokens.ts (1)
65-66: Token additions look consistent.No issues with the new DI tokens.
packages/lib/server/repository/dto/IProfileRepository.ts (1)
1-13: Interface definitions are clear.No concerns with these additions.
packages/features/bookings/repositories/PrismaBookingAttendeeRepository.ts (1)
5-14: Implementation aligns with the interface.Looks good.
apps/api/v2/src/lib/repositories/prisma-booking-reference.repository.ts (1)
6-10: DI wiring looks correct.No issues spotted.
packages/features/bookingReference/repositories/BookingReferenceRepository.ts (2)
7-22: DI-ready repository wiring looks good.Constructor injection + interface implementation are clear, and the expanded select matches the richer reference needs.
68-78: Update helper is straightforward.packages/lib/server/repository/dto/IBookingRepository.ts (1)
1-55: Repository contract additions look coherent.packages/features/profile/repositories/ProfileRepository.ts (4)
100-105: DI constructor + interface adoption look good.
216-223: Formatting-only change.
1019-1029: Formatting-only change.
1034-1041: Instance lookup method fits the DI use case.apps/api/v2/src/lib/repositories/prisma-profile.repository.ts (1)
1-10: DI wrapper for the profile repository looks solid.packages/features/users/di/Profile.module.ts (1)
1-22: ProfileRepository module binding is clean.packages/features/bookings/repositories/BookingRepository.ts (5)
13-31: Select helpers align with the new repository contract.
347-349: Interface implementation is clear.
1509-1514: Update-by-unique wrapper looks good.
1520-1543: Enriched update + select shape is clear.
1549-1565: Bulk fetch with reminders/references looks good.packages/features/bookings/lib/handleCancelBooking.ts (7)
21-51: Repository and enum imports look consistent.
89-153: Dependency injection fallback is clear.
Optional dependencies with a default repository construction keeps the handler usable in non-DI contexts.
299-393: Repository lookups integrated cleanly.
Organizer/profile fetches are now routed through repositories and the team payload stays consistent.
470-477: Workflow reminder typing is now explicit.
The narrowed shape aligns with the reminder cleanup usage.
542-558: Seat attendee cleanup and booking update look good.
639-639: Reference cleanup via repository is clear.
703-725: Service wiring to pass dependencies is solid.packages/features/bookings/di/BookingAttendeeRepository.module.ts (1)
1-20: DI module wiring looks good.packages/features/bookings/di/BookingReferenceRepository.module.ts (1)
1-22: DI module wiring looks good.apps/api/v2/src/lib/modules/booking-cancel.module.ts (1)
1-19: Provider registration aligns with the repository-based service.packages/platform/libraries/repositories.ts (1)
14-16: Repository re‑exports are consistent.packages/features/bookings/di/BookingCancelService.module.ts (1)
1-33: LGTM! Clean repository DI wiring.The module correctly replaces the single
prismaClientdependency with granular repository module loaders. The dependency names indepsMapalign with the constructor parameters expected byBookingCancelService, and the module loader pattern is consistent with the codebase conventions.packages/features/bookings/di/tokens.ts (1)
10-13: LGTM! New DI tokens follow established naming conventions.The new
BOOKING_REFERENCE_REPOSITORYandBOOKING_ATTENDEE_REPOSITORYtokens (with their module counterparts) follow the existing pattern in this file. The distinction from the existingATTENDEE_REPOSITORYtoken appears intentional for booking-specific attendee operations.apps/api/v2/src/lib/repositories/prisma-booking-attendee.repository.ts (1)
1-11: LGTM! Clean repository wrapper implementation.This thin wrapper correctly bridges NestJS dependency injection with the platform-libraries base repository. The pattern of injecting
PrismaWriteServiceand passingdbWrite.prismato the base class is consistent with other Prisma repositories in the codebase.apps/api/v2/src/lib/services/booking-cancel.service.ts (1)
12-26: LGTM! Repository injection follows DI best practices.The constructor now correctly injects five granular repositories instead of a single
PrismaWriteService, improving testability and separation of concerns. All five repository classes (PrismaUserRepository,PrismaBookingRepository,PrismaProfileRepository,PrismaBookingReferenceRepository,PrismaBookingAttendeeRepository) are properly registered as providers inBookingCancelModule, and the repository instances are correctly forwarded to the base class.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| async updateMany({ where, data }: { where: BookingWhereInput; data: BookingUpdateData }) { | ||
| await this.prismaClient.booking.updateMany({ | ||
| where: where, | ||
| data, | ||
| }); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd -t f "IBookingRepository" packages/features/bookingsRepository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 68
🏁 Script executed:
rg "interface IBookingRepository" -A 30 packages/features/bookings/Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 68
🏁 Script executed:
rg "IBookingRepository\|export interface.*BookingRepository" packages/features/bookings/ -A 20Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 68
🏁 Script executed:
cat -n packages/features/bookings/repositories/BookingRepository.ts | sed -n '1490,1520p'Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 1116
🏁 Script executed:
rg "updateMany" packages/features/bookings/repositories/ -B 2 -A 2Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 628
🏁 Script executed:
rg "class BookingRepository" packages/features/bookings/repositories/ -A 5Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 698
🏁 Script executed:
rg "interface IBookingRepository|type IBookingRepository" packages/features/bookings/ -A 50Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 68
🏁 Script executed:
head -50 packages/features/bookings/repositories/BookingRepository.tsRepository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 1452
🏁 Script executed:
fd "IBookingRepository" -type fRepository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 256
🏁 Script executed:
fd "IBookingRepository" -t fRepository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 142
🏁 Script executed:
cat -n packages/lib/server/repository/dto/IBookingRepository.tsRepository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 1761
Return the updateMany result to honor the interface contract.
The IBookingRepository interface (line 48 of packages/lib/server/repository/dto/IBookingRepository.ts) specifies that updateMany must return Promise<{ count: number }>, but the current implementation discards the Prisma result. Change await to return to match the interface contract and allow callers to access the count.
🛠️ Suggested fix
- async updateMany({ where, data }: { where: BookingWhereInput; data: BookingUpdateData }) {
- await this.prismaClient.booking.updateMany({
- where: where,
- data,
- });
- }
+ async updateMany({ where, data }: { where: BookingWhereInput; data: BookingUpdateData }) {
+ return this.prismaClient.booking.updateMany({
+ where,
+ data,
+ });
+ }📝 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.
| async updateMany({ where, data }: { where: BookingWhereInput; data: BookingUpdateData }) { | |
| await this.prismaClient.booking.updateMany({ | |
| where: where, | |
| data, | |
| }); | |
| } | |
| async updateMany({ where, data }: { where: BookingWhereInput; data: BookingUpdateData }) { | |
| return this.prismaClient.booking.updateMany({ | |
| where, | |
| data, | |
| }); | |
| } |
🤖 Prompt for AI Agents
In `@packages/features/bookings/repositories/BookingRepository.ts` around lines
1502 - 1507, The updateMany implementation in BookingRepository currently awaits
but does not return the Prisma result, violating IBookingRepository.updateMany's
Promise<{ count: number }> contract; modify BookingRepository.updateMany so it
returns the result of this.prismaClient.booking.updateMany(...) (i.e., replace
the lone await with a return of prismaClient.booking.updateMany) so callers can
receive the { count } response consistent with the IBookingRepository interface.
Benchmark PR from agentic-review-benchmarks#3
Summary by CodeRabbit
Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.