Skip to content

Commit 13e2e34

Browse files
refactor: convert handleNotificationWhenNoSlots to service class with DI (calcom#23055)
* refactor: convert handleNotificationWhenNoSlots to service class with DI - Convert standalone handleNotificationWhenNoSlots function to NoSlotsNotificationService class - Add INoSlotsNotificationService interface following existing patterns - Create NoSlotsNotification DI module and add to container - Add NO_SLOTS_NOTIFICATION_SERVICE tokens to DI_TOKENS - Inject service into AvailableSlotsService dependencies - Update AvailableSlotsService to use injected service instead of direct function call - Update all test cases to use service class pattern - Follows existing DI patterns used by other services like BusyTimesService and CheckBookingLimitsService Co-Authored-By: morgan@cal.com <morgan@cal.com> * refactor: move Prisma calls to repositories and create dedicated DI container - Add findOrganizationSettingsBySlug and findTeamSlugById methods to TeamRepository - Add findTeamAdminsByTeamId method to MembershipRepository - Create MembershipRepository DI module and tokens - Update NoSlotsNotificationService to inject TeamRepository, MembershipRepository, and Redis client - Create dedicated DI container for NoSlotsNotificationService - Update AvailableSlots DI container to include MembershipRepository - Replace direct Prisma and Redis calls with repository methods and injected client - Update tests to use DI container instead of direct service instantiation - Fix Redis interface import path Co-Authored-By: morgan@cal.com <morgan@cal.com> * chore: DI noSlotsNotification service * chore: bump library --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: morgan@cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
1 parent 0af62da commit 13e2e34

19 files changed

Lines changed: 258 additions & 124 deletions

apps/api/v2/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"@axiomhq/winston": "^1.2.0",
3939
"@calcom/platform-constants": "*",
4040
"@calcom/platform-enums": "*",
41-
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.311",
41+
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.312",
4242
"@calcom/platform-types": "*",
4343
"@calcom/platform-utils": "*",
4444
"@calcom/prisma": "*",

apps/api/v2/src/lib/modules/available-slots.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PrismaBookingRepository } from "@/lib/repositories/prisma-booking.repository";
22
import { PrismaEventTypeRepository } from "@/lib/repositories/prisma-event-type.repository";
33
import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository";
4+
import { PrismaMembershipRepository } from "@/lib/repositories/prisma-membership.repository";
45
import { PrismaOOORepository } from "@/lib/repositories/prisma-ooo.repository";
56
import { PrismaRoutingFormResponseRepository } from "@/lib/repositories/prisma-routing-form-response.repository";
67
import { PrismaScheduleRepository } from "@/lib/repositories/prisma-schedule.repository";
@@ -12,6 +13,7 @@ import { BusyTimesService } from "@/lib/services/busy-times.service";
1213
import { CacheService } from "@/lib/services/cache.service";
1314
import { CheckBookingLimitsService } from "@/lib/services/check-booking-limits.service";
1415
import { FilterHostsService } from "@/lib/services/filter-hosts.service";
16+
import { NoSlotsNotificationService } from "@/lib/services/no-slots-notification.service";
1517
import { QualifiedHostsService } from "@/lib/services/qualified-hosts.service";
1618
import { UserAvailabilityService } from "@/lib/services/user-availability.service";
1719
import { PrismaModule } from "@/modules/prisma/prisma.module";
@@ -31,13 +33,15 @@ import { Module } from "@nestjs/common";
3133
PrismaTeamRepository,
3234
RedisService,
3335
PrismaFeaturesRepository,
36+
PrismaMembershipRepository,
3437
CheckBookingLimitsService,
3538
CacheService,
3639
AvailableSlotsService,
3740
UserAvailabilityService,
3841
BusyTimesService,
3942
FilterHostsService,
4043
QualifiedHostsService,
44+
NoSlotsNotificationService,
4145
],
4246
exports: [AvailableSlotsService],
4347
})
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
2+
import { Injectable } from "@nestjs/common";
3+
4+
import { PrismaMembershipRepository as PrismaMembershipRepositoryLib } from "@calcom/platform-libraries/repositories";
5+
import { PrismaClient } from "@calcom/prisma";
6+
7+
@Injectable()
8+
export class PrismaMembershipRepository extends PrismaMembershipRepositoryLib {
9+
constructor(private readonly dbWrite: PrismaWriteService) {
10+
super(dbWrite.prisma as unknown as PrismaClient);
11+
}
12+
}

