Files
calendar/packages/features/booking-audit/lib/actions/ReassignmentAuditActionService.ts
T
Hariom BalharaGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
f350542d0d feat: add booking audit action services for lib/actions folder (#25720)
Extract lib/actions folder changes from booking-audit-more-infra branch:
- AcceptedAuditActionService
- AttendeeAddedAuditActionService
- AttendeeNoShowUpdatedAuditActionService
- AttendeeRemovedAuditActionService
- CancelledAuditActionService
- CreatedAuditActionService (modified)
- HostNoShowUpdatedAuditActionService
- IAuditActionService (modified)
- LocationChangedAuditActionService
- ReassignmentAuditActionService
- RejectedAuditActionService
- RescheduleRequestedAuditActionService
- RescheduledAuditActionService

Also includes common/changeSchemas.ts required for type-checks to pass.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-12-09 14:29:41 +05:30

92 lines
3.4 KiB
TypeScript

import { z } from "zod";
import type { UserRepository } from "@calcom/features/users/repositories/UserRepository";
import { StringChangeSchema, NumberChangeSchema } from "../common/changeSchemas";
import { AuditActionServiceHelper } from "./AuditActionServiceHelper";
import type { IAuditActionService, TranslationWithParams } from "./IAuditActionService";
/**
* Reassignment Audit Action Service
* Handles REASSIGNMENT action with per-action versioning
*/
// Module-level because it is passed to IAuditActionService type outside the class scope
const fieldsSchemaV1 = z.object({
assignedToId: NumberChangeSchema,
assignedById: NumberChangeSchema,
reassignmentReason: StringChangeSchema,
userPrimaryEmail: StringChangeSchema.optional(),
title: StringChangeSchema.optional(),
});
export class ReassignmentAuditActionService
implements IAuditActionService<typeof fieldsSchemaV1, typeof fieldsSchemaV1> {
readonly VERSION = 1;
public static readonly TYPE = "REASSIGNMENT" as const;
private static dataSchemaV1 = z.object({
version: z.literal(1),
fields: fieldsSchemaV1,
});
private static fieldsSchemaV1 = fieldsSchemaV1;
public static readonly latestFieldsSchema = fieldsSchemaV1;
// Union of all versions
public static readonly storedDataSchema = ReassignmentAuditActionService.dataSchemaV1;
// Union of all versions
public static readonly storedFieldsSchema = ReassignmentAuditActionService.fieldsSchemaV1;
private helper: AuditActionServiceHelper<
typeof ReassignmentAuditActionService.latestFieldsSchema,
typeof ReassignmentAuditActionService.storedDataSchema
>;
constructor(private userRepository: UserRepository) {
this.helper = new AuditActionServiceHelper({
latestVersion: this.VERSION,
latestFieldsSchema: ReassignmentAuditActionService.latestFieldsSchema,
storedDataSchema: ReassignmentAuditActionService.storedDataSchema,
});
}
getVersionedData(fields: unknown) {
return this.helper.getVersionedData(fields);
}
parseStored(data: unknown) {
return this.helper.parseStored(data);
}
getVersion(data: unknown): number {
return this.helper.getVersion(data);
}
migrateToLatest(data: unknown) {
// V1-only: validate and return as-is (no migration needed)
const validated = fieldsSchemaV1.parse(data);
return { isMigrated: false, latestData: validated };
}
async getDisplayTitle(storedData: { version: number; fields: z.infer<typeof fieldsSchemaV1> }): Promise<TranslationWithParams> {
const { fields } = storedData;
const user = await this.userRepository.findById({ id: fields.assignedToId.new });
const reassignedToName = user?.name || "Unknown";
return {
key: "booking_audit_action.booking_reassigned_to_host",
params: { host: reassignedToName },
};
}
getDisplayJson(storedData: { version: number; fields: z.infer<typeof fieldsSchemaV1> }): ReassignmentAuditDisplayData {
const { fields } = storedData;
return {
newAssignedToId: fields.assignedToId.new,
reassignmentReason: fields.reassignmentReason.new ?? null,
};
}
}
export type ReassignmentAuditData = z.infer<typeof fieldsSchemaV1>;
export type ReassignmentAuditDisplayData = {
newAssignedToId: number;
reassignmentReason: string | null;
};