Skip to content

Commit 0b4fa8f

Browse files
author
Hariom Balhara
committed
Merge remote-tracking branch 'origin/main' into feat/org-payment-before-creation
2 parents ba335de + 5d709cf commit 0b4fa8f

File tree

292 files changed

+24443
-12206
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

292 files changed

+24443
-12206
lines changed

.env.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL=
288288
# use organizations
289289
ORGANIZATIONS_ENABLED=
290290
NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS=30
291-
NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE=3700 # $37.00 per seat
291+
NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW=37 # $37.00 per seat
292292

293293
# This variable should only be set to 1 or true if you want to autolink external provider sign-ups with
294294
# existing organizations based on email domain address

.yarn/versions/3c2036fd.yml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
undecided:
2+
- calcom-monorepo
3+
- "@calcom/prisma"

.yarn/versions/97a32d13.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
undecided:
2+
- "@calcom/app-store-cli"
3+
- "@calcom/platform-constants"
4+
- "@calcom/platform-enums"
5+
- "@calcom/platform-types"
6+
- "@calcom/platform-utils"

.yarn/versions/b7d8df6e.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
undecided:
2+
- calcom-monorepo
3+
- "@calcom/app-store-cli"
4+
- "@calcom/platform-constants"
5+
- "@calcom/platform-enums"
6+
- "@calcom/platform-types"
7+
- "@calcom/platform-utils"
8+
- "@calcom/prisma"

PR_TODO.md

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
Description:
2+
- Org is now created only through stripe webhook and thus code has been adapted to be idempotent in case of retries from Stripe when failure happens.
3+
- We store the complete progress of the onboarding in OrganizationOnboarding table including any error that last happened and the end of lifecycle with isComplete set to true.
4+
- Admin can configure a custom price for a customer(identified by email) and handover the onboarding to the customer(through a handover onboarding link). In this way, the customer still setups the onboarding himself but pays a custom price.
5+
- Admin Doing organization onboarding on behalf of an email that doesn't exist in our system, is temporarily disabled. [Can be enabled in the future if needed]
6+
- Earlier Organization onboarding updated DB step by step but now in one go after the payment, we create everything - Domain Creation, Org Setup, Teams Creation, Teams Migration, Migrating Teams' members migration, member invitations. So, we have been extra careful with the logic to ensure errors don;t occur and if occur they are retried by webhook and also recorded in OrganizationOnboarding table.
7+
8+
Deprecations/Removals:
9+
- NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE env variable is removed and user must set NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW with the difference that it doesn't have 00 in the end (37 instead of 3700 now). Reason was that 00 is a stripe specific thing and also because we store the price in DB with OrganizationOnboarding record and it doesn't make sense for it to be 3700 when infact it is 37.
10+
111
Deployment Plan:
212
- [ ] Need Stripe Product ID in Env variable
313
- [ ] Set NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW to 37
@@ -52,6 +62,8 @@ Testing:
5262

5363
Followup Improvements:
5464
- [ ] If due to the number of people being invited during the onboarding if the seats increase, we should show that as a toast in the last onboarding step
65+
- [ ] Onboarding handover URL should take the user to the first step(intead of second step) where he could review the org and price details first
66+
- [ ] Allow admin to change the price of an existing onboarding. This is important because the admin might need to change the price of the onboarding after it is created and there can only be one onboarding for an orgOwner email.
5567
- [ ] Logo upload isn't working form onboarding(Existing bug)
5668
- [ ] Send telemetry event for org creation,
5769
- [ ] What if renewal of plan fails? Need to handle that.

apps/api/v2/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"@axiomhq/winston": "^1.2.0",
3131
"@calcom/platform-constants": "*",
3232
"@calcom/platform-enums": "*",
33-
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.95",
33+
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.99",
3434
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
3535
"@calcom/platform-types": "*",
3636
"@calcom/platform-utils": "*",
@@ -61,6 +61,7 @@
6161
"helmet": "^7.1.0",
6262
"ioredis": "^5.3.2",
6363
"jsforce": "^1.11.0",
64+
"lodash": "^4.17.21",
6465
"luxon": "^3.4.4",
6566
"nest-winston": "^1.9.4",
6667
"next-auth": "^4.22.1",

apps/api/v2/src/ee/bookings/2024-04-15/inputs/create-booking.input.ts

