feat: Write wrong assignment reports to the database (#27405)
* Add DB table for wrong assignment reports * When report is submitted write to the db * Prevent duplicate reportings * test: add migration and tests for WrongAssignmentReport table Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add unique constraint on bookingUid and booking access check for hasWrongAssignmentReport - Add @unique constraint on bookingUid in WrongAssignmentReport model to prevent duplicate reports at DB level - Add booking ownership check using BookingAccessService in hasWrongAssignmentReport endpoint - Refactor hasWrongAssignmentReport into separate handler and schema files Addresses Cubic AI review feedback on PR #27405 Co-Authored-By: unknown <> * feat: add routingFormId to WrongAssignmentReport and fix Select clearing - Add routingFormId field to WrongAssignmentReport model in schema.prisma - Add relation to App_RoutingForms_Form with SetNull on delete - Update WrongAssignmentReportRepository.createReport to accept routingFormId - Update BookingRepository.findByUidIncludeEventTypeAndTeamAndAssignmentReason to include routedFromRoutingFormReponse - Extract routingFormId from booking in reportWrongAssignment handler - Fix Select clearing issue: handle null case when user clears team member selection - Update tests to include routingFormId field Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: add migration for routingFormId in WrongAssignmentReport Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: address Udit's review comments - hasWrongAssignmentReport: throw UNAUTHORIZED error instead of returning false - reportWrongAssignment: add try-catch for Prisma P2002 unique constraint error - WrongAssignmentReport: add Team relation to teamId field - WrongAssignmentReportRepository: use findUnique instead of findFirst - reportWrongAssignment: use i18n for error messages Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: revert hasWrongAssignmentReport to return false when user lacks access Per PR checklist, hasWrongAssignmentReport should return { hasReport: false } when user lacks access to booking, not throw an error. This allows the UI to gracefully treat 'no access' as 'no report exists'. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: update mocks for findUnique and i18n in unit tests Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: throw UNAUTHORIZED in hasWrongAssignmentReport and squash migrations Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: change User relation onDelete from Cascade to SetNull in WrongAssignmentReport Address Hariom's review feedback: - Changed reportedById from Int to Int? (nullable) - Changed reportedBy relation from onDelete: Cascade to onDelete: SetNull - Updated migration SQL to reflect these changes This preserves wrong assignment reports even when the reporting user is deleted, as the data is still useful for analysis. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
12 files changed
+513
-2
No files matched your search
@@ -164,7 +164,7 @@ function AssigneeSection(props: AssigneeSectionProps): JSX.Element {
|
||||
field: ControllerRenderProps<FormValues, "correctAssignee">;
|
||||
}): JSX.Element => {
|
||||
const handleChange = (option: TeamMemberOption | null): void => {
|
||||
if (option) field.onChange(option.value);
|
||||
field.onChange(option ? option.value : "");
|
||||
};
|
||||
return (
|
||||
<Select
|
||||
@@ -234,6 +234,12 @@ export function WrongAssignmentDialog(props: IWrongAssignmentDialog): JSX.Elemen
|
||||
},
|
||||
});
|
||||
|
||||
const { data: existingReport, isPending: isCheckingReport } = trpc.viewer.bookings.hasWrongAssignmentReport.useQuery(
|
||||
{ bookingUid },
|
||||
{ enabled: isOpenDialog }
|
||||
);
|
||||
const alreadyReported = existingReport?.hasReport ?? false;
|
||||
|
||||
const teamIdForQuery = teamId ?? 0;
|
||||
const { data: teamMembersData } = trpc.viewer.teams.listMembers.useQuery(
|
||||
{ teamId: teamIdForQuery, limit: 100 },
|
||||
@@ -311,6 +317,10 @@ export function WrongAssignmentDialog(props: IWrongAssignmentDialog): JSX.Elemen
|
||||
errorMessage={errors.additionalNotes?.message}
|
||||
/>
|
||||
|
||||
{alreadyReported && (
|
||||
<Alert severity="warning" message={t("wrong_assignment_already_reported")} className="mb-4" />
|
||||
)}
|
||||
|
||||
<Alert severity="info" title={t("did_you_know")} message={t("wrong_assignment_crm_info")} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -319,7 +329,7 @@ export function WrongAssignmentDialog(props: IWrongAssignmentDialog): JSX.Elemen
|
||||
<Button type="button" color="secondary" onClick={handleCloseClick} disabled={isPending}>
|
||||
{t("close")}
|
||||
</Button>
|
||||
<Button type="submit" color="primary" disabled={isPending} loading={isPending}>
|
||||
<Button type="submit" color="primary" disabled={isPending || alreadyReported || isCheckingReport} loading={isPending || isCheckingReport}>
|
||||
{t("submit")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -840,6 +840,7 @@
|
||||
"report_wrong_assignment": "Report wrong assignment",
|
||||
"wrong_assignment": "Wrong Assignment",
|
||||
"wrong_assignment_reported": "Wrong assignment reported successfully",
|
||||
"wrong_assignment_already_reported": "A wrong assignment report has already been submitted for this booking.",
|
||||
"routing_reason": "Routing Reason",
|
||||
"no_routing_reason": "No routing reason available",
|
||||
"who_booked_it": "Who booked it?",
|
||||
|
||||
Reference in new issue
Block a user