Files
calendar/apps
Hariom BalharaandGitHub 95f7f03f0e chore: Integrate round-robin reassignment booking audit (#26586)
## What does this PR do?

Implements booking audit logging for round-robin reassignment events (both manual and automatic). This is part of the booking audit integration plan (PR 7).

Changes:
- Added audit logging to `roundRobinManualReassignment.ts` for manual host reassignments
- Added audit logging to `roundRobinReassignment.ts` for automatic round-robin reassignments
- Updated tRPC handlers to pass `actionSource: "WEBAPP"` and `reassignedByUuid`
- Updated API v2 bookings service to pass `actionSource: "API_V2"` and `reassignedByUuid`
- Updated `ReassignmentAuditActionService.ts` with proper field schemas and translation keys

The audit logging uses `BookingEventHandlerService.onReassignment()` with proper actor identification and action source tracking.

## Updates since last revision

Addressed review feedback:
- Renamed `title` field to `hostName` for semantic clarity (tracks host name changes, not booking titles)
- Fixed `assignedById` schema: changed from `NumberChangeSchema` to `z.number()` (no old/new pattern needed - it's always the user who performed the reassignment)
- Fixed `reassignmentReason` schema: changed from `StringChangeSchema` to `z.string().nullable()` (no old/new pattern needed)
- Added `ValidActionSource` type that excludes `UNKNOWN` - clients must pass explicit action sources
- Made `actionSource` required in both reassignment functions (no longer optional)
- Added integration tests for `ReassignmentAuditActionService` (15 tests covering all methods)
- Updated `roundRobinManualReassign.handler.ts` to pass required `actionSource` and `reassignedByUuid` params

**Latest fixes:**
- Fixed `hasAttendeeUpdated` check in `ReassignmentAuditActionService.ts`: changed from `!== null` to `!= null` to properly handle undefined values
- Updated test expectations in `ReassignmentAuditActionService.test.ts` to match the new display JSON field names (`hostAttendeeUserUuidNew`/`hostAttendeeUserUuidOld` instead of `newAssignedRRHostUuid`/`previousAssignedRRHostUuid`)
- Fixed async `getDisplayFields` tests to properly await the Promise and include the `previous_assignee` field
- Fixed `hasAttendeeUpdated` to check for `hostAttendeeUpdated` object presence instead of optional `id` field - host changes with only `withUserUuid` populated were being ignored (identified by Cubic AI, confidence 9/10)
- Fixed test expectation in `getDisplayJson` test: removed incorrect null expectations for `hostAttendeeIdUpdated`, `hostAttendeeUserUuidNew`, `hostAttendeeUserUuidOld` - the implementation uses conditional spreading to omit these fields when `hostAttendeeUpdated` is not present, rather than setting them to null

## Mandatory Tasks (DO NOT REMOVE)

- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - no documentation changes needed.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.

## How should this be tested?

1. Trigger a manual round-robin reassignment via the webapp and verify audit logs are created with `actionSource: "WEBAPP"`
2. Trigger an automatic round-robin reassignment and verify audit logs are created
3. Use API v2 to reassign a booking and verify audit logs are created with `actionSource: "API_V2"`
4. Verify the audit data contains correct values for `organizerUuid`, `hostAttendeeUpdated`, `reassignmentReason`, and `reassignmentType`

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have checked if my changes generate no new warnings

## Human Review Checklist


- [x] Verify the `hasAttendeeUpdated` fix is correct: now checks `fields.hostAttendeeUpdated != null` to detect any host attendee update regardless of whether `id` is populated
- [x] Verify `getDisplayJson` test fix: fields are correctly omitted (not set to null) when `hostAttendeeUpdated` is not present, matching the conditional spreading implementation
- [ ] Verify all callers of reassignment functions pass required `actionSource` and `reassignedByUuid`
- [ ] Confirm `getDisplayFields` is properly awaited in all call sites (it's now async)
- [ ] Check that `ValidActionSource` type properly excludes `UNKNOWN` for client-side validation

## Important Notes for Reviewer

1. **Dependency on base PR**: The translation key changes use the format from base PR (#26046). This PR should be merged after the base PR.

2. **Schema changes**: The `organizerUuid` and `hostAttendeeUpdated` fields track both organizer changes and round-robin host attendee changes separately for complete audit trail.

---


Link to Devin run: https://app.devin.ai/sessions/e4353e2ec6ea4a51ab33313bdc630aba
Requested by: @hariombalhara
2026-01-23 08:13:22 +05:30
..