+15
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,19 @@ export class CreateBookingInput_2024_04_15 {
169169
label?: string | undefined;
170170
}
171171
>;
172+
173+
@IsString()
174+
@IsOptional()
175+
@ApiPropertyOptional()
176+
teamMemberEmail?: string;
177+
178+
@IsString()
179+
@IsOptional()
180+
@ApiPropertyOptional()
181+
crmAppSlug?: string;
182+
183+
@IsString()
184+
@IsOptional()
185+
@ApiPropertyOptional()
186+
crmOwnerRecordType?: string;
172187
}

apps/api/v2/src/ee/bookings/2024-08-13/controllers/e2e/booking-fields.e2e-spec.ts

-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,6 @@ describe("Bookings Endpoints 2024-08-13", () => {
455455
// eslint-disable-next-line
456456
// @ts-ignore
457457
const data: GetSeatedBookingOutput_2024_08_13 = responseBody.data;
458-
console.log("asap data", JSON.stringify(data, null, 2));
459458
expect(data.attendees[0].name).toEqual(`${splitName.firstName} ${splitName.lastName}`);
460459
expect(data.attendees[0].bookingFieldsResponses.name).toEqual(splitName);
461460
} else {

apps/api/v2/src/ee/bookings/2024-08-13/controllers/e2e/user-bookings.e2e-spec.ts

+25
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
167167
timeZone: "Europe/Rome",
168168
},
169169
},
170+
rating: 10,
170171
});
171172

172173
app = moduleRef.createNestApplication();
@@ -552,6 +553,30 @@ describe("Bookings Endpoints 2024-08-13", () => {
552553
});
553554
});
554555