apps/api/v2/src/lib/services/available-slots.service.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { PrismaUserRepository } from "@/lib/repositories/prisma-user.repository"
1010
import { BusyTimesService } from "@/lib/services/busy-times.service";
1111
import { CacheService } from "@/lib/services/cache.service";
1212
import { CheckBookingLimitsService } from "@/lib/services/check-booking-limits.service";
13+
import { NoSlotsNotificationService } from "@/lib/services/no-slots-notification.service";
1314
import { QualifiedHostsService } from "@/lib/services/qualified-hosts.service";
1415
import { RedisService } from "@/modules/redis/redis.service";
1516
import { Injectable } from "@nestjs/common";
@@ -35,7 +36,8 @@ export class AvailableSlotsService extends BaseAvailableSlotsService {
3536
checkBookingLimitsService: CheckBookingLimitsService,
3637
cacheService: CacheService,
3738
userAvailabilityService: UserAvailabilityService,
38-
busyTimesService: BusyTimesService
39+
busyTimesService: BusyTimesService,
40+
noSlotsNotificationService: NoSlotsNotificationService
3941
) {
4042
super({
4143
oooRepo: oooRepoDependency,
@@ -53,6 +55,7 @@ export class AvailableSlotsService extends BaseAvailableSlotsService {
5355
busyTimesService,
5456
qualifiedHostsService,
5557
featuresRepo: featuresRepository,
58+
noSlotsNotificationService,
5659
});
5760
}
5861
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { PrismaMembershipRepository } from "@/lib/repositories/prisma-membership.repository";
2+
import { PrismaTeamRepository } from "@/lib/repositories/prisma-team.repository";
3+
import { RedisService } from "@/modules/redis/redis.service";
4+
import { Injectable } from "@nestjs/common";
5+
6+
import { NoSlotsNotificationService as BaseNoSlotsNotificationService } from "@calcom/platform-libraries/slots";
7+
8+
@Injectable()
9+
export class NoSlotsNotificationService extends BaseNoSlotsNotificationService {
10+
constructor(
11+
teamRepository: PrismaTeamRepository,
12+
membershipRepository: PrismaMembershipRepository,
13+
redisService: RedisService
14+
) {
15+
super({
16+
teamRepo: teamRepository,
17+
membershipRepo: membershipRepository,
18+
redisClient: redisService,
19+
});
20+
}
21+
}

packages/lib/di/containers/AvailableSlots.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { eventTypeRepositoryModule } from "../modules/EventType";
1414
import { featuresRepositoryModule } from "../modules/Features";
1515
import { filterHostsModule } from "../modules/FilterHosts";
1616
import { getUserAvailabilityModule } from "../modules/GetUserAvailability";
17+
import { membershipRepositoryModule } from "../modules/Membership";
18+
import { noSlotsNotificationModule } from "../modules/NoSlotsNotification";
1719
import { oooRepositoryModule } from "../modules/Ooo";
1820
import { qualifiedHostsModule } from "../modules/QualifiedHosts";
1921
import { routingFormResponseRepositoryModule } from "../modules/RoutingFormResponse";
@@ -29,6 +31,7 @@ container.load(DI_TOKENS.OOO_REPOSITORY_MODULE, oooRepositoryModule);
2931
container.load(DI_TOKENS.SCHEDULE_REPOSITORY_MODULE, scheduleRepositoryModule);
3032
container.load(DI_TOKENS.SELECTED_SLOT_REPOSITORY_MODULE, selectedSlotsRepositoryModule);
3133
container.load(DI_TOKENS.TEAM_REPOSITORY_MODULE, teamRepositoryModule);
34+
container.load(DI_TOKENS.MEMBERSHIP_REPOSITORY_MODULE, membershipRepositoryModule);
3235
container.load(DI_TOKENS.USER_REPOSITORY_MODULE, userRepositoryModule);
3336
container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule);
3437
container.load(DI_TOKENS.EVENT_TYPE_REPOSITORY_MODULE, eventTypeRepositoryModule);
@@ -42,6 +45,7 @@ container.load(DI_TOKENS.BUSY_TIMES_SERVICE_MODULE, busyTimesModule);
4245
container.load(DI_TOKENS.BUSY_TIMES_SERVICE_MODULE, busyTimesModule);
4346
container.load(DI_TOKENS.FILTER_HOSTS_SERVICE_MODULE, filterHostsModule);
4447
container.load(DI_TOKENS.QUALIFIED_HOSTS_SERVICE_MODULE, qualifiedHostsModule);
48+
container.load(DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE_MODULE, noSlotsNotificationModule);
4549

