Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
c141adc
feat: Add all audit action services to booking-audit-more-infra
hariombalhara Nov 29, 2025
7b350fd
feat: Add BookingAuditViewerService demo with CREATED action only
hariombalhara Nov 29, 2025
fde380a
feat: Implement booking audit producer-consumer pattern with feature …
hariombalhara Nov 29, 2025
12e12a4
fix: restore accidentally deleted getAuditLogs files
hariombalhara Nov 29, 2025
0ce15a5
fix: restore BookingAuditViewerService files
hariombalhara Nov 29, 2025
b543e81
Add plan for more actions
hariombalhara Nov 14, 2025
ae7bc05
feat(audit): add linkedBookingUid support for booking relationships
hariombalhara Nov 17, 2025
e6029a0
feat(audit): integrate endpoints with bookingEventHandlerService
hariombalhara Nov 17, 2025
3618b5a
feat: Add todo.md for tracking audit integration tasks
hariombalhara Nov 28, 2025
ee5174b
feat: Implement Booking Audit System with Tasker Integration
hariombalhara Dec 1, 2025
96f0855
refactor: Transition to BookingAuditTaskConsumer for audit actions
hariombalhara Dec 1, 2025
a1d46de
feat: Add all audit action services to booking-audit-more-infra
hariombalhara Nov 29, 2025
ea1a499
feat: Add BookingAuditViewerService demo with CREATED action only
hariombalhara Nov 29, 2025
08df744
feat: Implement Booking Audit System with Tasker Integration
hariombalhara Dec 1, 2025
a996c34
refactor: Enhance BookingLogsView with improved filtering and display…
hariombalhara Dec 1, 2025
cfd43aa
feat: Introduce TaskerService for improved task management
hariombalhara Dec 2, 2025
983d7c5
refactor: Enhance BookingLogsView with new filtering components and i…
hariombalhara Dec 4, 2025
c6d10ba
refactor: Convert Task class to TaskRepository with instance methods
devin-ai-integration[bot] Dec 6, 2025
90778c5
fix failing tests
hariombalhara Dec 6, 2025
b92ca4b
Merge branch 'main' into booking-audit-viewer-demo
hariombalhara Dec 6, 2025
8fc2fb9
Merge branch 'booking-audit-viewer-demo' into booking-audit-more-infra
hariombalhara Dec 6, 2025
0961aa9
Merge booking-audit-all-integration into booking-audit-more-infra
hariombalhara Dec 6, 2025
229874a
Enhance booking audit logging and refactor services
hariombalhara Dec 6, 2025
9f64654
Enhance booking audit services and improve logging
hariombalhara Dec 6, 2025
f4c957a
Merge main into booking-audit-more-infra
hariombalhara Dec 8, 2025
2e48fdc
Refactor booking audit services to enhance user tracking and logging
hariombalhara Dec 8, 2025
72cd20a
update architecture.md
hariombalhara Dec 8, 2025
d3c5033
Merge remote-tracking branch 'origin/booking-audit-more-infra' into b…
hariombalhara Dec 8, 2025
b77cc1c
Enhance booking audit infrastructure with improved translation suppor…
hariombalhara Dec 9, 2025
951007e
feat: add booking audit action services for lib/actions folder
devin-ai-integration[bot] Dec 9, 2025
40235ab
refactor: update AttendeeRemovedAuditActionService to correctly filte…
hariombalhara Dec 9, 2025
38df3e0
refactor: update attendee tracking in booking audit services
hariombalhara Dec 9, 2025
c56f337
Merge remote-tracking branch 'origin/devin/lib-actions-only-176526206…
hariombalhara Dec 9, 2025
da7226b
refactor: update AcceptedAuditActionService to use BookingStatus enum
hariombalhara Dec 9, 2025
5d73f55
Merge remote-tracking branch 'origin/main' into booking-audit-more-infra
hariombalhara Dec 9, 2025
d549595
refactor: update booking logs view and audit services for rescheduling
hariombalhara Dec 9, 2025
4919303
feat: add uuid plumbing from API v2 to packages/features
devin-ai-integration[bot] Dec 9, 2025
074f401
fix: correct indentation in bookings.controller.ts
devin-ai-integration[bot] Dec 9, 2025
2c2279a
refactor: rename getOwnerId to getOwner and return user object with i…
devin-ai-integration[bot] Dec 9, 2025
745b745
Merge remote-tracking branch 'origin/devin/uuid-plumbing-1765274128' …
hariombalhara Dec 9, 2025
256aec8
Merge remote-tracking branch 'origin/main' into booking-audit-more-infra
hariombalhara Dec 9, 2025
4c3ebe8
feat: enhance booking logs view with display fields and JSON viewer
hariombalhara Dec 9, 2025
cf39c1d
feat: enhance booking logs view with display fields and JSON viewer
hariombalhara Dec 9, 2025
9d4e3d2
feat: extract core booking audit infrastructure from PR 25125
devin-ai-integration[bot] Dec 9, 2025
589f76c
fix: make booking audit interfaces backwards-compatible with main
devin-ai-integration[bot] Dec 9, 2025
2dc949b
fix switch eslint and ts
hariombalhara Dec 10, 2025
046cbc5
fix switch eslint and ts
hariombalhara Dec 10, 2025
3421820
feat: implement booking audit access control and logging
hariombalhara Dec 10, 2025
3ebb113
Merge branch '11-14-add_plan_for_more_actions' into booking-audit-mor…
hariombalhara Dec 10, 2025
76fdf8a
feat: add seat booking and rescheduling audit actions
hariombalhara Dec 10, 2025
2e538f2
feat: refactor action source handling in booking audit services
hariombalhara Dec 11, 2025
e584cce
refactor: streamline booking event handling and actor retrieval
hariombalhara Dec 11, 2025
19051c8
feat: enhance booking audit logging with action source tracking
hariombalhara Dec 11, 2025
1cedf7d
feat: integrate PrismaAuditActorRepository for enhanced booking audit…
hariombalhara Dec 12, 2025
079fb78
feat: enhance BookingAuditViewerService with logging and type improve…
hariombalhara Dec 12, 2025
4c4f290
Readme
hariombalhara Dec 13, 2025
7251321
Update migration
hariombalhara Dec 13, 2025
a285479
feat: enhance booking audit system with actor and source tracking
hariombalhara Dec 13, 2025
3364d60
feat: enhance payment success handling with app actor integration
hariombalhara Dec 15, 2025
2b956ca
feat: add missing booking audit calls and fix actor attribution
devin-ai-integration[bot] Dec 15, 2025
f8b41f7
Merge branch 'devin/booking-audit-core-1765285076' into booking-audit…
hariombalhara Dec 15, 2025
89b8a24
fix: replace BookingAuditTaskBasePayload with BookingAuditTaskConsume…
hariombalhara Dec 15, 2025
5d85163
Merged devin/booking-audit-core-1765285076
hariombalhara Dec 15, 2025
f2085f0
Better types with GetDisplayTitleParams and GetDisplayJsonParams
hariombalhara Dec 15, 2025
8f6093d
feat: introduce operationId for enhanced audit log correlation
hariombalhara Dec 15, 2025
419e512
feat: implement bulk booking audit processing
hariombalhara Dec 16, 2025
5ac29f9
feat(booking-audit): extract core audit system changes from PR 25125
devin-ai-integration[bot] Dec 16, 2025
01b87af
refactor(booking-audit): streamline action handling and enhance local…
hariombalhara Dec 16, 2025
c657e1d
fix(booking-audit): enhance actor role localization and operation ID …
hariombalhara Dec 16, 2025
107fa64
feat: integrate credential repository and enhance app actor handling
hariombalhara Dec 17, 2025
f0bfb93
feat: integrate credential repository and enhance app actor handling
hariombalhara Dec 17, 2025
ed5c47c
Add uuid
hariombalhara Dec 17, 2025
ceb0fd0
feat: enhance booking event handling with bulk audit capabilities
hariombalhara Dec 18, 2025
0274eae
feat: update handlePaymentSuccess to use appSlug for actor identifica…
hariombalhara Dec 18, 2025
794c7e4
misc
hariombalhara Dec 18, 2025
e2681d5
Merge remote-tracking branch 'origin/devin/booking-audit-core-only-17…
hariombalhara Dec 18, 2025
e4ef443
Merge remote-tracking branch 'origin/main' into booking-audit-more-infra
hariombalhara Dec 18, 2025
61821eb
Refactor to fireBookingEvents
hariombalhara Dec 19, 2025
3b05064
Merge origin/main into booking-audit-more-infra: resolve conflicts
devin-ai-integration[bot] Jan 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ export class BookingsController_2024_04_15 {
platformCancelUrl: bookingRequest.platformCancelUrl,
platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
platformBookingUrl: bookingRequest.platformBookingUrl,
actionSource: "API_V2" as const,
});
if (!res.onlyRemovedAttendee) {
void (await this.billingService.cancelUsageByBookingUid(res.bookingUid));
Expand Down Expand Up @@ -311,6 +312,7 @@ export class BookingsController_2024_04_15 {
noShowHost: body.noShowHost,
userId: user.id,
userUuid: user.uuid,
actionSource: "API_V2" as const,
});