556+
it("should should get a booking with rating", async () => {
557+
return request(app.getHttpServer())
558+
.get(`/v2/bookings/${bookingInThePast.uid}`)
559+
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
560+
.expect(200)
561+
.then(async (response) => {
562+
const responseBody: GetBookingOutput_2024_08_13 = response.body;
563+
expect(responseBody.status).toEqual(SUCCESS_STATUS);
564+
expect(responseBody.data).toBeDefined();
565+
expect(responseDataIsBooking(responseBody.data)).toBe(true);
566+
567+
if (responseDataIsBooking(responseBody.data)) {
568+
const data: BookingOutput_2024_08_13 = responseBody.data;
569+
expect(data.id).toEqual(bookingInThePast.id);
570+
expect(data.uid).toEqual(bookingInThePast.uid);
571+
expect(data.rating).toEqual(bookingInThePast.rating);
572+
} else {
573+
throw new Error(
574+
"Invalid response data - expected booking but received array of possibily recurring bookings"
575+
);
576+
}
577+
});
578+
});
579+
555580
it("should should get 1 recurrence of a recurring booking", async () => {
556581
const recurrenceUid = createdRecurringBooking[0].uid;
557582
return request(app.getHttpServer())

apps/api/v2/src/ee/bookings/2024-08-13/services/output.service.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ export class OutputBookingsService_2024_08_13 {
133133
absentHost: !!databaseBooking.noShowHost,
134134
createdAt: databaseBooking.createdAt,
135135
updatedAt: databaseBooking.updatedAt,
136+
rating: databaseBooking.rating,
136137
};
137138

138139
const bookingTransformed = plainToClass(BookingOutput_2024_08_13, booking, { strategy: "excludeAll" });
@@ -227,6 +228,7 @@ export class OutputBookingsService_2024_08_13 {
227228
bookingFieldsResponses: databaseBooking.responses,
228229
createdAt: databaseBooking.createdAt,
229230
updatedAt: databaseBooking.updatedAt,
231+
rating: databaseBooking.rating,
230232
};
231233

232234
const bookingTransformed = plainToClass(RecurringBookingOutput_2024_08_13, booking, {
@@ -274,6 +276,7 @@ export class OutputBookingsService_2024_08_13 {
274276
absentHost: !!databaseBooking.noShowHost,
275277
createdAt: databaseBooking.createdAt,
276278
updatedAt: databaseBooking.updatedAt,
279+
rating: databaseBooking.rating,
277280
};
278281

279282
const parsed = plainToClass(GetSeatedBookingOutput_2024_08_13, booking, { strategy: "excludeAll" });
@@ -283,7 +286,8 @@ export class OutputBookingsService_2024_08_13 {
283286
const { responses } = safeParse(
284287
seatedBookingDataSchema,
285288
attendee.bookingSeat?.data,
286-
defaultSeatedBookingData
289+
defaultSeatedBookingData,
290+
false
287291
);
288292

289293
const attendeeData = {
@@ -300,7 +304,8 @@ export class OutputBookingsService_2024_08_13 {
300304
attendeeParsed.metadata = safeParse(
301305
seatedBookingMetadataSchema,
302306
attendee.bookingSeat?.metadata,
303-
defaultSeatedBookingMetadata
307+
defaultSeatedBookingMetadata,
308+
false
304309
);
305310
// note(Lauris): as of now email is not returned for privacy
306311
delete attendeeParsed.bookingFieldsResponses.email;
@@ -380,6 +385,7 @@ export class OutputBookingsService_2024_08_13 {
380385
absentHost: !!databaseBooking.noShowHost,
381386
createdAt: databaseBooking.createdAt,
382387
updatedAt: databaseBooking.updatedAt,
388+
rating: databaseBooking.rating,
383389
};
384390

385391
const parsed = plainToClass(GetRecurringSeatedBookingOutput_2024_08_13, booking, {
@@ -391,7 +397,8 @@ export class OutputBookingsService_2024_08_13 {
391397
const { responses } = safeParse(
392398
seatedBookingDataSchema,
393399
attendee.bookingSeat?.data,
394-
defaultSeatedBookingData
400+
defaultSeatedBookingData,
401+
false
395402
);
396403

397404
const attendeeData = {
@@ -408,7 +415,8 @@ export class OutputBookingsService_2024_08_13 {
408415
attendeeParsed.metadata = safeParse(
409416
seatedBookingMetadataSchema,
410417
attendee.bookingSeat?.metadata,
411-
defaultSeatedBookingMetadata
418+
defaultSeatedBookingMetadata,
419+
false
412420
);
413421
// note(Lauris): as of now email is not returned for privacy
414422
delete attendeeParsed.bookingFieldsResponses.email;

apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts

+28-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
Post,
3535
Body,
3636
} from "@nestjs/common";
37-
import { ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger";
37+
import { ApiOperation, ApiParam, ApiTags as DocsTags } from "@nestjs/swagger";
3838
import { User } from "@prisma/client";
3939
import { plainToClass } from "class-transformer";
4040
import { Request } from "express";
@@ -123,10 +123,15 @@ export class CalendarsController {
123123
};
124124
}
125125

126+
@ApiParam({
127+
enum: [OFFICE_365_CALENDAR, GOOGLE_CALENDAR],
128+
type: String,
129+
name: "calendar",
130+
})
126131
@UseGuards(ApiAuthGuard)
127132
@Get("/:calendar/connect")
128133
@HttpCode(HttpStatus.OK)
129-
@ApiOperation({ summary: "Get connect URL" })
134+
@ApiOperation({ summary: "Get oAuth connect URL" })
130135
async redirect(
131136
@Req() req: Request,
132137
@Headers("Authorization") authorization: string,
@@ -146,10 +151,15 @@ export class CalendarsController {
146151
}
147152
}
148153

154+
@ApiParam({
155+
enum: [OFFICE_365_CALENDAR, GOOGLE_CALENDAR],
156+
type: String,
157+
name: "calendar",
158+
})
149159
@Get("/:calendar/save")
150160
@HttpCode(HttpStatus.OK)
151161
@Redirect(undefined, 301)
152-
@ApiOperation({ summary: "Save a calendar" })
162+
@ApiOperation({ summary: "Save an oAuth calendar credentials" })
153163
async save(
154164
@Query("state") state: string,
155165
@Query("code") code: string,
@@ -177,6 +187,11 @@ export class CalendarsController {
177187
}
178188
}
179189

190+
@ApiParam({
191+
enum: [APPLE_CALENDAR],
192+
type: String,
193+
name: "calendar",
194+
})
180195
@UseGuards(ApiAuthGuard)
181196
@Post("/:calendar/credentials")
182197
@ApiOperation({ summary: "Sync credentials" })
@@ -198,6 +213,11 @@ export class CalendarsController {
198213
}
199214
}
200215

216+
@ApiParam({
217+
enum: [APPLE_CALENDAR, GOOGLE_CALENDAR, OFFICE_365_CALENDAR],
218+
type: String,
219+
name: "calendar",
220+
})
201221
@Get("/:calendar/check")
202222
@HttpCode(HttpStatus.OK)
203223
@UseGuards(ApiAuthGuard, PermissionsGuard)
@@ -219,6 +239,11 @@ export class CalendarsController {
219239
}
220240
}
221241

242+
@ApiParam({
243+
enum: [APPLE_CALENDAR, GOOGLE_CALENDAR, OFFICE_365_CALENDAR],
244+
type: String,
245+
name: "calendar",
246+
})
222247
@UseGuards(ApiAuthGuard)
223248
@Post("/:calendar/disconnect")
224249
@HttpCode(HttpStatus.OK)

apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ import { InputEventTransformed_2024_06_14 } from "@calcom/platform-types";
77

88
@Injectable()
99
export class EventTypesRepository_2024_06_14 {
10-
constructor(
11-
private readonly dbRead: PrismaReadService,
12-
private readonly dbWrite: PrismaWriteService,
13-
private usersService: UsersService
14-
) {}
10+
constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {}
1511

1612
async createUserEventType(
1713
userId: number,
@@ -47,6 +43,13 @@ export class EventTypesRepository_2024_06_14 {
4743
});
4844
}
4945

46+
async getEventTypeWithHosts(eventTypeId: number) {
47+
return this.dbRead.prisma.eventType.findUnique({
48+
where: { id: eventTypeId },
49+
include: { hosts: true },
50+
});
51+
}
52+
5053
async getUserEventType(userId: number, eventTypeId: number) {
5154
return this.dbRead.prisma.eventType.findFirst({
5255
where: {

apps/api/v2/src/ee/event-types/event-types_2024_06_14/outputs/create-phone-call.output.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ApiProperty } from "@nestjs/swagger";
22
import { Type } from "class-transformer";
3-
import { IsEnum, IsString, ValidateNested } from "class-validator";
3+
import { IsEnum, IsString, ValidateNested, IsOptional } from "class-validator";
44

55
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
66

@@ -10,8 +10,9 @@ class Data {
1010
callId!: string;
1111

1212
@IsString()
13+
@IsOptional()
1314
@ApiProperty()
14-
agentId!: string;
15+
agentId?: string;
1516
}
1617

1718
export class CreatePhoneCallOutput {

apps/api/v2/src/ee/platform-endpoints-module.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { MeModule } from "@/ee/me/me.module";
88
import { ProviderModule } from "@/ee/provider/provider.module";
99
import { SchedulesModule_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/schedules.module";
1010
import { SchedulesModule_2024_06_11 } from "@/ee/schedules/schedules_2024_06_11/schedules.module";
11-
import { SlotsModule } from "@/modules/slots/slots.module";
11+
import { SlotsModule_2024_04_15 } from "@/modules/slots/slots-2024-04-15/slots.module";
12+
import { SlotsModule_2024_09_04 } from "@/modules/slots/slots-2024-09-04/slots.module";
1213
import { TeamsEventTypesModule } from "@/modules/teams/event-types/teams-event-types.module";
1314
import { TeamsMembershipsModule } from "@/modules/teams/memberships/teams-memberships.module";
1415
import { TeamsModule } from "@/modules/teams/teams/teams.module";
@@ -29,7 +30,8 @@ import { Module } from "@nestjs/common";
2930
BookingsModule_2024_04_15,
3031
BookingsModule_2024_08_13,
3132
TeamsMembershipsModule,
32-
SlotsModule,
33+
SlotsModule_2024_04_15,
34+
SlotsModule_2024_09_04,
3335
TeamsModule,
3436
],
3537
})

apps/api/v2/src/lib/api-versions.ts

+3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@ import {
66
VERSION_2024_06_11,
77
VERSION_2024_06_14,
88
VERSION_2024_08_13,
9+
VERSION_2024_09_04,
910
} from "@calcom/platform-constants";
1011

1112
export const API_VERSIONS_VALUES: VersionValue = API_VERSIONS as unknown as VersionValue;
1213
export const VERSION_2024_06_14_VALUE: VersionValue = VERSION_2024_06_14 as unknown as VersionValue;
1314
export const VERSION_2024_06_11_VALUE: VersionValue = VERSION_2024_06_11 as unknown as VersionValue;
1415
export const VERSION_2024_04_15_VALUE: VersionValue = VERSION_2024_04_15 as unknown as VersionValue;
1516
export const VERSION_2024_08_13_VALUE: VersionValue = VERSION_2024_08_13 as unknown as VersionValue;
17+
export const VERSION_2024_09_04_VALUE: VersionValue = VERSION_2024_09_04 as unknown as VersionValue;
1618

1719
export { VERSION_2024_04_15 };
1820
export { VERSION_2024_06_11 };
1921
export { VERSION_2024_06_14 };
2022
export { VERSION_2024_08_13 };
23+
export { VERSION_2024_09_04 };

0 commit comments

Comments
 (0)