4650
export function getAvailableSlotsService() {
4751
return container.get<AvailableSlotsService>(DI_TOKENS.AVAILABLE_SLOTS_SERVICE);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createContainer } from "@evyweb/ioctopus";
2+
3+
import { redisModule } from "@calcom/features/redis/di/redisModule";
4+
import { DI_TOKENS } from "@calcom/lib/di/tokens";
5+
import { prismaModule } from "@calcom/prisma/prisma.module";
6+
import type { NoSlotsNotificationService } from "@calcom/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots";
7+
8+
import { membershipRepositoryModule } from "../modules/Membership";
9+
import { noSlotsNotificationModule } from "../modules/NoSlotsNotification";
10+
import { teamRepositoryModule } from "../modules/Team";
11+
12+
const container = createContainer();
13+
container.load(DI_TOKENS.REDIS_CLIENT, redisModule);
14+
container.load(DI_TOKENS.PRISMA_MODULE, prismaModule);
15+
container.load(DI_TOKENS.TEAM_REPOSITORY_MODULE, teamRepositoryModule);
16+
container.load(DI_TOKENS.MEMBERSHIP_REPOSITORY_MODULE, membershipRepositoryModule);
17+
container.load(DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE_MODULE, noSlotsNotificationModule);
18+
19+
export function getNoSlotsNotificationService() {
20+
return container.get<NoSlotsNotificationService>(DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE);
21+
}

packages/lib/di/modules/AvailableSlots.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ availableSlotsModule.bind(DI_TOKENS.AVAILABLE_SLOTS_SERVICE).toClass(AvailableSl
2222
busyTimesService: DI_TOKENS.BUSY_TIMES_SERVICE,
2323
featuresRepo: DI_TOKENS.FEATURES_REPOSITORY,
2424
qualifiedHostsService: DI_TOKENS.QUALIFIED_HOSTS_SERVICE,
25+
noSlotsNotificationService: DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE,
2526
} satisfies Record<keyof IAvailableSlotsService, symbol>);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { createModule } from "@evyweb/ioctopus";
2+
3+
import { DI_TOKENS } from "@calcom/lib/di/tokens";
4+
import { MembershipRepository } from "@calcom/lib/server/repository/membership";
5+
6+
export const membershipRepositoryModule = createModule();
7+
membershipRepositoryModule
8+
.bind(DI_TOKENS.MEMBERSHIP_REPOSITORY)
9+
.toClass(MembershipRepository, [DI_TOKENS.PRISMA_CLIENT]);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { createModule } from "@evyweb/ioctopus";
2+
3+
import type { INoSlotsNotificationService } from "@calcom/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots";
4+
import { NoSlotsNotificationService } from "@calcom/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots";
5+
6+
import { DI_TOKENS } from "../tokens";
7+
8+
export const noSlotsNotificationModule = createModule();
9+
noSlotsNotificationModule.bind(DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE).toClass(NoSlotsNotificationService, {
10+
teamRepo: DI_TOKENS.TEAM_REPOSITORY,
11+
membershipRepo: DI_TOKENS.MEMBERSHIP_REPOSITORY,
12+
redisClient: DI_TOKENS.REDIS_CLIENT,
13+
} satisfies Record<keyof INoSlotsNotificationService, symbol>);

0 commit comments

Comments
 (0)