return { status: SUCCESS_STATUS, data: markNoShowResponse };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class BookingGuestsService_2024_08_13 {
private readonly bookingsRepository: BookingsRepository_2024_08_13,
private readonly bookingsService: BookingsService_2024_08_13,
private readonly platformBookingsService: PlatformBookingsService
) {}
) { }

async addGuests(bookingUid: string, input: AddGuestsInput_2024_08_13, user: ApiAuthGuardUser) {
const booking = await this.bookingsRepository.getByUidWithAttendeesAndUserAndEvent(bookingUid);
Expand All @@ -33,6 +33,7 @@ export class BookingGuestsService_2024_08_13 {
ctx: { user },
input: { bookingId: booking.id, guests: input.guests },
emailsEnabled,
actionSource: "API_V2",
});
if (res.message === "Guests added") {
return await this.bookingsService.getBooking(bookingUid, user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@ export class BookingsService_2024_08_13 {
private readonly regularBookingService: RegularBookingService,
private readonly recurringBookingService: RecurringBookingService,
private readonly instantBookingCreateService: InstantBookingCreateService,
private readonly eventTypeAccessService: EventTypeAccessService
) {}
private readonly eventTypeAccessService: EventTypeAccessService,
private readonly auditActorRepository: PrismaAuditActorRepository
) { }

async createBooking(request: Request, body: CreateBookingInput, authUser: AuthOptionalUser) {
let bookingTeamEventType = false;
Expand Down Expand Up @@ -321,8 +322,7 @@ export class BookingsService_2024_08_13 {
const allowedOptionValues = eventTypeBookingField.options.map((opt) => opt.value);
if (!this.isValidSingleOptionValue(submittedValue, allowedOptionValues)) {
throw new BadRequestException(
`Invalid option '${submittedValue}' for booking field '${
eventTypeBookingField.name
`Invalid option '${submittedValue}' for booking field '${eventTypeBookingField.name
}'. Allowed options are: ${allowedOptionValues.join(", ")}.`
);
}
Expand All @@ -336,8 +336,7 @@ export class BookingsService_2024_08_13 {
const allowedOptionValues = eventTypeBookingField.options.map((opt) => opt.value);
if (!this.areValidMultipleOptionValues(submittedValues, allowedOptionValues)) {
throw new BadRequestException(
`One or more invalid options for booking field '${
eventTypeBookingField.name
`One or more invalid options for booking field '${eventTypeBookingField.name
}'. Allowed options are: ${allowedOptionValues.join(", ")}.`
);
}
Expand All @@ -351,8 +350,7 @@ export class BookingsService_2024_08_13 {
const allowedOptionValues = eventTypeBookingField.options.map((opt) => opt.value);
if (!this.areValidMultipleOptionValues(submittedValues, allowedOptionValues)) {
throw new BadRequestException(
`One or more invalid options for booking field '${
eventTypeBookingField.name
`One or more invalid options for booking field '${eventTypeBookingField.name
}'. Allowed options are: ${allowedOptionValues.join(", ")}.`
);
}
Expand All @@ -367,8 +365,7 @@ export class BookingsService_2024_08_13 {
const allowedOptionValues = eventTypeBookingField.options.map((opt) => opt.value);
if (!this.isValidSingleOptionValue(submittedValue, allowedOptionValues)) {
throw new BadRequestException(
`Invalid option '${submittedValue}' for booking field '${
eventTypeBookingField.name
`Invalid option '${submittedValue}' for booking field '${eventTypeBookingField.name
}'. Allowed options are: ${allowedOptionValues.join(", ")}.`
);
}
Expand Down Expand Up @@ -921,40 +918,41 @@ export class BookingsService_2024_08_13 {
return await this.getBooking(recurringBookingUid, authUser);
}

async markAbsent(
bookingUid: string,
bookingOwnerId: number,
body: MarkAbsentBookingInput_2024_08_13,
userUuid?: string
) {
const bodyTransformed = this.inputService.transformInputMarkAbsentBooking(body);
const bookingBefore = await this.bookingsRepository.getByUid(bookingUid);

if (!bookingBefore) {
throw new NotFoundException(`Booking with uid=${bookingUid} not found.`);
}
async markAbsent(
bookingUid: string,
bookingOwnerId: number,
body: MarkAbsentBookingInput_2024_08_13,
userUuid?: string
) {
const bodyTransformed = this.inputService.transformInputMarkAbsentBooking(body);
const bookingBefore = await this.bookingsRepository.getByUid(bookingUid);

const nowUtc = DateTime.utc();
const bookingStartTimeUtc = DateTime.fromJSDate(bookingBefore.startTime, { zone: "utc" });
if (!bookingBefore) {
throw new NotFoundException(`Booking with uid=${bookingUid} not found.`);
}

if (nowUtc < bookingStartTimeUtc) {
throw new BadRequestException(
`Bookings can only be marked as absent after their scheduled start time. Current time in UTC+0: ${nowUtc.toISO()}, Booking start time in UTC+0: ${bookingStartTimeUtc.toISO()}`
);
}
const nowUtc = DateTime.utc();
const bookingStartTimeUtc = DateTime.fromJSDate(bookingBefore.startTime, { zone: "utc" });

const platformClientParams = bookingBefore?.eventTypeId
? await this.platformBookingsService.getOAuthClientParams(bookingBefore.eventTypeId)
: undefined;
if (nowUtc < bookingStartTimeUtc) {
throw new BadRequestException(
`Bookings can only be marked as absent after their scheduled start time. Current time in UTC+0: ${nowUtc.toISO()}, Booking start time in UTC+0: ${bookingStartTimeUtc.toISO()}`
);
}

await handleMarkNoShow({
bookingUid,
attendees: bodyTransformed.attendees,
noShowHost: bodyTransformed.noShowHost,
userId: bookingOwnerId,
userUuid,
platformClientParams,
});
const platformClientParams = bookingBefore?.eventTypeId
? await this.platformBookingsService.getOAuthClientParams(bookingBefore.eventTypeId)
: undefined;

await handleMarkNoShow({
bookingUid,
attendees: bodyTransformed.attendees,
noShowHost: bodyTransformed.noShowHost,
userId: bookingOwnerId,
userUuid,
platformClientParams,
actionSource: "API_V2",
});

const booking = await this.bookingsRepository.getByUidWithAttendeesAndUserAndEvent(bookingUid);

Expand Down Expand Up @@ -1038,6 +1036,8 @@ export class BookingsService_2024_08_13 {
emailsEnabled,
platformClientParams,
reassignedById: reassignedByUser.id,
reassignedByUuid: reassignedByUser.uuid,
actionSource: "API_V2",
});
} catch (error) {
if (error instanceof Error) {
Expand Down Expand Up @@ -1103,8 +1103,10 @@ export class BookingsService_2024_08_13 {
orgId: profile?.organizationId || null,
reassignReason: body.reason,
reassignedById: reassignedByUser.id,
reassignedByUuid: reassignedByUser.uuid,
emailsEnabled,
platformClientParams,
actionSource: "API_V2",
});

return this.outputService.getOutputReassignedBooking(reassigned);
Expand Down
7 changes: 6 additions & 1 deletion apps/api/v2/src/lib/services/recurring-booking.service.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { RegularBookingService } from "@/lib/services/regular-booking.service";
import { BookingEventHandlerService } from "@/lib/services/booking-event-handler.service";
import { Injectable } from "@nestjs/common";

import { RecurringBookingService as BaseRecurringBookingService } from "@calcom/platform-libraries/bookings";

@Injectable()
export class RecurringBookingService extends BaseRecurringBookingService {
constructor(regularBookingService: RegularBookingService) {
constructor(
regularBookingService: RegularBookingService,
bookingEventHandler: BookingEventHandlerService
) {
super({
regularBookingService,
bookingEventHandler,
});
}
}
18 changes: 1 addition & 17 deletions apps/web/pages/api/book/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,28 +54,12 @@ async function handler(req: NextApiRequest & { userId?: number; traceContext: Tr
hostname: req.headers.host || "",
forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
traceContext: req.traceContext,
userUuid: session?.user?.uuid || undefined,
impersonatedByUserUuid: session?.user?.impersonatedBy?.uuid,
},
});

// const booking = await createBookingThroughFactory();
return booking;

// To be added in the follow-up PR
// async function createBookingThroughFactory() {
// console.log("Creating booking through factory");
// const regularBookingService = getRegularBookingService();

// const booking = await regularBookingService.createBooking({
// bookingData: req.body,
// bookingMeta: {
// userId: session?.user?.id || -1,
// hostname: req.headers.host || "",
// forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
// },
// });
// return booking;
// }
}

export default defaultResponder(handler, "/api/book/event");
8 changes: 6 additions & 2 deletions apps/web/pages/api/book/recurring-event.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { NextApiRequest } from "next";

import { CreationSource } from "@calcom/prisma/enums";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { getRecurringBookingService } from "@calcom/features/bookings/di/RecurringBookingService.container";
import type { BookingResponse } from "@calcom/features/bookings/types";
Expand Down Expand Up @@ -45,7 +45,10 @@ async function handler(req: NextApiRequest & RequestMeta) {

const recurringBookingService = getRecurringBookingService();
const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
bookingData: req.body,
bookingData: {
...req.body,
creationSource: CreationSource.WEBAPP,
},
bookingMeta: {
userId: session?.user?.id || -1,
platformClientId: req.platformClientId,
Expand All @@ -54,6 +57,7 @@ async function handler(req: NextApiRequest & RequestMeta) {
platformRescheduleUrl: req.platformRescheduleUrl,
platformBookingLocation: req.platformBookingLocation,
noEmail: req.noEmail,
userUuid: session?.user?.uuid || undefined,
},
});

Expand Down
16 changes: 11 additions & 5 deletions apps/web/public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -3238,7 +3238,7 @@
"only_if_field_is_empty": "Only if field is empty",
"booking_start_date": "Booking start date",
"booking_created_date": "Booking created date",
"booking_reassigned_to_host": "Booking reassigned to {{host}}",
"booking_reassigned_to_host": "Reassigned to {{host}}",
"no_contact_owner": "No contact owner",
"routing_forms_created": "Routing Forms Created",
"routing_forms_total_responses": "Total Responses",
Expand Down Expand Up @@ -3642,6 +3642,8 @@
"pbac_action_read_team_bookings": "View Team Bookings",
"pbac_action_read_org_bookings": "View Organization Bookings",
"pbac_action_read_recordings": "View Recordings",
"pbac_action_read_team_audit_logs": "View team audit logs",
"pbac_action_read_org_audit_logs": "View organization audit logs",
"pbac_action_impersonate": "Impersonate",
"pbac_action_edit_users": "Edit Users",
"role_created_successfully": "Role created successfully",
Expand Down Expand Up @@ -3712,6 +3714,8 @@
"pbac_desc_view_team_bookings": "View team bookings",
"pbac_desc_view_organization_bookings": "View organization bookings",
"pbac_desc_view_booking_recordings": "View booking recordings",
"pbac_desc_view_team_audit_logs": "View audit logs for team bookings",
"pbac_desc_view_org_audit_logs": "View audit logs for organization bookings",
"pbac_desc_update_bookings": "Update bookings",
"pbac_desc_manage_bookings": "All actions on bookings",
"pbac_desc_view_team_insights": "View team insights",
Expand Down Expand Up @@ -4180,7 +4184,7 @@
"booking_history": "Booking History",
"booking_history_description": "View the history of actions performed on this booking",
"booking_audit_action": {
"created": "Created",
"created": "Booked with {{host}}",
"cancelled": "Cancelled",
"rescheduled": "Rescheduled {{oldDate}} -> <0>{{newDate}}</0>",
"rescheduled_from": "Rescheduled <0>{{oldDate}}</0> -> {{newDate}}",
Expand All @@ -4195,9 +4199,11 @@
"location_changed": "Location Changed",
"location_changed_from_to": "Location changed from {{fromLocation}} to {{toLocation}}",
"attendee_no_show_updated": "Attendee No-Show Updated",
"type": "Assignment Type",
"assignmentType_manual": "Manual Assignment",
"assignmentType_roundRobin": "Round Robin Assignment",
"seat_booked": "Seat Booked",
"seat_rescheduled": "Seat Rescheduled {{oldDate}} -> <0>{{newDate}}</0>",
"assignment_type": "Assignment",
"assignmentType_manual": "Manual",
"assignmentType_roundRobin": "Round Robin",
"actor_impersonated_by": "Impersonator",
"source": "Source"
},
Expand Down
28 changes: 26 additions & 2 deletions packages/app-store/_utils/payments/handlePaymentSuccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/book
import { handleBookingRequested } from "@calcom/features/bookings/lib/handleBookingRequested";
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
import { getBooking } from "@calcom/features/bookings/lib/payment/getBooking";
import type { Actor } from "@calcom/features/booking-audit/lib/dto/types";
import { makeAppActor, makeAppActorUsingSlug } from "@calcom/features/booking-audit/lib/makeActor";
import { CreditService } from "@calcom/features/ee/billing/credit-service";
import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer";
import { getAllWorkflowsFromEventType } from "@calcom/features/ee/workflows/lib/getAllWorkflowsFromEventType";
Expand All @@ -28,16 +30,37 @@ import prisma from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";
import { BookingStatus, WebhookTriggerEvents, WorkflowTriggerEvents } from "@calcom/prisma/enums";
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
import { getAppNameFromSlug } from "@calcom/features/booking-audit/lib/getAppNameFromSlug";

const log = logger.getSubLogger({ prefix: ["[handlePaymentSuccess]"] });
export async function handlePaymentSuccess(paymentId: number, bookingId: number, traceContext: TraceContext) {

export async function handlePaymentSuccess(params: { paymentId: number; appSlug: string; bookingId: number; traceContext: TraceContext }) {
const { paymentId, bookingId, appSlug, traceContext } = params;
const updatedTraceContext = distributedTracing.updateTrace(traceContext, {
bookingId,
paymentId,
});
log.debug(`handling payment success for bookingId ${bookingId}`);
const { booking, user: userWithCredentials, evt, eventType } = await getBooking(bookingId);

const apps = eventTypeAppMetadataOptionalSchema.parse(eventType?.metadata?.apps);

let actor: Actor;
const appData = apps?.[appSlug as keyof typeof apps];
if (appData?.credentialId) {
actor = makeAppActor({ credentialId: appData.credentialId });
} else {
log.warn(`Missing credentialId for payment app, using appSlug fallback`, {
bookingId,
eventTypeId: eventType?.id,
appSlug,
});
actor = makeAppActorUsingSlug({
appSlug,
name: getAppNameFromSlug({ appSlug }),
});
}

try {
await tasker.cancelWithReference(booking.uid, "sendAwaitingPaymentEmail");
log.debug(`Cancelled scheduled awaiting payment email for booking ${bookingId}`);
Expand Down Expand Up @@ -70,7 +93,6 @@ export async function handlePaymentSuccess(paymentId: number, bookingId: number,
const areEmailsEnabled = platformOAuthClient?.areEmailsEnabled ?? true;

if (isConfirmed) {
const apps = eventTypeAppMetadataOptionalSchema.parse(eventType?.metadata?.apps);
const eventManager = new EventManager({ ...userWithCredentials, credentials: allCredentials }, apps);
const scheduleResult = areCalendarEventsEnabled
? await eventManager.create(evt)
Expand Down Expand Up @@ -237,6 +259,8 @@ export async function handlePaymentSuccess(paymentId: number, bookingId: number,
booking,
paid: true,
platformClientParams,
source: "WEBHOOK",
actor,
traceContext: updatedTraceContext,
});
} else {
Expand Down
7 changes: 6 additions & 1 deletion packages/app-store/alby/api/webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const traceContext = distributedTracing.createTrace("alby_webhook", {
meta: { paymentId: payment.id, bookingId: payment.bookingId },
});
return await handlePaymentSuccess(payment.id, payment.bookingId, traceContext);
return await handlePaymentSuccess({
paymentId: payment.id,
bookingId: payment.bookingId,
appSlug: "alby",
traceContext,
});
} catch (_err) {
const err = getServerErrorFromUnknown(_err);
console.error(`Webhook Error: ${err.message}`);
Expand Down
7 changes: 6 additions & 1 deletion packages/app-store/btcpayserver/api/webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const traceContext = distributedTracing.createTrace("btcpayserver_webhook", {
meta: { paymentId: payment.id, bookingId: payment.bookingId },
});
await handlePaymentSuccess(payment.id, payment.bookingId, traceContext);
await handlePaymentSuccess({
paymentId: payment.id,
bookingId: payment.bookingId,
appSlug: "btcpayserver",
traceContext,
});
return res.status(200).json({ success: true });
} catch (_err) {
const err = getServerErrorFromUnknown(_err);
Expand Down
Loading
Loading